You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by ju...@apache.org on 2023/10/05 16:33:11 UTC
[superset] branch master updated: chore(sqllab): Typescript for SqlEditor component (#25228)
This is an automated email from the ASF dual-hosted git repository.
justinpark pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/master by this push:
new 34f99708d4 chore(sqllab): Typescript for SqlEditor component (#25228)
34f99708d4 is described below
commit 34f99708d46e1b5b0f0211f493be9617da86dcbf
Author: JUST.in DO IT <ju...@airbnb.com>
AuthorDate: Thu Oct 5 12:33:01 2023 -0400
chore(sqllab): Typescript for SqlEditor component (#25228)
---
superset-frontend/package-lock.json | 13 ++
superset-frontend/package.json | 1 +
.../SqlLab/components/AceEditorWrapper/index.tsx | 3 +-
.../components/RunQueryActionButton/index.tsx | 3 +-
.../src/SqlLab/components/SaveQuery/index.tsx | 7 +-
.../components/ScheduleQueryButton/index.tsx | 2 +-
.../{SqlEditor.test.jsx => SqlEditor.test.tsx} | 41 +++--
.../components/SqlEditor/{index.jsx => index.tsx} | 198 ++++++++++++---------
.../SqlLab/components/SqlEditorLeftBar/index.tsx | 10 +-
.../components/TemplateParamsEditor/index.tsx | 2 +-
superset-frontend/src/SqlLab/constants.ts | 3 +-
superset-frontend/src/SqlLab/types.ts | 2 +
.../src/components/DatabaseSelector/index.tsx | 8 +-
.../databases/DatabaseModal/index.test.tsx | 2 +
superset-frontend/src/features/databases/types.ts | 5 +-
15 files changed, 179 insertions(+), 121 deletions(-)
diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json
index 4c0fa255e1..b8780a78a0 100644
--- a/superset-frontend/package-lock.json
+++ b/superset-frontend/package-lock.json
@@ -191,6 +191,7 @@
"@types/jquery": "^3.5.8",
"@types/js-levenshtein": "^1.1.0",
"@types/json-bigint": "^1.0.1",
+ "@types/mousetrap": "^1.6.11",
"@types/react": "^16.9.43",
"@types/react-dom": "^16.9.8",
"@types/react-gravatar": "^2.6.8",
@@ -19514,6 +19515,12 @@
"integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==",
"dev": true
},
+ "node_modules/@types/mousetrap": {
+ "version": "1.6.11",
+ "resolved": "https://registry.npmjs.org/@types/mousetrap/-/mousetrap-1.6.11.tgz",
+ "integrity": "sha512-F0oAily9Q9QQpv9JKxKn0zMKfOo36KHCW7myYsmUyf2t0g+sBTbG3UleTPoguHdE1z3GLFr3p7/wiOio52QFjQ==",
+ "dev": true
+ },
"node_modules/@types/ms": {
"version": "0.7.31",
"resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz",
@@ -79317,6 +79324,12 @@
"integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==",
"dev": true
},
+ "@types/mousetrap": {
+ "version": "1.6.11",
+ "resolved": "https://registry.npmjs.org/@types/mousetrap/-/mousetrap-1.6.11.tgz",
+ "integrity": "sha512-F0oAily9Q9QQpv9JKxKn0zMKfOo36KHCW7myYsmUyf2t0g+sBTbG3UleTPoguHdE1z3GLFr3p7/wiOio52QFjQ==",
+ "dev": true
+ },
"@types/ms": {
"version": "0.7.31",
"resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz",
diff --git a/superset-frontend/package.json b/superset-frontend/package.json
index 299017b0d0..8cee75833c 100644
--- a/superset-frontend/package.json
+++ b/superset-frontend/package.json
@@ -256,6 +256,7 @@
"@types/jquery": "^3.5.8",
"@types/js-levenshtein": "^1.1.0",
"@types/json-bigint": "^1.0.1",
+ "@types/mousetrap": "^1.6.11",
"@types/react": "^16.9.43",
"@types/react-dom": "^16.9.8",
"@types/react-gravatar": "^2.6.8",
diff --git a/superset-frontend/src/SqlLab/components/AceEditorWrapper/index.tsx b/superset-frontend/src/SqlLab/components/AceEditorWrapper/index.tsx
index 0adf3f8e1f..17c84a3664 100644
--- a/superset-frontend/src/SqlLab/components/AceEditorWrapper/index.tsx
+++ b/superset-frontend/src/SqlLab/components/AceEditorWrapper/index.tsx
@@ -17,6 +17,7 @@
* under the License.
*/
import React, { useState, useEffect, useRef } from 'react';
+import type { IAceEditor } from 'react-ace/lib/types';
import { useDispatch } from 'react-redux';
import { css, styled, usePrevious } from '@superset-ui/core';
@@ -30,7 +31,7 @@ type HotKey = {
key: string;
descr: string;
name: string;
- func: () => void;
+ func: (aceEditor: IAceEditor) => void;
};
type AceEditorWrapperProps = {
diff --git a/superset-frontend/src/SqlLab/components/RunQueryActionButton/index.tsx b/superset-frontend/src/SqlLab/components/RunQueryActionButton/index.tsx
index d2da587091..30f8121132 100644
--- a/superset-frontend/src/SqlLab/components/RunQueryActionButton/index.tsx
+++ b/superset-frontend/src/SqlLab/components/RunQueryActionButton/index.tsx
@@ -19,7 +19,6 @@
import React, { useMemo } from 'react';
import { t, styled, useTheme } from '@superset-ui/core';
-import { Menu } from 'src/components/Menu';
import Button from 'src/components/Button';
import Icons from 'src/components/Icons';
import { DropdownButton } from 'src/components/DropdownButton';
@@ -33,7 +32,7 @@ export interface RunQueryActionButtonProps {
queryState?: string;
runQuery: (c?: boolean) => void;
stopQuery: () => void;
- overlayCreateAsMenu: typeof Menu | null;
+ overlayCreateAsMenu: React.ReactElement | null;
}
const buildText = (
diff --git a/superset-frontend/src/SqlLab/components/SaveQuery/index.tsx b/superset-frontend/src/SqlLab/components/SaveQuery/index.tsx
index 6ed0f4c668..a7ac8b1b2a 100644
--- a/superset-frontend/src/SqlLab/components/SaveQuery/index.tsx
+++ b/superset-frontend/src/SqlLab/components/SaveQuery/index.tsx
@@ -17,6 +17,7 @@
* under the License.
*/
import React, { useState, useEffect, useMemo } from 'react';
+import type { DatabaseObject } from 'src/features/databases/types';
import { Row, Col } from 'src/components';
import { Input, TextArea } from 'src/components/Input';
import { t, styled } from '@superset-ui/core';
@@ -39,10 +40,10 @@ interface SaveQueryProps {
onSave: (arg0: QueryPayload, id: string) => void;
onUpdate: (arg0: QueryPayload, id: string) => void;
saveQueryWarning: string | null;
- database: Record<string, any>;
+ database: Partial<DatabaseObject> | undefined;
}
-type QueryPayload = {
+export type QueryPayload = {
name: string;
description?: string;
id?: string;
@@ -65,7 +66,7 @@ const SaveQuery = ({
queryEditorId,
onSave = () => {},
onUpdate,
- saveQueryWarning = null,
+ saveQueryWarning,
database,
columns,
}: SaveQueryProps) => {
diff --git a/superset-frontend/src/SqlLab/components/ScheduleQueryButton/index.tsx b/superset-frontend/src/SqlLab/components/ScheduleQueryButton/index.tsx
index d0a381638d..f2e3d33581 100644
--- a/superset-frontend/src/SqlLab/components/ScheduleQueryButton/index.tsx
+++ b/superset-frontend/src/SqlLab/components/ScheduleQueryButton/index.tsx
@@ -79,7 +79,7 @@ interface ScheduleQueryButtonProps {
defaultLabel?: string;
sql: string;
schema?: string;
- dbId: number;
+ dbId?: number;
animation?: boolean;
onSchedule?: Function;
scheduleQueryWarning: string | null;
diff --git a/superset-frontend/src/SqlLab/components/SqlEditor/SqlEditor.test.jsx b/superset-frontend/src/SqlLab/components/SqlEditor/SqlEditor.test.tsx
similarity index 89%
rename from superset-frontend/src/SqlLab/components/SqlEditor/SqlEditor.test.jsx
rename to superset-frontend/src/SqlLab/components/SqlEditor/SqlEditor.test.tsx
index ff335e14ea..63f67170d0 100644
--- a/superset-frontend/src/SqlLab/components/SqlEditor/SqlEditor.test.jsx
+++ b/superset-frontend/src/SqlLab/components/SqlEditor/SqlEditor.test.tsx
@@ -21,7 +21,6 @@ import { act } from 'react-dom/test-utils';
import { fireEvent, render, waitFor } from 'spec/helpers/testing-library';
import fetchMock from 'fetch-mock';
import reducers from 'spec/helpers/reducerIndex';
-import SqlEditor from 'src/SqlLab/components/SqlEditor';
import { setupStore } from 'src/views/store';
import {
initialState,
@@ -34,10 +33,20 @@ import ResultSet from 'src/SqlLab/components/ResultSet';
import { api } from 'src/hooks/apiResources/queryApi';
import { getExtensionsRegistry } from '@superset-ui/core';
import setupExtensions from 'src/setup/setupExtensions';
+import type { Action, Middleware, Store } from 'redux';
+import SqlEditor, { Props } from '.';
jest.mock('src/components/AsyncAceEditor', () => ({
...jest.requireActual('src/components/AsyncAceEditor'),
- FullSQLEditor: ({ onChange, onBlur, value }) => (
+ FullSQLEditor: ({
+ onChange,
+ onBlur,
+ value,
+ }: {
+ onChange: (value: string) => void;
+ onBlur: React.FocusEventHandler<HTMLTextAreaElement>;
+ value: string;
+ }) => (
<textarea
data-test="react-ace"
onChange={evt => onChange(evt.target.value)}
@@ -56,8 +65,8 @@ fetchMock.get('glob:*/api/v1/database/*', { result: [] });
fetchMock.get('glob:*/api/v1/database/*/tables/*', { options: [] });
fetchMock.post('glob:*/sqllab/execute/*', { result: [] });
-let store;
-let actions;
+let store: Store;
+let actions: Action[];
const latestQuery = {
...queries[0],
sqlEditorId: defaultQueryEditor.id,
@@ -91,13 +100,13 @@ const mockInitialState = {
},
};
-const setup = (props = {}, store) =>
+const setup = (props: Props, store: Store) =>
render(<SqlEditor {...props} />, {
useRedux: true,
...(store && { store }),
});
-const logAction = () => next => action => {
+const logAction: Middleware = () => next => action => {
if (typeof action === 'function') {
return next(action);
}
@@ -105,9 +114,9 @@ const logAction = () => next => action => {
return next(action);
};
-const createStore = initState =>
+const createStore = (initState: object) =>
setupStore({
- disableDegugger: true,
+ disableDebugger: true,
initialState: initState,
rootReducers: reducers,
middleware: getDefaultMiddleware =>
@@ -124,18 +133,22 @@ describe('SqlEditor', () => {
defaultQueryLimit: 1000,
maxRow: 100000,
displayLimit: 100,
+ saveQueryWarning: '',
+ scheduleQueryWarning: '',
};
beforeEach(() => {
store = createStore(mockInitialState);
actions = [];
- SqlEditorLeftBar.mockClear();
- SqlEditorLeftBar.mockImplementation(() => (
+ (SqlEditorLeftBar as jest.Mock).mockClear();
+ (SqlEditorLeftBar as jest.Mock).mockImplementation(() => (
<div data-test="mock-sql-editor-left-bar" />
));
- ResultSet.mockClear();
- ResultSet.mockImplementation(() => <div data-test="mock-result-set" />);
+ (ResultSet as jest.Mock).mockClear();
+ (ResultSet as jest.Mock).mockImplementation(() => (
+ <div data-test="mock-result-set" />
+ ));
});
afterEach(() => {
@@ -168,8 +181,8 @@ describe('SqlEditor', () => {
const { findByTestId } = setup(mockedProps, store);
const editor = await findByTestId('react-ace');
const sql = 'select *';
- const renderCount = SqlEditorLeftBar.mock.calls.length;
- const renderCountForSouthPane = ResultSet.mock.calls.length;
+ const renderCount = (SqlEditorLeftBar as jest.Mock).mock.calls.length;
+ const renderCountForSouthPane = (ResultSet as jest.Mock).mock.calls.length;
expect(SqlEditorLeftBar).toHaveBeenCalledTimes(renderCount);
expect(ResultSet).toHaveBeenCalledTimes(renderCountForSouthPane);
fireEvent.change(editor, { target: { value: sql } });
diff --git a/superset-frontend/src/SqlLab/components/SqlEditor/index.jsx b/superset-frontend/src/SqlLab/components/SqlEditor/index.tsx
similarity index 87%
rename from superset-frontend/src/SqlLab/components/SqlEditor/index.jsx
rename to superset-frontend/src/SqlLab/components/SqlEditor/index.tsx
index 2626d70d73..08ddf2b0fb 100644
--- a/superset-frontend/src/SqlLab/components/SqlEditor/index.jsx
+++ b/superset-frontend/src/SqlLab/components/SqlEditor/index.tsx
@@ -24,11 +24,12 @@ import React, {
useMemo,
useRef,
useCallback,
+ ChangeEvent,
} from 'react';
+import type AceEditor from 'react-ace';
import useEffectEvent from 'src/hooks/useEffectEvent';
import { CSSTransition } from 'react-transition-group';
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
-import PropTypes from 'prop-types';
import Split from 'react-split';
import {
css,
@@ -38,7 +39,11 @@ import {
t,
useTheme,
getExtensionsRegistry,
+ QueryResponse,
+ Query,
} from '@superset-ui/core';
+import type { QueryEditor, SqlLabRootState } from 'src/SqlLab/types';
+import type { DatabaseObject } from 'src/features/databases/types';
import debounce from 'lodash/debounce';
import throttle from 'lodash/throttle';
import Modal from 'src/components/Modal';
@@ -90,11 +95,11 @@ import getBootstrapData from 'src/utils/getBootstrapData';
import { isEmpty } from 'lodash';
import TemplateParamsEditor from '../TemplateParamsEditor';
import SouthPane from '../SouthPane';
-import SaveQuery from '../SaveQuery';
+import SaveQuery, { QueryPayload } from '../SaveQuery';
import ScheduleQueryButton from '../ScheduleQueryButton';
import EstimateQueryCostButton from '../EstimateQueryCostButton';
import ShareSqlLabQuery from '../ShareSqlLabQuery';
-import SqlEditorLeftBar from '../SqlEditorLeftBar';
+import SqlEditorLeftBar, { ExtendedTable } from '../SqlEditorLeftBar';
import AceEditorWrapper from '../AceEditorWrapper';
import RunQueryActionButton from '../RunQueryActionButton';
import QueryLimitSelect from '../QueryLimitSelect';
@@ -133,7 +138,7 @@ const StyledToolbar = styled.div`
}
`;
-const StyledSidebar = styled.div`
+const StyledSidebar = styled.div<{ width: number; hide: boolean | undefined }>`
flex: 0 0 ${({ width }) => width}px;
width: ${({ width }) => width}px;
padding: ${({ theme, hide }) => (hide ? 0 : theme.gridUnit * 2.5)}px;
@@ -198,46 +203,60 @@ const StyledSqlEditor = styled.div`
`}
`;
-const propTypes = {
- tables: PropTypes.array.isRequired,
- queryEditor: PropTypes.object.isRequired,
- defaultQueryLimit: PropTypes.number.isRequired,
- maxRow: PropTypes.number.isRequired,
- displayLimit: PropTypes.number.isRequired,
- saveQueryWarning: PropTypes.string,
- scheduleQueryWarning: PropTypes.string,
-};
-
const extensionsRegistry = getExtensionsRegistry();
-const SqlEditor = ({
+export type Props = {
+ tables: ExtendedTable[];
+ queryEditor: QueryEditor;
+ defaultQueryLimit: number;
+ maxRow: number;
+ displayLimit: number;
+ saveQueryWarning: string | null;
+ scheduleQueryWarning: string | null;
+};
+
+const elementStyle = (
+ dimension: string,
+ elementSize: number,
+ gutterSize: number,
+) => ({
+ [dimension]: `calc(${elementSize}% - ${
+ gutterSize + SQL_EDITOR_GUTTER_MARGIN
+ }px)`,
+});
+
+const SqlEditor: React.FC<Props> = ({
tables,
queryEditor,
defaultQueryLimit,
maxRow,
displayLimit,
saveQueryWarning,
- scheduleQueryWarning = null,
+ scheduleQueryWarning,
}) => {
const theme = useTheme();
const dispatch = useDispatch();
- const { database, latestQuery, hideLeftBar } = useSelector(
- ({ sqlLab: { unsavedQueryEditor, databases, queries } }) => {
- let { dbId, latestQueryId, hideLeftBar } = queryEditor;
- if (unsavedQueryEditor?.id === queryEditor.id) {
- dbId = unsavedQueryEditor.dbId || dbId;
- latestQueryId = unsavedQueryEditor.latestQueryId || latestQueryId;
- hideLeftBar = unsavedQueryEditor.hideLeftBar || hideLeftBar;
- }
- return {
- database: databases[dbId],
- latestQuery: queries[latestQueryId],
- hideLeftBar,
- };
- },
- shallowEqual,
- );
+ const { database, latestQuery, hideLeftBar } = useSelector<
+ SqlLabRootState,
+ {
+ database?: DatabaseObject;
+ latestQuery?: QueryResponse;
+ hideLeftBar?: boolean;
+ }
+ >(({ sqlLab: { unsavedQueryEditor, databases, queries } }) => {
+ let { dbId, latestQueryId, hideLeftBar } = queryEditor;
+ if (unsavedQueryEditor?.id === queryEditor.id) {
+ dbId = unsavedQueryEditor.dbId || dbId;
+ latestQueryId = unsavedQueryEditor.latestQueryId || latestQueryId;
+ hideLeftBar = unsavedQueryEditor.hideLeftBar || hideLeftBar;
+ }
+ return {
+ database: databases[dbId || ''],
+ latestQuery: queries[latestQueryId || ''],
+ hideLeftBar,
+ };
+ }, shallowEqual);
const [height, setHeight] = useState(0);
const [autorun, setAutorun] = useState(queryEditor.autorun);
@@ -255,8 +274,8 @@ const SqlEditor = ({
const [createAs, setCreateAs] = useState('');
const [showEmptyState, setShowEmptyState] = useState(false);
- const sqlEditorRef = useRef(null);
- const northPaneRef = useRef(null);
+ const sqlEditorRef = useRef<HTMLDivElement>(null);
+ const northPaneRef = useRef<HTMLDivElement>(null);
const SqlFormExtension = extensionsRegistry.get('sqleditor.extension.form');
@@ -311,7 +330,7 @@ const SqlEditor = ({
const getHotkeyConfig = useCallback(() => {
// Get the user's OS
const userOS = detectOS();
- const base = [
+ return [
{
name: 'runQuery1',
key: 'ctrl+r',
@@ -332,11 +351,34 @@ const SqlEditor = ({
}
},
},
+ {
+ name: 'newTab',
+ key: userOS === 'Windows' ? 'ctrl+q' : 'ctrl+t',
+ descr: t('New tab'),
+ func: () => {
+ dispatch(addNewQueryEditor());
+ },
+ },
+ {
+ name: 'stopQuery',
+ key: userOS === 'MacOS' ? 'ctrl+x' : 'ctrl+e',
+ descr: t('Stop query'),
+ func: stopQuery,
+ },
+ ];
+ }, [dispatch, queryEditor.sql, startQuery, stopQuery]);
+
+ const hotkeys = useMemo(() => {
+ // Get all hotkeys including ace editor hotkeys
+ // Get the user's OS
+ const userOS = detectOS();
+ const base = [
+ ...getHotkeyConfig(),
{
name: 'runQuery3',
key: 'ctrl+shift+enter',
descr: t('Run current query'),
- func: editor => {
+ func: (editor: AceEditor['editor']) => {
if (!editor.getValue().trim()) {
return;
}
@@ -347,7 +389,6 @@ const SqlEditor = ({
let end = editor.find(';', {
backwards: false,
skipCurrent: true,
- start: cursorPosition,
})?.end;
if (!end || end.row < cursorPosition.row) {
end = {
@@ -358,18 +399,13 @@ const SqlEditor = ({
let start = editor.find(';', {
backwards: true,
skipCurrent: true,
- start: cursorPosition,
})?.end;
- let currentLine = editor.find(';', {
- backwards: true,
- skipCurrent: true,
- start: cursorPosition,
- })?.end?.row;
+ let currentLine = start?.row;
if (
!currentLine ||
currentLine > cursorPosition.row ||
(currentLine === cursorPosition.row &&
- start?.column > cursorPosition.column)
+ (start?.column || 0) > cursorPosition.column)
) {
currentLine = 0;
}
@@ -384,7 +420,7 @@ const SqlEditor = ({
if (currentLine !== start?.row) {
start = { row: currentLine, column: 0 };
}
- editor.selection.setRange({
+ editor.selection.setSelectionRange({
start: start ?? { row: 0, column: 0 },
end,
});
@@ -394,35 +430,20 @@ const SqlEditor = ({
editor.scrollToRow(currentRow);
},
},
- {
- name: 'newTab',
- key: userOS === 'Windows' ? 'ctrl+q' : 'ctrl+t',
- descr: t('New tab'),
- func: () => {
- dispatch(addNewQueryEditor());
- },
- },
- {
- name: 'stopQuery',
- key: userOS === 'MacOS' ? 'ctrl+x' : 'ctrl+e',
- descr: t('Stop query'),
- func: stopQuery,
- },
];
-
if (userOS === 'MacOS') {
base.push({
name: 'previousLine',
key: 'ctrl+p',
descr: t('Previous Line'),
func: editor => {
- editor.navigateUp(1);
+ editor.navigateUp();
},
});
}
return base;
- }, [dispatch, queryEditor.sql, startQuery, stopQuery]);
+ }, [getHotkeyConfig, startQuery]);
const onBeforeUnload = useEffectEvent(event => {
if (
@@ -461,20 +482,29 @@ const SqlEditor = ({
useEffect(() => {
// setup hotkeys
- Mousetrap.reset();
const hotkeys = getHotkeyConfig();
hotkeys.forEach(keyConfig => {
Mousetrap.bind([keyConfig.key], keyConfig.func);
});
+ return () => {
+ hotkeys.forEach(keyConfig => {
+ Mousetrap.unbind(keyConfig.key);
+ });
+ };
}, [getHotkeyConfig, latestQuery]);
const onResizeStart = () => {
// Set the heights on the ace editor and the ace content area after drag starts
// to smooth out the visual transition to the new heights when drag ends
- document.getElementsByClassName('ace_content')[0].style.height = '100%';
+ const editorEl = document.getElementsByClassName(
+ 'ace_content',
+ )[0] as HTMLElement;
+ if (editorEl) {
+ editorEl.style.height = '100%';
+ }
};
- const onResizeEnd = ([northPercent, southPercent]) => {
+ const onResizeEnd = ([northPercent, southPercent]: number[]) => {
setNorthPercent(northPercent);
setSouthPercent(southPercent);
@@ -495,7 +525,7 @@ const SqlEditor = ({
[setQueryEditorAndSaveSql],
);
- const onSqlChanged = sql => {
+ const onSqlChanged = (sql: string) => {
dispatch(queryEditorSetSql(queryEditor, sql));
setQueryEditorAndSaveSqlWithDebounce(sql);
};
@@ -503,9 +533,9 @@ const SqlEditor = ({
// Return the heights for the ace editor and the south pane as an object
// given the height of the sql editor, north pane percent and south pane percent.
const getAceEditorAndSouthPaneHeights = (
- height,
- northPercent,
- southPercent,
+ height: number,
+ northPercent: number,
+ southPercent: number,
) => ({
aceEditorHeight:
(height * northPercent) / (theme.gridUnit * 25) -
@@ -530,12 +560,6 @@ const SqlEditor = ({
setAutocompleteEnabled(!autocompleteEnabled);
};
- const elementStyle = (dimension, elementSize, gutterSize) => ({
- [dimension]: `calc(${elementSize}% - ${
- gutterSize + SQL_EDITOR_GUTTER_MARGIN
- }px)`,
- });
-
const createTableAs = () => {
startQuery(true, CtasEnum.TABLE);
setShowCreateAsModal(false);
@@ -548,7 +572,7 @@ const SqlEditor = ({
setCtas('');
};
- const ctasChanged = event => {
+ const ctasChanged = (event: ChangeEvent<HTMLInputElement>) => {
setCtas(event.target.value);
};
@@ -566,7 +590,6 @@ const SqlEditor = ({
<AntdSwitch
checked={autocompleteEnabled}
onChange={handleToggleAutocompleteEnabled}
- name="autocomplete-switch"
/>{' '}
</Menu.Item>
{isFeatureEnabled(FeatureFlag.ENABLE_TEMPLATE_PROCESSING) && (
@@ -585,7 +608,7 @@ const SqlEditor = ({
<ScheduleQueryButton
defaultLabel={qe.name}
sql={qe.sql}
- onSchedule={query => dispatch(scheduleQuery(query))}
+ onSchedule={(query: Query) => dispatch(scheduleQuery(query))}
schema={qe.schema}
dbId={qe.dbId}
scheduleQueryWarning={scheduleQueryWarning}
@@ -598,7 +621,7 @@ const SqlEditor = ({
);
};
- const onSaveQuery = async (query, clientId) => {
+ const onSaveQuery = async (query: QueryPayload, clientId: string) => {
const savedQuery = await dispatch(saveQuery(query, clientId));
dispatch(addSavedQueryToTabState(queryEditor, savedQuery));
};
@@ -639,7 +662,7 @@ const SqlEditor = ({
<div className="leftItems">
<span>
<RunQueryActionButton
- allowAsync={database ? database.allow_run_async : false}
+ allowAsync={database?.allow_run_async === true}
queryEditorId={queryEditor.id}
queryState={latestQuery?.state}
runQuery={runQuery}
@@ -668,7 +691,7 @@ const SqlEditor = ({
<Timer
startTime={latestQuery.startDttm}
endTime={latestQuery.endDttm}
- state={STATE_TYPE_MAP[latestQuery.state]}
+ status={STATE_TYPE_MAP[latestQuery.state]}
isRunning={latestQuery.state === 'running'}
/>
)}
@@ -679,8 +702,8 @@ const SqlEditor = ({
queryEditorId={queryEditor.id}
columns={latestQuery?.results?.columns || []}
onSave={onSaveQuery}
- onUpdate={(query, remoteId, id) =>
- dispatch(updateSavedQuery(query, remoteId, id))
+ onUpdate={(query, remoteId) =>
+ dispatch(updateSavedQuery(query, remoteId))
}
saveQueryWarning={saveQueryWarning}
database={database}
@@ -689,7 +712,7 @@ const SqlEditor = ({
<span>
<ShareSqlLabQuery queryEditorId={queryEditor.id} />
</span>
- <AntdDropdown overlay={renderDropdown()} trigger="click">
+ <AntdDropdown overlay={renderDropdown()} trigger={['click']}>
<Icons.MoreHoriz iconColor={theme.colors.grayscale.base} />
</AntdDropdown>
</div>
@@ -698,7 +721,6 @@ const SqlEditor = ({
};
const queryPane = () => {
- const hotkeys = getHotkeyConfig();
const { aceEditorHeight, southPaneHeight } =
getAceEditorAndSouthPaneHeights(height, northPercent, southPercent);
return (
@@ -731,7 +753,7 @@ const SqlEditor = ({
height={`${aceEditorHeight}px`}
hotkeys={hotkeys}
/>
- {renderEditorBottomBar(hotkeys)}
+ {renderEditorBottomBar()}
</div>
<SouthPane
queryEditorId={queryEditor.id}
@@ -792,7 +814,7 @@ const SqlEditor = ({
queryPane()
)}
<Modal
- visible={showCreateAsModal}
+ show={showCreateAsModal}
title={t(createViewModalTitle)}
onHide={() => setShowCreateAsModal(false)}
footer={
@@ -828,6 +850,4 @@ const SqlEditor = ({
);
};
-SqlEditor.propTypes = propTypes;
-
export default SqlEditor;
diff --git a/superset-frontend/src/SqlLab/components/SqlEditorLeftBar/index.tsx b/superset-frontend/src/SqlLab/components/SqlEditorLeftBar/index.tsx
index ef55e30ec6..1a9cb17f97 100644
--- a/superset-frontend/src/SqlLab/components/SqlEditorLeftBar/index.tsx
+++ b/superset-frontend/src/SqlLab/components/SqlEditorLeftBar/index.tsx
@@ -46,7 +46,7 @@ import Icons from 'src/components/Icons';
import { TableSelectorMultiple } from 'src/components/TableSelector';
import { IconTooltip } from 'src/components/IconTooltip';
import useQueryEditor from 'src/SqlLab/hooks/useQueryEditor';
-import { DatabaseObject } from 'src/components/DatabaseSelector';
+import type { DatabaseObject } from 'src/components/DatabaseSelector';
import { emptyStateComponent } from 'src/components/EmptyState';
import {
getItem,
@@ -55,7 +55,7 @@ import {
} from 'src/utils/localStorageHelpers';
import TableElement from '../TableElement';
-interface ExtendedTable extends Table {
+export interface ExtendedTable extends Table {
expanded: boolean;
}
@@ -63,7 +63,7 @@ interface SqlEditorLeftBarProps {
queryEditorId: string;
height?: number;
tables?: ExtendedTable[];
- database: DatabaseObject;
+ database?: DatabaseObject;
setEmptyState: Dispatch<SetStateAction<boolean>>;
}
@@ -134,7 +134,9 @@ const SqlEditorLeftBar = ({
if (bool && userSelected) {
setUserSelected(userSelected);
setItem(LocalStorageKeys.db, null);
- } else setUserSelected(database);
+ } else if (database) {
+ setUserSelected(database);
+ }
}, [database]);
const onEmptyResults = (searchText?: string) => {
diff --git a/superset-frontend/src/SqlLab/components/TemplateParamsEditor/index.tsx b/superset-frontend/src/SqlLab/components/TemplateParamsEditor/index.tsx
index a862fd326a..0aa5503861 100644
--- a/superset-frontend/src/SqlLab/components/TemplateParamsEditor/index.tsx
+++ b/superset-frontend/src/SqlLab/components/TemplateParamsEditor/index.tsx
@@ -37,7 +37,7 @@ const StyledConfigEditor = styled(ConfigEditor)`
export type TemplateParamsEditorProps = {
queryEditorId: string;
language: 'yaml' | 'json';
- onChange: () => void;
+ onChange: (params: any) => void;
};
const TemplateParamsEditor = ({
diff --git a/superset-frontend/src/SqlLab/constants.ts b/superset-frontend/src/SqlLab/constants.ts
index 03f725c09d..5a944663b8 100644
--- a/superset-frontend/src/SqlLab/constants.ts
+++ b/superset-frontend/src/SqlLab/constants.ts
@@ -17,8 +17,9 @@
* under the License.
*/
import { t } from '@superset-ui/core';
+import type { Type } from 'src/components/Label';
-export const STATE_TYPE_MAP = {
+export const STATE_TYPE_MAP: Record<string, Type> = {
offline: 'danger',
failed: 'danger',
pending: 'info',
diff --git a/superset-frontend/src/SqlLab/types.ts b/superset-frontend/src/SqlLab/types.ts
index d8a78a858d..5ecd69293c 100644
--- a/superset-frontend/src/SqlLab/types.ts
+++ b/superset-frontend/src/SqlLab/types.ts
@@ -46,6 +46,8 @@ export interface QueryEditor {
description?: string;
loaded?: boolean;
inLocalStorage?: boolean;
+ northPercent?: number;
+ southPercent?: number;
}
export type toastState = {
diff --git a/superset-frontend/src/components/DatabaseSelector/index.tsx b/superset-frontend/src/components/DatabaseSelector/index.tsx
index 8516017b20..d17489a9c2 100644
--- a/superset-frontend/src/components/DatabaseSelector/index.tsx
+++ b/superset-frontend/src/components/DatabaseSelector/index.tsx
@@ -74,13 +74,13 @@ type DatabaseValue = {
value: number;
id: number;
database_name: string;
- backend: string;
+ backend?: string;
};
export type DatabaseObject = {
id: number;
database_name: string;
- backend: string;
+ backend?: string;
};
export interface DatabaseSelectorProps {
@@ -102,11 +102,11 @@ const SelectLabel = ({
backend,
databaseName,
}: {
- backend: string;
+ backend?: string;
databaseName: string;
}) => (
<LabelStyle>
- <Label className="backend">{backend}</Label>
+ <Label className="backend">{backend || ''}</Label>
<span className="name" title={databaseName}>
{databaseName}
</span>
diff --git a/superset-frontend/src/features/databases/DatabaseModal/index.test.tsx b/superset-frontend/src/features/databases/DatabaseModal/index.test.tsx
index 385b771efe..bcd9fbe694 100644
--- a/superset-frontend/src/features/databases/DatabaseModal/index.test.tsx
+++ b/superset-frontend/src/features/databases/DatabaseModal/index.test.tsx
@@ -302,6 +302,7 @@ fetchMock.post(VALIDATE_PARAMS_ENDPOINT, {
});
const databaseFixture: DatabaseObject = {
+ id: 123,
backend: 'postgres',
configuration_method: CONFIGURATION_METHOD.DYNAMIC_FORM,
database_name: 'Postgres',
@@ -2012,6 +2013,7 @@ describe('dbReducer', () => {
const currentState = dbReducer({}, action);
expect(currentState).toEqual({
+ id: db.id,
database_name: db.database_name,
engine: backend,
configuration_method: db.configuration_method,
diff --git a/superset-frontend/src/features/databases/types.ts b/superset-frontend/src/features/databases/types.ts
index e7089425bc..e138a91436 100644
--- a/superset-frontend/src/features/databases/types.ts
+++ b/superset-frontend/src/features/databases/types.ts
@@ -47,7 +47,7 @@ export type DatabaseObject = {
driver: string;
engine?: string;
extra?: string;
- id?: number;
+ id: number;
uuid?: null | string;
name: string; // synonym to database_name
paramProperties?: Record<string, any>;
@@ -78,11 +78,14 @@ export type DatabaseObject = {
allow_run_async?: boolean;
// SQL Lab
+ allows_cost_estimate?: boolean;
allow_ctas?: boolean;
allow_cvas?: boolean;
allow_dml?: boolean;
+ allows_virtual_table_explore?: boolean;
expose_in_sqllab?: boolean;
force_ctas_schema?: string;
+ extra_json?: ExtraJson;
// Security
allow_file_upload?: boolean;