From 38fefff3488e1fb2ad65f9c4f20c6c55cc0c2388 Mon Sep 17 00:00:00 2001 From: Ricardo Espinoza Date: Fri, 8 Nov 2024 08:11:36 -0500 Subject: [PATCH] refactor(editor): Migrate `ndv.store` to composition API (#11574) --- packages/editor-ui/src/Interface.ts | 41 ++ .../InlineExpressionTip.test.ts | 15 +- .../InlineExpressionTip.vue | 2 +- .../src/components/NDVDraggablePanels.vue | 18 +- .../src/components/NodeExecuteButton.vue | 2 +- .../editor-ui/src/components/OutputPanel.vue | 2 +- .../src/components/ParameterInput.test.ts | 3 +- .../src/components/ParameterInput.vue | 2 +- packages/editor-ui/src/components/RunData.vue | 8 +- packages/editor-ui/src/stores/ndv.store.ts | 680 ++++++++++-------- 10 files changed, 458 insertions(+), 315 deletions(-) diff --git a/packages/editor-ui/src/Interface.ts b/packages/editor-ui/src/Interface.ts index b4e8f7cc4b..11c30c67c3 100644 --- a/packages/editor-ui/src/Interface.ts +++ b/packages/editor-ui/src/Interface.ts @@ -1585,3 +1585,44 @@ export type ApiKey = { createdAt: string; updatedAt: string; }; + +export type InputPanel = { + displayMode: IRunDataDisplayMode; + nodeName?: string; + run?: number; + branch?: number; + data: { + isEmpty: boolean; + }; +}; + +export type OutputPanel = { + branch?: number; + displayMode: IRunDataDisplayMode; + data: { + isEmpty: boolean; + }; + editMode: { + enabled: boolean; + value: string; + }; +}; + +export type Draggable = { + isDragging: boolean; + type: string; + data: string; + dimensions: DOMRect | null; + activeTarget: { id: string; stickyPosition: null | XYPosition } | null; +}; + +export type MainPanelType = 'regular' | 'dragless' | 'inputless' | 'unknown' | 'wide'; + +export type MainPanelDimensions = Record< + MainPanelType, + { + relativeLeft: number; + relativeRight: number; + relativeWidth: number; + } +>; diff --git a/packages/editor-ui/src/components/InlineExpressionEditor/InlineExpressionTip.test.ts b/packages/editor-ui/src/components/InlineExpressionEditor/InlineExpressionTip.test.ts index 604152c29d..5242a53290 100644 --- a/packages/editor-ui/src/components/InlineExpressionEditor/InlineExpressionTip.test.ts +++ b/packages/editor-ui/src/components/InlineExpressionEditor/InlineExpressionTip.test.ts @@ -26,7 +26,8 @@ describe('InlineExpressionTip.vue', () => { beforeEach(() => { mockNdvState = { hasInputData: true, - isNDVDataEmpty: vi.fn(() => true), + isInputPanelEmpty: true, + isOutputPanelEmpty: true, setHighlightDraggables: vi.fn(), }; }); @@ -42,7 +43,8 @@ describe('InlineExpressionTip.vue', () => { test('should show the drag-n-drop tip', async () => { mockNdvState = { hasInputData: true, - isNDVDataEmpty: vi.fn(() => false), + isInputPanelEmpty: false, + isOutputPanelEmpty: false, focusedMappableInput: 'Some Input', setHighlightDraggables: vi.fn(), }; @@ -62,7 +64,8 @@ describe('InlineExpressionTip.vue', () => { mockNdvState = { hasInputData: false, isInputParentOfActiveNode: true, - isNDVDataEmpty: vi.fn(() => false), + isInputPanelEmpty: false, + isOutputPanelEmpty: false, focusedMappableInput: 'Some Input', setHighlightDraggables: vi.fn(), }; @@ -77,7 +80,8 @@ describe('InlineExpressionTip.vue', () => { test('should show the correct tip for objects', async () => { mockNdvState = { hasInputData: true, - isNDVDataEmpty: vi.fn(() => false), + isInputPanelEmpty: false, + isOutputPanelEmpty: false, focusedMappableInput: 'Some Input', setHighlightDraggables: vi.fn(), }; @@ -106,7 +110,8 @@ describe('InlineExpressionTip.vue', () => { test('should show the correct tip for primitives', async () => { mockNdvState = { hasInputData: true, - isNDVDataEmpty: vi.fn(() => false), + isInputPanelEmpty: false, + isOutputPanelEmpty: false, focusedMappableInput: 'Some Input', setHighlightDraggables: vi.fn(), }; diff --git a/packages/editor-ui/src/components/InlineExpressionEditor/InlineExpressionTip.vue b/packages/editor-ui/src/components/InlineExpressionEditor/InlineExpressionTip.vue index 19258d2df9..9abd13dda6 100644 --- a/packages/editor-ui/src/components/InlineExpressionEditor/InlineExpressionTip.vue +++ b/packages/editor-ui/src/components/InlineExpressionEditor/InlineExpressionTip.vue @@ -30,7 +30,7 @@ const canAddDotToExpression = ref(false); const resolvedExpressionHasFields = ref(false); const canDragToFocusedInput = computed( - () => !ndvStore.isNDVDataEmpty('input') && ndvStore.focusedMappableInput, + () => !ndvStore.isInputPanelEmpty && ndvStore.focusedMappableInput, ); const emptyExpression = computed(() => props.unresolvedExpression.trim().length === 0); diff --git a/packages/editor-ui/src/components/NDVDraggablePanels.vue b/packages/editor-ui/src/components/NDVDraggablePanels.vue index 537c0dceac..6ece740eb4 100644 --- a/packages/editor-ui/src/components/NDVDraggablePanels.vue +++ b/packages/editor-ui/src/components/NDVDraggablePanels.vue @@ -9,7 +9,7 @@ import { useNDVStore } from '@/stores/ndv.store'; import { ndvEventBus } from '@/event-bus'; import NDVFloatingNodes from '@/components/NDVFloatingNodes.vue'; import { useDebounce } from '@/composables/useDebounce'; -import type { XYPosition } from '@/Interface'; +import type { MainPanelType, XYPosition } from '@/Interface'; import { ref, onMounted, onBeforeUnmount, computed, watch } from 'vue'; import { useUIStore } from '@/stores/ui.store'; @@ -20,7 +20,7 @@ const PANEL_WIDTH = 350; const PANEL_WIDTH_LARGE = 420; const MIN_WINDOW_WIDTH = 2 * (SIDE_MARGIN + SIDE_PANELS_MARGIN) + MIN_PANEL_WIDTH; -const initialMainPanelWidth: { [key: string]: number } = { +const initialMainPanelWidth: Record = { regular: MAIN_NODE_PANEL_WIDTH, dragless: MAIN_NODE_PANEL_WIDTH, unknown: MAIN_NODE_PANEL_WIDTH, @@ -106,22 +106,16 @@ watch(containerWidth, (width) => { setPositions(mainPanelDimensions.value.relativeLeft); }); -const currentNodePaneType = computed((): string => { +const currentNodePaneType = computed((): MainPanelType => { if (!hasInputSlot.value) return 'inputless'; if (!props.isDraggable) return 'dragless'; if (props.nodeType === null) return 'unknown'; return props.nodeType.parameterPane ?? 'regular'; }); -const mainPanelDimensions = computed( - (): { - relativeWidth: number; - relativeLeft: number; - relativeRight: number; - } => { - return ndvStore.getMainPanelDimensions(currentNodePaneType.value); - }, -); +const mainPanelDimensions = computed(() => { + return ndvStore.mainPanelDimensions[currentNodePaneType.value]; +}); const calculatedPositions = computed( (): { inputPanelRelativeRight: number; outputPanelRelativeLeft: number } => { diff --git a/packages/editor-ui/src/components/NodeExecuteButton.vue b/packages/editor-ui/src/components/NodeExecuteButton.vue index e130f400ea..43b4dfa7dc 100644 --- a/packages/editor-ui/src/components/NodeExecuteButton.vue +++ b/packages/editor-ui/src/components/NodeExecuteButton.vue @@ -316,7 +316,7 @@ async function onClick() { codeGenerationInProgress.value = false; } - if (isChatNode.value || (isChatChild.value && ndvStore.isNDVDataEmpty('input'))) { + if (isChatNode.value || (isChatChild.value && ndvStore.isInputPanelEmpty)) { ndvStore.setActiveNodeName(null); nodeViewEventBus.emit('openChat'); } else if (isListeningForEvents.value) { diff --git a/packages/editor-ui/src/components/OutputPanel.vue b/packages/editor-ui/src/components/OutputPanel.vue index 10d87eb810..0503ad5c94 100644 --- a/packages/editor-ui/src/components/OutputPanel.vue +++ b/packages/editor-ui/src/components/OutputPanel.vue @@ -78,7 +78,7 @@ const { isSubNodeType } = useNodeType({ }); const pinnedData = usePinnedData(activeNode, { runIndex: props.runIndex, - displayMode: ndvStore.getPanelDisplayMode('output'), + displayMode: ndvStore.outputPanelDisplayMode, }); // Data diff --git a/packages/editor-ui/src/components/ParameterInput.test.ts b/packages/editor-ui/src/components/ParameterInput.test.ts index 05637e3903..121c17c0d0 100644 --- a/packages/editor-ui/src/components/ParameterInput.test.ts +++ b/packages/editor-ui/src/components/ParameterInput.test.ts @@ -54,7 +54,8 @@ describe('ParameterInput.vue', () => { type: 'test', typeVersion: 1, }, - isNDVDataEmpty: vi.fn(() => false), + isInputPanelEmpty: false, + isOutputPanelEmpty: false, }; mockNodeTypesState = { allNodeTypes: [], diff --git a/packages/editor-ui/src/components/ParameterInput.vue b/packages/editor-ui/src/components/ParameterInput.vue index 8162e854a2..0339c561db 100644 --- a/packages/editor-ui/src/components/ParameterInput.vue +++ b/packages/editor-ui/src/components/ParameterInput.vue @@ -523,7 +523,7 @@ const isHtmlNode = computed(() => !!node.value && node.value.type === HTML_NODE_ const isInputTypeString = computed(() => props.parameter.type === 'string'); const isInputTypeNumber = computed(() => props.parameter.type === 'number'); -const isInputDataEmpty = computed(() => ndvStore.isNDVDataEmpty('input')); +const isInputDataEmpty = computed(() => ndvStore.isInputPanelEmpty); const isDropDisabled = computed( () => props.parameter.noDataExpression || diff --git a/packages/editor-ui/src/components/RunData.vue b/packages/editor-ui/src/components/RunData.vue index 351fdd8890..e1f74f215b 100644 --- a/packages/editor-ui/src/components/RunData.vue +++ b/packages/editor-ui/src/components/RunData.vue @@ -185,12 +185,17 @@ const node = toRef(props, 'node'); const pinnedData = usePinnedData(node, { runIndex: props.runIndex, - displayMode: ndvStore.getPanelDisplayMode(props.paneType), + displayMode: + props.paneType === 'input' ? ndvStore.inputPanelDisplayMode : ndvStore.outputPanelDisplayMode, }); const { isSubNodeType } = useNodeType({ node, }); +const displayMode = computed(() => + props.paneType === 'input' ? ndvStore.inputPanelDisplayMode : ndvStore.outputPanelDisplayMode, +); + const isReadOnlyRoute = computed(() => route.meta.readOnlyCanvas === true); const isWaitNodeWaiting = computed( () => @@ -200,7 +205,6 @@ const isWaitNodeWaiting = computed( ); const { activeNode } = storeToRefs(ndvStore); -const displayMode = computed(() => ndvStore.getPanelDisplayMode(props.paneType)); const nodeType = computed(() => { if (!node.value) return null; diff --git a/packages/editor-ui/src/stores/ndv.store.ts b/packages/editor-ui/src/stores/ndv.store.ts index e3be5db5fe..137c8ac828 100644 --- a/packages/editor-ui/src/stores/ndv.store.ts +++ b/packages/editor-ui/src/stores/ndv.store.ts @@ -1,10 +1,13 @@ import type { - INodeUi, + Draggable, + InputPanel, IRunDataDisplayMode, + MainPanelDimensions, + MainPanelType, NDVState, NodePanelType, + OutputPanel, TargetItem, - XYPosition, } from '@/Interface'; import { useStorage } from '@/composables/useStorage'; import { @@ -13,316 +16,411 @@ import { LOCAL_STORAGE_TABLE_HOVER_IS_ONBOARDED, STORES, } from '@/constants'; -import type { INodeExecutionData, INodeIssues } from 'n8n-workflow'; +import type { INodeIssues } from 'n8n-workflow'; import { NodeConnectionType } from 'n8n-workflow'; import { defineStore } from 'pinia'; import { v4 as uuid } from 'uuid'; import { useWorkflowsStore } from './workflows.store'; +import { computed, ref } from 'vue'; -export const useNDVStore = defineStore(STORES.NDV, { - state: (): NDVState => ({ - activeNodeName: null, - mainPanelDimensions: {}, - pushRef: '', - input: { - displayMode: 'schema', - nodeName: undefined, - run: undefined, - branch: undefined, - data: { - isEmpty: true, - }, +const DEFAULT_MAIN_PANEL_DIMENSIONS = { + relativeLeft: 1, + relativeRight: 1, + relativeWidth: 1, +}; + +export const useNDVStore = defineStore(STORES.NDV, () => { + const localStorageMappingIsOnboarded = useStorage(LOCAL_STORAGE_MAPPING_IS_ONBOARDED); + const localStorageTableHoverIsOnboarded = useStorage(LOCAL_STORAGE_TABLE_HOVER_IS_ONBOARDED); + const localStorageAutoCompleteIsOnboarded = useStorage(LOCAL_STORAGE_AUTOCOMPLETE_IS_ONBOARDED); + + const activeNodeName = ref(null); + const mainPanelDimensions = ref({ + unknown: { ...DEFAULT_MAIN_PANEL_DIMENSIONS }, + regular: { ...DEFAULT_MAIN_PANEL_DIMENSIONS }, + dragless: { ...DEFAULT_MAIN_PANEL_DIMENSIONS }, + inputless: { ...DEFAULT_MAIN_PANEL_DIMENSIONS }, + wide: { ...DEFAULT_MAIN_PANEL_DIMENSIONS }, + }); + const pushRef = ref(''); + const input = ref({ + displayMode: 'schema', + nodeName: undefined, + run: undefined, + branch: undefined, + data: { + isEmpty: true, }, - output: { - displayMode: 'table', - branch: undefined, - data: { - isEmpty: true, - }, - editMode: { - enabled: false, - value: '', - }, + }); + const output = ref({ + displayMode: 'table', + branch: undefined, + data: { + isEmpty: true, }, - focusedMappableInput: '', - focusedInputPath: '', - mappingTelemetry: {}, - hoveringItem: null, - expressionOutputItemIndex: 0, - draggable: { + editMode: { + enabled: false, + value: '', + }, + }); + const focusedMappableInput = ref(''); + const focusedInputPath = ref(''); + const mappingTelemetry = ref>({}); + const hoveringItem = ref(null); + const expressionOutputItemIndex = ref(0); + const draggable = ref({ + isDragging: false, + type: '', + data: '', + dimensions: null, + activeTarget: null, + }); + const isMappingOnboarded = ref(localStorageMappingIsOnboarded.value === 'true'); + const isTableHoverOnboarded = ref(localStorageTableHoverIsOnboarded.value === 'true'); + + const isAutocompleteOnboarded = ref(localStorageAutoCompleteIsOnboarded.value === 'true'); + + const highlightDraggables = ref(false); + + const workflowsStore = useWorkflowsStore(); + + const activeNode = computed(() => { + return workflowsStore.getNodeByName(activeNodeName.value || ''); + }); + + const ndvInputData = computed(() => { + const executionData = workflowsStore.getWorkflowExecution; + const inputNodeName: string | undefined = input.value.nodeName; + const inputRunIndex: number = input.value.run ?? 0; + const inputBranchIndex: number = input.value.branch ?? 0; + + if ( + !executionData || + !inputNodeName || + inputRunIndex === undefined || + inputBranchIndex === undefined + ) { + return []; + } + + return ( + executionData.data?.resultData?.runData?.[inputNodeName]?.[inputRunIndex]?.data?.main?.[ + inputBranchIndex + ] ?? [] + ); + }); + + const ndvInputNodeName = computed(() => { + return input.value.nodeName; + }); + + const ndvInputDataWithPinnedData = computed(() => { + const data = ndvInputData.value; + return ndvInputNodeName.value + ? (workflowsStore.pinDataByNodeName(ndvInputNodeName.value) ?? data) + : data; + }); + + const hasInputData = computed(() => { + return ndvInputDataWithPinnedData.value.length > 0; + }); + + const inputPanelDisplayMode = computed(() => input.value.displayMode); + + const outputPanelDisplayMode = computed(() => output.value.displayMode); + + const isDraggableDragging = computed(() => draggable.value.isDragging); + + const draggableType = computed(() => draggable.value.type); + + const draggableData = computed(() => draggable.value.data); + + const canDraggableDrop = computed(() => draggable.value.activeTarget !== null); + + const outputPanelEditMode = computed(() => output.value.editMode); + + const draggableStickyPos = computed(() => draggable.value.activeTarget?.stickyPosition ?? null); + + const ndvNodeInputNumber = computed(() => { + const returnData: { [nodeName: string]: number[] } = {}; + const workflow = workflowsStore.getCurrentWorkflow(); + const activeNodeConections = ( + workflow.connectionsByDestinationNode[activeNode.value?.name || ''] ?? {} + ).main; + + if (!activeNodeConections || activeNodeConections.length < 2) return returnData; + + for (const [index, connection] of activeNodeConections.entries()) { + for (const node of connection) { + if (!returnData[node.node]) { + returnData[node.node] = []; + } + returnData[node.node].push(index + 1); + } + } + + return returnData; + }); + + const ndvInputRunIndex = computed(() => input.value.run); + + const ndvInputBranchIndex = computed(() => input.value.branch); + + const isInputPanelEmpty = computed(() => input.value.data.isEmpty); + + const isOutputPanelEmpty = computed(() => output.value.data.isEmpty); + + const isInputParentOfActiveNode = computed(() => { + const inputNodeName = ndvInputNodeName.value; + if (!activeNode.value || !inputNodeName) { + return false; + } + const workflow = workflowsStore.getCurrentWorkflow(); + const parentNodes = workflow.getParentNodes(activeNode.value.name, NodeConnectionType.Main, 1); + return parentNodes.includes(inputNodeName); + }); + + const getHoveringItem = computed(() => { + if (isInputParentOfActiveNode.value) { + return hoveringItem.value; + } + + return null; + }); + + const expressionTargetItem = computed(() => { + if (getHoveringItem.value) { + return getHoveringItem.value; + } + + if (expressionOutputItemIndex.value && ndvInputNodeName.value) { + return { + nodeName: ndvInputNodeName.value, + runIndex: ndvInputRunIndex.value ?? 0, + outputIndex: ndvInputBranchIndex.value ?? 0, + itemIndex: expressionOutputItemIndex.value, + }; + } + + return null; + }); + + const isNDVOpen = computed(() => activeNodeName.value !== null); + + const setActiveNodeName = (nodeName: string | null): void => { + activeNodeName.value = nodeName; + }; + + const setInputNodeName = (nodeName: string | undefined): void => { + input.value.nodeName = nodeName; + }; + + const setInputRunIndex = (run?: number): void => { + input.value.run = run; + }; + + const setMainPanelDimensions = (params: { + panelType: MainPanelType; + dimensions: { relativeLeft?: number; relativeRight?: number; relativeWidth?: number }; + }): void => { + mainPanelDimensions.value[params.panelType] = { + ...mainPanelDimensions.value[params.panelType], + ...params.dimensions, + }; + }; + + const setNDVPushRef = (): void => { + pushRef.value = `ndv-${uuid()}`; + }; + + const resetNDVPushRef = (): void => { + pushRef.value = ''; + }; + + const setPanelDisplayMode = (params: { + pane: NodePanelType; + mode: IRunDataDisplayMode; + }): void => { + if (params.pane === 'input') { + input.value.displayMode = params.mode; + } else { + output.value.displayMode = params.mode; + } + }; + + const setOutputPanelEditModeEnabled = (isEnabled: boolean): void => { + output.value.editMode.enabled = isEnabled; + }; + + const setOutputPanelEditModeValue = (payload: string): void => { + output.value.editMode.value = payload; + }; + + const setMappableNDVInputFocus = (paramName: string): void => { + focusedMappableInput.value = paramName; + }; + + const draggableStartDragging = ({ + type, + data, + dimensions, + }: { type: string; data: string; dimensions: DOMRect | null }): void => { + draggable.value = { + isDragging: true, + type, + data, + dimensions, + activeTarget: null, + }; + }; + + const draggableStopDragging = (): void => { + draggable.value = { isDragging: false, type: '', data: '', dimensions: null, activeTarget: null, - }, - isMappingOnboarded: useStorage(LOCAL_STORAGE_MAPPING_IS_ONBOARDED).value === 'true', - isTableHoverOnboarded: useStorage(LOCAL_STORAGE_TABLE_HOVER_IS_ONBOARDED).value === 'true', - isAutocompleteOnboarded: useStorage(LOCAL_STORAGE_AUTOCOMPLETE_IS_ONBOARDED).value === 'true', - highlightDraggables: false, - }), - getters: { - activeNode(): INodeUi | null { - const workflowsStore = useWorkflowsStore(); - return workflowsStore.getNodeByName(this.activeNodeName || ''); - }, - ndvInputData(): INodeExecutionData[] { - const workflowsStore = useWorkflowsStore(); - const executionData = workflowsStore.getWorkflowExecution; - const inputNodeName: string | undefined = this.input.nodeName; - const inputRunIndex: number = this.input.run ?? 0; - const inputBranchIndex: number = this.input.branch ?? 0; + }; + }; - if ( - !executionData || - !inputNodeName || - inputRunIndex === undefined || - inputBranchIndex === undefined - ) { - return []; - } + const setDraggableTarget = (target: NDVState['draggable']['activeTarget']): void => { + draggable.value.activeTarget = target; + }; - return ( - executionData.data?.resultData?.runData?.[inputNodeName]?.[inputRunIndex]?.data?.main?.[ - inputBranchIndex - ] ?? [] - ); - }, - ndvInputDataWithPinnedData(): INodeExecutionData[] { - const data = this.ndvInputData; - return this.ndvInputNodeName - ? (useWorkflowsStore().pinDataByNodeName(this.ndvInputNodeName) ?? data) - : data; - }, - hasInputData(): boolean { - return this.ndvInputDataWithPinnedData.length > 0; - }, - getPanelDisplayMode() { - return (panel: NodePanelType) => this[panel].displayMode; - }, - inputPanelDisplayMode(): IRunDataDisplayMode { - return this.input.displayMode; - }, - outputPanelDisplayMode(): IRunDataDisplayMode { - return this.output.displayMode; - }, - isDraggableDragging(): boolean { - return this.draggable.isDragging; - }, - draggableType(): string { - return this.draggable.type; - }, - draggableData(): string { - return this.draggable.data; - }, - canDraggableDrop(): boolean { - return this.draggable.activeTarget !== null; - }, - outputPanelEditMode(): NDVState['output']['editMode'] { - return this.output.editMode; - }, - getMainPanelDimensions() { - return (panelType: string) => { - const defaults = { relativeRight: 1, relativeLeft: 1, relativeWidth: 1 }; - return { ...defaults, ...this.mainPanelDimensions[panelType] }; - }; - }, - draggableStickyPos(): XYPosition | null { - return this.draggable.activeTarget?.stickyPosition ?? null; - }, - ndvInputNodeName(): string | undefined { - return this.input.nodeName; - }, - ndvInputRunIndex(): number | undefined { - return this.input.run; - }, - ndvInputBranchIndex(): number | undefined { - return this.input.branch; - }, - isNDVDataEmpty() { - return (panel: 'input' | 'output'): boolean => this[panel].data.isEmpty; - }, - isInputParentOfActiveNode(): boolean { - const inputNodeName = this.ndvInputNodeName; - if (!this.activeNode || !inputNodeName) { - return false; - } - const workflow = useWorkflowsStore().getCurrentWorkflow(); - const parentNodes = workflow.getParentNodes(this.activeNode.name, NodeConnectionType.Main, 1); - return parentNodes.includes(inputNodeName); - }, - getHoveringItem(): TargetItem | null { - if (this.isInputParentOfActiveNode) { - return this.hoveringItem; - } + const setMappingTelemetry = (telemetry: { [key: string]: string | number | boolean }): void => { + mappingTelemetry.value = { ...mappingTelemetry.value, ...telemetry }; + }; - return null; - }, - expressionTargetItem(): TargetItem | null { - if (this.getHoveringItem) { - return this.getHoveringItem; - } + const resetMappingTelemetry = (): void => { + mappingTelemetry.value = {}; + }; - if (this.expressionOutputItemIndex && this.ndvInputNodeName) { - return { - nodeName: this.ndvInputNodeName, - runIndex: this.ndvInputRunIndex ?? 0, - outputIndex: this.ndvInputBranchIndex ?? 0, - itemIndex: this.expressionOutputItemIndex, - }; - } + const setHoveringItem = (item: TargetItem | null): void => { + if (item) setTableHoverOnboarded(); + hoveringItem.value = item; + }; - return null; - }, - isNDVOpen(): boolean { - return this.activeNodeName !== null; - }, - ndvNodeInputNumber() { - const returnData: { [nodeName: string]: number[] } = {}; - const workflow = useWorkflowsStore().getCurrentWorkflow(); - const activeNodeConections = ( - workflow.connectionsByDestinationNode[this.activeNode?.name || ''] ?? {} - ).main; + const setNDVBranchIndex = (e: { pane: NodePanelType; branchIndex: number }): void => { + if (e.pane === 'input') { + input.value.branch = e.branchIndex; + } else { + output.value.branch = e.branchIndex; + } + }; - if (!activeNodeConections || activeNodeConections.length < 2) return returnData; + const setNDVPanelDataIsEmpty = (params: { + panel: NodePanelType; + isEmpty: boolean; + }): void => { + if (params.panel === 'input') { + input.value.data.isEmpty = params.isEmpty; + } else { + output.value.data.isEmpty = params.isEmpty; + } + }; - for (const [index, connection] of activeNodeConections.entries()) { - for (const node of connection) { - if (!returnData[node.node]) { - returnData[node.node] = []; - } - returnData[node.node].push(index + 1); - } - } + const setMappingOnboarded = () => { + isMappingOnboarded.value = true; + localStorageMappingIsOnboarded.value = 'true'; + }; - return returnData; - }, - }, - actions: { - setActiveNodeName(nodeName: string | null): void { - this.activeNodeName = nodeName; - }, - setInputNodeName(nodeName: string | undefined): void { - this.input = { - ...this.input, - nodeName, - }; - }, - setInputRunIndex(run?: number): void { - this.input = { - ...this.input, - run, - }; - }, - setMainPanelDimensions(params: { - panelType: string; - dimensions: { relativeLeft?: number; relativeRight?: number; relativeWidth?: number }; - }): void { - this.mainPanelDimensions = { - ...this.mainPanelDimensions, - [params.panelType]: { - ...this.mainPanelDimensions[params.panelType], - ...params.dimensions, + const setTableHoverOnboarded = () => { + isTableHoverOnboarded.value = true; + localStorageTableHoverIsOnboarded.value = 'true'; + }; + + const setAutocompleteOnboarded = () => { + isAutocompleteOnboarded.value = true; + localStorageAutoCompleteIsOnboarded.value = 'true'; + }; + + const setHighlightDraggables = (highlight: boolean) => { + highlightDraggables.value = highlight; + }; + + const updateNodeParameterIssues = (issues: INodeIssues): void => { + const activeNode = workflowsStore.getNodeByName(activeNodeName.value || ''); + + if (activeNode) { + const nodeIndex = workflowsStore.workflow.nodes.findIndex((node) => { + return node.name === activeNode.name; + }); + + workflowsStore.updateNodeAtIndex(nodeIndex, { + issues: { + ...activeNode.issues, + ...issues, }, - }; - }, - setNDVPushRef(): void { - this.pushRef = `ndv-${uuid()}`; - }, - resetNDVPushRef(): void { - this.pushRef = ''; - }, - setPanelDisplayMode(params: { pane: NodePanelType; mode: IRunDataDisplayMode }): void { - this[params.pane].displayMode = params.mode; - }, - setOutputPanelEditModeEnabled(isEnabled: boolean): void { - this.output.editMode.enabled = isEnabled; - }, - setOutputPanelEditModeValue(payload: string): void { - this.output.editMode.value = payload; - }, - setMappableNDVInputFocus(paramName: string): void { - this.focusedMappableInput = paramName; - }, - draggableStartDragging({ - type, - data, - dimensions, - }: { - type: string; - data: string; - dimensions: DOMRect | null; - }): void { - this.draggable = { - isDragging: true, - type, - data, - dimensions, - activeTarget: null, - }; - }, - draggableStopDragging(): void { - this.draggable = { - isDragging: false, - type: '', - data: '', - dimensions: null, - activeTarget: null, - }; - }, - setDraggableTarget(target: NDVState['draggable']['activeTarget']): void { - this.draggable.activeTarget = target; - }, - setMappingTelemetry(telemetry: { [key: string]: string | number | boolean }): void { - this.mappingTelemetry = { ...this.mappingTelemetry, ...telemetry }; - }, - resetMappingTelemetry(): void { - this.mappingTelemetry = {}; - }, - setHoveringItem(item: null | NDVState['hoveringItem']): void { - if (item) this.setTableHoverOnboarded(); - this.hoveringItem = item; - }, - setNDVBranchIndex(e: { pane: 'input' | 'output'; branchIndex: number }): void { - this[e.pane].branch = e.branchIndex; - }, - setNDVPanelDataIsEmpty(payload: { panel: 'input' | 'output'; isEmpty: boolean }): void { - this[payload.panel].data.isEmpty = payload.isEmpty; - }, - setMappingOnboarded() { - this.isMappingOnboarded = true; - useStorage(LOCAL_STORAGE_MAPPING_IS_ONBOARDED).value = 'true'; - }, - setTableHoverOnboarded() { - this.isTableHoverOnboarded = true; - useStorage(LOCAL_STORAGE_TABLE_HOVER_IS_ONBOARDED).value = 'true'; - }, - setAutocompleteOnboarded() { - this.isAutocompleteOnboarded = true; - useStorage(LOCAL_STORAGE_AUTOCOMPLETE_IS_ONBOARDED).value = 'true'; - }, - setHighlightDraggables(highlight: boolean) { - this.highlightDraggables = highlight; - }, - updateNodeParameterIssues(issues: INodeIssues): void { - const workflowsStore = useWorkflowsStore(); - const activeNode = workflowsStore.getNodeByName(this.activeNodeName || ''); + }); + } + }; - if (activeNode) { - const nodeIndex = workflowsStore.workflow.nodes.findIndex((node) => { - return node.name === activeNode.name; - }); + const setFocusedInputPath = (path: string) => { + focusedInputPath.value = path; + }; - workflowsStore.updateNodeAtIndex(nodeIndex, { - issues: { - ...activeNode.issues, - ...issues, - }, - }); - } - }, - setFocusedInputPath(path: string) { - this.focusedInputPath = path; - }, - }, + return { + activeNode, + ndvInputData, + ndvInputNodeName, + ndvInputDataWithPinnedData, + hasInputData, + inputPanelDisplayMode, + outputPanelDisplayMode, + isDraggableDragging, + draggableType, + draggableData, + canDraggableDrop, + outputPanelEditMode, + draggableStickyPos, + ndvNodeInputNumber, + ndvInputRunIndex, + ndvInputBranchIndex, + isInputParentOfActiveNode, + getHoveringItem, + expressionTargetItem, + isNDVOpen, + isInputPanelEmpty, + isOutputPanelEmpty, + focusedMappableInput, + isMappingOnboarded, + pushRef, + activeNodeName, + focusedInputPath, + input, + output, + hoveringItem, + highlightDraggables, + mappingTelemetry, + draggable, + isAutocompleteOnboarded, + expressionOutputItemIndex, + isTableHoverOnboarded, + mainPanelDimensions, + setActiveNodeName, + setInputNodeName, + setInputRunIndex, + setMainPanelDimensions, + setNDVPushRef, + resetNDVPushRef, + setPanelDisplayMode, + setOutputPanelEditModeEnabled, + setOutputPanelEditModeValue, + setMappableNDVInputFocus, + draggableStartDragging, + draggableStopDragging, + setDraggableTarget, + setMappingTelemetry, + resetMappingTelemetry, + setHoveringItem, + setNDVBranchIndex, + setNDVPanelDataIsEmpty, + setMappingOnboarded, + setTableHoverOnboarded, + setAutocompleteOnboarded, + setHighlightDraggables, + updateNodeParameterIssues, + setFocusedInputPath, + }; });