From 2c86460fe30938394b038da5c06fcf77deec0304 Mon Sep 17 00:00:00 2001 From: Yunwen Zheng Date: Tue, 22 Jul 2025 10:31:08 -0400 Subject: [PATCH] BulkDeleteProvisionedResource: Move progress bar into a second step (#108417) * Move progress bar into a second step --------- Co-authored-by: Alex Khomenko --- .../components/BulkActionProgress.tsx | 23 ++-- .../BulkDeleteProvisionedResource.tsx | 116 +++++++++++------- .../provisioning/Shared/ProgressBar.tsx | 9 +- public/locales/en-US/grafana.json | 8 +- 4 files changed, 97 insertions(+), 59 deletions(-) diff --git a/public/app/features/browse-dashboards/components/BulkActionProgress.tsx b/public/app/features/browse-dashboards/components/BulkActionProgress.tsx index 1456162886e..0b49fd547be 100644 --- a/public/app/features/browse-dashboards/components/BulkActionProgress.tsx +++ b/public/app/features/browse-dashboards/components/BulkActionProgress.tsx @@ -1,5 +1,5 @@ import { Trans } from '@grafana/i18n'; -import { Box, Text } from '@grafana/ui'; +import { Box, Icon, Text, Stack } from '@grafana/ui'; import ProgressBar from 'app/features/provisioning/Shared/ProgressBar'; export interface ProgressState { @@ -13,16 +13,19 @@ export function BulkActionProgress({ progress }: { progress: ProgressState }) { return ( - - - - + + + + + + + - {progress.item} + {progress.item} ); diff --git a/public/app/features/browse-dashboards/components/BulkDeleteProvisionedResource.tsx b/public/app/features/browse-dashboards/components/BulkDeleteProvisionedResource.tsx index 4e7155b6187..378e530672c 100644 --- a/public/app/features/browse-dashboards/components/BulkDeleteProvisionedResource.tsx +++ b/public/app/features/browse-dashboards/components/BulkDeleteProvisionedResource.tsx @@ -2,10 +2,8 @@ import { useState } from 'react'; import { FormProvider, useForm } from 'react-hook-form'; import { useNavigate } from 'react-router-dom-v5-compat'; -import { AppEvents } from '@grafana/data'; import { Trans, t } from '@grafana/i18n'; -import { getAppEvents } from '@grafana/runtime'; -import { Box, Button, Stack } from '@grafana/ui'; +import { Alert, Box, Button, Stack } from '@grafana/ui'; import { DeleteRepositoryFilesWithPathApiArg, DeleteRepositoryFilesWithPathApiResponse, @@ -56,6 +54,11 @@ type BulkSuccessResponse = Array<{ data: DeleteRepositoryFilesWithPathApiResponse; }>; +type MoveResultSuccessState = { + allSuccess: boolean; + repoUrl?: string; +}; + function FormContent({ initialValues, selectedItems, @@ -65,10 +68,17 @@ function FormContent({ isGitHub, onDismiss, }: FormProps) { - const [deleteRepoFile, request] = useDeleteRepositoryFilesWithPathMutation(); + // States const [progress, setProgress] = useState(null); const [failureResults, setFailureResults] = useState(); + const [successState, setSuccessState] = useState({ + allSuccess: false, + repoUrl: '', + }); + const [hasSubmitted, setHasSubmitted] = useState(false); + // Hooks + const [deleteRepoFile, request] = useDeleteRepositoryFilesWithPathMutation(); const methods = useForm({ defaultValues: initialValues }); const childrenByParentUID = useChildrenByParentUIDState(); const rootItems = useSelector(rootItemsSelector); @@ -84,21 +94,11 @@ function FormContent({ return isFolder ? `${folderPath}/${item.title}/` : fetchProvisionedDashboardPath(uid); }; - const handleSuccess = (successes: BulkSuccessResponse) => { - getAppEvents().publish({ - type: AppEvents.alertSuccess.name, - payload: [ - t('browse-dashboards.bulk-delete-resources-form.api-success', `Successfully deleted {{count}} items`, { - count: successes.length, - }), - ], - }); - + const handleSuccess = () => { if (workflow === 'branch') { onDismiss?.(); - const repoUrl = successes[0].data.urls?.repositoryURL; - if (repoUrl) { - navigate({ search: `?repo_url=${encodeURIComponent(repoUrl)}` }); + if (successState.repoUrl) { + navigate({ search: `?repo_url=${encodeURIComponent(successState.repoUrl)}` }); return; } window.location.reload(); @@ -110,6 +110,7 @@ function FormContent({ const handleSubmitForm = async (data: BulkDeleteFormData) => { setFailureResults(undefined); + setHasSubmitted(true); const targets = collectSelectedItems(selectedItems, childrenByParentUID, rootItems?.items || []); @@ -175,12 +176,43 @@ function FormContent({ setProgress(null); if (successes.length > 0 && failures.length === 0) { - handleSuccess(successes); + // handleSuccess(successes); + setSuccessState({ + allSuccess: true, + repoUrl: successes[0].data.urls?.repositoryURL, + }); } else if (failures.length > 0) { setFailureResults(failures); } }; + const getPostSubmitContent = () => { + if (progress) { + return ; + } + + if (successState.allSuccess) { + return ( + <> + + + All resources have been deleted successfully. + + + + + + + ); + } else if (failureResults) { + return setFailureResults(undefined)} />; + } + + return null; + }; + return (
@@ -192,31 +224,31 @@ function FormContent({ - {failureResults && ( - setFailureResults(undefined)} /> + {hasSubmitted ? ( + getPostSubmitContent() + ) : ( + <> + + + + + + + )} - - {progress && } - - - - - - -
diff --git a/public/app/features/provisioning/Shared/ProgressBar.tsx b/public/app/features/provisioning/Shared/ProgressBar.tsx index 681321bb0b1..a9d9e3c57b0 100644 --- a/public/app/features/provisioning/Shared/ProgressBar.tsx +++ b/public/app/features/provisioning/Shared/ProgressBar.tsx @@ -5,9 +5,10 @@ import { useStyles2 } from '@grafana/ui'; interface ProgressBarProps { progress?: number; + topBottomSpacing?: number; } -const ProgressBar = ({ progress }: ProgressBarProps) => { - const styles = useStyles2(getStyles); +const ProgressBar = ({ progress, topBottomSpacing }: ProgressBarProps) => { + const styles = useStyles2(getStyles, topBottomSpacing); if (progress === undefined) { return null; @@ -20,14 +21,14 @@ const ProgressBar = ({ progress }: ProgressBarProps) => { ); }; -const getStyles = (theme: GrafanaTheme2) => ({ +const getStyles = (theme: GrafanaTheme2, topBottomSpacing = 2) => ({ container: css({ height: '10px', width: '400px', backgroundColor: theme.colors.background.secondary, borderRadius: theme.shape.radius.pill, overflow: 'hidden', - margin: theme.spacing(2, 0), + margin: theme.spacing(topBottomSpacing, 0), }), filler: css({ height: '100%', diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index 98c2721d47f..d689ec15261 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -3516,15 +3516,17 @@ "failed-alert_other": "{{count}} items failed" }, "bulk-delete-resources-form": { - "api-success_one": "Successfully deleted {{count}} item", - "api-success_other": "Successfully deleted {{count}} items", "button-cancel": "Cancel", "button-delete": "Delete", "button-deleting": "Deleting...", + "button-done": "Done", "delete-warning": "This will delete selected folders and their descendants. In total, this will affect:", - "error-path-not-found": "Path not found" + "error-path-not-found": "Path not found", + "progress-title": "Success", + "success-message": "All resources have been deleted successfully." }, "bulk-move-resources-form": { + "deleting": "Deleting:", "progress": "Progress: {{current}} of {{total}}" }, "counts": {