From 9ddedb03dfa2c096c4fb84400a1871dadc0f9987 Mon Sep 17 00:00:00 2001 From: Nikhil Kuriakose Date: Mon, 17 Nov 2025 16:49:38 +0100 Subject: [PATCH] fix(editor): Take user back to correct project after archive/delete (#21940) --- .../MainHeader/WorkflowDetails.test.ts | 132 ++++++++++++++++++ .../components/MainHeader/WorkflowDetails.vue | 25 +++- 2 files changed, 155 insertions(+), 2 deletions(-) diff --git a/packages/frontend/editor-ui/src/app/components/MainHeader/WorkflowDetails.test.ts b/packages/frontend/editor-ui/src/app/components/MainHeader/WorkflowDetails.test.ts index 17c9de9844e..edb7e76540b 100644 --- a/packages/frontend/editor-ui/src/app/components/MainHeader/WorkflowDetails.test.ts +++ b/packages/frontend/editor-ui/src/app/components/MainHeader/WorkflowDetails.test.ts @@ -391,6 +391,72 @@ describe('WorkflowDetails', () => { }); }); + it("should navigate to team project workflows page on 'Archive' for team project workflow", async () => { + const teamProjectId = 'team-project-123'; + const teamWorkflow = { + ...workflow, + homeProject: { + id: teamProjectId, + name: 'Team Project', + type: 'team', + }, + }; + + workflowsStore.getWorkflowById = vi.fn().mockReturnValue(teamWorkflow); + workflowsStore.archiveWorkflow.mockResolvedValue(undefined); + + const { getByTestId } = renderComponent({ + props: { + ...teamWorkflow, + active: false, + readOnly: false, + isArchived: false, + scopes: ['workflow:delete'], + }, + }); + + await userEvent.click(getByTestId('workflow-menu')); + await userEvent.click(getByTestId('workflow-menu-item-archive')); + + expect(workflowsStore.archiveWorkflow).toHaveBeenCalledWith(teamWorkflow.id); + expect(router.push).toHaveBeenCalledWith({ + name: VIEWS.PROJECTS_WORKFLOWS, + params: { projectId: teamProjectId }, + }); + }); + + it("should navigate to personal workflows page on 'Archive' for personal project workflow", async () => { + const personalWorkflow = { + ...workflow, + homeProject: { + id: 'personal-project-123', + name: 'Personal Project', + type: 'personal', + }, + }; + + workflowsStore.getWorkflowById = vi.fn().mockReturnValue(personalWorkflow); + workflowsStore.archiveWorkflow.mockResolvedValue(undefined); + + const { getByTestId } = renderComponent({ + props: { + ...personalWorkflow, + active: false, + readOnly: false, + isArchived: false, + scopes: ['workflow:delete'], + }, + }); + + await userEvent.click(getByTestId('workflow-menu')); + await userEvent.click(getByTestId('workflow-menu-item-archive')); + + expect(workflowsStore.archiveWorkflow).toHaveBeenCalledWith(personalWorkflow.id); + expect(router.push).toHaveBeenCalledWith({ + name: VIEWS.WORKFLOWS, + }); + }); + it("should confirm onWorkflowMenuSelect on 'Archive' option click on active workflow", async () => { const { getByTestId } = renderComponent({ props: { @@ -461,6 +527,72 @@ describe('WorkflowDetails', () => { }); }); + it("should navigate to team project workflows page on 'Delete' for team project workflow", async () => { + const teamProjectId = 'team-project-456'; + const teamWorkflow = { + ...workflow, + isArchived: true, + homeProject: { + id: teamProjectId, + name: 'Team Project', + type: 'team', + }, + }; + + workflowsStore.getWorkflowById = vi.fn().mockReturnValue(teamWorkflow); + workflowsStore.deleteWorkflow.mockResolvedValue(undefined); + + const { getByTestId } = renderComponent({ + props: { + ...teamWorkflow, + readOnly: false, + isArchived: true, + scopes: ['workflow:delete'], + }, + }); + + await userEvent.click(getByTestId('workflow-menu')); + await userEvent.click(getByTestId('workflow-menu-item-delete')); + + expect(workflowsStore.deleteWorkflow).toHaveBeenCalledWith(teamWorkflow.id); + expect(router.push).toHaveBeenCalledWith({ + name: VIEWS.PROJECTS_WORKFLOWS, + params: { projectId: teamProjectId }, + }); + }); + + it("should navigate to personal workflows page on 'Delete' for personal project workflow", async () => { + const personalWorkflow = { + ...workflow, + isArchived: true, + homeProject: { + id: 'personal-project-456', + name: 'Personal Project', + type: 'personal', + }, + }; + + workflowsStore.getWorkflowById = vi.fn().mockReturnValue(personalWorkflow); + workflowsStore.deleteWorkflow.mockResolvedValue(undefined); + + const { getByTestId } = renderComponent({ + props: { + ...personalWorkflow, + readOnly: false, + isArchived: true, + scopes: ['workflow:delete'], + }, + }); + + await userEvent.click(getByTestId('workflow-menu')); + await userEvent.click(getByTestId('workflow-menu-item-delete')); + + expect(workflowsStore.deleteWorkflow).toHaveBeenCalledWith(personalWorkflow.id); + expect(router.push).toHaveBeenCalledWith({ + name: VIEWS.WORKFLOWS, + }); + }); + it("should call onWorkflowMenuSelect on 'Change owner' option click", async () => { const openModalSpy = vi.spyOn(uiStore, 'openModalWithData'); diff --git a/packages/frontend/editor-ui/src/app/components/MainHeader/WorkflowDetails.vue b/packages/frontend/editor-ui/src/app/components/MainHeader/WorkflowDetails.vue index cee155d7a35..7e627be65f5 100644 --- a/packages/frontend/editor-ui/src/app/components/MainHeader/WorkflowDetails.vue +++ b/packages/frontend/editor-ui/src/app/components/MainHeader/WorkflowDetails.vue @@ -487,7 +487,16 @@ async function handleArchiveWorkflow() { type: 'success', }); - await router.push({ name: VIEWS.WORKFLOWS }); + // Navigate to the appropriate project's workflow list + const workflow = workflowsStore.getWorkflowById(props.id); + if (workflow?.homeProject?.type === ProjectTypes.Team) { + await router.push({ + name: VIEWS.PROJECTS_WORKFLOWS, + params: { projectId: workflow.homeProject.id }, + }); + } else { + await router.push({ name: VIEWS.WORKFLOWS }); + } } async function handleUnarchiveWorkflow() { @@ -521,6 +530,10 @@ async function handleDeleteWorkflow() { return; } + // Get workflow before deletion to know which project to navigate to + const workflow = workflowsStore.getWorkflowById(props.id); + const isTeamProject = workflow?.homeProject?.type === ProjectTypes.Team; + try { await workflowsStore.deleteWorkflow(props.id); } catch (error) { @@ -537,7 +550,15 @@ async function handleDeleteWorkflow() { type: 'success', }); - await router.push({ name: VIEWS.WORKFLOWS }); + // Navigate to the appropriate project's workflow list + if (isTeamProject && workflow?.homeProject) { + await router.push({ + name: VIEWS.PROJECTS_WORKFLOWS, + params: { projectId: workflow.homeProject.id }, + }); + } else { + await router.push({ name: VIEWS.WORKFLOWS }); + } } async function onWorkflowMenuSelect(action: WORKFLOW_MENU_ACTIONS): Promise {