diff --git a/packages/web/src/designer/DesignerQueryDumper.ts b/packages/web/src/designer/DesignerQueryDumper.ts index 21dfbf313..492c7e887 100644 --- a/packages/web/src/designer/DesignerQueryDumper.ts +++ b/packages/web/src/designer/DesignerQueryDumper.ts @@ -55,7 +55,7 @@ export class DesignerQueryDumper { }); // cross join conditions in subcomponents - for (const ref of this.designer.references) { + for (const ref of this.designer.references || []) { if (referenceIsCrossJoin(ref) && referenceIsConnecting(ref, component.tables, component.myAndParentTables)) { select.where = mergeConditions(select.where, { conditionType: 'and', @@ -70,9 +70,9 @@ export class DesignerQueryDumper { } addConditions(select: Select, tables: DesignerTableInfo[]) { - for (const column of this.designer.columns) { + for (const column of this.designer.columns || []) { if (!column.filter) continue; - const table = this.designer.tables.find((x) => x.designerId == column.designerId); + const table = (this.designer.tables || []).find((x) => x.designerId == column.designerId); if (!tables.find((x) => x.designerId == table.designerId)) continue; const condition = parseFilter(column.filter, findDesignerFilterType(column, this.designer)); @@ -102,7 +102,7 @@ export class DesignerQueryDumper { // top level cross join conditions const topLevelTables = this.topLevelTables; - for (const ref of this.designer.references) { + for (const ref of this.designer.references || []) { if (referenceIsCrossJoin(ref) && referenceIsConnecting(ref, topLevelTables, topLevelTables)) { res.where = mergeConditions(res.where, { conditionType: 'and', @@ -111,7 +111,7 @@ export class DesignerQueryDumper { } } - const topLevelColumns = this.designer.columns.filter((col) => + const topLevelColumns = (this.designer.columns || []).filter((col) => topLevelTables.find((tbl) => tbl.designerId == col.designerId) ); const selectIsGrouped = !!topLevelColumns.find((x) => x.isGrouped || (x.aggregate && x.aggregate != '---')); diff --git a/packages/web/src/designer/QueryDesignToolbar.js b/packages/web/src/designer/QueryDesignToolbar.js new file mode 100644 index 000000000..58efb9f30 --- /dev/null +++ b/packages/web/src/designer/QueryDesignToolbar.js @@ -0,0 +1,19 @@ +import React from 'react'; +import useHasPermission from '../utility/useHasPermission'; +import ToolbarButton from '../widgets/ToolbarButton'; + +export default function QueryDesignToolbar({ execute, isDatabaseDefined, busy, save }) { + const hasPermission = useHasPermission(); + return ( + <> + + Execute + + {hasPermission('files/query/write') && ( + + Save + + )} + + ); +} diff --git a/packages/web/src/designer/QueryDesigner.js b/packages/web/src/designer/QueryDesigner.js index 53947a8f8..f5f1969ae 100644 --- a/packages/web/src/designer/QueryDesigner.js +++ b/packages/web/src/designer/QueryDesigner.js @@ -2,6 +2,6 @@ import React from 'react'; import styled from 'styled-components'; import Designer from './Designer'; -export default function QueryDesigner({ value, conid, database, engine, onChange, onKeyDown }) { +export default function QueryDesigner({ value, conid, database, engine, onChange }) { return ; } diff --git a/packages/web/src/sqleditor/ResultTabs.js b/packages/web/src/sqleditor/ResultTabs.js index 6b81eadeb..8642051ad 100644 --- a/packages/web/src/sqleditor/ResultTabs.js +++ b/packages/web/src/sqleditor/ResultTabs.js @@ -27,7 +27,7 @@ export default function ResultTabs({ children, sessionId, executeNumber }) { }, [sessionId, socket]); return ( - 0 ? 1 : 0}> + 0 ? 'Result 1' : null}> {children} {_.sortBy(resultInfos, 'resultIndex').map((info) => ( diff --git a/packages/web/src/tabs/QueryDesignTab.js b/packages/web/src/tabs/QueryDesignTab.js index 8359bf15d..50f56b0c2 100644 --- a/packages/web/src/tabs/QueryDesignTab.js +++ b/packages/web/src/tabs/QueryDesignTab.js @@ -6,7 +6,7 @@ import axios from '../utility/axios'; import { useConnectionInfo } from '../utility/metadataLoaders'; import SqlEditor from '../sqleditor/SqlEditor'; import { useUpdateDatabaseForTab, useSetOpenedTabs } from '../utility/globalState'; -import QueryToolbar from '../query/QueryToolbar'; +import QueryDesignToolbar from '../designer/QueryDesignToolbar'; import SocketMessagesView from '../query/SocketMessagesView'; import { TabPage } from '../widgets/TabControl'; import ResultTabs from '../sqleditor/ResultTabs'; @@ -62,7 +62,7 @@ export default function QueryDesignTab({ const generatePreview = (value, engine) => { if (!engine || !value) return; const sql = generateDesignedQuery(value, engine); - setSqlPreview(sql); + setSqlPreview(sqlFormatter.format(sql)); }; React.useEffect(() => { @@ -84,10 +84,9 @@ export default function QueryDesignTab({ useUpdateDatabaseForTab(tabVisible, conid, database); - const handleExecute = async () => { + const handleExecute = React.useCallback(async () => { if (busy) return; setExecuteNumber((num) => num + 1); - const selectedText = editorRef.current.editor.getSelectedText(); let sesid = sessionId; if (!sesid) { @@ -101,9 +100,9 @@ export default function QueryDesignTab({ setBusy(true); await axios.post('sessions/execute-query', { sesid, - sql: selectedText || editorData, + sql: sqlPreview, }); - }; + }, [busy]); const handleCancel = () => { axios.post('sessions/cancel', { @@ -119,12 +118,21 @@ export default function QueryDesignTab({ setBusy(false); }; - const handleKeyDown = (data, hash, keyString, keyCode, event) => { - if (keyCode == keycodes.f5) { - event.preventDefault(); + const handleKeyDown = React.useCallback((e) => { + if (e.keyCode == keycodes.f5) { + e.preventDefault(); handleExecute(); } - }; + }, []); + + React.useEffect(() => { + if (tabVisible) { + document.addEventListener('keydown', handleKeyDown, false); + return () => { + document.removeEventListener('keydown', handleKeyDown); + }; + } + }, [tabVisible, handleKeyDown]); if (isLoading) { return ( @@ -143,7 +151,6 @@ export default function QueryDesignTab({ database={database} engine={connection && connection.engine} onChange={setEditorData} - onKeyDown={handleKeyDown} > @@ -162,22 +169,22 @@ export default function QueryDesignTab({ )} - {/* {toolbarPortalRef && + {toolbarPortalRef && toolbarPortalRef.current && tabVisible && ReactDOM.createPortal( - , toolbarPortalRef.current - )} */} + )} { + if (activePageLabel != null) { + const pageIndex = _.findIndex(childrenArray, (x) => x.props.label == activePageLabel); + if (pageIndex >= 0) setValue(pageIndex); + } + }, [activePageLabel]); + const theme = useTheme(); // // cleanup closed tabs