From 2f3e11db668327ce55466a23fe6866458d2e08cc Mon Sep 17 00:00:00 2001 From: Phillip Kelley-Dotson Date: Tue, 26 Jul 2022 11:32:30 -0700 Subject: [PATCH] feat: blankstate metrics columns (#20755) * add POC ExploreMixin * Working POC > columns are loading into page * Created/tested query dataset dropdown * Add isValidDatasourceType to @superset-ui/core and hide query dropdown * Visual updates to explore datasource panel * Temporarily make Query icon visible * Remove Query icon visibility * Removed isValidDatasourceType check * Added Query preview Modal from DatasourceControl if the data source type is Query [41493] Initial commit to add ability for the a Query Preview Modal to be available when the data source type is Query and not Dataset Converted ModalTrigger to a functional TypeScript component * > fix integration point with frontend > allow for all records to be displayed > fix select with all columns queries > filters are now working * Adjusts conditional logic approach to be extensible for additional types from DatasourceTypes options * refactor * set field for sql * Fixes issue where Missing query parameters error was showing in datasourcePanel * add query_language * fix ds main_dttm * Fixes issue where menu.tsx was blocking access to redux debugging for SqlLab and Explore * Fixes issue where database id was not available to save query as dataset, adds default metric when chart source is query * oops * fix pre-commit to 50 errors now * fix circuliar dep * Disables showing Metrics section in DatasourcePanel when Query is the datasource A follow on separate effort will enable having a default Count metric when Query is the datasource type * adds condition to use query.columns if query.results is not present enable saving query as a dataset * down to 26 now * patch for pre-commit * one more pre-commit * added explore_json error * added error messages * add for metrics * add text for columns * add model open/close method * add propogation and methods * change link to span * lint fix * Fixes frontend lint and TypeScript errors unit test fixes will be next commit * Aditional TypeScript error fix * Fixes unit test failure * fix some types * added frontend piece * fix type * Fixes bad import caused by merge from master and removes duplicate showSaveDatasetModal check * Fixes for DartasourceControl Test Suite * Fix lint error * Fixes unit test issues due to array instead of a component being passed to modal footer * Fixes unit test failure for DatasourceControl and simplifies getDatasourceTitle based on PR comment * fix ts * pylint * core_test fix * Fixes line error post merge from master * fixed from master * fixed from master * Fixes issue where Overwrite dataset does not work due to userid error SPA refractor changed Redux structure that is used when in explore (which is now within SPA). user object is at the root of the store now for anything under SPA. * Resolves TypeScript errors with changes made for SPA merging in and changes needed for overwriting dataset from SaveDatasetModal * fix: top right panel view query functionality * remove unneeded code from core.py * working samples endpoint for query * add owner check * update FE for it * handle columns are dict vs object * fix exceptions * fix fe lint * fix test * add tab_name to payload * Enables use of tab name from Query * fix cypress test * save columns on execution * fix frontend build test * remove parathesis around columns * changing column types * fixing samples that has literal_columns * address comments * add changes * fix path * fix merge * fix types * remove console * add type * fix linting * update to enum * fix test * remove explore from buttons * fix logic * fix logic * oops Co-authored-by: Hugh A. Miles II Co-authored-by: lyndsiWilliams Co-authored-by: Eric Briscoe Co-authored-by: AAfghahi Co-authored-by: AAfghahi <48933336+AAfghahi@users.noreply.github.com> --- .../ColumnSelectPopover.tsx | 81 +++++++++++++++++-- .../ColumnSelectPopoverTrigger.tsx | 42 +++++++--- .../DndColumnSelect.test.tsx | 8 +- .../AdhocMetricEditPopover/index.jsx | 24 +++++- .../AdhocMetricPopoverTrigger.tsx | 55 +++++++++---- 5 files changed, 176 insertions(+), 34 deletions(-) diff --git a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopover.tsx b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopover.tsx index f979f231e211..bc59fb06e69a 100644 --- a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopover.tsx +++ b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopover.tsx @@ -18,13 +18,23 @@ */ /* eslint-disable camelcase */ import React, { + Dispatch, + SetStateAction, useCallback, useEffect, useMemo, useRef, useState, } from 'react'; -import { AdhocColumn, isAdhocColumn, t, styled, css } from '@superset-ui/core'; +import { useSelector } from 'react-redux'; +import { + AdhocColumn, + isAdhocColumn, + t, + styled, + css, + DatasourceType, +} from '@superset-ui/core'; import { ColumnMeta, isSavedExpression } from '@superset-ui/chart-controls'; import Tabs from 'src/components/Tabs'; import Button from 'src/components/Button'; @@ -38,6 +48,7 @@ import { POPOVER_INITIAL_HEIGHT, UNRESIZABLE_POPOVER_WIDTH, } from 'src/explore/constants'; +import { ExplorePageState } from 'src/explore/types'; const StyledSelect = styled(Select)` .metric-option { @@ -60,6 +71,7 @@ interface ColumnSelectPopoverProps { getCurrentTab: (tab: string) => void; label: string; isTemporal?: boolean; + setDatasetModal?: Dispatch>; } const getInitialColumnValues = ( @@ -82,11 +94,16 @@ const ColumnSelectPopover = ({ editedColumn, onChange, onClose, + setDatasetModal, setLabel, getCurrentTab, label, isTemporal, }: ColumnSelectPopoverProps) => { + const datasourceType = useSelector( + state => state.explore.datasource.type, + ); + console.log('datasource', datasourceType); const [initialLabel] = useState(label); const [initialAdhocColumn, initialCalculatedColumn, initialSimpleColumn] = getInitialColumnValues(editedColumn); @@ -214,6 +231,11 @@ const ColumnSelectPopover = ({ sqlEditorRef.current?.editor.resize(); }, []); + const setDatasetAndClose = () => { + if (setDatasetModal) setDatasetModal(true); + onClose(); + }; + const stateIsValid = adhocColumn || selectedCalculatedColumn || selectedSimpleColumn; const hasUnsavedChanges = @@ -226,6 +248,8 @@ const ColumnSelectPopover = ({ const savedExpressionsLabel = t('Saved expressions'); const simpleColumnsLabel = t('Column'); + console.log(calculatedColumns.length > 0); + console.log(datasourceType === DatasourceType.Query); return (
- ) : ( + ) : datasourceType === DatasourceType.Table ? ( + ) : ( + + + {t('Create a dataset')} + {' '} + {t(' to mark a column as a time column')} + + ) : ( + <> + + {t('Create a dataset')} + {' '} + {t(' to add calculated columns')} + + ) + } + /> )} @@ -286,9 +344,22 @@ const ColumnSelectPopover = ({ + + {t('Create a dataset')} + {' '} + {t(' to mark a column as a time column')} + + ) + } /> ) : ( diff --git a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopoverTrigger.tsx b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopoverTrigger.tsx index c258b3d5bad9..4340317f04d1 100644 --- a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopoverTrigger.tsx +++ b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopoverTrigger.tsx @@ -17,9 +17,11 @@ * under the License. */ import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import { useSelector } from 'react-redux'; import { AdhocColumn, t, isAdhocColumn } from '@superset-ui/core'; import { ColumnMeta, isColumnMeta } from '@superset-ui/chart-controls'; import { ExplorePopoverContent } from 'src/explore/components/ExploreContentPopover'; +import { SaveDatasetModal } from 'src/SqlLab/components/SaveDatasetModal'; import ColumnSelectPopover from './ColumnSelectPopover'; import { DndColumnSelectPopoverTitle } from './DndColumnSelectPopoverTitle'; import ControlPopover from '../ControlPopover/ControlPopover'; @@ -48,10 +50,13 @@ const ColumnSelectPopoverTrigger = ({ isTemporal, ...props }: ColumnSelectPopoverTriggerProps) => { + // @ts-ignore + const datasource = useSelector(state => state.explore.datasource); const [popoverLabel, setPopoverLabel] = useState(defaultPopoverLabel); const [popoverVisible, setPopoverVisible] = useState(false); const [isTitleEditDisabled, setIsTitleEditDisabled] = useState(true); const [hasCustomLabel, setHasCustomLabel] = useState(false); + const [showDatasetModal, setDatasetModal] = useState(false); let initialPopoverLabel = defaultPopoverLabel; if (editedColumn && isColumnMeta(editedColumn)) { @@ -95,6 +100,7 @@ const ColumnSelectPopoverTrigger = ({ - {children} - + <> + {showDatasetModal && ( + setDatasetModal(false)} + buttonTextOnSave={t('Save')} + buttonTextOnOverwrite={t('Overwrite')} + modalDescription={t( + 'Save this query as a virtual dataset to continue exploring', + )} + datasource={datasource} + /> + )} + + {children} + + ); }; diff --git a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/DndColumnSelect.test.tsx b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/DndColumnSelect.test.tsx index b02905191fc5..bc837203dbc4 100644 --- a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/DndColumnSelect.test.tsx +++ b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/DndColumnSelect.test.tsx @@ -34,13 +34,17 @@ const defaultProps: DndColumnSelectProps = { }; test('renders with default props', () => { - render(, { useDnd: true }); + render(, { + useDnd: true, + useRedux: true, + }); expect(screen.getByText('Drop columns here')).toBeInTheDocument(); }); test('renders with value', () => { render(, { useDnd: true, + useRedux: true, }); expect(screen.getByText('Column A')).toBeInTheDocument(); }); @@ -55,7 +59,7 @@ test('renders adhoc column', () => { expressionType: 'SQL', }} />, - { useDnd: true }, + { useDnd: true, useRedux: true }, ); expect(screen.getByText('adhoc column')).toBeVisible(); expect(screen.getByLabelText('calculator')).toBeVisible(); diff --git a/superset-frontend/src/explore/components/controls/MetricControl/AdhocMetricEditPopover/index.jsx b/superset-frontend/src/explore/components/controls/MetricControl/AdhocMetricEditPopover/index.jsx index 85abc2f83477..1a87502aa5d3 100644 --- a/superset-frontend/src/explore/components/controls/MetricControl/AdhocMetricEditPopover/index.jsx +++ b/superset-frontend/src/explore/components/controls/MetricControl/AdhocMetricEditPopover/index.jsx @@ -19,7 +19,7 @@ /* eslint-disable camelcase */ import React from 'react'; import PropTypes from 'prop-types'; -import { t, styled, ensureIsArray } from '@superset-ui/core'; +import { t, styled, ensureIsArray, DatasourceType } from '@superset-ui/core'; import Tabs from 'src/components/Tabs'; import Button from 'src/components/Button'; import { Select } from 'src/components'; @@ -370,7 +370,7 @@ export default class AdhocMetricEditPopover extends React.PureComponent { {...savedSelectProps} /> - ) : ( + ) : datasource.type === DatasourceType.Table ? ( + ) : ( + + { + this.props.handleDatasetModal(true); + this.props.onClose(); + }} + > + {t('Create a dataset')}{' '} + + {t('to add metrics')} + + } + /> )} - {this.props.children} - + <> + {this.state.showSaveDatasetModal && ( + this.handleDatasetModal(false)} + buttonTextOnSave={t('Save')} + buttonTextOnOverwrite={t('Overwrite')} + modalDescription={t( + 'Save this query as a virtual dataset to continue exploring', + )} + datasource={datasource} + /> + )} + + {this.props.children} + + ); } }