Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

106 changes: 61 additions & 45 deletions packages/frontend/editor-ui/src/app/composables/useCanvasOperations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ import {
useWorkflowDocumentStore,
createWorkflowDocumentId,
pinDataToExecutionData,
convertToWorkflowAccessors,
} from '@/app/stores/workflowDocument.store';

type AddNodeData = Partial<INodeUi> & {
Expand Down Expand Up @@ -213,7 +214,12 @@ export function useCanvasOperations() {
const preventOpeningNDV = !!localStorage.getItem('NodeView.preventOpeningNDV');

const editableWorkflow = computed<IWorkflowDb>(() => workflowsStore.workflow);
const editableWorkflowObject = computed(() => workflowsStore.workflowObject as Workflow);

const editableWorkflowObject = computed(() =>
workflowDocumentStore.value
? convertToWorkflowAccessors(workflowDocumentStore.value)
: undefined,
);

const triggerNodes = computed<INodeUi[]>(() => {
return workflowsStore.workflowTriggerNodes;
Expand Down Expand Up @@ -546,17 +552,21 @@ export function useCanvasOperations() {
if (!previousNode || !newNode) {
return;
}
const workflowObject = workflowsStore.workflowObject;

const inputNodeNames = replaceInputs
? uniq(workflowObject.getParentNodes(previousNode.name, 'ALL', 1))
? uniq(workflowDocumentStore.value?.getParentNodes(previousNode.name, 'ALL', 1))
: [];
const outputNodeNames = replaceOutputs
? uniq(workflowObject.getChildNodes(previousNode.name, 'ALL', 1))
? uniq(workflowDocumentStore.value?.getChildNodes(previousNode.name, 'ALL', 1))
: [];
const connectionPairs = [
...workflowObject.getConnectionsBetweenNodes(inputNodeNames, [previousNode.name]),
...workflowObject.getConnectionsBetweenNodes([previousNode.name], outputNodeNames),
...(workflowDocumentStore.value?.getConnectionsBetweenNodes(inputNodeNames, [
previousNode.name,
]) ?? []),
...(workflowDocumentStore.value?.getConnectionsBetweenNodes(
[previousNode.name],
outputNodeNames,
) ?? []),
];

if (trackHistory && trackBulk) {
Expand Down Expand Up @@ -825,7 +835,7 @@ export function useCanvasOperations() {
}

function updatePositionForNodeWithMultipleInputs(node: INodeUi) {
const inputNodes = editableWorkflowObject.value.getParentNodesByDepth(node.name, 1);
const inputNodes = workflowDocumentStore.value?.getParentNodesByDepth(node.name, 1) ?? [];

if (inputNodes.length > 1) {
inputNodes.slice(1).forEach((inputNode, index) => {
Expand Down Expand Up @@ -1247,7 +1257,7 @@ export function useCanvasOperations() {
lastInteractedWithNode.type,
lastInteractedWithNode.typeVersion,
);
const lastInteractedWithNodeObject = editableWorkflowObject.value.getNode(
const lastInteractedWithNodeObject = workflowDocumentStore.value?.getNodeByName(
lastInteractedWithNode.name,
);

Expand Down Expand Up @@ -1322,11 +1332,14 @@ export function useCanvasOperations() {
}
}

const lastInteractedWithNodeInputs = NodeHelpers.getNodeInputs(
editableWorkflowObject.value,
lastInteractedWithNodeObject,
lastInteractedWithNodeTypeDescription,
);
const expression = workflowDocumentStore.value?.getExpressionHandler();
const lastInteractedWithNodeInputs = expression
? NodeHelpers.getNodeInputs(
{ expression },
lastInteractedWithNodeObject,
lastInteractedWithNodeTypeDescription,
)
: [];
const lastInteractedWithNodeInputTypes = NodeHelpers.getConnectionTypes(
lastInteractedWithNodeInputs,
);
Expand All @@ -1335,11 +1348,13 @@ export function useCanvasOperations() {
lastInteractedWithNodeInputTypes || []
).filter((input) => input !== NodeConnectionTypes.Main);

const lastInteractedWithNodeOutputs = NodeHelpers.getNodeOutputs(
editableWorkflowObject.value,
lastInteractedWithNodeObject,
lastInteractedWithNodeTypeDescription,
);
const lastInteractedWithNodeOutputs = expression
? NodeHelpers.getNodeOutputs(
{ expression },
lastInteractedWithNodeObject,
lastInteractedWithNodeTypeDescription,
)
: [];
const lastInteractedWithNodeOutputTypes = NodeHelpers.getConnectionTypes(
lastInteractedWithNodeOutputs,
);
Expand Down Expand Up @@ -1401,11 +1416,9 @@ export function useCanvasOperations() {
// outputs here is to calculate the position, it is fine to assume
// that they have no outputs and are so treated as a regular node
// with only "main" outputs.
outputs = NodeHelpers.getNodeOutputs(
editableWorkflowObject.value,
node as INode,
nodeTypeDescription,
);
outputs = expression
? NodeHelpers.getNodeOutputs({ expression }, node as INode, nodeTypeDescription)
: [];
} catch (e) {}
const outputTypes = NodeHelpers.getConnectionTypes(outputs);

Expand Down Expand Up @@ -1666,11 +1679,14 @@ export function useCanvasOperations() {
// Step 2: Add all downstream connected nodes from initial candidates
const candidateNames = new Set(initialCandidates.map((node) => node.name));
for (const candidate of initialCandidates) {
const downstream = workflowHelpers.getConnectedNodes(
'downstream',
editableWorkflowObject.value,
candidate.name,
);
const downstream = editableWorkflowObject.value
? workflowHelpers.getConnectedNodes(
'downstream',
editableWorkflowObject.value,
candidate.name,
)
: [];

downstream
// Filter the downstream nodes to find candidates that need to be shifted right.
.filter((name) => {
Expand Down Expand Up @@ -2182,19 +2198,20 @@ export function useCanvasOperations() {
}

const sourceNodeType = getNodeType(sourceNode);
const sourceWorkflowNode = editableWorkflowObject.value.getNode(sourceNode.name);
const sourceWorkflowNode = workflowDocumentStore.value?.getNodeByName(sourceNode.name);
if (!sourceWorkflowNode) {
return false;
}

let sourceNodeOutputs: Array<NodeConnectionType | INodeOutputConfiguration> = [];
if (sourceNodeType) {
sourceNodeOutputs =
NodeHelpers.getNodeOutputs(
editableWorkflowObject.value,
sourceWorkflowNode,
sourceNodeType,
) || [];
sourceNodeOutputs = workflowDocumentStore.value
? NodeHelpers.getNodeOutputs(
{ expression: workflowDocumentStore.value.getExpressionHandler() },
sourceWorkflowNode,
sourceNodeType,
) || []
: [];
}

const sourceOutputsOfType = filterConnectionsByType(sourceNodeOutputs, sourceConnection.type);
Expand All @@ -2215,19 +2232,20 @@ export function useCanvasOperations() {
}

const targetNodeType = getNodeType(targetNode);
const targetWorkflowNode = editableWorkflowObject.value.getNode(targetNode.name);
const targetWorkflowNode = workflowDocumentStore.value?.getNodeByName(targetNode.name);
if (!targetWorkflowNode) {
return false;
}

let targetNodeInputs: Array<NodeConnectionType | INodeInputConfiguration> = [];
if (targetNodeType) {
targetNodeInputs =
NodeHelpers.getNodeInputs(
editableWorkflowObject.value,
targetWorkflowNode,
targetNodeType,
) || [];
targetNodeInputs = workflowDocumentStore.value
? NodeHelpers.getNodeInputs(
{ expression: workflowDocumentStore.value.getExpressionHandler() },
targetWorkflowNode,
targetNodeType,
) || []
: [];
}

const targetInputsOfType = filterConnectionsByType(targetNodeInputs, targetConnection.type);
Expand Down Expand Up @@ -2974,12 +2992,10 @@ export function useCanvasOperations() {
return;
}

const workflowObject = workflowsStore.workflowObject; // @TODO Check if we actually need workflowObject here

logsStore.toggleOpen(true);

const payload = {
workflow_id: workflowObject.id,
workflow_id: workflowDocumentStore.value?.workflowId,
button_type: source,
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,6 @@ export function handleExecutionFinishedWithWaitTill(
const workflowsStore = useWorkflowsStore();
const settingsStore = useSettingsStore();
const workflowSaving = useWorkflowSaving(options);
const workflowObject = workflowsStore.workflowObject;

const workflowDocumentStore = workflowId
? useWorkflowDocumentStore(createWorkflowDocumentId(workflowId))
Expand All @@ -297,7 +296,7 @@ export function handleExecutionFinishedWithWaitTill(
}

// Workflow did start but had been put to wait
useDocumentTitle().setDocumentTitle(workflowObject.name as string, 'IDLE');
useDocumentTitle().setDocumentTitle(workflowDocumentStore?.name as string, 'IDLE');
}

/**
Expand All @@ -311,11 +310,13 @@ export function handleExecutionFinishedWithErrorOrCanceled(
const i18n = useI18n();
const telemetry = useTelemetry();
const workflowsStore = useWorkflowsStore();
const workflowDocumentStore = useWorkflowDocumentStore(
createWorkflowDocumentId(workflowsStore.workflowId),
);
const documentTitle = useDocumentTitle();
const workflowHelpers = useWorkflowHelpers();
const workflowObject = workflowsStore.workflowObject;

documentTitle.setDocumentTitle(workflowObject.name as string, 'ERROR');
documentTitle.setDocumentTitle(workflowDocumentStore.name as string, 'ERROR');

if (
runExecutionData.resultData.error?.name === 'ExpressionError' &&
Expand All @@ -342,7 +343,7 @@ export function handleExecutionFinishedWithErrorOrCanceled(
error.context.nodeCause &&
['paired_item_no_info', 'paired_item_invalid_info'].includes(error.context.type as string)
) {
const node = workflowObject.getNode(error.context.nodeCause as string);
const node = workflowDocumentStore.getNodeByName(error.context.nodeCause as string);

if (node) {
const workflowDocumentStore = workflowsStore.workflowId
Expand Down Expand Up @@ -412,12 +413,11 @@ export function handleExecutionFinishedWithSuccessOrOther(
const toast = useToast();
const i18n = useI18n();
const nodeTypesStore = useNodeTypesStore();
const workflowObject = workflowsStore.workflowObject;
const workflowName = workflowObject.name ?? '';

const workflowDocumentStore = workflowsStore.workflowId
? useWorkflowDocumentStore(createWorkflowDocumentId(workflowsStore.workflowId))
: undefined;
const workflowName = workflowDocumentStore?.name ?? '';

useDocumentTitle().setDocumentTitle(workflowName, 'IDLE');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import type {
ExtractableErrorResult,
IConnections,
INode,
Workflow,
} from 'n8n-workflow';
import { computed } from 'vue';
import { useToast } from './useToast';
Expand Down Expand Up @@ -52,8 +51,6 @@ export function useWorkflowExtraction() {
buildAdjacencyList(workflowDocumentStore?.value?.connectionsBySourceNode ?? {}),
);

const workflowObject = computed(() => workflowsStore.workflowObject as Workflow);

function showError(message: string) {
toast.showMessage({
type: 'error',
Expand Down Expand Up @@ -333,8 +330,10 @@ export function useWorkflowExtraction() {
if (!node) return true; // invariant broken -> abort onto error path
const nodeType = useNodeTypesStore().getNodeType(node.type, node.typeVersion);
if (!nodeType) return true; // invariant broken -> abort onto error path
const expression = workflowDocumentStore?.value?.getExpressionHandler();
if (!expression) return true;

const ios = getIOs(workflowObject.value, node, nodeType);
const ios = getIOs({ expression }, node, nodeType);
return (
ios.filter((x) => (typeof x === 'string' ? x === 'main' : x.type === 'main')).length <= 1
);
Expand Down Expand Up @@ -462,17 +461,17 @@ export function useWorkflowExtraction() {
while (subGraphNames.includes(returnNodeName)) returnNodeName += '_1';

const directAfterEndNodeNames = end
? workflowObject.value
.getChildNodes(end, 'main', 1)
.map((x) => workflowObject.value.getNode(x)?.name)
.filter((x) => x !== undefined)
? (workflowDocumentStore?.value
?.getChildNodes(end, 'main', 1)
.map((x) => workflowDocumentStore?.value?.getNodeByName(x)?.name)
.filter((x) => x !== undefined) ?? [])
: [];

const allAfterEndNodes = end
? workflowObject.value
.getChildNodes(end, 'ALL')
.map((x) => workflowObject.value.getNode(x))
.filter((x) => x !== null)
? (workflowDocumentStore?.value
?.getChildNodes(end, 'ALL')
.map((x) => workflowDocumentStore?.value?.getNodeByName(x) ?? null)
.filter((x) => x !== null) ?? [])
: [];

const { nodes, variables } = extractReferencesInNodeExpressions(
Expand Down
1 change: 1 addition & 0 deletions packages/frontend/editor-ui/src/app/types/workflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { Workflow } from 'n8n-workflow';
* Will be removed when workflowsStore.workflowObject migration is complete.
*/
export interface WorkflowObjectAccessors {
id: Workflow['id'];
connectionsBySourceNode: Workflow['connectionsByDestinationNode'];
expression: Workflow['expression'];
pinData?: Workflow['pinData'];
Expand Down
Loading
Loading