From 7ad6358e40a11f06b880719a698a4aea4e6a04f3 Mon Sep 17 00:00:00 2001 From: Yunwen Zheng Date: Mon, 14 Jul 2025 11:01:43 -0400 Subject: [PATCH] DeleteProvisionedFolderForm: navigate user to dashboard page with open PR banner when push to branch (#107989) * DeleteProvisionedFolderForm: navigate user to dashboard page with open PR banner when push to branch --- .../DeleteProvisionedFolderForm.test.tsx | 23 +++++++++++++++---- .../DeleteProvisionedFolderForm.tsx | 10 ++++---- .../components/FolderActionsButton.tsx | 3 +-- .../SaveProvisionedDashboardForm.tsx | 4 +++- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/public/app/features/browse-dashboards/components/DeleteProvisionedFolderForm.test.tsx b/public/app/features/browse-dashboards/components/DeleteProvisionedFolderForm.test.tsx index 0412efd0c18..01d9216ff5f 100644 --- a/public/app/features/browse-dashboards/components/DeleteProvisionedFolderForm.test.tsx +++ b/public/app/features/browse-dashboards/components/DeleteProvisionedFolderForm.test.tsx @@ -16,6 +16,11 @@ jest.mock('@grafana/runtime', () => ({ })), })); +const mockNavigate = jest.fn(); +jest.mock('react-router-dom-v5-compat', () => ({ + useNavigate: () => mockNavigate, +})); + jest.mock('app/api/clients/provisioning/v0alpha1', () => ({ useDeleteRepositoryFilesWithPathMutation: jest.fn(), provisioningAPI: { @@ -140,6 +145,7 @@ function setup( ...renderResult, onDismiss, mockDeleteRepoFile, + mockNavigate, clickDeleteButton, }; } @@ -147,6 +153,7 @@ function setup( describe('DeleteProvisionedFolderForm', () => { beforeEach(() => { jest.clearAllMocks(); + mockNavigate.mockClear(); jest.spyOn(console, 'error').mockImplementation(() => {}); // Mock window.location.href Object.defineProperty(window, 'location', { @@ -272,13 +279,21 @@ describe('DeleteProvisionedFolderForm', () => { }); }); - it('should handle branch workflow success without navigation', async () => { + it('should handle branch workflow success with navigation', async () => { const branchFormData = { ...mockFormData, workflow: 'branch' } as unknown as typeof mockFormData; - const successState = { isLoading: false, isSuccess: true, isError: false, error: null }; - setup({}, { ...defaultHookData, initialValues: branchFormData }, successState); + const successState = { + isLoading: false, + isSuccess: true, + isError: false, + error: null, + data: { urls: { newPullRequestURL: 'https://github.com/test/repo/pull/new' } }, + }; + const { mockNavigate } = setup({}, { ...defaultHookData, initialValues: branchFormData }, successState); await waitFor(() => { - expect(window.location.href).toBe(''); + expect(mockNavigate).toHaveBeenCalledWith( + '/dashboards?new_pull_request_url=https://github.com/test/repo/pull/new' + ); }); }); }); diff --git a/public/app/features/browse-dashboards/components/DeleteProvisionedFolderForm.tsx b/public/app/features/browse-dashboards/components/DeleteProvisionedFolderForm.tsx index 2b4a6ebb92f..2491b7bc506 100644 --- a/public/app/features/browse-dashboards/components/DeleteProvisionedFolderForm.tsx +++ b/public/app/features/browse-dashboards/components/DeleteProvisionedFolderForm.tsx @@ -1,5 +1,6 @@ import { useEffect } 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'; @@ -42,6 +43,7 @@ function FormContent({ const resourceId = parentFolder?.uid || ''; const [deleteRepoFile, request] = useDeleteRepositoryFilesWithPathMutation(); + const navigate = useNavigate(); const methods = useForm({ defaultValues: initialValues }); const { handleSubmit, watch } = methods; @@ -66,9 +68,9 @@ function FormContent({ // TODO: move to a hook if this useEffect shared mostly the same logic as in NewProvisionedFolderForm useEffect(() => { if (request.isSuccess && repository) { - if (workflow === 'branch') { - // TODO: handle display banner https://github.com/grafana/git-ui-sync-project/issues/300 - // TODO: implement when BE is ready + const prUrl = request.data?.urls?.newPullRequestURL; + if (workflow === 'branch' && prUrl) { + navigate(`/dashboards?new_pull_request_url=${prUrl}`); return; } @@ -101,7 +103,7 @@ function FormContent({ }); return; } - }, [request, repository, workflow, parentFolder]); + }, [request, repository, workflow, parentFolder, navigate]); return ( diff --git a/public/app/features/browse-dashboards/components/FolderActionsButton.tsx b/public/app/features/browse-dashboards/components/FolderActionsButton.tsx index 9640314aec9..dcb798a9749 100644 --- a/public/app/features/browse-dashboards/components/FolderActionsButton.tsx +++ b/public/app/features/browse-dashboards/components/FolderActionsButton.tsx @@ -103,8 +103,7 @@ export function FolderActionsButton({ folder }: Props) { {canViewPermissions && setShowPermissionsDrawer(true)} label={managePermissionsLabel} />} {canMoveFolder && } - {/* TODO: remove isProvisionedFolder check once BE folder delete flow is complete */} - {canDeleteFolders && !isProvisionedFolder && ( + {canDeleteFolders && (