diff --git a/packages/frontend/editor-ui/src/components/canvas/elements/nodes/render-types/CanvasNodeDefault.vue b/packages/frontend/editor-ui/src/components/canvas/elements/nodes/render-types/CanvasNodeDefault.vue
index 1011c87da9..9cc934ce2b 100644
--- a/packages/frontend/editor-ui/src/components/canvas/elements/nodes/render-types/CanvasNodeDefault.vue
+++ b/packages/frontend/editor-ui/src/components/canvas/elements/nodes/render-types/CanvasNodeDefault.vue
@@ -30,6 +30,7 @@ const {
hasPinnedData,
executionStatus,
executionWaiting,
+ executionWaitingForNext,
executionRunning,
hasRunData,
hasIssues,
@@ -61,7 +62,7 @@ const classes = computed(() => {
[$style.error]: hasIssues.value,
[$style.pinned]: hasPinnedData.value,
[$style.waiting]: executionWaiting.value ?? executionStatus.value === 'waiting',
- [$style.running]: executionRunning.value,
+ [$style.running]: executionRunning.value || executionWaitingForNext.value,
[$style.configurable]: renderOptions.value.configurable,
[$style.configuration]: renderOptions.value.configuration,
[$style.trigger]: renderOptions.value.trigger,
diff --git a/packages/frontend/editor-ui/src/components/canvas/elements/nodes/render-types/parts/CanvasNodeStatusIcons.vue b/packages/frontend/editor-ui/src/components/canvas/elements/nodes/render-types/parts/CanvasNodeStatusIcons.vue
index 0f45dab127..ecb1499906 100644
--- a/packages/frontend/editor-ui/src/components/canvas/elements/nodes/render-types/parts/CanvasNodeStatusIcons.vue
+++ b/packages/frontend/editor-ui/src/components/canvas/elements/nodes/render-types/parts/CanvasNodeStatusIcons.vue
@@ -16,6 +16,7 @@ const {
hasIssues,
executionStatus,
executionWaiting,
+ executionWaitingForNext,
executionRunning,
hasRunData,
runDataIterations,
@@ -59,7 +60,7 @@ const dirtiness = computed(() =>
diff --git a/packages/frontend/editor-ui/src/composables/useCanvasMapping.test.ts b/packages/frontend/editor-ui/src/composables/useCanvasMapping.test.ts
index 75ee5be9a9..72a08e8232 100644
--- a/packages/frontend/editor-ui/src/composables/useCanvasMapping.test.ts
+++ b/packages/frontend/editor-ui/src/composables/useCanvasMapping.test.ts
@@ -112,6 +112,7 @@ describe('useCanvasMapping', () => {
status: 'new',
running: false,
waiting: undefined,
+ waitingForNext: false,
},
issues: {
items: [],
@@ -1202,6 +1203,98 @@ describe('useCanvasMapping', () => {
});
});
+ describe('nodeExecutionWaitingForNextById', () => {
+ it('should be true when already executed node is waiting for next', () => {
+ const workflowsStore = mockedStore(useWorkflowsStore);
+ const node1 = createTestNode({
+ name: 'Node 1',
+ });
+ const node2 = createTestNode({
+ name: 'Node 2',
+ });
+ const nodes = [node1, node2];
+ const connections = {};
+
+ const workflowObject = createTestWorkflowObject({
+ nodes,
+ connections,
+ });
+
+ workflowsStore.executingNode = [];
+ workflowsStore.lastAddedExecutingNode = node1.name;
+ workflowsStore.isWorkflowRunning = true;
+
+ const { nodeExecutionWaitingForNextById } = useCanvasMapping({
+ nodes: ref(nodes),
+ connections: ref(connections),
+ workflowObject: ref(workflowObject) as Ref,
+ });
+
+ expect(nodeExecutionWaitingForNextById.value[node1.id]).toBe(true);
+ expect(nodeExecutionWaitingForNextById.value[node2.id]).toBe(false);
+ });
+
+ it('should be false when workflow is not executing', () => {
+ const workflowsStore = mockedStore(useWorkflowsStore);
+ const node1 = createTestNode({
+ name: 'Node 1',
+ });
+ const node2 = createTestNode({
+ name: 'Node 2',
+ });
+ const nodes = [node1, node2];
+ const connections = {};
+
+ const workflowObject = createTestWorkflowObject({
+ nodes,
+ connections,
+ });
+
+ workflowsStore.executingNode = [];
+ workflowsStore.lastAddedExecutingNode = node1.name;
+ workflowsStore.isWorkflowRunning = false;
+
+ const { nodeExecutionWaitingForNextById } = useCanvasMapping({
+ nodes: ref(nodes),
+ connections: ref(connections),
+ workflowObject: ref(workflowObject) as Ref,
+ });
+
+ expect(nodeExecutionWaitingForNextById.value[node1.id]).toBe(false);
+ expect(nodeExecutionWaitingForNextById.value[node2.id]).toBe(false);
+ });
+
+ it('should be false when there are nodes that are executing', () => {
+ const workflowsStore = mockedStore(useWorkflowsStore);
+ const node1 = createTestNode({
+ name: 'Node 1',
+ });
+ const node2 = createTestNode({
+ name: 'Node 2',
+ });
+ const nodes = [node1, node2];
+ const connections = {};
+
+ const workflowObject = createTestWorkflowObject({
+ nodes,
+ connections,
+ });
+
+ workflowsStore.executingNode = [node2.name];
+ workflowsStore.lastAddedExecutingNode = node1.name;
+ workflowsStore.isWorkflowRunning = false;
+
+ const { nodeExecutionWaitingForNextById } = useCanvasMapping({
+ nodes: ref(nodes),
+ connections: ref(connections),
+ workflowObject: ref(workflowObject) as Ref,
+ });
+
+ expect(nodeExecutionWaitingForNextById.value[node1.id]).toBe(false);
+ expect(nodeExecutionWaitingForNextById.value[node2.id]).toBe(false);
+ });
+ });
+
describe('connections', () => {
it('should map connections to canvas connections', () => {
const [manualTriggerNode, setNode] = mockNodes.slice(0, 2);
diff --git a/packages/frontend/editor-ui/src/composables/useCanvasMapping.ts b/packages/frontend/editor-ui/src/composables/useCanvasMapping.ts
index b7d98e8b92..24358bf063 100644
--- a/packages/frontend/editor-ui/src/composables/useCanvasMapping.ts
+++ b/packages/frontend/editor-ui/src/composables/useCanvasMapping.ts
@@ -327,6 +327,17 @@ export function useCanvasMapping({
}, {}),
);
+ const nodeExecutionWaitingForNextById = computed(() =>
+ nodes.value.reduce>((acc, node) => {
+ acc[node.id] =
+ node.name === workflowsStore.lastAddedExecutingNode &&
+ workflowsStore.executingNode.length === 0 &&
+ workflowsStore.isWorkflowRunning;
+
+ return acc;
+ }, {}),
+ );
+
const nodeExecutionStatusById = computed(() =>
nodes.value.reduce>((acc, node) => {
const tasks = workflowsStore.getWorkflowRunData?.[node.name] ?? [];
@@ -589,6 +600,7 @@ export function useCanvasMapping({
execution: {
status: nodeExecutionStatusById.value[node.id],
waiting: nodeExecutionWaitingById.value[node.id],
+ waitingForNext: nodeExecutionWaitingForNextById.value[node.id],
running: nodeExecutionRunningById.value[node.id],
},
runData: {
@@ -704,6 +716,7 @@ export function useCanvasMapping({
return {
additionalNodePropertiesById,
nodeExecutionRunDataOutputMapById,
+ nodeExecutionWaitingForNextById,
nodeIssuesById,
nodeHasIssuesById,
connections: mappedConnections,
diff --git a/packages/frontend/editor-ui/src/composables/useCanvasNode.ts b/packages/frontend/editor-ui/src/composables/useCanvasNode.ts
index d62279a8bb..f35aa578e8 100644
--- a/packages/frontend/editor-ui/src/composables/useCanvasNode.ts
+++ b/packages/frontend/editor-ui/src/composables/useCanvasNode.ts
@@ -52,6 +52,7 @@ export function useCanvasNode() {
const executionStatus = computed(() => data.value.execution.status);
const executionWaiting = computed(() => data.value.execution.waiting);
+ const executionWaitingForNext = computed(() => data.value.execution.waitingForNext);
const executionRunning = computed(() => data.value.execution.running);
const runDataOutputMap = computed(() => data.value.runData.outputMap);
@@ -83,6 +84,7 @@ export function useCanvasNode() {
hasIssues,
executionStatus,
executionWaiting,
+ executionWaitingForNext,
executionRunning,
render,
eventBus,
diff --git a/packages/frontend/editor-ui/src/composables/useExecutingNode.ts b/packages/frontend/editor-ui/src/composables/useExecutingNode.ts
index ed6bfa109a..641aebdac1 100644
--- a/packages/frontend/editor-ui/src/composables/useExecutingNode.ts
+++ b/packages/frontend/editor-ui/src/composables/useExecutingNode.ts
@@ -14,9 +14,11 @@ import { ref } from 'vue';
*/
export function useExecutingNode() {
const executingNode = ref([]);
+ const lastAddedExecutingNode = ref(null);
function addExecutingNode(nodeName: string) {
executingNode.value.push(nodeName);
+ lastAddedExecutingNode.value = nodeName;
}
function removeExecutingNode(nodeName: string) {
@@ -30,6 +32,7 @@ export function useExecutingNode() {
function clearNodeExecutionQueue() {
executingNode.value = [];
+ lastAddedExecutingNode.value = null;
}
function isNodeExecuting(nodeName: string): boolean {
@@ -38,6 +41,7 @@ export function useExecutingNode() {
return {
executingNode,
+ lastAddedExecutingNode,
addExecutingNode,
removeExecutingNode,
isNodeExecuting,
diff --git a/packages/frontend/editor-ui/src/composables/usePushConnection/handlers/nodeExecuteAfter.ts b/packages/frontend/editor-ui/src/composables/usePushConnection/handlers/nodeExecuteAfter.ts
index 32d116a179..39f575f8fb 100644
--- a/packages/frontend/editor-ui/src/composables/usePushConnection/handlers/nodeExecuteAfter.ts
+++ b/packages/frontend/editor-ui/src/composables/usePushConnection/handlers/nodeExecuteAfter.ts
@@ -27,12 +27,7 @@ export async function nodeExecuteAfter({ data: pushData }: NodeExecuteAfter) {
}
workflowsStore.updateNodeExecutionData(pushData);
-
- // Remove the node from the executing queue after a short delay
- // To allow the running spinner to show for at least 50ms
- setTimeout(() => {
- workflowsStore.removeExecutingNode(pushData.nodeName);
- }, 50);
+ workflowsStore.removeExecutingNode(pushData.nodeName);
void assistantStore.onNodeExecution(pushData);
void schemaPreviewStore.trackSchemaPreviewExecution(pushData);
diff --git a/packages/frontend/editor-ui/src/stores/workflows.store.ts b/packages/frontend/editor-ui/src/stores/workflows.store.ts
index b122fd1eb6..95dba1f305 100644
--- a/packages/frontend/editor-ui/src/stores/workflows.store.ts
+++ b/packages/frontend/editor-ui/src/stores/workflows.store.ts
@@ -163,6 +163,7 @@ export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, () => {
const {
executingNode,
+ lastAddedExecutingNode,
addExecutingNode,
removeExecutingNode,
isNodeExecuting,
@@ -1938,6 +1939,7 @@ export const useWorkflowsStore = defineStore(STORES.WORKFLOWS, () => {
subWorkflowExecutionError,
executionWaitingForWebhook,
executingNode,
+ lastAddedExecutingNode,
workflowsById,
nodeMetadata,
isInDebugMode,
diff --git a/packages/frontend/editor-ui/src/types/canvas.ts b/packages/frontend/editor-ui/src/types/canvas.ts
index c0d7665aea..66dbb91ad3 100644
--- a/packages/frontend/editor-ui/src/types/canvas.ts
+++ b/packages/frontend/editor-ui/src/types/canvas.ts
@@ -123,6 +123,7 @@ export interface CanvasNodeData {
status?: ExecutionStatus;
waiting?: string;
running: boolean;
+ waitingForNext?: boolean;
};
runData: {
outputMap: ExecutionOutputMap;