mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 18:12:04 +00:00
feat(editor): Add support for Simulate nodes in new canvas (no-changelog) (#13675)
This commit is contained in:
@@ -56,7 +56,7 @@ export function createCanvasNodeData({
|
||||
|
||||
export function createCanvasNodeElement({
|
||||
id = '1',
|
||||
type = 'default',
|
||||
type = 'canvas-node',
|
||||
label = 'Node',
|
||||
position = { x: 100, y: 100 },
|
||||
data,
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
MANUAL_TRIGGER_NODE_TYPE,
|
||||
NO_OP_NODE_TYPE,
|
||||
SET_NODE_TYPE,
|
||||
SIMULATE_NODE_TYPE,
|
||||
STICKY_NODE_TYPE,
|
||||
} from '@/constants';
|
||||
import type { INodeUi, IWorkflowDb } from '@/Interface';
|
||||
@@ -50,6 +51,7 @@ export const mockNode = ({
|
||||
|
||||
export const mockNodeTypeDescription = ({
|
||||
name = SET_NODE_TYPE,
|
||||
icon = 'fa:pen',
|
||||
version = 1,
|
||||
credentials = [],
|
||||
inputs = [NodeConnectionTypes.Main],
|
||||
@@ -58,6 +60,7 @@ export const mockNodeTypeDescription = ({
|
||||
properties = [],
|
||||
}: {
|
||||
name?: INodeTypeDescription['name'];
|
||||
icon?: INodeTypeDescription['icon'];
|
||||
version?: INodeTypeDescription['version'];
|
||||
credentials?: INodeTypeDescription['credentials'];
|
||||
inputs?: INodeTypeDescription['inputs'];
|
||||
@@ -67,6 +70,7 @@ export const mockNodeTypeDescription = ({
|
||||
} = {}) =>
|
||||
mock<INodeTypeDescription>({
|
||||
name,
|
||||
icon,
|
||||
displayName: name,
|
||||
description: '',
|
||||
version,
|
||||
@@ -102,6 +106,7 @@ export const mockNodes = [
|
||||
mockNode({ name: 'Chat Trigger', type: CHAT_TRIGGER_NODE_TYPE }),
|
||||
mockNode({ name: 'Agent', type: AGENT_NODE_TYPE }),
|
||||
mockNode({ name: 'Sticky', type: STICKY_NODE_TYPE }),
|
||||
mockNode({ name: 'Simulate', type: SIMULATE_NODE_TYPE }),
|
||||
mockNode({ name: CanvasNodeRenderType.AddNodes, type: CanvasNodeRenderType.AddNodes }),
|
||||
mockNode({ name: 'End', type: NO_OP_NODE_TYPE }),
|
||||
];
|
||||
|
||||
@@ -8,6 +8,7 @@ import { createCanvasConnection, createCanvasNodeElement } from '@/__tests__/dat
|
||||
import { NodeConnectionTypes } from 'n8n-workflow';
|
||||
import type { useDeviceSupport } from '@n8n/composables/useDeviceSupport';
|
||||
import { useVueFlow } from '@vue-flow/core';
|
||||
import { SIMULATE_NODE_TYPE } from '@/constants';
|
||||
|
||||
const matchMedia = global.window.matchMedia;
|
||||
// @ts-expect-error Initialize window object
|
||||
@@ -273,4 +274,30 @@ describe('Canvas', () => {
|
||||
expect(patternCanvas?.innerHTML).not.toContain('<circle');
|
||||
});
|
||||
});
|
||||
|
||||
describe('simulate', () => {
|
||||
it('should render simulate node', async () => {
|
||||
const nodes = [
|
||||
createCanvasNodeElement({
|
||||
id: '1',
|
||||
label: 'Node',
|
||||
position: { x: 200, y: 200 },
|
||||
data: {
|
||||
type: SIMULATE_NODE_TYPE,
|
||||
typeVersion: 1,
|
||||
},
|
||||
}),
|
||||
];
|
||||
|
||||
const { container } = renderComponent({
|
||||
props: {
|
||||
nodes,
|
||||
},
|
||||
});
|
||||
|
||||
await waitFor(() => expect(container.querySelectorAll('.vue-flow__node')).toHaveLength(1));
|
||||
|
||||
expect(container.querySelector('.icon')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
<script lang="ts" setup>
|
||||
import ContextMenu from '@/components/ContextMenu/ContextMenu.vue';
|
||||
import {
|
||||
type CanvasLayoutEvent,
|
||||
type CanvasLayoutSource,
|
||||
useCanvasLayout,
|
||||
} from '@/composables/useCanvasLayout';
|
||||
import type { CanvasLayoutEvent, CanvasLayoutSource } from '@/composables/useCanvasLayout';
|
||||
import { useCanvasLayout } from '@/composables/useCanvasLayout';
|
||||
import { useCanvasNodeHover } from '@/composables/useCanvasNodeHover';
|
||||
import { useCanvasTraversal } from '@/composables/useCanvasTraversal';
|
||||
import { type ContextMenuAction, useContextMenu } from '@/composables/useContextMenu';
|
||||
|
||||
@@ -44,7 +44,14 @@ import {
|
||||
WAIT_INDEFINITELY,
|
||||
} from 'n8n-workflow';
|
||||
import type { INodeUi } from '@/Interface';
|
||||
import { CUSTOM_API_CALL_KEY, FORM_NODE_TYPE, STICKY_NODE_TYPE, WAIT_NODE_TYPE } from '@/constants';
|
||||
import {
|
||||
CUSTOM_API_CALL_KEY,
|
||||
FORM_NODE_TYPE,
|
||||
SIMULATE_NODE_TYPE,
|
||||
SIMULATE_TRIGGER_NODE_TYPE,
|
||||
STICKY_NODE_TYPE,
|
||||
WAIT_NODE_TYPE,
|
||||
} from '@/constants';
|
||||
import { sanitizeHtml } from '@/utils/htmlUtils';
|
||||
import { MarkerType } from '@vue-flow/core';
|
||||
import { useNodeHelpers } from './useNodeHelpers';
|
||||
@@ -88,7 +95,12 @@ export function useCanvasMapping({
|
||||
|
||||
function createDefaultNodeRenderType(node: INodeUi): CanvasNodeDefaultRender {
|
||||
const nodeType = nodeTypeDescriptionByNodeId.value[node.id];
|
||||
const icon = getNodeIconSource(nodeType);
|
||||
const icon = getNodeIconSource(
|
||||
simulatedNodeTypeDescriptionByNodeId.value[node.id]
|
||||
? simulatedNodeTypeDescriptionByNodeId.value[node.id]
|
||||
: nodeType,
|
||||
);
|
||||
|
||||
return {
|
||||
type: CanvasNodeRenderType.Default,
|
||||
options: {
|
||||
@@ -514,6 +526,26 @@ export function useCanvasMapping({
|
||||
);
|
||||
});
|
||||
|
||||
const simulatedNodeTypeDescriptionByNodeId = computed(() => {
|
||||
return nodes.value.reduce<Record<string, INodeTypeDescription | null>>((acc, node) => {
|
||||
if ([SIMULATE_NODE_TYPE, SIMULATE_TRIGGER_NODE_TYPE].includes(node.type)) {
|
||||
const icon = node.parameters?.icon as string;
|
||||
const iconValue = workflowObject.value.expression.getSimpleParameterValue(
|
||||
node,
|
||||
icon,
|
||||
'internal',
|
||||
{},
|
||||
);
|
||||
|
||||
if (iconValue && typeof iconValue === 'string') {
|
||||
acc[node.id] = nodeTypesStore.getNodeType(iconValue);
|
||||
}
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
});
|
||||
|
||||
const mappedNodes = computed<CanvasNode[]>(() => [
|
||||
...nodes.value.map<CanvasNode>((node) => {
|
||||
const inputConnections = workflowObject.value.connectionsByDestinationNode[node.name] ?? {};
|
||||
|
||||
Reference in New Issue
Block a user