From b70cc944fc15f750efe77532e72d0d2ed7bd56d5 Mon Sep 17 00:00:00 2001 From: Michael Kret <88898367+michael-radency@users.noreply.github.com> Date: Wed, 25 Jun 2025 21:23:33 +0300 Subject: [PATCH] fix: Helper to set proper operation for sendAndWait action (#16701) --- .../Node/NodeCreator/Modes/NodesMode.vue | 7 +- .../components/Node/NodeCreator/utils.test.ts | 86 +++++++++++++++++++ .../src/components/Node/NodeCreator/utils.ts | 26 ++++++ 3 files changed, 114 insertions(+), 5 deletions(-) diff --git a/packages/frontend/editor-ui/src/components/Node/NodeCreator/Modes/NodesMode.vue b/packages/frontend/editor-ui/src/components/Node/NodeCreator/Modes/NodesMode.vue index f6eaa50030..61946eaf05 100644 --- a/packages/frontend/editor-ui/src/components/Node/NodeCreator/Modes/NodesMode.vue +++ b/packages/frontend/editor-ui/src/components/Node/NodeCreator/Modes/NodesMode.vue @@ -29,6 +29,7 @@ import { transformNodeType, getRootSearchCallouts, shouldShowCommunityNodeDetails, + getHumanInTheLoopActions, } from '../utils'; import { useViewStacks } from '../composables/useViewStacks'; import { useKeyboardNavigation } from '../composables/useKeyboardNavigation'; @@ -40,7 +41,7 @@ import { useI18n } from '@n8n/i18n'; import { getNodeIconSource } from '@/utils/nodeIcon'; import { useActions } from '../composables/useActions'; -import { SEND_AND_WAIT_OPERATION, type INodeParameters } from 'n8n-workflow'; +import { type INodeParameters } from 'n8n-workflow'; import { isCommunityPackageName } from '@/utils/nodeTypesUtils'; import { useNodeTypesStore } from '@/stores/nodeTypes.store'; @@ -102,10 +103,6 @@ function getFilteredActions( return nodeActions; } -function getHumanInTheLoopActions(nodeActions: ActionTypeDescription[]) { - return nodeActions.filter((action) => action.actionKey === SEND_AND_WAIT_OPERATION); -} - function onSelected(item: INodeCreateElement) { if (item.type === 'subcategory') { const subcategoryKey = camelCase(item.properties.title); diff --git a/packages/frontend/editor-ui/src/components/Node/NodeCreator/utils.test.ts b/packages/frontend/editor-ui/src/components/Node/NodeCreator/utils.test.ts index ce73fbad9f..f9d8d052b8 100644 --- a/packages/frontend/editor-ui/src/components/Node/NodeCreator/utils.test.ts +++ b/packages/frontend/editor-ui/src/components/Node/NodeCreator/utils.test.ts @@ -12,6 +12,7 @@ import { removeTrailingTrigger, sortNodeCreateElements, shouldShowCommunityNodeDetails, + getHumanInTheLoopActions, } from './utils'; import { mockActionCreateElement, @@ -23,6 +24,8 @@ import { createTestingPinia } from '@pinia/testing'; import { mock } from 'vitest-mock-extended'; import type { ViewStack } from './composables/useViewStacks'; +import { SEND_AND_WAIT_OPERATION } from 'n8n-workflow'; +import { DISCORD_NODE_TYPE, MICROSOFT_TEAMS_NODE_TYPE } from '../../../constants'; vi.mock('@/stores/settings.store', () => ({ useSettingsStore: vi.fn(() => ({ settings: {}, isAskAiEnabled: true })), @@ -379,4 +382,87 @@ describe('NodeCreator - utils', () => { expect(shouldShowCommunityNodeDetails(false, {})).toBe(false); }); }); + + describe('getHumanInTheLoopActions', () => { + it('should return an empty array if no actions are passed in', () => { + const actions: ActionTypeDescription[] = []; + expect(getHumanInTheLoopActions(actions)).toEqual([]); + }); + + it('should return an empty array if no actions have the SEND_AND_WAIT_OPERATION actionKey', () => { + const actions: ActionTypeDescription[] = [ + { + name: 'Test Action', + group: ['trigger'], + codex: { + label: 'Test Actions', + categories: ['Actions'], + }, + iconUrl: 'icons/n8n-nodes-preview-test/dist/nodes/Test/test.svg', + outputs: ['main'], + defaults: { + name: 'TestAction', + }, + actionKey: 'test', + description: 'Test action', + displayName: 'Test Action', + }, + ]; + expect(getHumanInTheLoopActions(actions)).toEqual([]); + }); + + it('should set the resource and operation for Discord actions', () => { + const actions: ActionTypeDescription[] = [ + { + name: DISCORD_NODE_TYPE, + group: ['trigger'], + codex: { + label: 'Discord Actions', + categories: ['Actions'], + }, + iconUrl: 'icons/n8n-nodes-preview-test/dist/nodes/Test/test.svg', + outputs: ['main'], + defaults: { + name: 'DiscordAction', + }, + actionKey: SEND_AND_WAIT_OPERATION, + description: 'Discord action', + displayName: 'Discord Action', + values: {}, + }, + ]; + const result = getHumanInTheLoopActions(actions); + expect(result[0].values).toEqual({ + resource: 'message', + operation: SEND_AND_WAIT_OPERATION, + }); + }); + + it('should set the resource and operation for Microsoft Teams actions', () => { + const actions: ActionTypeDescription[] = [ + { + name: MICROSOFT_TEAMS_NODE_TYPE, + group: ['trigger'], + codex: { + label: 'Microsoft Teams Actions', + categories: ['Actions'], + }, + iconUrl: 'icons/n8n-nodes-preview-test/dist/nodes/Test/test.svg', + outputs: ['main'], + defaults: { + name: 'MicrosoftTeamsAction', + }, + actionKey: SEND_AND_WAIT_OPERATION, + description: 'Microsoft Teams action', + displayName: 'Microsoft Teams Action', + values: {}, + }, + ]; + const result = getHumanInTheLoopActions(actions); + expect(result[0].values).toEqual({ + resource: 'chatMessage', + operation: SEND_AND_WAIT_OPERATION, + }); + }); + }); }); diff --git a/packages/frontend/editor-ui/src/components/Node/NodeCreator/utils.ts b/packages/frontend/editor-ui/src/components/Node/NodeCreator/utils.ts index 3b9c7c2b46..a362b12014 100644 --- a/packages/frontend/editor-ui/src/components/Node/NodeCreator/utils.ts +++ b/packages/frontend/editor-ui/src/components/Node/NodeCreator/utils.ts @@ -15,7 +15,9 @@ import { AI_TRANSFORM_NODE_TYPE, CORE_NODES_CATEGORY, DEFAULT_SUBCATEGORY, + DISCORD_NODE_TYPE, HUMAN_IN_THE_LOOP_CATEGORY, + MICROSOFT_TEAMS_NODE_TYPE, } from '@/constants'; import { v4 as uuidv4 } from 'uuid'; @@ -336,3 +338,27 @@ export const shouldShowCommunityNodeDetails = (communityNode: boolean, viewStack return communityNode && !viewStack.communityNodeDetails; }; + +export function getHumanInTheLoopActions(nodeActions: ActionTypeDescription[]) { + const actions = nodeActions.filter((action) => action.actionKey === SEND_AND_WAIT_OPERATION); + + if (actions.length) { + const name = actions[0].name; + if (name === DISCORD_NODE_TYPE) { + actions[0].values = { + ...actions[0].values, + resource: 'message', + operation: SEND_AND_WAIT_OPERATION, + }; + } + if (name === MICROSOFT_TEAMS_NODE_TYPE) { + actions[0].values = { + ...actions[0].values, + resource: 'chatMessage', + operation: SEND_AND_WAIT_OPERATION, + }; + } + } + + return actions; +}