Display node-error only on executing nodes (#2274)

*  Dot not display errors on disconnected nodes

*  Fix some more inconsistencies
This commit is contained in:
Jan 2021-10-06 12:02:31 -05:00 committed by GitHub
parent 9dbf6e5f6d
commit f7148bdd77
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 70 additions and 10 deletions

View file

@ -582,7 +582,14 @@ export class WorkflowExecute {
const startedAt = new Date(); const startedAt = new Date();
const workflowIssues = workflow.checkReadyForExecution(); const startNode = this.runExecutionData.executionData!.nodeExecutionStack[0].node.name;
let destinationNode: string | undefined;
if (this.runExecutionData.startData && this.runExecutionData.startData.destinationNode) {
destinationNode = this.runExecutionData.startData.destinationNode;
}
const workflowIssues = workflow.checkReadyForExecution({ startNode, destinationNode });
if (workflowIssues !== null) { if (workflowIssues !== null) {
throw new Error( throw new Error(
'The workflow has issues and can for that reason not be executed. Please fix them first.', 'The workflow has issues and can for that reason not be executed. Please fix them first.',

View file

@ -1,6 +1,9 @@
import { import {
ERROR_TRIGGER_NODE_NAME,
PLACEHOLDER_FILLED_AT_EXECUTION_TIME, PLACEHOLDER_FILLED_AT_EXECUTION_TIME,
PLACEHOLDER_EMPTY_WORKFLOW_ID, PLACEHOLDER_EMPTY_WORKFLOW_ID,
START_NODE_TYPE,
WEBHOOK_NODE_NAME,
} from '@/constants'; } from '@/constants';
import { import {
@ -144,13 +147,39 @@ export const workflowHelpers = mixins(
}, },
// Checks if everything in the workflow is complete and ready to be executed // Checks if everything in the workflow is complete and ready to be executed
checkReadyForExecution (workflow: Workflow) { checkReadyForExecution (workflow: Workflow, lastNodeName?: string) {
let node: INode; let node: INode;
let nodeType: INodeType | undefined; let nodeType: INodeType | undefined;
let nodeIssues: INodeIssues | null = null; let nodeIssues: INodeIssues | null = null;
const workflowIssues: IWorfklowIssues = {}; const workflowIssues: IWorfklowIssues = {};
for (const nodeName of Object.keys(workflow.nodes)) { let checkNodes = Object.keys(workflow.nodes);
if (lastNodeName) {
checkNodes = workflow.getParentNodes(lastNodeName);
checkNodes.push(lastNodeName);
} else {
// As webhook nodes always take presidence check first
// if there are any
let checkWebhook: string[] = [];
for (const nodeName of Object.keys(workflow.nodes)) {
if (workflow.nodes[nodeName].disabled !== true && workflow.nodes[nodeName].type === WEBHOOK_NODE_NAME) {
checkWebhook = [nodeName, ...checkWebhook, ...workflow.getChildNodes(nodeName)];
}
}
if (checkWebhook.length) {
checkNodes = checkWebhook;
} else {
// If no webhook nodes got found try to find another trigger node
const startNode = workflow.getStartNode();
if (startNode !== undefined) {
checkNodes = workflow.getChildNodes(startNode.name);
checkNodes.push(startNode.name);
}
}
}
for (const nodeName of checkNodes) {
nodeIssues = null; nodeIssues = null;
node = workflow.nodes[nodeName]; node = workflow.nodes[nodeName];
@ -214,6 +243,10 @@ export const workflowHelpers = mixins(
return { return {
description: nodeTypeDescription, description: nodeTypeDescription,
// As we do not have the trigger/poll functions available in the frontend
// we use the information available to figure out what are trigger nodes
// @ts-ignore
trigger: ![ERROR_TRIGGER_NODE_NAME, START_NODE_TYPE].includes(nodeType) && nodeTypeDescription.inputs.length === 0 && !nodeTypeDescription.webhooks || undefined,
}; };
}, },
}; };
@ -498,7 +531,7 @@ export const workflowHelpers = mixins(
} as IUpdateInformation; } as IUpdateInformation;
this.$store.commit('setNodeValue', changes); this.$store.commit('setNodeValue', changes);
}); });
const createdTags = (workflowData.tags || []) as ITag[]; const createdTags = (workflowData.tags || []) as ITag[];
const tagIds = createdTags.map((tag: ITag): string => tag.id); const tagIds = createdTags.map((tag: ITag): string => tag.id);
this.$store.commit('setWorkflowTagIds', tagIds); this.$store.commit('setWorkflowTagIds', tagIds);

View file

@ -55,7 +55,7 @@ export const workflowRun = mixins(
return response; return response;
}, },
async runWorkflow (nodeName: string, source?: string): Promise<IExecutionPushResponse | undefined> { async runWorkflow (nodeName?: string, source?: string): Promise<IExecutionPushResponse | undefined> {
if (this.$store.getters.isActionActive('workflowRunning') === true) { if (this.$store.getters.isActionActive('workflowRunning') === true) {
return; return;
} }
@ -70,7 +70,7 @@ export const workflowRun = mixins(
const issuesExist = this.$store.getters.nodesIssuesExist; const issuesExist = this.$store.getters.nodesIssuesExist;
if (issuesExist === true) { if (issuesExist === true) {
// If issues exist get all of the issues of all nodes // If issues exist get all of the issues of all nodes
const workflowIssues = this.checkReadyForExecution(workflow); const workflowIssues = this.checkReadyForExecution(workflow, nodeName);
if (workflowIssues !== null) { if (workflowIssues !== null) {
const errorMessages = []; const errorMessages = [];
let nodeIssues: string[]; let nodeIssues: string[];
@ -94,7 +94,10 @@ export const workflowRun = mixins(
} }
// Get the direct parents of the node // Get the direct parents of the node
const directParentNodes = workflow.getParentNodes(nodeName, 'main', 1); let directParentNodes: string[] = [];
if (nodeName !== undefined) {
directParentNodes = workflow.getParentNodes(nodeName, 'main', 1);
}
const runData = this.$store.getters.getWorkflowRunData; const runData = this.$store.getters.getWorkflowRunData;
@ -133,7 +136,7 @@ export const workflowRun = mixins(
} }
} }
if (startNodes.length === 0) { if (startNodes.length === 0 && nodeName !== undefined) {
startNodes.push(nodeName); startNodes.push(nodeName);
} }

View file

@ -54,6 +54,7 @@ export const ALL_NODE_FILTER = 'All';
export const UNCATEGORIZED_CATEGORY = 'Miscellaneous'; export const UNCATEGORIZED_CATEGORY = 'Miscellaneous';
export const UNCATEGORIZED_SUBCATEGORY = 'Helpers'; export const UNCATEGORIZED_SUBCATEGORY = 'Helpers';
export const HIDDEN_NODES = ['n8n-nodes-base.start']; export const HIDDEN_NODES = ['n8n-nodes-base.start'];
export const ERROR_TRIGGER_NODE_NAME = 'n8n-nodes-base.errorTrigger';
export const WEBHOOK_NODE_NAME = 'n8n-nodes-base.webhook'; export const WEBHOOK_NODE_NAME = 'n8n-nodes-base.webhook';
export const HTTP_REQUEST_NODE_NAME = 'n8n-nodes-base.httpRequest'; export const HTTP_REQUEST_NODE_NAME = 'n8n-nodes-base.httpRequest';
export const REQUEST_NODE_FORM_URL = 'https://n8n-community.typeform.com/to/K1fBVTZ3'; export const REQUEST_NODE_FORM_URL = 'https://n8n-community.typeform.com/to/K1fBVTZ3';

View file

@ -231,13 +231,29 @@ export class Workflow {
* @returns {(IWorfklowIssues | null)} * @returns {(IWorfklowIssues | null)}
* @memberof Workflow * @memberof Workflow
*/ */
checkReadyForExecution(): IWorfklowIssues | null { checkReadyForExecution(inputData: {
startNode?: string;
destinationNode?: string;
}): IWorfklowIssues | null {
let node: INode; let node: INode;
let nodeType: INodeType | undefined; let nodeType: INodeType | undefined;
let nodeIssues: INodeIssues | null = null; let nodeIssues: INodeIssues | null = null;
const workflowIssues: IWorfklowIssues = {}; const workflowIssues: IWorfklowIssues = {};
for (const nodeName of Object.keys(this.nodes)) { let checkNodes: string[] = [];
if (inputData.destinationNode) {
// If a destination node is given we have to check all the nodes
// leading up to it
checkNodes = this.getParentNodes(inputData.destinationNode);
checkNodes.push(inputData.destinationNode);
} else if (inputData.startNode) {
// If a start node is given we have to check all nodes which
// come after it
checkNodes = this.getChildNodes(inputData.startNode);
checkNodes.push(inputData.startNode);
}
for (const nodeName of checkNodes) {
nodeIssues = null; nodeIssues = null;
node = this.nodes[nodeName]; node = this.nodes[nodeName];