From 5640c7430a5d7c47b93e4feb72369a8f2c65da40 Mon Sep 17 00:00:00 2001 From: Maxime Beauchemin Date: Wed, 15 Jan 2025 00:08:37 -0800 Subject: [PATCH 1/3] chore: Empty state refactor - making `size` a prop instead of one-component-per-size - fixing up the svg so its themable using `currentColor` - centralizing/fixing up references --- .../SqlLab/components/QueryHistory/index.tsx | 5 +- .../SqlLab/components/SouthPane/Results.tsx | 4 +- .../src/SqlLab/components/SqlEditor/index.tsx | 5 +- .../components/SqlEditorLeftBar/index.tsx | 6 +- .../components/TabbedSqlEditors/index.tsx | 5 +- superset-frontend/src/assets/images/chart.svg | 6 +- .../src/assets/images/document.svg | 4 +- .../src/assets/images/empty-charts.svg | 22 +- .../src/assets/images/empty-dashboard.svg | 14 +- .../src/assets/images/empty-dataset.svg | 39 +-- .../src/assets/images/empty-queries.svg | 16 +- .../src/assets/images/empty-query.svg | 12 +- .../src/assets/images/empty-table.svg | 6 +- superset-frontend/src/assets/images/empty.svg | 6 +- .../src/assets/images/empty_sql_chart.svg | 6 +- .../src/assets/images/filter-results.svg | 67 +++-- .../src/assets/images/filter.svg | 52 +++- .../src/assets/images/star-circle.svg | 6 +- superset-frontend/src/assets/images/union.svg | 6 +- .../src/assets/images/vector.svg | 4 +- .../src/components/Chart/Chart.tsx | 8 +- .../src/components/Chart/ChartRenderer.jsx | 7 +- .../Chart/DrillDetail/DrillDetailPane.tsx | 4 +- .../DatabaseSelector.test.tsx | 4 +- .../EmptyState/EmptyState.stories.tsx | 99 ++++--- .../src/components/EmptyState/index.tsx | 251 +++++++----------- .../src/components/ListView/ListView.tsx | 8 +- .../src/components/Table/index.tsx | 59 ++-- .../DashboardBuilder/DashboardBuilder.tsx | 5 +- .../dashboard/components/DashboardGrid.jsx | 11 +- .../gridComponents/ChartHolder.test.tsx | 2 +- .../components/gridComponents/Tab.jsx | 4 +- .../components/gridComponents/Tab.test.tsx | 4 +- .../nativeFilters/FilterBar/Vertical.tsx | 5 +- .../DataTablesPane/components/SamplesPane.tsx | 4 +- .../components/useResultsPane.tsx | 6 +- .../AnnotationLayer.jsx | 5 +- .../ColumnSelectPopover.tsx | 11 +- .../AdhocMetricEditPopover/index.jsx | 8 +- .../features/allEntities/AllEntitiesTable.tsx | 5 +- .../DatasetPanel/MessageContent.tsx | 7 +- .../AddDataset/EditDataset/UsageTab/index.tsx | 7 +- .../datasets/AddDataset/LeftPanel/index.tsx | 21 +- .../src/features/home/EmptyState.tsx | 206 +++++--------- 44 files changed, 500 insertions(+), 542 deletions(-) diff --git a/superset-frontend/src/SqlLab/components/QueryHistory/index.tsx b/superset-frontend/src/SqlLab/components/QueryHistory/index.tsx index 30103dafa566c..6916e1e19b1a5 100644 --- a/superset-frontend/src/SqlLab/components/QueryHistory/index.tsx +++ b/superset-frontend/src/SqlLab/components/QueryHistory/index.tsx @@ -20,7 +20,7 @@ import { useEffect, useMemo, useState } from 'react'; import { shallowEqual, useSelector } from 'react-redux'; import { useInView } from 'react-intersection-observer'; import { omit } from 'lodash'; -import { EmptyStateMedium } from 'src/components/EmptyState'; +import { EmptyState } from 'src/components/EmptyState'; import { t, styled, @@ -143,8 +143,9 @@ const QueryHistory = ({ ) : ( - diff --git a/superset-frontend/src/SqlLab/components/SouthPane/Results.tsx b/superset-frontend/src/SqlLab/components/SouthPane/Results.tsx index 3dfec40bdc037..6a2a60831bf74 100644 --- a/superset-frontend/src/SqlLab/components/SouthPane/Results.tsx +++ b/superset-frontend/src/SqlLab/components/SouthPane/Results.tsx @@ -19,7 +19,7 @@ import { FC } from 'react'; import { shallowEqual, useSelector } from 'react-redux'; import Alert from 'src/components/Alert'; -import { EmptyStateMedium } from 'src/components/EmptyState'; +import { EmptyState } from 'src/components/EmptyState'; import { FeatureFlag, styled, t, isFeatureEnabled } from '@superset-ui/core'; import { SqlLabRootState } from 'src/SqlLab/types'; @@ -67,7 +67,7 @@ const Results: FC = ({ ) { return ( - diff --git a/superset-frontend/src/SqlLab/components/SqlEditor/index.tsx b/superset-frontend/src/SqlLab/components/SqlEditor/index.tsx index cab82cd02f5c2..b3d176d90e1dc 100644 --- a/superset-frontend/src/SqlLab/components/SqlEditor/index.tsx +++ b/superset-frontend/src/SqlLab/components/SqlEditor/index.tsx @@ -100,7 +100,7 @@ import { LocalStorageKeys, setItem, } from 'src/utils/localStorageHelpers'; -import { EmptyStateBig } from 'src/components/EmptyState'; +import { EmptyState } from 'src/components/EmptyState'; import Alert from 'src/components/Alert'; import getBootstrapData from 'src/utils/getBootstrapData'; import useLogAction from 'src/logger/useLogAction'; @@ -967,8 +967,9 @@ const SqlEditor: FC = ({ ) : showEmptyState && !hasSqlStatement ? ( - ( null, ); @@ -249,7 +249,7 @@ const SqlEditorLeftBar = ({ } database={userSelectedDb} getDbList={handleDbList} handleError={handleError} diff --git a/superset-frontend/src/SqlLab/components/TabbedSqlEditors/index.tsx b/superset-frontend/src/SqlLab/components/TabbedSqlEditors/index.tsx index df3099994ec31..7f43e8adb7bb1 100644 --- a/superset-frontend/src/SqlLab/components/TabbedSqlEditors/index.tsx +++ b/superset-frontend/src/SqlLab/components/TabbedSqlEditors/index.tsx @@ -27,7 +27,7 @@ import { Logger } from 'src/logger/LogUtils'; import { Tooltip } from 'src/components/Tooltip'; import { detectOS } from 'src/utils/common'; import * as Actions from 'src/SqlLab/actions/sqlLab'; -import { EmptyStateBig } from 'src/components/EmptyState'; +import { EmptyState } from 'src/components/EmptyState'; import getBootstrapData from 'src/utils/getBootstrapData'; import { locationContext } from 'src/pages/SqlLab/LocationContext'; import SqlEditor from '../SqlEditor'; @@ -255,8 +255,9 @@ class TabbedSqlEditors extends PureComponent { tab={emptyTab} closable={false} > - diff --git a/superset-frontend/src/assets/images/chart.svg b/superset-frontend/src/assets/images/chart.svg index 2267342bccd1f..34e45631e08d8 100644 --- a/superset-frontend/src/assets/images/chart.svg +++ b/superset-frontend/src/assets/images/chart.svg @@ -16,7 +16,7 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> - - - + + + diff --git a/superset-frontend/src/assets/images/document.svg b/superset-frontend/src/assets/images/document.svg index e3d1bfe1beb28..552fc8d220b34 100644 --- a/superset-frontend/src/assets/images/document.svg +++ b/superset-frontend/src/assets/images/document.svg @@ -17,6 +17,6 @@ specific language governing permissions and limitations under the License. --> - - + + diff --git a/superset-frontend/src/assets/images/empty-charts.svg b/superset-frontend/src/assets/images/empty-charts.svg index b4cdd99086c76..8c7b205d2a904 100644 --- a/superset-frontend/src/assets/images/empty-charts.svg +++ b/superset-frontend/src/assets/images/empty-charts.svg @@ -16,15 +16,15 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> - - - - - - - - - - - + + + + + + + diff --git a/superset-frontend/src/assets/images/empty-dashboard.svg b/superset-frontend/src/assets/images/empty-dashboard.svg index c76eca0c30aaa..2acf05c801186 100644 --- a/superset-frontend/src/assets/images/empty-dashboard.svg +++ b/superset-frontend/src/assets/images/empty-dashboard.svg @@ -16,11 +16,11 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> - - - - - - - + + + + + + + diff --git a/superset-frontend/src/assets/images/empty-dataset.svg b/superset-frontend/src/assets/images/empty-dataset.svg index 5ce1752545b29..9a0299d3b422d 100644 --- a/superset-frontend/src/assets/images/empty-dataset.svg +++ b/superset-frontend/src/assets/images/empty-dataset.svg @@ -16,23 +16,24 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + diff --git a/superset-frontend/src/assets/images/empty-queries.svg b/superset-frontend/src/assets/images/empty-queries.svg index 2239c0ae8e920..1d2d8b00f229f 100644 --- a/superset-frontend/src/assets/images/empty-queries.svg +++ b/superset-frontend/src/assets/images/empty-queries.svg @@ -16,20 +16,20 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> - - - - + + + + - + - - - + + + diff --git a/superset-frontend/src/assets/images/empty-query.svg b/superset-frontend/src/assets/images/empty-query.svg index be72857d8e5c4..a19fc73eebfa9 100644 --- a/superset-frontend/src/assets/images/empty-query.svg +++ b/superset-frontend/src/assets/images/empty-query.svg @@ -16,10 +16,10 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> - - - - - - + + + + + + diff --git a/superset-frontend/src/assets/images/empty-table.svg b/superset-frontend/src/assets/images/empty-table.svg index c1062502f39dc..9079b07114cab 100644 --- a/superset-frontend/src/assets/images/empty-table.svg +++ b/superset-frontend/src/assets/images/empty-table.svg @@ -16,7 +16,7 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> - - - + + + diff --git a/superset-frontend/src/assets/images/empty.svg b/superset-frontend/src/assets/images/empty.svg index e2c78339ce64c..b503324f6764f 100644 --- a/superset-frontend/src/assets/images/empty.svg +++ b/superset-frontend/src/assets/images/empty.svg @@ -16,7 +16,7 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> - - - + + + diff --git a/superset-frontend/src/assets/images/empty_sql_chart.svg b/superset-frontend/src/assets/images/empty_sql_chart.svg index 6ab969575c9db..b729b471a6562 100644 --- a/superset-frontend/src/assets/images/empty_sql_chart.svg +++ b/superset-frontend/src/assets/images/empty_sql_chart.svg @@ -16,7 +16,7 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> - - - + + + diff --git a/superset-frontend/src/assets/images/filter-results.svg b/superset-frontend/src/assets/images/filter-results.svg index 770a54b34f37f..7244f5538b262 100644 --- a/superset-frontend/src/assets/images/filter-results.svg +++ b/superset-frontend/src/assets/images/filter-results.svg @@ -16,19 +16,56 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> - - - - - - - - - - - - - - - + + + + + + diff --git a/superset-frontend/src/assets/images/filter.svg b/superset-frontend/src/assets/images/filter.svg index 0e1f6b41efc3d..2e8c5e0f0991a 100644 --- a/superset-frontend/src/assets/images/filter.svg +++ b/superset-frontend/src/assets/images/filter.svg @@ -16,17 +16,43 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> - - - - - - - - - - - - - + + + + + + + diff --git a/superset-frontend/src/assets/images/star-circle.svg b/superset-frontend/src/assets/images/star-circle.svg index a46a1dd0fb81c..d9e6c77e2c5c0 100644 --- a/superset-frontend/src/assets/images/star-circle.svg +++ b/superset-frontend/src/assets/images/star-circle.svg @@ -16,7 +16,7 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> - - - + + + diff --git a/superset-frontend/src/assets/images/union.svg b/superset-frontend/src/assets/images/union.svg index 6ac0e0f01621b..9ccf437b225a8 100644 --- a/superset-frontend/src/assets/images/union.svg +++ b/superset-frontend/src/assets/images/union.svg @@ -16,7 +16,7 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> - - - + + + diff --git a/superset-frontend/src/assets/images/vector.svg b/superset-frontend/src/assets/images/vector.svg index 0bf9c39c6ccb0..d2f946e8107a7 100644 --- a/superset-frontend/src/assets/images/vector.svg +++ b/superset-frontend/src/assets/images/vector.svg @@ -16,6 +16,6 @@ KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> - - + + diff --git a/superset-frontend/src/components/Chart/Chart.tsx b/superset-frontend/src/components/Chart/Chart.tsx index 3526a26b3f9ce..fd7b5fcaabe0d 100644 --- a/superset-frontend/src/components/Chart/Chart.tsx +++ b/superset-frontend/src/components/Chart/Chart.tsx @@ -31,7 +31,7 @@ import { } from '@superset-ui/core'; import { PLACEHOLDER_DATASOURCE } from 'src/dashboard/constants'; import Loading from 'src/components/Loading'; -import { EmptyStateBig } from 'src/components/EmptyState'; +import { EmptyState } from 'src/components/EmptyState'; import ErrorBoundary from 'src/components/ErrorBoundary'; import { Logger, LOG_ACTIONS_RENDER_CHART } from 'src/logger/LogUtils'; import { URL_PARAMS } from 'src/constants'; @@ -337,7 +337,8 @@ class Chart extends PureComponent { if (errorMessage && ensureIsArray(queriesResponse).length === 0) { return ( - { ensureIsArray(queriesResponse).length === 0 ) { return ( - diff --git a/superset-frontend/src/components/Chart/ChartRenderer.jsx b/superset-frontend/src/components/Chart/ChartRenderer.jsx index d93e30a107b13..dd456b0db43c3 100644 --- a/superset-frontend/src/components/Chart/ChartRenderer.jsx +++ b/superset-frontend/src/components/Chart/ChartRenderer.jsx @@ -30,7 +30,7 @@ import { VizType, } from '@superset-ui/core'; import { Logger, LOG_ACTIONS_RENDER_CHART } from 'src/logger/LogUtils'; -import { EmptyStateBig, EmptyStateSmall } from 'src/components/EmptyState'; +import { EmptyState } from 'src/components/EmptyState'; import { ChartSource } from 'src/types/ChartSource'; import ChartContextMenu from './ChartContextMenu/ChartContextMenu'; @@ -308,7 +308,8 @@ class ChartRenderer extends Component { const noResultImage = 'chart.svg'; if (width > BIG_NO_RESULT_MIN_WIDTH && height > BIG_NO_RESULT_MIN_HEIGHT) { noResultsComponent = ( - + ); } diff --git a/superset-frontend/src/components/Chart/DrillDetail/DrillDetailPane.tsx b/superset-frontend/src/components/Chart/DrillDetail/DrillDetailPane.tsx index 9cf0102b5ef91..bcab733f48c00 100644 --- a/superset-frontend/src/components/Chart/DrillDetail/DrillDetailPane.tsx +++ b/superset-frontend/src/components/Chart/DrillDetail/DrillDetailPane.tsx @@ -41,7 +41,7 @@ import Loading from 'src/components/Loading'; import BooleanCell from 'src/components/Table/cell-renderers/BooleanCell'; import NullCell from 'src/components/Table/cell-renderers/NullCell'; import TimeCell from 'src/components/Table/cell-renderers/TimeCell'; -import { EmptyStateMedium } from 'src/components/EmptyState'; +import { EmptyState } from 'src/components/EmptyState'; import { getDatasourceSamples } from 'src/components/Chart/chartAction'; import Table, { ColumnsType, TableSize } from 'src/components/Table'; import HeaderWithRadioGroup from 'src/components/Table/header-renderers/HeaderWithRadioGroup'; @@ -285,7 +285,7 @@ export default function DrillDetailPane({ } else if (resultsPage?.total === 0) { // Render empty state if no results are returned for page const title = t('No rows were returned for this dataset'); - tableContent = ; + tableContent = ; } else { // Render table if at least one page has successfully loaded tableContent = ( diff --git a/superset-frontend/src/components/DatabaseSelector/DatabaseSelector.test.tsx b/superset-frontend/src/components/DatabaseSelector/DatabaseSelector.test.tsx index 44d0bff0e04bd..ee17f2d801d49 100644 --- a/superset-frontend/src/components/DatabaseSelector/DatabaseSelector.test.tsx +++ b/superset-frontend/src/components/DatabaseSelector/DatabaseSelector.test.tsx @@ -28,7 +28,7 @@ import { import userEvent from '@testing-library/user-event'; import { api } from 'src/hooks/apiResources/queryApi'; import DatabaseSelector, { DatabaseSelectorProps } from '.'; -import { EmptyStateSmall } from '../EmptyState'; +import { EmptyState } from '../EmptyState'; const createProps = (): DatabaseSelectorProps => ({ db: { @@ -307,7 +307,7 @@ test('should show empty state if there are no options', async () => { } + emptyState={} />, { useRedux: true, store }, ); diff --git a/superset-frontend/src/components/EmptyState/EmptyState.stories.tsx b/superset-frontend/src/components/EmptyState/EmptyState.stories.tsx index 9d6f56c52d002..dbc3a0af9cc86 100644 --- a/superset-frontend/src/components/EmptyState/EmptyState.stories.tsx +++ b/superset-frontend/src/components/EmptyState/EmptyState.stories.tsx @@ -9,64 +9,59 @@ * * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an + * "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS + * OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ +import { Meta, StoryFn } from '@storybook/react'; +import { Row, Col } from 'antd'; +import { EmptyState, imageMap } from '.'; -import EmptyImage from 'src/assets/images/empty.svg'; -import ChartImage from 'src/assets/images/chart.svg'; -import FilterImage from 'src/assets/images/filter.svg'; -import { EmptyStateBig, EmptyStateMedium, EmptyStateSmall } from '.'; +const emptyStates = [ + { title: null, description: null, image: undefined }, + ...Object.keys(imageMap).map(key => ({ + image: key, + title: `Empty State with image ${key}`, + description: 'This is the default empty state.', + })), +]; export default { - title: 'Empty state', - component: EmptyStateMedium, -}; - -export const SmallEmptyState = () => ( - } - title="Small empty state" - description="This is an example of a small empty state" - /> -); - -export const MediumEmptyState = () => ( - } - title="Medium empty state" - description="This is an example of a medium empty state" - /> -); + title: 'Empty State Gallery', + component: EmptyState, + argTypes: { + size: { + control: { type: 'select' }, + options: ['small', 'medium', 'large'], + defaultValue: 'medium', + description: 'Size of the Empty State components', + }, + }, +} as Meta; -export const MediumEmptyStateWithButton = () => ( - } - title="Medium empty state" - description="This is an example of a medium empty state with a button" - buttonAction={() => {}} - buttonText="Click!" - /> +export const Gallery: StoryFn<{ size: 'small' | 'medium' | 'large' }> = ({ + size, +}) => ( + + {emptyStates.map((state, index) => ( + + + Childrens render here. + + + ))} + ); -export const BigEmptyState = () => ( - } - title="Big empty state" - description="This is an example of a big empty state" - /> -); - -export const BigEmptyStateWithButton = () => ( - } - title="Big empty state" - description="This is an example of a big empty state with a button" - buttonText="Click!" - buttonAction={() => {}} - /> -); +Gallery.args = { + size: 'medium', +}; diff --git a/superset-frontend/src/components/EmptyState/index.tsx b/superset-frontend/src/components/EmptyState/index.tsx index edc13e622fa34..a083b6cdcfaa8 100644 --- a/superset-frontend/src/components/EmptyState/index.tsx +++ b/superset-frontend/src/components/EmptyState/index.tsx @@ -16,38 +16,57 @@ * specific language governing permissions and limitations * under the License. */ - -import { - ReactNode, - SyntheticEvent, - MouseEventHandler as ReactMouseEventHandler, -} from 'react'; +import { ReactNode, SyntheticEvent } from 'react'; import { styled, css, SupersetTheme, t } from '@superset-ui/core'; import Button from 'src/components/Button'; + +// Importing svg images +import FilterResultsImage from 'src/assets/images/filter-results.svg'; +import ChartImage from 'src/assets/images/chart.svg'; +import FilterImage from 'src/assets/images/filter.svg'; +import EmptyChartsImage from 'src/assets/images/empty-charts.svg'; +import EmptyDashboardImage from 'src/assets/images/empty-dashboard.svg'; +import UnionImage from 'src/assets/images/union.svg'; +import EmptyQueriesImage from 'src/assets/images/empty-queries.svg'; +import StarCircleImage from 'src/assets/images/star-circle.svg'; +import VectorImage from 'src/assets/images/vector.svg'; +import DocumentImage from 'src/assets/images/document.svg'; +import DatasetImage from 'src/assets/images/empty-dataset.svg'; +import EmptySqlChartImage from 'src/assets/images/empty_sql_chart.svg'; +import EmptyQueryImage from 'src/assets/images/empty-query.svg'; +import EmptyTableImage from 'src/assets/images/empty-table.svg'; +import EmptyImage from 'src/assets/images/empty.svg'; import { Empty } from './Empty'; -export enum EmptyStateSize { - Small, - Medium, - Big, -} +export const imageMap = { + 'chart.svg': , + 'document.svg': , + 'empty-charts.svg': , + 'empty-dashboard.svg': , + 'empty-dataset.svg': , + 'empty-queries.svg': , + 'empty-query.svg': , + 'empty-table.svg': , + 'empty.svg': , + 'empty_sql_chart.svg': , + 'filter-results.svg': , + 'filter.svg': , + 'star-circle.svg': , + 'union.svg': , + 'vector.svg': , +}; -export interface EmptyStateSmallProps { +type EmptyStateSize = 'small' | 'medium' | 'large'; + +export type EmptyStateProps = { title?: ReactNode; description?: ReactNode; - image?: ReactNode; -} - -export interface EmptyStateProps extends EmptyStateSmallProps { + image?: ReactNode | string; buttonText?: ReactNode; - buttonAction?: ReactMouseEventHandler; - className?: string; -} - -export interface ImageContainerProps { - image: ReactNode; - size: EmptyStateSize; -} + buttonAction?: (event: SyntheticEvent) => void; + size?: EmptyStateSize; + children?: ReactNode; +}; const EmptyStateContainer = styled.div` ${({ theme }) => css` @@ -55,6 +74,7 @@ const EmptyStateContainer = styled.div` flex-direction: column; width: 100%; height: 100%; + color: ${theme.colors.grayscale.light2}; align-items: center; justify-content: center; padding: ${theme.gridUnit * 4}px; @@ -75,43 +95,24 @@ const EmptyStateContainer = styled.div` `} `; -const TextContainer = styled.div``; - -const Title = styled.p` - ${({ theme }) => css` - font-size: ${theme.typography.sizes.m}px; +const Title = styled.p<{ size: EmptyStateSize }>` + ${({ theme, size }) => css` + font-size: ${size === 'large' + ? theme.typography.sizes.l + : theme.typography.sizes.m}px; color: ${theme.colors.grayscale.light1}; - margin: ${theme.gridUnit * 2}px 0 0 0; + margin-top: ${size === 'large' ? theme.gridUnit * 4 : theme.gridUnit * 2}px; font-weight: ${theme.typography.weights.bold}; `} `; -const BigTitle = styled(Title)` - ${({ theme }) => css` - font-size: ${theme.typography.sizes.l}px; - color: ${theme.colors.grayscale.light1}; - margin-top: ${theme.gridUnit * 4}px; - `} -`; - -const Description = styled.p` - ${({ theme }) => css` - font-size: ${theme.typography.sizes.s}px; +const Description = styled.p<{ size: EmptyStateSize }>` + ${({ theme, size }) => css` + font-size: ${size === 'large' + ? theme.typography.sizes.m + : theme.typography.sizes.s}px; color: ${theme.colors.grayscale.light1}; - margin: ${theme.gridUnit * 2}px 0 0 0; - `} -`; - -const BigDescription = styled(Description)` - ${({ theme }) => css` - font-size: ${theme.typography.sizes.m}px; - `} -`; - -const SmallDescription = styled(Description)` - ${({ theme }) => css` - margin-top: ${theme.gridUnit}px; - line-height: 1.2; + margin-top: ${theme.gridUnit * 2}px; `} `; @@ -122,81 +123,68 @@ const ActionButton = styled(Button)` `} `; -const getImage = (image: string | ReactNode) => - typeof image === 'string' ? `/static/assets/images/${image}` : image; - const getImageHeight = (size: EmptyStateSize) => { switch (size) { - case EmptyStateSize.Small: + case 'small': return { height: '50px' }; - case EmptyStateSize.Medium: + case 'medium': return { height: '80px' }; - case EmptyStateSize.Big: + case 'large': return { height: '150px' }; default: - return { height: '50px' }; + return { height: '80px' }; } }; -const ImageContainer = ({ image, size }: ImageContainerProps) => ( - -); +const ImageContainer = ({ + image, + size, +}: { + image?: ReactNode | string; + size: EmptyStateSize; +}) => { + if (!image) return null; + const mappedImage = typeof image === 'string' ? imageMap[image] : image; + return ( +
+ +
+ ); +}; const handleMouseDown = (e: SyntheticEvent) => { e.preventDefault(); e.stopPropagation(); }; -export const EmptyStateBig = ({ - title, - image, - description, - buttonAction, +export const EmptyState: React.FC = ({ + title = t('No results'), + description = t('There is currently no information to display.'), + image = 'empty.svg', buttonText, - className, -}: EmptyStateProps) => ( - - {image && } - css` - max-width: ${theme.gridUnit * 150}px; - `} - > - {title} - {description && {description}} - {buttonAction && buttonText && ( - - {buttonText} - - )} - - -); - -export const EmptyStateMedium = ({ - title, - image, - description, buttonAction, - buttonText, -}: EmptyStateProps) => ( + size = 'medium', + children, +}) => ( - {image && } - } +
css` - max-width: ${theme.gridUnit * 100}px; + max-width: ${size === 'large' + ? theme.gridUnit * 150 + : theme.gridUnit * 100}px; `} > - {title} - {description && {description}} + {title && {title}} + {description && ( + + {description} + + )} {buttonText && buttonAction && ( )} - - -); - -export const EmptyStateSmall = ({ - title, - image, - description, -}: EmptyStateSmallProps) => ( - - {image && } - css` - max-width: ${theme.gridUnit * 75}px; - `} - > - {title} - {description && {description}} - + {children} +
); - -const TRANSLATIONS = { - NO_DATABASES_MATCH_TITLE: t('No databases match your search'), - NO_DATABASES_AVAILABLE_TITLE: t('There are no databases available'), - MANAGE_YOUR_DATABASES_TEXT: t('Manage your databases'), - HERE_TEXT: t('here'), -}; - -export const emptyStateComponent = (emptyResultsWithSearch: boolean) => ( - - {TRANSLATIONS.MANAGE_YOUR_DATABASES_TEXT}{' '} - {TRANSLATIONS.HERE_TEXT} -

- } - /> -); diff --git a/superset-frontend/src/components/ListView/ListView.tsx b/superset-frontend/src/components/ListView/ListView.tsx index 30bcb99aa3b98..cfa060f11da63 100644 --- a/superset-frontend/src/components/ListView/ListView.tsx +++ b/superset-frontend/src/components/ListView/ListView.tsx @@ -37,7 +37,7 @@ import { ViewModeType, } from './types'; import { ListViewError, useListViewState } from './utils'; -import { EmptyStateBig, EmptyStateProps } from '../EmptyState'; +import { EmptyState, EmptyStateProps } from '../EmptyState'; const ListViewStyles = styled.div` text-align: center; @@ -447,17 +447,19 @@ function ListView({ {!loading && rows.length === 0 && ( {query.filters ? ( - handleClearFilterControls()} buttonText={t('clear all filters')} /> ) : ( - )} diff --git a/superset-frontend/src/components/Table/index.tsx b/superset-frontend/src/components/Table/index.tsx index 1495befa5acc9..11a803893b92c 100644 --- a/superset-frontend/src/components/Table/index.tsx +++ b/superset-frontend/src/components/Table/index.tsx @@ -16,13 +16,12 @@ * specific language governing permissions and limitations * under the License. */ -import { useState, useEffect, useRef, ReactElement, Key } from 'react'; +import { useState, useEffect, useRef, Key } from 'react'; import AntTable, { ColumnsType, TableProps as AntTableProps, } from 'antd/lib/table'; -import ConfigProvider from 'antd/lib/config-provider'; import { PaginationProps } from 'antd/lib/pagination'; import { t, useTheme, logging, styled } from '@superset-ui/core'; import Loading from 'src/components/Loading'; @@ -116,10 +115,6 @@ export interface TableProps { * Set table to display no data even if data has been provided */ hideData?: boolean; - /** - * emptyComponent - */ - emptyComponent?: ReactElement; /** * Enables setting the text displayed in various components and tooltips within the Table UI. */ @@ -256,7 +251,6 @@ export function Table( defaultPageSize = 15, pageSizeOptions = ['5', '15', '25', '50', '100'], hideData = false, - emptyComponent, locale, height, virtualize = false, @@ -288,9 +282,6 @@ export function Table( onChange: onSelectChange, }; - const renderEmpty = () => - emptyComponent ??
{mergedLocale.emptyText}
; - // Log use of experimental features useEffect(() => { if (reorderable === true) { @@ -403,31 +394,29 @@ export function Table( }; return ( - -
- {!virtualize && ( - - )} - {virtualize && ( - - )} -
-
+
+ {!virtualize && ( + + )} + {virtualize && ( + + )} +
); } diff --git a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx index e5caed6968642..cdddff00b0e8e 100644 --- a/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx +++ b/superset-frontend/src/dashboard/components/DashboardBuilder/DashboardBuilder.tsx @@ -64,7 +64,7 @@ import { } from 'src/dashboard/util/constants'; import FilterBar from 'src/dashboard/components/nativeFilters/FilterBar'; import Loading from 'src/components/Loading'; -import { EmptyStateBig } from 'src/components/EmptyState'; +import { EmptyState } from 'src/components/EmptyState'; import { useUiConfig } from 'src/components/UiConfigContext'; import ResizableSidebar from 'src/components/ResizableSidebar'; import { @@ -666,8 +666,9 @@ const DashboardBuilder = () => { {!editMode && !topLevelTabs && dashboardLayout[DASHBOARD_GRID_ID]?.children?.length === 0 && ( - @@ -228,8 +229,9 @@ class DashboardGrid extends PureComponent { ); const topLevelTabEmptyState = editMode ? ( - ) : ( - { 'Make sure that the controls are configured properly and the datasource contains data for the selected time range', ), ).not.toBeInTheDocument(); // description should display only in Explore view - expect(screen.getByAltText('empty')).toBeVisible(); + expect(screen.getByRole('img', { name: 'empty' })).toBeVisible(); }); it('should render anchor link when not editing', async () => { diff --git a/superset-frontend/src/dashboard/components/gridComponents/Tab.jsx b/superset-frontend/src/dashboard/components/gridComponents/Tab.jsx index 2c4695f8c7285..36a77316413be 100644 --- a/superset-frontend/src/dashboard/components/gridComponents/Tab.jsx +++ b/superset-frontend/src/dashboard/components/gridComponents/Tab.jsx @@ -22,7 +22,7 @@ import classNames from 'classnames'; import { useDispatch, useSelector } from 'react-redux'; import { styled, t } from '@superset-ui/core'; -import { EmptyStateMedium } from 'src/components/EmptyState'; +import { EmptyState } from 'src/components/EmptyState'; import EditableTitle from 'src/components/EditableTitle'; import { setEditMode } from 'src/dashboard/actions/dashboardState'; import DashboardComponent from 'src/dashboard/containers/DashboardComponent'; @@ -197,7 +197,7 @@ const Tab = props => { )} {shouldDisplayEmptyState && ( - { expect( screen.getByText('There are no components added to this tab'), ).toBeVisible(); - expect(screen.getByAltText('empty')).toBeVisible(); + expect(screen.getByRole('img', { name: 'empty' })).toBeVisible(); expect(screen.queryByText('edit mode')).not.toBeInTheDocument(); }); @@ -397,7 +397,7 @@ test('Render tab content with no children, editMode: true, canEdit: true', () => expect( screen.getByText('Drag and drop components to this tab'), ).toBeVisible(); - expect(screen.getByAltText('empty')).toBeVisible(); + expect(screen.getByRole('img', { name: 'empty' })).toBeVisible(); expect( screen.getByRole('link', { name: 'create a new chart' }), ).toBeVisible(); diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Vertical.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Vertical.tsx index b76b65c13395c..d6960ad37027f 100644 --- a/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Vertical.tsx +++ b/superset-frontend/src/dashboard/components/nativeFilters/FilterBar/Vertical.tsx @@ -33,7 +33,7 @@ import cx from 'classnames'; import { FeatureFlag, isFeatureEnabled, styled, t } from '@superset-ui/core'; import Icons from 'src/components/Icons'; import Loading from 'src/components/Loading'; -import { EmptyStateSmall } from 'src/components/EmptyState'; +import { EmptyState } from 'src/components/EmptyState'; import { getFilterBarTestId } from './utils'; import { VerticalBarProps } from './types'; import Header from './Header'; @@ -168,7 +168,8 @@ const VerticalFilterBar: FC = ({ () => filterValues.length === 0 ? ( - ; + return ; } return ( diff --git a/superset-frontend/src/explore/components/DataTablesPane/components/useResultsPane.tsx b/superset-frontend/src/explore/components/DataTablesPane/components/useResultsPane.tsx index fe262fe72078d..e96963d10854d 100644 --- a/superset-frontend/src/explore/components/DataTablesPane/components/useResultsPane.tsx +++ b/superset-frontend/src/explore/components/DataTablesPane/components/useResultsPane.tsx @@ -26,7 +26,7 @@ import { getClientErrorObject, } from '@superset-ui/core'; import Loading from 'src/components/Loading'; -import { EmptyStateMedium } from 'src/components/EmptyState'; +import { EmptyState } from 'src/components/EmptyState'; import { getChartDataRequest } from 'src/components/Chart/chartAction'; import { ResultsPaneProps, QueryResultInterface } from '../types'; import { SingleQueryResultPane } from './SingleQueryResultPane'; @@ -110,7 +110,7 @@ export const useResultsPane = ({ if (errorMessage) { const title = t('Run a query to display results'); return Array(queryCount).fill( - , + , ); } @@ -136,7 +136,7 @@ export const useResultsPane = ({ if (resultResp.length === 0) { const title = t('No results were returned for this query'); return Array(queryCount).fill( - , + , ); } return resultResp diff --git a/superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.jsx b/superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.jsx index 304ec3409d342..905fd04f9ceb5 100644 --- a/superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.jsx +++ b/superset-frontend/src/explore/components/controls/AnnotationLayerControl/AnnotationLayer.jsx @@ -38,7 +38,7 @@ import TextControl from 'src/explore/components/controls/TextControl'; import CheckboxControl from 'src/explore/components/controls/CheckboxControl'; import PopoverSection from 'src/components/PopoverSection'; import ControlHeader from 'src/explore/components/ControlHeader'; -import { EmptyStateSmall } from 'src/components/EmptyState'; +import { EmptyState } from 'src/components/EmptyState'; import { ANNOTATION_SOURCE_TYPES, ANNOTATION_TYPES, @@ -111,8 +111,9 @@ const NotFoundContentWrapper = styled.div` const NotFoundContent = () => ( - {t('Add an annotation layer')}{' '} diff --git a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopover.tsx b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopover.tsx index 711cad392de2f..6e0a256965bba 100644 --- a/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopover.tsx +++ b/superset-frontend/src/explore/components/controls/DndColumnSelectControl/ColumnSelectPopover.tsx @@ -43,7 +43,7 @@ import { Select } from 'src/components'; import { Form, FormItem } from 'src/components/Form'; import sqlKeywords from 'src/SqlLab/utils/sqlKeywords'; import { SQLEditor } from 'src/components/AsyncAceEditor'; -import { EmptyStateSmall } from 'src/components/EmptyState'; +import { EmptyState } from 'src/components/EmptyState'; import { getColumnKeywords } from 'src/explore/controlUtils/getColumnKeywords'; import { StyledColumnOption } from 'src/explore/components/optionRenderers'; import { @@ -334,8 +334,9 @@ const ColumnSelectPopover = ({ /> ) : datasourceType === DatasourceType.Table ? ( - ) : ( - {isTemporal && simpleColumns.length === 0 ? ( - ) : datasource.type === DatasourceType.Table ? ( - ) : ( - diff --git a/superset-frontend/src/features/allEntities/AllEntitiesTable.tsx b/superset-frontend/src/features/allEntities/AllEntitiesTable.tsx index 8ecbf33872185..ae51762d788ae 100644 --- a/superset-frontend/src/features/allEntities/AllEntitiesTable.tsx +++ b/superset-frontend/src/features/allEntities/AllEntitiesTable.tsx @@ -23,7 +23,7 @@ import { TagsList } from 'src/components/Tags'; import FacePile from 'src/components/FacePile'; import Tag from 'src/types/TagType'; import Owner from 'src/types/Owner'; -import { EmptyStateBig } from 'src/components/EmptyState'; +import { EmptyState } from 'src/components/EmptyState'; import { NumberParam, useQueryParam } from 'use-query-params'; const MAX_TAGS_TO_SHOW = 3; @@ -160,8 +160,9 @@ export default function AllEntitiesTable({ {renderTable('query')} ) : ( - setShowTagModal(true)} buttonText={t('Add tag to entities')} diff --git a/superset-frontend/src/features/datasets/AddDataset/DatasetPanel/MessageContent.tsx b/superset-frontend/src/features/datasets/AddDataset/DatasetPanel/MessageContent.tsx index 9f57935947897..5aab72027222a 100644 --- a/superset-frontend/src/features/datasets/AddDataset/DatasetPanel/MessageContent.tsx +++ b/superset-frontend/src/features/datasets/AddDataset/DatasetPanel/MessageContent.tsx @@ -18,7 +18,7 @@ */ import { t, styled } from '@superset-ui/core'; -import { EmptyStateBig } from 'src/components/EmptyState'; +import { EmptyState } from 'src/components/EmptyState'; import { Link } from 'react-router-dom'; const StyledContainer = styled.div` @@ -31,7 +31,7 @@ const StyledContainer = styled.div` height: 100%; `; -const StyledEmptyStateBig = styled(EmptyStateBig)` +const StyledEmptyState = styled(EmptyState)` max-width: 50%; p { @@ -91,8 +91,9 @@ export const MessageContent = (props: MessageContentProps) => { } return ( - diff --git a/superset-frontend/src/features/datasets/AddDataset/EditDataset/UsageTab/index.tsx b/superset-frontend/src/features/datasets/AddDataset/EditDataset/UsageTab/index.tsx index 0e41182096130..289a67f5aa98f 100644 --- a/superset-frontend/src/features/datasets/AddDataset/EditDataset/UsageTab/index.tsx +++ b/superset-frontend/src/features/datasets/AddDataset/EditDataset/UsageTab/index.tsx @@ -32,7 +32,7 @@ import Table, { TableSize, OnChangeFunction, } from 'src/components/Table'; -import { EmptyStateBig } from 'src/components/EmptyState'; +import { EmptyState } from 'src/components/EmptyState'; import ChartImage from 'src/assets/images/chart.svg'; import Icons from 'src/components/Icons'; import { useToasts } from 'src/components/MessageToasts/withToasts'; @@ -147,7 +147,7 @@ const emptyStateButtonText = ( ); -const StyledEmptyStateBig = styled(EmptyStateBig)` +const StyledEmptyState = styled(EmptyState)` margin: ${({ theme }) => 13 * theme.gridUnit}px 0; `; @@ -250,8 +250,9 @@ const DatasetUsage = ({ datasetId }: DatasetUsageProps) => { onChange={onChange} /> {!data.length && !loading ? ( - } + size="large" title={t('No charts')} description={t('This dataset is not used to power any charts.')} buttonText={emptyStateButtonText} diff --git a/superset-frontend/src/features/datasets/AddDataset/LeftPanel/index.tsx b/superset-frontend/src/features/datasets/AddDataset/LeftPanel/index.tsx index c14109aede56f..adb52234224b9 100644 --- a/superset-frontend/src/features/datasets/AddDataset/LeftPanel/index.tsx +++ b/superset-frontend/src/features/datasets/AddDataset/LeftPanel/index.tsx @@ -20,7 +20,7 @@ import { useEffect, SetStateAction, Dispatch, useCallback } from 'react'; import { styled, t } from '@superset-ui/core'; import TableSelector, { TableOption } from 'src/components/TableSelector'; import { DatabaseObject } from 'src/components/DatabaseSelector'; -import { emptyStateComponent } from 'src/components/EmptyState'; +import { EmptyState } from 'src/components/EmptyState'; import { useToasts } from 'src/components/MessageToasts/withToasts'; import { LocalStorageKeys, getItem } from 'src/utils/localStorageHelpers'; import { @@ -178,13 +178,30 @@ export default function LeftPanel({ ), [datasetNames], ); + const getDatabaseEmptyState = (emptyResultsWithSearch: boolean) => ( + + {t('Manage your databases')}{' '} + {t('here')} + + } + size="small" + /> + ); return ( = { - [WelcomeTable.Charts]: t('charts'), - [WelcomeTable.Dashboards]: t('dashboards'), - [WelcomeTable.Recents]: t('recents'), - [WelcomeTable.SavedQueries]: t('saved queries'), -}; - -const welcomeTableEmpty: Record = { - [WelcomeTable.Charts]: t('No charts yet'), - [WelcomeTable.Dashboards]: t('No dashboards yet'), - [WelcomeTable.Recents]: t('No recents yet'), - [WelcomeTable.SavedQueries]: t('No saved queries yet'), -}; - -const welcomeTableWillAppear: Record string> = - { - [WelcomeTable.Charts]: (other: string) => - t('%(other)s charts will appear here', { other }), - [WelcomeTable.Dashboards]: (other: string) => - t('%(other)s dashboards will appear here', { other }), - [WelcomeTable.Recents]: (other: string) => - t('%(other)s recents will appear here', { other }), - [WelcomeTable.SavedQueries]: (other: string) => - t('%(other)s saved queries will appear here', { other }), - }; - -export interface EmptyStateProps { - tableName: WelcomeTable; - tab?: string; - otherTabTitle?: string; -} const EmptyContainer = styled.div` min-height: 200px; display: flex; + color: ${({ theme }) => theme.colors.grayscale.light2}; flex-direction: column; justify-content: space-around; `; -const ButtonContainer = styled.div` - Button { - svg { - color: ${({ theme }) => theme.colors.grayscale.light5}; - } - } -`; -type Redirects = Record< - WelcomeTable.Charts | WelcomeTable.Dashboards | WelcomeTable.SavedQueries, - string ->; +const ICONS = { + [WelcomeTable.Charts]: 'empty-charts.svg', + [WelcomeTable.Dashboards]: 'empty-dashboard.svg', + [WelcomeTable.Recents]: 'union.svg', + [WelcomeTable.SavedQueries]: 'empty-queries.svg', +} as const; -export default function EmptyState({ - tableName, - tab, - otherTabTitle, -}: EmptyStateProps) { - const mineRedirects: Redirects = { +const REDIRECTS = { + create: { [WelcomeTable.Charts]: '/chart/add', [WelcomeTable.Dashboards]: '/dashboard/new', [WelcomeTable.SavedQueries]: '/sqllab?new=true', - }; - const favRedirects: Redirects = { + }, + viewAll: { [WelcomeTable.Charts]: '/chart/list', [WelcomeTable.Dashboards]: '/dashboard/list/', [WelcomeTable.SavedQueries]: '/savedqueryview/list/', - }; - const tableIcon: Record = { - [WelcomeTable.Charts]: 'empty-charts.svg', - [WelcomeTable.Dashboards]: 'empty-dashboard.svg', - [WelcomeTable.Recents]: 'union.svg', - [WelcomeTable.SavedQueries]: 'empty-queries.svg', - }; - const mine = {welcomeTableEmpty[tableName]}; - const recent = ( - - {(() => { - if (tab === TableTab.Viewed) { - return t( - `Recently viewed charts, dashboards, and saved queries will appear here`, - ); - } - if (tab === TableTab.Created) { - return t( - 'Recently created charts, dashboards, and saved queries will appear here', - ); - } - if (tab === TableTab.Other) { - const other = otherTabTitle || t('Other'); - return welcomeTableWillAppear[tableName](other); - } - if (tab === TableTab.Edited) { - return t( - `Recently edited charts, dashboards, and saved queries will appear here`, - ); - } - return null; - })()} - - ); + }, +} as const; + +export interface EmptyStateProps { + tableName: WelcomeTable; + tab?: string; + otherTabTitle?: string; +} + +export default function EmptyState({ + tableName, + tab, + otherTabTitle, +}: EmptyStateProps) { + const getActionButton = () => { + if (tableName === WelcomeTable.Recents) { + return null; + } + + const isFavorite = tab === TableTab.Favorite; + const buttonText = + tableName === WelcomeTable.SavedQueries + ? isFavorite + ? t('SQL Lab queries') + : t('SQL query') + : isFavorite + ? t(tableName.toLowerCase()) + : tableName.slice(0, -1); + + const url = isFavorite + ? REDIRECTS.viewAll[tableName] + : REDIRECTS.create[tableName]; - // Mine and Recent Activity(all tabs) tab empty state - if ( - tab === TableTab.Mine || - tableName === WelcomeTable.Recents || - tab === TableTab.Other - ) { return ( - - - {tableName !== WelcomeTable.Recents && ( - - - - - - )} - - + ); - } - // Favorite tab empty state + }; + + const image = + tab === TableTab.Favorite ? 'star-circle.svg' : ICONS[tableName]; + return ( - - {t("You don't have any favorites yet!")} - - } + - - + {getActionButton()} + ); } From 3f82485053f32c048e303bc46f2d0f023139f97d Mon Sep 17 00:00:00 2001 From: Maxime Beauchemin Date: Wed, 15 Jan 2025 22:58:21 -0800 Subject: [PATCH 2/3] fixed two tets --- superset-frontend/src/features/home/ChartTable.test.tsx | 4 +--- superset-frontend/src/features/home/EmptyState.test.tsx | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/superset-frontend/src/features/home/ChartTable.test.tsx b/superset-frontend/src/features/home/ChartTable.test.tsx index f03a705245e81..0e19f8c059ad4 100644 --- a/superset-frontend/src/features/home/ChartTable.test.tsx +++ b/superset-frontend/src/features/home/ChartTable.test.tsx @@ -87,9 +87,7 @@ const renderChartTable = (props: any) => test('renders with EmptyState if no data present', async () => { await renderChartTable(mockedProps); expect(screen.getAllByRole('tab')).toHaveLength(3); - expect( - screen.getByText(/other charts will appear here/i), - ).toBeInTheDocument(); + expect(screen.getByText(/nothing here yet/i)).toBeInTheDocument(); }); test('fetches chart favorites and renders chart cards', async () => { diff --git a/superset-frontend/src/features/home/EmptyState.test.tsx b/superset-frontend/src/features/home/EmptyState.test.tsx index fe633bc788632..3753b70deedff 100644 --- a/superset-frontend/src/features/home/EmptyState.test.tsx +++ b/superset-frontend/src/features/home/EmptyState.test.tsx @@ -95,9 +95,7 @@ describe('EmptyState', () => { expect(wrapper.find('.ant-empty-image').children()).toHaveLength(1); // Check the correct text is displayed - expect(textContainer.text()).toContain( - `Recently ${recent.tab?.toLowerCase()} charts, dashboards, and saved queries will appear here`, - ); + expect(textContainer.text()).toContain(`Nothing here yet`); }); }); }); From a6746a640dfb4f488cd1bab147ebbeaf26057793 Mon Sep 17 00:00:00 2001 From: Maxime Beauchemin Date: Thu, 16 Jan 2025 00:29:25 -0800 Subject: [PATCH 3/3] nothing here yet --- superset-frontend/package-lock.json | 118 ++++-------------- .../src/features/home/ActivityTable.test.tsx | 6 +- .../src/features/home/EmptyState.test.tsx | 10 +- 3 files changed, 26 insertions(+), 108 deletions(-) diff --git a/superset-frontend/package-lock.json b/superset-frontend/package-lock.json index 337ee7a84294a..57230094854bc 100644 --- a/superset-frontend/package-lock.json +++ b/superset-frontend/package-lock.json @@ -1702,15 +1702,18 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.24.7", + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "license": "MIT", "engines": { "node": ">=6.9.0" @@ -3481,13 +3484,13 @@ "license": "MIT" }, "node_modules/@babel/types": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz", - "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.5.tgz", + "integrity": "sha512-L6mZmwFDK6Cjh1nRCLXpa6no13ZIioJDz7mdkzHv399pThrTa/k0nUlNaenOeh2kWu/iaOQYElEpKPUswUa9Vg==", + "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -51614,13 +51617,6 @@ "dev": true, "license": "BSD-3-Clause" }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/to-object-path": { "version": "0.3.0", "dev": true, @@ -57074,26 +57070,6 @@ "node": ">=6.9.0" } }, - "packages/superset-ui-demo/node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "packages/superset-ui-demo/node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, "packages/superset-ui-demo/node_modules/@babel/helper-validator-option": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", @@ -59086,26 +59062,6 @@ "react-dom": "^16.13.1" } }, - "plugins/plugin-chart-pivot-table/node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "plugins/plugin-chart-pivot-table/node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, "plugins/plugin-chart-pivot-table/node_modules/@babel/types": { "version": "7.26.3", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", @@ -60212,12 +60168,14 @@ } }, "@babel/helper-string-parser": { - "version": "7.24.8", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", - "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==" + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==" }, "@babel/helper-validator-identifier": { - "version": "7.24.7" + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==" }, "@babel/helper-validator-option": { "version": "7.24.7" @@ -61267,13 +61225,12 @@ } }, "@babel/types": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz", - "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==", + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.5.tgz", + "integrity": "sha512-L6mZmwFDK6Cjh1nRCLXpa6no13ZIioJDz7mdkzHv399pThrTa/k0nUlNaenOeh2kWu/iaOQYElEpKPUswUa9Vg==", "requires": { - "@babel/helper-string-parser": "^7.24.8", - "@babel/helper-validator-identifier": "^7.24.7", - "to-fast-properties": "^2.0.0" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" } }, "@base2/pretty-print-object": { @@ -67537,18 +67494,6 @@ "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", "dev": true }, - "@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", - "dev": true - }, - "@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", - "dev": true - }, "@babel/helper-validator-option": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", @@ -69677,18 +69622,6 @@ "jest": "^29.7.0" }, "dependencies": { - "@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", - "dev": true - }, - "@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", - "dev": true - }, "@babel/types": { "version": "7.26.3", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", @@ -95191,9 +95124,6 @@ "version": "1.0.5", "dev": true }, - "to-fast-properties": { - "version": "2.0.0" - }, "to-object-path": { "version": "0.3.0", "dev": true, diff --git a/superset-frontend/src/features/home/ActivityTable.test.tsx b/superset-frontend/src/features/home/ActivityTable.test.tsx index 54fe3c7542ee0..9b5ee127b7f4e 100644 --- a/superset-frontend/src/features/home/ActivityTable.test.tsx +++ b/superset-frontend/src/features/home/ActivityTable.test.tsx @@ -137,9 +137,5 @@ test('calls the getEdited batch call when edited tab is clicked', async () => { }); test('show empty state if there is no data', () => { renderActivityTable(emptyActivityProps); - expect( - screen.getByText( - /recently created charts, dashboards, and saved queries will appear here/i, - ), - ).toBeInTheDocument(); + expect(screen.getByText(/nothing here yet/i)).toBeInTheDocument(); }); diff --git a/superset-frontend/src/features/home/EmptyState.test.tsx b/superset-frontend/src/features/home/EmptyState.test.tsx index 3753b70deedff..0be86559dcf63 100644 --- a/superset-frontend/src/features/home/EmptyState.test.tsx +++ b/superset-frontend/src/features/home/EmptyState.test.tsx @@ -70,15 +70,7 @@ describe('EmptyState', () => { // Select the first description node const textContainer = wrapper.find('.ant-empty-description').at(0); - expect(textContainer.text()).toEqual( - variant.tab === TableTab.Favorite - ? "You don't have any favorites yet!" - : `No ${ - variant.tableName === WelcomeTable.SavedQueries - ? 'saved queries' - : variant.tableName.toLowerCase() - } yet`, - ); + expect(textContainer.text()).toEqual('Nothing here yet'); expect(wrapper.find('button')).toHaveLength(1); }); });