From cdf035f813606da7b2deed779b84e1b1688020c9 Mon Sep 17 00:00:00 2001
From: Laura Benz <48948963+L-M-K-B@users.noreply.github.com>
Date: Mon, 2 Sep 2024 18:04:02 +0200
Subject: [PATCH 01/12] Scenes/RestoreDashboards: Adjust DeleteDashboardModal
and Toast message (#92601)
* refactor: replace soft delete method
* refactor: adjust test to new naming
* refactor: clean up unused functions
* refactor: replace delete modal
* refactor: use new delete modal outside of scenes
---
.betterer.results | 10 +-
.../scene/DashboardScene.test.tsx | 2 +-
.../dashboard-scene/scene/DashboardScene.tsx | 4 +-
.../settings/DeleteDashboardButton.tsx | 97 +++++++++++++------
.../DeleteDashboard/DeleteDashboardModal.tsx | 27 +-----
.../manage-dashboards/state/actions.ts | 44 ---------
public/locales/en-US/grafana.json | 5 +-
public/locales/pseudo-LOCALE/grafana.json | 5 +-
8 files changed, 79 insertions(+), 115 deletions(-)
diff --git a/.betterer.results b/.betterer.results
index 0cbbf2c2539..bafa487b8df 100644
--- a/.betterer.results
+++ b/.betterer.results
@@ -2886,8 +2886,7 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings. Wrap text with ", "2"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "3"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "4"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "5"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "6"]
+ [0, 0, 0, "No untranslated strings. Wrap text with ", "5"]
],
"public/app/features/dashboard-scene/settings/JsonModelEditView.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with ", "0"],
@@ -4679,12 +4678,7 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "5"],
[0, 0, 0, "Unexpected any. Specify a different type.", "6"],
[0, 0, 0, "Unexpected any. Specify a different type.", "7"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "8"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "9"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "10"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "11"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "12"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "13"]
+ [0, 0, 0, "Unexpected any. Specify a different type.", "8"]
],
"public/app/features/manage-dashboards/state/reducers.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
diff --git a/public/app/features/dashboard-scene/scene/DashboardScene.test.tsx b/public/app/features/dashboard-scene/scene/DashboardScene.test.tsx
index 9e2ca410700..10fb8788a03 100644
--- a/public/app/features/dashboard-scene/scene/DashboardScene.test.tsx
+++ b/public/app/features/dashboard-scene/scene/DashboardScene.test.tsx
@@ -1000,7 +1000,7 @@ describe('DashboardScene', () => {
scene.setState({ isDirty: true });
locationService.push('/d/adsdas');
- await scene.deleteDashboard();
+ await scene.onDashboardDelete();
expect(scene.state.isDirty).toBe(false);
});
diff --git a/public/app/features/dashboard-scene/scene/DashboardScene.tsx b/public/app/features/dashboard-scene/scene/DashboardScene.tsx
index 13f1069c653..3378af54647 100644
--- a/public/app/features/dashboard-scene/scene/DashboardScene.tsx
+++ b/public/app/features/dashboard-scene/scene/DashboardScene.tsx
@@ -34,7 +34,6 @@ import store from 'app/core/store';
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
import { dashboardWatcher } from 'app/features/live/dashboard/dashboardWatcher';
-import { deleteDashboard } from 'app/features/manage-dashboards/state/actions';
import { getClosestScopesFacade, ScopesFacade } from 'app/features/scopes';
import { VariablesChanged } from 'app/features/variables/types';
import { DashboardDTO, DashboardMeta, KioskMode, SaveDashboardResponseDTO } from 'app/types';
@@ -891,8 +890,7 @@ export class DashboardScene extends SceneObjectBase {
this._initialSaveModel = saveModel;
}
- public async deleteDashboard() {
- await deleteDashboard(this.state.uid!, true);
+ public async onDashboardDelete() {
// Need to mark it non dirty to navigate away without unsaved changes warning
this.setState({ isDirty: false });
locationService.replace('/');
diff --git a/public/app/features/dashboard-scene/settings/DeleteDashboardButton.tsx b/public/app/features/dashboard-scene/settings/DeleteDashboardButton.tsx
index aca70195cf1..19494d5663d 100644
--- a/public/app/features/dashboard-scene/settings/DeleteDashboardButton.tsx
+++ b/public/app/features/dashboard-scene/settings/DeleteDashboardButton.tsx
@@ -2,17 +2,56 @@ import { useAsyncFn, useToggle } from 'react-use';
import { selectors } from '@grafana/e2e-selectors';
import { config, reportInteraction } from '@grafana/runtime';
-import { Button, ConfirmModal, Modal } from '@grafana/ui';
-import { Trans } from 'app/core/internationalization';
+import { Button, ConfirmModal, Modal, Space, Text } from '@grafana/ui';
+import { t, Trans } from 'app/core/internationalization';
+import { useDeleteItemsMutation } from '../../browse-dashboards/api/browseDashboardsAPI';
import { DashboardScene } from '../scene/DashboardScene';
interface ButtonProps {
dashboard: DashboardScene;
}
+interface ProvisionedDeleteModalProps {
+ dashboardId: string | undefined;
+ onClose: () => void;
+}
+
+interface DeleteModalProps {
+ dashboardTitle: string;
+ onConfirm: () => void;
+ onClose: () => void;
+}
+
export function DeleteDashboardButton({ dashboard }: ButtonProps) {
const [showModal, toggleModal] = useToggle(false);
+ const [deleteItems] = useDeleteItemsMutation();
+
+ const [, onConfirm] = useAsyncFn(async () => {
+ reportInteraction('grafana_manage_dashboards_delete_clicked', {
+ item_counts: {
+ dashboard: 1,
+ },
+ source: 'dashboard_scene_settings',
+ restore_enabled: config.featureToggles.dashboardRestoreUI,
+ });
+ toggleModal();
+ if (dashboard.state.uid) {
+ await deleteItems({
+ selectedItems: {
+ dashboard: {
+ [dashboard.state.uid]: true,
+ },
+ folder: {},
+ },
+ });
+ }
+ await dashboard.onDashboardDelete();
+ }, [dashboard, toggleModal]);
+
+ if (dashboard.state.meta.provisioned && showModal) {
+ return ;
+ }
return (
<>
@@ -24,52 +63,48 @@ export function DeleteDashboardButton({ dashboard }: ButtonProps) {
Delete dashboard
- {showModal && }
+ {showModal && (
+
+ )}
>
);
}
-interface ModalProps {
- dashboard: DashboardScene;
- onClose: () => void;
-}
-
-function DeleteDashboardModal({ dashboard, onClose }: ModalProps) {
- const [, onConfirm] = useAsyncFn(async () => {
- reportInteraction('grafana_manage_dashboards_delete_clicked', {
- item_counts: {
- dashboard: 1,
- },
- source: 'dashboard_scene_settings',
- restore_enabled: config.featureToggles.dashboardRestoreUI,
- });
- onClose();
- await dashboard.deleteDashboard();
- }, [dashboard, onClose]);
-
- if (dashboard.state.meta.provisioned) {
- return ;
- }
-
+export function DeleteDashboardModal({ dashboardTitle, onConfirm, onClose }: DeleteModalProps) {
return (
-
Do you want to delete this dashboard?
-
{dashboard.state.title}
+ {config.featureToggles.dashboardRestore && (
+ <>
+
+
+ This action will mark the dashboard for deletion in 30 days. Your organization administrator can
+ restore it anytime before the 30 days expire.
+
+
+
+ >
+ )}
+
+ Do you want to delete this dashboard?
+
+ {dashboardTitle}
+
>
}
onConfirm={onConfirm}
onDismiss={onClose}
- title="Delete"
+ title={t('dashboard-settings.delete-modal.title', 'Delete')}
icon="trash-alt"
- confirmText="Delete"
+ confirmText={t('dashboard-settings.delete-modal.delete-button', 'Delete')}
+ confirmationText={t('dashboard-settings.delete-modal.confirmation-text', 'Delete')}
/>
);
}
-function ProvisionedDeleteModal({ dashboard, onClose }: ModalProps) {
+function ProvisionedDeleteModal({ dashboardId, onClose }: ProvisionedDeleteModalProps) {
return (
@@ -90,7 +125,7 @@ function ProvisionedDeleteModal({ dashboard, onClose }: ModalProps) {
for more information about provisioning.
- File path: {dashboard.state.meta.provisionedExternalId}
+ File path: {dashboardId}