feat: add empty states to sqlab editor and select (#19598)

* feat: add empty states to sqlab editor and select

* add suggestions and test

* update type

* lint fix and add suggestions

* fix typo

* run lint

* remove unused code

* fix test

* remove redux for propagation and other suggestions

* add t

* lint

* fix text and remove code

* ts and fix t in p

* fix spelling

* remove unused prop

* add fn to prop change state

* remove unused code

* remove unused types

* update code and test

* fix lint

* fix ts

* update ts

* add type export and fix test

* Update superset-frontend/src/SqlLab/components/SqlEditorLeftBar/index.tsx

Co-authored-by: Michael S. Molina <70410625+michael-s-molina@users.noreply.github.com>

* Update superset-frontend/src/SqlLab/components/SqlEditorLeftBar/index.tsx

Co-authored-by: Michael S. Molina <70410625+michael-s-molina@users.noreply.github.com>

* Update superset-frontend/src/SqlLab/components/SqlEditorLeftBar/index.tsx

Co-authored-by: Michael S. Molina <70410625+michael-s-molina@users.noreply.github.com>

* Update superset-frontend/src/SqlLab/components/SqlEditorLeftBar/index.tsx

Co-authored-by: Michael S. Molina <70410625+michael-s-molina@users.noreply.github.com>

* remove handlerror and unused code

Co-authored-by: Michael S. Molina <70410625+michael-s-molina@users.noreply.github.com>
This commit is contained in:
Phillip Kelley-Dotson
2022-04-15 15:09:07 -07:00
committed by GitHub
parent 154f1ea8c9
commit 06ec88eb99
9 changed files with 147 additions and 17 deletions

View File

@@ -38,6 +38,7 @@ import {
queryEditorSetSelectedText,
queryEditorSetSchemaOptions,
} from 'src/SqlLab/actions/sqlLab';
import { EmptyStateBig } from 'src/components/EmptyState';
import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint';
import { initialState, queries, table } from 'src/SqlLab/fixtures';
@@ -57,7 +58,19 @@ describe('SqlEditor', () => {
queryEditorSetSchemaOptions,
addDangerToast: jest.fn(),
},
database: {},
database: {
allow_ctas: false,
allow_cvas: false,
allow_dml: false,
allow_file_upload: false,
allow_multi_schema_metadata_fetch: false,
allow_run_async: false,
backend: 'postgresql',
database_name: 'examples',
expose_in_sqllab: true,
force_ctas_schema: null,
id: 1,
},
queryEditorId: initialState.sqlLab.queryEditors[0].id,
latestQuery: queries[0],
tables: [table],
@@ -80,6 +93,12 @@ describe('SqlEditor', () => {
},
);
it('does not render SqlEditor if no db selected', () => {
const database = {};
const updatedProps = { ...mockedProps, database };
const wrapper = buildWrapper(updatedProps);
expect(wrapper.find(EmptyStateBig)).toExist();
});
it('render a SqlEditorLeftBar', async () => {
const wrapper = buildWrapper();
await waitForComponentToPaint(wrapper);

View File

@@ -66,6 +66,8 @@ import {
setItem,
} from 'src/utils/localStorageHelpers';
import { FeatureFlag, isFeatureEnabled } from 'src/featureFlags';
import { EmptyStateBig } from 'src/components/EmptyState';
import { isEmpty } from 'lodash';
import TemplateParamsEditor from '../TemplateParamsEditor';
import ConnectedSouthPane from '../SouthPane/state';
import SaveQuery from '../SaveQuery';
@@ -180,6 +182,7 @@ class SqlEditor extends React.PureComponent {
),
showCreateAsModal: false,
createAs: '',
showEmptyState: false,
};
this.sqlEditorRef = React.createRef();
this.northPaneRef = React.createRef();
@@ -189,6 +192,7 @@ class SqlEditor extends React.PureComponent {
this.onResizeEnd = this.onResizeEnd.bind(this);
this.canValidateQuery = this.canValidateQuery.bind(this);
this.runQuery = this.runQuery.bind(this);
this.setEmptyState = this.setEmptyState.bind(this);
this.stopQuery = this.stopQuery.bind(this);
this.saveQuery = this.saveQuery.bind(this);
this.onSqlChanged = this.onSqlChanged.bind(this);
@@ -228,7 +232,11 @@ class SqlEditor extends React.PureComponent {
// We need to measure the height of the sql editor post render to figure the height of
// the south pane so it gets rendered properly
// eslint-disable-next-line react/no-did-mount-set-state
const db = this.props.database;
this.setState({ height: this.getSqlEditorHeight() });
if (!db || isEmpty(db)) {
this.setEmptyState(true);
}
window.addEventListener('resize', this.handleWindowResize);
window.addEventListener('beforeunload', this.onBeforeUnload);
@@ -369,6 +377,10 @@ class SqlEditor extends React.PureComponent {
return base;
}
setEmptyState(bool) {
this.setState({ showEmptyState: bool });
}
setQueryEditorSql(sql) {
this.props.queryEditorSetSql(this.props.queryEditor, sql);
}
@@ -760,10 +772,21 @@ class SqlEditor extends React.PureComponent {
queryEditor={this.props.queryEditor}
tables={this.props.tables}
actions={this.props.actions}
setEmptyState={this.setEmptyState}
/>
</div>
</CSSTransition>
{this.queryPane()}
{this.state.showEmptyState ? (
<EmptyStateBig
image="vector.svg"
title={t('Select a database to write a query')}
description={t(
'Choose one of the available databases from the panel on the left.',
)}
/>
) : (
this.queryPane()
)}
<StyledModal
visible={this.state.showCreateAsModal}
title={t(createViewModalTitle)}

View File

@@ -16,7 +16,15 @@
* specific language governing permissions and limitations
* under the License.
*/
import React, { useEffect, useRef, useCallback, useMemo } from 'react';
import React, {
useEffect,
useRef,
useCallback,
useMemo,
useState,
Dispatch,
SetStateAction,
} from 'react';
import Button from 'src/components/Button';
import { t, styled, css, SupersetTheme } from '@superset-ui/core';
import Collapse from 'src/components/Collapse';
@@ -25,6 +33,7 @@ import { TableSelectorMultiple } from 'src/components/TableSelector';
import { IconTooltip } from 'src/components/IconTooltip';
import { QueryEditor } from 'src/SqlLab/types';
import { DatabaseObject } from 'src/components/DatabaseSelector';
import { EmptyStateSmall } from 'src/components/EmptyState';
import TableElement, { Table, TableElementProps } from '../TableElement';
interface ExtendedTable extends Table {
@@ -54,6 +63,8 @@ interface SqlEditorLeftBarProps {
tables?: ExtendedTable[];
actions: actionsTypes & TableElementProps['actions'];
database: DatabaseObject;
setEmptyState: Dispatch<SetStateAction<boolean>>;
showDisabled: boolean;
}
const StyledScrollbarContainer = styled.div`
@@ -88,15 +99,23 @@ export default function SqlEditorLeftBar({
queryEditor,
tables = [],
height = 500,
setEmptyState,
}: SqlEditorLeftBarProps) {
// Ref needed to avoid infinite rerenders on handlers
// that require and modify the queryEditor
const queryEditorRef = useRef<QueryEditor>(queryEditor);
const [emptyResultsWithSearch, setEmptyResultsWithSearch] = useState(false);
useEffect(() => {
queryEditorRef.current = queryEditor;
}, [queryEditor]);
const onEmptyResults = (searchText?: string) => {
setEmptyResultsWithSearch(!!searchText);
};
const onDbChange = ({ id: dbId }: { id: number }) => {
setEmptyState(false);
actions.queryEditorSetDb(queryEditor, dbId);
actions.queryEditorSetFunctionNames(queryEditor, dbId);
};
@@ -164,6 +183,22 @@ export default function SqlEditorLeftBar({
const shouldShowReset = window.location.search === '?reset=1';
const tableMetaDataHeight = height - 130; // 130 is the height of the selects above
const emptyStateComponent = (
<EmptyStateSmall
image="empty.svg"
title={
emptyResultsWithSearch
? t('No databases match your search')
: t('There are no databases available')
}
description={
<p>
{t('Manage your databases')}{' '}
<a href="/databaseview/list">{t('here')}</a>
</p>
}
/>
);
const handleSchemaChange = useCallback(
(schema: string) => {
if (queryEditorRef.current) {
@@ -185,6 +220,8 @@ export default function SqlEditorLeftBar({
return (
<div className="SqlEditorLeftBar">
<TableSelectorMultiple
onEmptyResults={onEmptyResults}
emptyState={emptyStateComponent}
database={database}
getDbList={actions.setDatabases}
handleError={actions.addDangerToast}