fix(n8n Form Trigger Node): Do not rerun trigger when it has run data (#10687)

This commit is contained in:
Michael Kret
2024-09-05 20:09:38 +03:00
committed by GitHub
parent 37a808896e
commit 3adbcab27d
3 changed files with 228 additions and 57 deletions

View File

@@ -6,7 +6,6 @@ import type {
IWorkflowDb,
} from '@/Interface';
import type {
IDataObject,
IRunData,
IRunExecutionData,
ITaskData,
@@ -14,24 +13,20 @@ import type {
Workflow,
StartNodeData,
IRun,
INode,
} from 'n8n-workflow';
import { NodeConnectionType } from 'n8n-workflow';
import { useToast } from '@/composables/useToast';
import { useNodeHelpers } from '@/composables/useNodeHelpers';
import {
CHAT_TRIGGER_NODE_TYPE,
FORM_TRIGGER_NODE_TYPE,
WAIT_NODE_TYPE,
WORKFLOW_LM_CHAT_MODAL_KEY,
} from '@/constants';
import { CHAT_TRIGGER_NODE_TYPE, WORKFLOW_LM_CHAT_MODAL_KEY } from '@/constants';
import { useTitleChange } from '@/composables/useTitleChange';
import { useRootStore } from '@/stores/root.store';
import { useUIStore } from '@/stores/ui.store';
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
import { useWorkflowsStore } from '@/stores/workflows.store';
import { openPopUpWindow } from '@/utils/executionUtils';
import { displayForm } from '@/utils/executionUtils';
import { useExternalHooks } from '@/composables/useExternalHooks';
import { useWorkflowHelpers } from '@/composables/useWorkflowHelpers';
import type { useRouter } from 'vue-router';
@@ -261,58 +256,44 @@ export function useRunWorkflow(useRunWorkflowOpts: { router: ReturnType<typeof u
const runWorkflowApiResponse = await runWorkflowApi(startRunData);
const pinData = workflowData.pinData ?? {};
for (const node of workflowData.nodes) {
if (pinData[node.name]) continue;
if (![FORM_TRIGGER_NODE_TYPE, WAIT_NODE_TYPE].includes(node.type)) {
continue;
}
if (
options.destinationNode &&
options.destinationNode !== node.name &&
!directParentNodes.includes(node.name)
) {
continue;
}
if (node.name === options.destinationNode || !node.disabled) {
let testUrl = '';
if (node.type === FORM_TRIGGER_NODE_TYPE) {
const nodeType = nodeTypesStore.getNodeType(node.type, node.typeVersion);
if (nodeType?.webhooks?.length) {
testUrl = workflowHelpers.getWebhookUrl(nodeType.webhooks[0], node, 'test');
}
const getTestUrl = (() => {
return (node: INode) => {
const nodeType = nodeTypesStore.getNodeType(node.type, node.typeVersion);
if (nodeType?.webhooks?.length) {
return workflowHelpers.getWebhookUrl(nodeType.webhooks[0], node, 'test');
}
return '';
};
})();
if (
node.type === WAIT_NODE_TYPE &&
node.parameters.resume === 'form' &&
runWorkflowApiResponse.executionId
) {
const workflowTriggerNodes = workflow
.getTriggerNodes()
.map((triggerNode) => triggerNode.name);
const shouldShowForm = (() => {
return (node: INode) => {
const workflowTriggerNodes = workflow
.getTriggerNodes()
.map((triggerNode) => triggerNode.name);
const showForm =
options.destinationNode === node.name ||
directParentNodes.includes(node.name) ||
workflowTriggerNodes.some((triggerNode) =>
workflowsStore.isNodeInOutgoingNodeConnections(triggerNode, node.name),
);
const showForm =
options.destinationNode === node.name ||
directParentNodes.includes(node.name) ||
workflowTriggerNodes.some((triggerNode) =>
workflowsStore.isNodeInOutgoingNodeConnections(triggerNode, node.name),
);
return showForm;
};
})();
if (!showForm) continue;
const { webhookSuffix } = (node.parameters.options ?? {}) as IDataObject;
const suffix =
webhookSuffix && typeof webhookSuffix !== 'object' ? `/${webhookSuffix}` : '';
testUrl = `${rootStore.formWaitingUrl}/${runWorkflowApiResponse.executionId}${suffix}`;
}
if (testUrl && options.source !== 'RunData.ManualChatMessage') openPopUpWindow(testUrl);
}
}
displayForm({
nodes: workflowData.nodes,
runData: workflowsStore.getWorkflowExecution?.data?.resultData?.runData,
destinationNode: options.destinationNode,
pinData,
directParentNodes,
formWaitingUrl: rootStore.formWaitingUrl,
executionId: runWorkflowApiResponse.executionId,
source: options.source,
getTestUrl,
shouldShowForm,
});
await useExternalHooks().run('workflowRun.runWorkflow', {
nodeName: options.destinationNode,