feat(editor): Add ‘execute workflow’ buttons below triggers on the canvas (#12769)

Co-authored-by: Danny Martini <danny@n8n.io>
Co-authored-by: Mutasem Aldmour <mutasem@n8n.io>
This commit is contained in:
autologie
2025-02-10 09:14:39 +01:00
committed by GitHub
parent e92556260f
commit b17cbec3af
28 changed files with 957 additions and 168 deletions

View File

@@ -15,9 +15,10 @@ import type {
IRun,
INode,
IDataObject,
IWorkflowBase,
} from 'n8n-workflow';
import { NodeConnectionType } from 'n8n-workflow';
import { NodeConnectionType, TelemetryHelpers } from 'n8n-workflow';
import { useToast } from '@/composables/useToast';
import { useNodeHelpers } from '@/composables/useNodeHelpers';
@@ -35,6 +36,7 @@ import { isEmpty } from '@/utils/typesUtils';
import { useI18n } from '@/composables/useI18n';
import { get } from 'lodash-es';
import { useExecutionsStore } from '@/stores/executions.store';
import { useTelemetry } from './useTelemetry';
import { useSettingsStore } from '@/stores/settings.store';
import { usePushConnectionStore } from '@/stores/pushConnection.store';
@@ -62,6 +64,9 @@ export function useRunWorkflow(useRunWorkflowOpts: { router: ReturnType<typeof u
const workflowHelpers = useWorkflowHelpers({ router: useRunWorkflowOpts.router });
const i18n = useI18n();
const toast = useToast();
const telemetry = useTelemetry();
const externalHooks = useExternalHooks();
const settingsStore = useSettingsStore();
const rootStore = useRootStore();
const pushConnectionStore = usePushConnectionStore();
@@ -168,7 +173,7 @@ export function useRunWorkflow(useRunWorkflowOpts: { router: ReturnType<typeof u
executedNode = options.triggerNode;
}
if (options.triggerNode && options.nodeData) {
if (options.triggerNode) {
triggerToStartFrom = {
name: options.triggerNode,
data: options.nodeData,
@@ -307,6 +312,7 @@ export function useRunWorkflow(useRunWorkflowOpts: { router: ReturnType<typeof u
stoppedAt: undefined,
workflowId: workflow.id,
executedNode,
triggerNode: triggerToStartFrom?.name,
data: {
resultData: {
runData: startRunData.runData ?? {},
@@ -352,7 +358,7 @@ export function useRunWorkflow(useRunWorkflowOpts: { router: ReturnType<typeof u
});
} catch (error) {}
await useExternalHooks().run('workflowRun.runWorkflow', {
await externalHooks.run('workflowRun.runWorkflow', {
nodeName: options.destinationNode,
source: options.source,
});
@@ -467,8 +473,31 @@ export function useRunWorkflow(useRunWorkflowOpts: { router: ReturnType<typeof u
}
}
async function runEntireWorkflow(source: 'node' | 'main', triggerNode?: string) {
const workflow = workflowHelpers.getCurrentWorkflow();
void workflowHelpers.getWorkflowDataToSave().then((workflowData) => {
const telemetryPayload = {
workflow_id: workflow.id,
node_graph_string: JSON.stringify(
TelemetryHelpers.generateNodesGraph(
workflowData as IWorkflowBase,
workflowHelpers.getNodeTypes(),
{ isCloudDeployment: settingsStore.isCloudDeployment },
).nodeGraph,
),
button_type: source,
};
telemetry.track('User clicked execute workflow button', telemetryPayload);
void externalHooks.run('nodeView.onRunWorkflow', telemetryPayload);
});
void runWorkflow({ triggerNode });
}
return {
consolidateRunDataAndStartNodes,
runEntireWorkflow,
runWorkflow,
runWorkflowApi,
stopCurrentExecution,