diff --git a/packages/frontend/editor-ui/src/composables/useCanvasOperations.test.ts b/packages/frontend/editor-ui/src/composables/useCanvasOperations.test.ts index 34e5eb695f..3e9233bb61 100644 --- a/packages/frontend/editor-ui/src/composables/useCanvasOperations.test.ts +++ b/packages/frontend/editor-ui/src/composables/useCanvasOperations.test.ts @@ -28,6 +28,10 @@ import { import { mock } from 'vitest-mock-extended'; import { useNodeTypesStore } from '@/stores/nodeTypes.store'; import { useCredentialsStore } from '@/stores/credentials.store'; +import { useExecutionsStore } from '@/stores/executions.store'; +import { useFocusPanelStore } from '@/stores/focusPanel.store'; +import { useNodeCreatorStore } from '@/stores/nodeCreator.store'; +import { useProjectsStore } from '@/stores/projects.store'; import { waitFor } from '@testing-library/vue'; import { createTestingPinia } from '@pinia/testing'; import { mockedStore } from '@/__tests__/utils'; @@ -43,7 +47,6 @@ import type { Connection } from '@vue-flow/core'; import { useClipboard } from '@/composables/useClipboard'; import { createCanvasConnectionHandleString } from '@/utils/canvasUtils'; import { nextTick } from 'vue'; -import { useProjectsStore } from '@/stores/projects.store'; import type { CanvasLayoutEvent } from './useCanvasLayout'; import { useTelemetry } from './useTelemetry'; import { useToast } from '@/composables/useToast'; @@ -2814,6 +2817,85 @@ describe('useCanvasOperations', () => { }); }); + describe('resetWorkspace', () => { + it('should reset the workspace', () => { + const nodeCreatorStore = mockedStore(useNodeCreatorStore); + const workflowsStore = mockedStore(useWorkflowsStore); + const uiStore = mockedStore(useUIStore); + const executionsStore = mockedStore(useExecutionsStore); + const focusPanelStore = mockedStore(useFocusPanelStore); + + const nodeHelpers = { credentialsUpdated: { value: true } }; + + nodeCreatorStore.setNodeCreatorState = vi.fn(); + nodeCreatorStore.setShowScrim = vi.fn(); + workflowsStore.removeTestWebhook = vi.fn(); + workflowsStore.resetWorkflow = vi.fn(); + workflowsStore.resetState = vi.fn(); + workflowsStore.setActiveExecutionId = vi.fn(); + uiStore.resetLastInteractedWith = vi.fn(); + focusPanelStore.reset = vi.fn(); + executionsStore.activeExecution = null; + + workflowsStore.executionWaitingForWebhook = true; + workflowsStore.workflowId = 'workflow-id'; + workflowsStore.currentWorkflowExecutions = [ + { + id: '1', + status: 'success', + mode: 'retry', + workflowId: 'workflow-id', + createdAt: new Date(), + startedAt: new Date(), + }, + { + id: '2', + status: 'running', + mode: 'error', + workflowId: 'workflow-id', + createdAt: new Date(), + startedAt: new Date(), + }, + ]; + nodeHelpers.credentialsUpdated.value = true; + + const { resetWorkspace } = useCanvasOperations(); + + resetWorkspace(); + + expect(nodeCreatorStore.setNodeCreatorState).toHaveBeenCalledWith({ + createNodeActive: false, + }); + expect(nodeCreatorStore.setShowScrim).toHaveBeenCalledWith(false); + expect(workflowsStore.removeTestWebhook).toHaveBeenCalledWith('workflow-id'); + expect(workflowsStore.resetWorkflow).toHaveBeenCalled(); + expect(workflowsStore.resetState).toHaveBeenCalled(); + expect(workflowsStore.currentWorkflowExecutions).toEqual([]); + expect(workflowsStore.setActiveExecutionId).toHaveBeenCalledWith(undefined); + expect(focusPanelStore.reset).toHaveBeenCalled(); + expect(uiStore.resetLastInteractedWith).toHaveBeenCalled(); + expect(uiStore.stateIsDirty).toBe(false); + expect(executionsStore.activeExecution).toBeNull(); + }); + + it('should not call removeTestWebhook if executionWaitingForWebhook is false', () => { + const nodeCreatorStore = mockedStore(useNodeCreatorStore); + const workflowsStore = mockedStore(useWorkflowsStore); + + nodeCreatorStore.setNodeCreatorState = vi.fn(); + nodeCreatorStore.setShowScrim = vi.fn(); + workflowsStore.removeTestWebhook = vi.fn(); + + workflowsStore.executionWaitingForWebhook = false; + + const { resetWorkspace } = useCanvasOperations(); + + resetWorkspace(); + + expect(workflowsStore.removeTestWebhook).not.toHaveBeenCalled(); + }); + }); + describe('filterConnectionsByNodes', () => { it('should return filtered connections when all nodes are included', () => { const connections: INodeConnections = { diff --git a/packages/frontend/editor-ui/src/composables/useCanvasOperations.ts b/packages/frontend/editor-ui/src/composables/useCanvasOperations.ts index 6132ee4695..808368aeb9 100644 --- a/packages/frontend/editor-ui/src/composables/useCanvasOperations.ts +++ b/packages/frontend/editor-ui/src/composables/useCanvasOperations.ts @@ -53,6 +53,7 @@ import { useSettingsStore } from '@/stores/settings.store'; import { useTagsStore } from '@/stores/tags.store'; import { useUIStore } from '@/stores/ui.store'; import { useWorkflowsStore } from '@/stores/workflows.store'; +import { useFocusPanelStore } from '@/stores/focusPanel.store'; import type { CanvasConnection, CanvasConnectionCreateData, @@ -152,6 +153,7 @@ export function useCanvasOperations() { const settingsStore = useSettingsStore(); const tagsStore = useTagsStore(); const nodeCreatorStore = useNodeCreatorStore(); + const focusPanelStore = useFocusPanelStore(); const executionsStore = useExecutionsStore(); const projectsStore = useProjectsStore(); const logsStore = useLogsStore(); @@ -1608,6 +1610,8 @@ export function useCanvasOperations() { workflowsStore.currentWorkflowExecutions = []; workflowsStore.setActiveExecutionId(undefined); + focusPanelStore.reset(); + // Reset actions uiStore.resetLastInteractedWith(); uiStore.stateIsDirty = false; diff --git a/packages/frontend/editor-ui/src/stores/focusPanel.store.ts b/packages/frontend/editor-ui/src/stores/focusPanel.store.ts index d56934a441..30afd31f65 100644 --- a/packages/frontend/editor-ui/src/stores/focusPanel.store.ts +++ b/packages/frontend/editor-ui/src/stores/focusPanel.store.ts @@ -54,6 +54,11 @@ export const useFocusPanelStore = defineStore(STORES.FOCUS_PANEL, () => { focusPanelActive.value = !focusPanelActive.value; }; + const reset = () => { + focusPanelActive.value = false; + _focusedNodeParameters.value = []; + }; + function isRichParameter( p: RichFocusedNodeParameter | FocusedNodeParameter, ): p is RichFocusedNodeParameter { @@ -67,5 +72,6 @@ export const useFocusPanelStore = defineStore(STORES.FOCUS_PANEL, () => { isRichParameter, closeFocusPanel, toggleFocusPanel, + reset, }; }); diff --git a/packages/frontend/editor-ui/src/views/NodeView.vue b/packages/frontend/editor-ui/src/views/NodeView.vue index 3708695bc8..c0ed35d245 100644 --- a/packages/frontend/editor-ui/src/views/NodeView.vue +++ b/packages/frontend/editor-ui/src/views/NodeView.vue @@ -1209,6 +1209,10 @@ function onOpenNodeCreatorFromCanvas(source: NodeCreatorOpenSource) { function onToggleNodeCreator(options: ToggleNodeCreatorOptions) { nodeCreatorStore.setNodeCreatorState(options); + if (options.createNodeActive) { + focusPanelStore.closeFocusPanel(); + } + if (!options.createNodeActive && !options.hasAddedNodes) { uiStore.resetLastInteractedWith(); }