feat: Displaying details to Dataset/Database deletion modals (#30016)

This commit is contained in:
Evan Rusackas 2024-09-10 15:27:25 -06:00 committed by GitHub
parent 5a0e88771b
commit 7bb6a14944
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 177 additions and 25 deletions

View File

@ -53,6 +53,7 @@ repos:
- id: debug-statements - id: debug-statements
- id: end-of-file-fixer - id: end-of-file-fixer
- id: trailing-whitespace - id: trailing-whitespace
exclude: ^.*\.(snap)
args: ["--markdown-linebreak-ext=md"] args: ["--markdown-linebreak-ext=md"]
- repo: https://github.com/pre-commit/mirrors-prettier - repo: https://github.com/pre-commit/mirrors-prettier
rev: v3.1.0 # Use the sha or tag you want to point at rev: v3.1.0 # Use the sha or tag you want to point at

View File

@ -61,6 +61,9 @@ tsconfig.tsbuildinfo
generator-superset/* generator-superset/*
temporary_superset_ui/* temporary_superset_ui/*
# skip license checks for auto-generated test snapshots
.*snap
# docs overrides for third party logos we don't have the rights to # docs overrides for third party logos we don't have the rights to
google-big-query.svg google-big-query.svg
google-sheets.svg google-sheets.svg

View File

@ -25,5 +25,6 @@ CHANGELOG/
*.geojson *.geojson
*-topo.json *-topo.json
storybook-static/ storybook-static/
*.snap
/.nx/workspace-data /.nx/workspace-data

View File

@ -84,6 +84,7 @@ export default function DeleteModal({
primaryButtonType="danger" primaryButtonType="danger"
show={open} show={open}
title={title} title={title}
centered
> >
<DescriptionContainer>{description}</DescriptionContainer> <DescriptionContainer>{description}</DescriptionContainer>
<StyledDiv> <StyledDiv>

View File

@ -164,14 +164,7 @@ describe('Admin DatabaseList', () => {
}); });
await waitForComponentToPaint(wrapper); await waitForComponentToPaint(wrapper);
expect(wrapper.find(DeleteModal).props().description) expect(wrapper.find(DeleteModal).props().description).toMatchSnapshot();
.toMatchInlineSnapshot(`
<React.Fragment>
<p>
The database db 0 is linked to 0 charts that appear on 0 dashboards and users have 0 SQL Lab tabs using this database open. Are you sure you want to continue? Deleting the database will break those objects.
</p>
</React.Fragment>
`);
act(() => { act(() => {
wrapper wrapper

View File

@ -0,0 +1,15 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Admin DatabaseList deletes 1`] = `
<React.Fragment>
<p>
The database
<b>
db 0
</b>
is linked to 0 charts that appear on 0 dashboards and users have 0 SQL Lab tabs using this database open. Are you sure you want to continue? Deleting the database will break those objects.
</p>
</React.Fragment>
`;

View File

@ -27,7 +27,6 @@ import rison from 'rison';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { useQueryParams, BooleanParam } from 'use-query-params'; import { useQueryParams, BooleanParam } from 'use-query-params';
import { LocalStorageKeys, setItem } from 'src/utils/localStorageHelpers'; import { LocalStorageKeys, setItem } from 'src/utils/localStorageHelpers';
import Loading from 'src/components/Loading'; import Loading from 'src/components/Loading';
import { useListViewResource } from 'src/views/CRUD/hooks'; import { useListViewResource } from 'src/views/CRUD/hooks';
import { import {
@ -65,8 +64,8 @@ const dbConfigExtraExtension = extensionsRegistry.get(
const PAGE_SIZE = 25; const PAGE_SIZE = 25;
interface DatabaseDeleteObject extends DatabaseObject { interface DatabaseDeleteObject extends DatabaseObject {
chart_count: number; charts: any;
dashboard_count: number; dashboards: any;
sqllab_tab_count: number; sqllab_tab_count: number;
} }
interface DatabaseListProps { interface DatabaseListProps {
@ -170,8 +169,8 @@ function DatabaseList({
.then(({ json = {} }) => { .then(({ json = {} }) => {
setDatabaseCurrentlyDeleting({ setDatabaseCurrentlyDeleting({
...database, ...database,
chart_count: json.charts.count, charts: json.charts,
dashboard_count: json.dashboards.count, dashboards: json.dashboards,
sqllab_tab_count: json.sqllab_tab_states.count, sqllab_tab_count: json.sqllab_tab_states.count,
}); });
}) })
@ -609,14 +608,82 @@ function DatabaseList({
description={ description={
<> <>
<p> <p>
{t('The database')}{' '}
<b>{databaseCurrentlyDeleting.database_name}</b>{' '}
{t( {t(
'The database %s is linked to %s charts that appear on %s dashboards and users have %s SQL Lab tabs using this database open. Are you sure you want to continue? Deleting the database will break those objects.', 'is linked to %s charts that appear on %s dashboards and users have %s SQL Lab tabs using this database open. Are you sure you want to continue? Deleting the database will break those objects.',
databaseCurrentlyDeleting.database_name, databaseCurrentlyDeleting.charts.count,
databaseCurrentlyDeleting.chart_count, databaseCurrentlyDeleting.dashboards.count,
databaseCurrentlyDeleting.dashboard_count,
databaseCurrentlyDeleting.sqllab_tab_count, databaseCurrentlyDeleting.sqllab_tab_count,
)} )}
</p> </p>
{databaseCurrentlyDeleting.dashboards.count >= 1 && (
<>
<h4>{t('Affected Dashboards')}</h4>
<ul>
{databaseCurrentlyDeleting.dashboards.result
.slice(0, 10)
.map(
(
result: { id: number; title: string },
index: number,
) => (
<li key={result.id}>
<a
href={`/superset/dashboard/${result.id}`}
target="_atRiskItem"
>
{result.title}
</a>
</li>
),
)}
{databaseCurrentlyDeleting.dashboards.result.length >
10 && (
<li>
{t(
'... and %s others',
databaseCurrentlyDeleting.dashboards.result.length -
10,
)}
</li>
)}
</ul>
</>
)}
{databaseCurrentlyDeleting.charts.count >= 1 && (
<>
<h4>{t('Affected Charts')}</h4>
<ul>
{databaseCurrentlyDeleting.charts.result.slice(0, 10).map(
(
result: {
id: number;
slice_name: string;
},
index: number,
) => (
<li key={result.id}>
<a
href={`/explore/?slice_id=${result.id}`}
target="_atRiskItem"
>
{result.slice_name}
</a>
</li>
),
)}
{databaseCurrentlyDeleting.charts.result.length > 10 && (
<li>
{t(
'... and %s others',
databaseCurrentlyDeleting.charts.result.length - 10,
)}
</li>
)}
</ul>
</>
)}
{DatabaseDeleteRelatedExtension && ( {DatabaseDeleteRelatedExtension && (
<DatabaseDeleteRelatedExtension <DatabaseDeleteRelatedExtension
database={databaseCurrentlyDeleting} database={databaseCurrentlyDeleting}

View File

@ -22,7 +22,7 @@ import {
SupersetClient, SupersetClient,
t, t,
} from '@superset-ui/core'; } from '@superset-ui/core';
import { FunctionComponent, useState, useMemo, useCallback } from 'react'; import { FunctionComponent, useState, useMemo, useCallback, Key } from 'react';
import { Link, useHistory } from 'react-router-dom'; import { Link, useHistory } from 'react-router-dom';
import rison from 'rison'; import rison from 'rison';
import { import {
@ -154,7 +154,11 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({
} = useListViewResource<Dataset>('dataset', t('dataset'), addDangerToast); } = useListViewResource<Dataset>('dataset', t('dataset'), addDangerToast);
const [datasetCurrentlyDeleting, setDatasetCurrentlyDeleting] = useState< const [datasetCurrentlyDeleting, setDatasetCurrentlyDeleting] = useState<
(Dataset & { chart_count: number; dashboard_count: number }) | null | (Dataset & {
charts: any;
dashboards: any;
})
| null
>(null); >(null);
const [datasetCurrentlyEditing, setDatasetCurrentlyEditing] = const [datasetCurrentlyEditing, setDatasetCurrentlyEditing] =
@ -243,8 +247,8 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({
.then(({ json = {} }) => { .then(({ json = {} }) => {
setDatasetCurrentlyDeleting({ setDatasetCurrentlyDeleting({
...dataset, ...dataset,
chart_count: json.charts.count, charts: json.charts,
dashboard_count: json.dashboards.count, dashboards: json.dashboards,
}); });
}) })
.catch( .catch(
@ -742,13 +746,80 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({
description={ description={
<> <>
<p> <p>
{t('The dataset')}
<b> {datasetCurrentlyDeleting.table_name} </b>
{t( {t(
'The dataset %s is linked to %s charts that appear on %s dashboards. Are you sure you want to continue? Deleting the dataset will break those objects.', 'is linked to %s charts that appear on %s dashboards. Are you sure you want to continue? Deleting the dataset will break those objects.',
datasetCurrentlyDeleting.table_name, datasetCurrentlyDeleting.charts.count,
datasetCurrentlyDeleting.chart_count, datasetCurrentlyDeleting.dashboards.count,
datasetCurrentlyDeleting.dashboard_count,
)} )}
</p> </p>
{datasetCurrentlyDeleting.dashboards.count >= 1 && (
<>
<h4>{t('Affected Dashboards')}</h4>
<ul>
{datasetCurrentlyDeleting.dashboards.result
.slice(0, 10)
.map(
(
result: { id: Key | null | undefined; title: string },
index: number,
) => (
<li key={result.id}>
<a
href={`/superset/dashboard/${result.id}`}
target="_atRiskItem"
>
{result.title}
</a>
</li>
),
)}
{datasetCurrentlyDeleting.dashboards.result.length > 10 && (
<li>
{t(
'... and %s others',
datasetCurrentlyDeleting.dashboards.result.length -
10,
)}
</li>
)}
</ul>
</>
)}
{datasetCurrentlyDeleting.charts.count >= 1 && (
<>
<h4>{t('Affected Charts')}</h4>
<ul>
{datasetCurrentlyDeleting.charts.result.slice(0, 10).map(
(
result: {
id: Key | null | undefined;
slice_name: string;
},
index: number,
) => (
<li key={result.id}>
<a
href={`/explore/?slice_id=${result.id}`}
target="_atRiskItem"
>
{result.slice_name}
</a>
</li>
),
)}
{datasetCurrentlyDeleting.charts.result.length > 10 && (
<li>
{t(
'... and %s others',
datasetCurrentlyDeleting.charts.result.length - 10,
)}
</li>
)}
</ul>
</>
)}
{DatasetDeleteRelatedExtension && ( {DatasetDeleteRelatedExtension && (
<DatasetDeleteRelatedExtension <DatasetDeleteRelatedExtension
dataset={datasetCurrentlyDeleting} dataset={datasetCurrentlyDeleting}