diff --git a/packages/editor-ui/src/components/NodeDetailsView.vue b/packages/editor-ui/src/components/NodeDetailsView.vue index eed5f085a1340..ba640a1a298f7 100644 --- a/packages/editor-ui/src/components/NodeDetailsView.vue +++ b/packages/editor-ui/src/components/NodeDetailsView.vue @@ -61,7 +61,7 @@ /> import { ref, onMounted, onBeforeUnmount, computed, watch } from 'vue'; import { createEventBus } from 'n8n-design-system/utils'; -import type { IRunData, ConnectionTypes } from 'n8n-workflow'; +import type { IRunData, ConnectionTypes, Workflow } from 'n8n-workflow'; import { jsonParse, NodeHelpers, NodeConnectionType } from 'n8n-workflow'; import type { IUpdateInformation, TargetItem } from '@/Interface'; @@ -171,8 +171,6 @@ import { useNodeHelpers } from '@/composables/useNodeHelpers'; import { useMessage } from '@/composables/useMessage'; import { useExternalHooks } from '@/composables/useExternalHooks'; import { usePinnedData } from '@/composables/usePinnedData'; -import { useRouter } from 'vue-router'; -import { useWorkflowHelpers } from '@/composables/useWorkflowHelpers'; import { useTelemetry } from '@/composables/useTelemetry'; import { useI18n } from '@/composables/useI18n'; import { storeToRefs } from 'pinia'; @@ -188,6 +186,7 @@ const emit = defineEmits([ const props = withDefaults( defineProps<{ + workflowObject: Workflow; readOnly?: boolean; renaming?: boolean; isProductionExecutionPreview?: boolean; @@ -202,8 +201,6 @@ const externalHooks = useExternalHooks(); const nodeHelpers = useNodeHelpers(); const { activeNode } = storeToRefs(ndvStore); const pinnedData = usePinnedData(activeNode); -const router = useRouter(); -const workflowHelpers = useWorkflowHelpers({ router }); const workflowActivate = useWorkflowActivate(); const nodeTypesStore = useNodeTypesStore(); const uiStore = useUIStore(); @@ -266,12 +263,12 @@ const workflowRunData = computed(() => { return null; }); -const workflow = computed(() => workflowHelpers.getCurrentWorkflow()); - const parentNodes = computed(() => { if (activeNode.value) { return ( - workflow.value.getParentNodesByDepth(activeNode.value.name, 1).map(({ name }) => name) || [] + props.workflowObject + .getParentNodesByDepth(activeNode.value.name, 1) + .map(({ name }) => name) || [] ); } else { return []; @@ -374,13 +371,17 @@ const maxInputRun = computed(() => { return 0; } - const workflowNode = workflow.value.getNode(activeNode.value.name); + const workflowNode = props.workflowObject.getNode(activeNode.value.name); if (!workflowNode || !activeNodeType.value) { return 0; } - const outputs = NodeHelpers.getNodeOutputs(workflow.value, workflowNode, activeNodeType.value); + const outputs = NodeHelpers.getNodeOutputs( + props.workflowObject, + workflowNode, + activeNodeType.value, + ); let node = inputNode.value; @@ -729,11 +730,7 @@ watch( } void externalHooks.run('dataDisplay.nodeTypeChanged', { - nodeSubtitle: nodeHelpers.getNodeSubtitle( - node, - activeNodeType.value, - workflowHelpers.getCurrentWorkflow(), - ), + nodeSubtitle: nodeHelpers.getNodeSubtitle(node, activeNodeType.value, props.workflowObject), }); setTimeout(() => { diff --git a/packages/editor-ui/src/components/__tests__/NodeDetailsView.test.ts b/packages/editor-ui/src/components/__tests__/NodeDetailsView.test.ts index d6fb0fb61984a..8b735f2303b38 100644 --- a/packages/editor-ui/src/components/__tests__/NodeDetailsView.test.ts +++ b/packages/editor-ui/src/components/__tests__/NodeDetailsView.test.ts @@ -37,23 +37,9 @@ async function createPiniaWithActiveNode() { await useSettingsStore().getSettings(); await useUsersStore().loginWithCookie(); - return pinia; + return { pinia, currentWorkflow: workflowsStore.getCurrentWorkflow() }; } -const renderComponent = createComponentRenderer(NodeDetailsView, { - props: { - teleported: false, - appendToBody: false, - }, - global: { - mocks: { - $route: { - name: VIEWS.WORKFLOW, - }, - }, - }, -}); - describe('NodeDetailsView', () => { let server: ReturnType; @@ -70,8 +56,25 @@ describe('NodeDetailsView', () => { }); it('should render correctly', async () => { + const { pinia, currentWorkflow } = await createPiniaWithActiveNode(); + + const renderComponent = createComponentRenderer(NodeDetailsView, { + props: { + teleported: false, + appendToBody: false, + workflowObject: currentWorkflow, + }, + global: { + mocks: { + $route: { + name: VIEWS.WORKFLOW, + }, + }, + }, + }); + const wrapper = renderComponent({ - pinia: await createPiniaWithActiveNode(), + pinia, }); await waitFor(() => diff --git a/packages/editor-ui/src/stores/workflows.store.ts b/packages/editor-ui/src/stores/workflows.store.ts index b81526789cb09..20b3ded3373fc 100644 --- a/packages/editor-ui/src/stores/workflows.store.ts +++ b/packages/editor-ui/src/stores/workflows.store.ts @@ -337,6 +337,23 @@ export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, () => { }; } + function updateCachedWorkflow() { + const nodeTypes = getNodeTypes(); + const nodes = getNodes(); + const connections = allConnections.value; + + cachedWorkflow = new Workflow({ + id: workflowId.value, + name: workflowName.value, + nodes, + connections, + active: false, + nodeTypes, + settings: workflowSettings.value, + pinData: pinnedWorkflowData.value, + }); + } + function getWorkflow(nodes: INodeUi[], connections: IConnections, copyData?: boolean): Workflow { const nodeTypes = getNodeTypes(); let cachedWorkflowId: string | undefined = workflowId.value; @@ -362,7 +379,7 @@ export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, () => { function getCurrentWorkflow(copyData?: boolean): Workflow { const nodes = getNodes(); const connections = allConnections.value; - const cacheKey = JSON.stringify({ nodes, connections, pinData: pinnedWorkflowData.value }); + const cacheKey = JSON.stringify({ nodes, connections }); if (!copyData && cachedWorkflow && cacheKey === cachedWorkflowKey) { return cachedWorkflow; } @@ -641,6 +658,7 @@ export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, () => { ...workflow.value, pinData: pinData || {}, }; + updateCachedWorkflow(); dataPinningEventBus.emit('pin-data', pinData || {}); } @@ -711,6 +729,7 @@ export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, () => { }; uiStore.stateIsDirty = true; + updateCachedWorkflow(); dataPinningEventBus.emit('pin-data', { [payload.node.name]: storedPinData }); } @@ -727,6 +746,7 @@ export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, () => { }; uiStore.stateIsDirty = true; + updateCachedWorkflow(); dataPinningEventBus.emit('unpin-data', { [payload.node.name]: undefined }); } diff --git a/packages/editor-ui/src/views/NodeView.v2.vue b/packages/editor-ui/src/views/NodeView.v2.vue index a044828451279..a620f6a97de43 100644 --- a/packages/editor-ui/src/views/NodeView.v2.vue +++ b/packages/editor-ui/src/views/NodeView.v2.vue @@ -709,6 +709,7 @@ onBeforeUnmount(() => {