diff --git a/packages/frontend/editor-ui/src/components/canvas/elements/nodes/CanvasNode.test.ts b/packages/frontend/editor-ui/src/components/canvas/elements/nodes/CanvasNode.test.ts index 27dc75b087..ca8da8c9eb 100644 --- a/packages/frontend/editor-ui/src/components/canvas/elements/nodes/CanvasNode.test.ts +++ b/packages/frontend/editor-ui/src/components/canvas/elements/nodes/CanvasNode.test.ts @@ -111,8 +111,8 @@ describe('CanvasNode', () => { const inputHandles = getAllByTestId('canvas-node-input-handle'); expect(inputHandles[1]).toHaveStyle('left: 40px'); - expect(inputHandles[2]).toHaveStyle('left: 168px'); - expect(inputHandles[3]).toHaveStyle('left: 232px'); + expect(inputHandles[2]).toHaveStyle('left: 136px'); + expect(inputHandles[3]).toHaveStyle('left: 184px'); }); }); diff --git a/packages/frontend/editor-ui/src/components/canvas/elements/nodes/CanvasNode.vue b/packages/frontend/editor-ui/src/components/canvas/elements/nodes/CanvasNode.vue index fc28695c65..5ced448610 100644 --- a/packages/frontend/editor-ui/src/components/canvas/elements/nodes/CanvasNode.vue +++ b/packages/frontend/editor-ui/src/components/canvas/elements/nodes/CanvasNode.vue @@ -34,7 +34,7 @@ import type { EventBus } from '@n8n/utils/event-bus'; import { createEventBus } from '@n8n/utils/event-bus'; import isEqual from 'lodash/isEqual'; import CanvasNodeTrigger from '@/components/canvas/elements/nodes/render-types/parts/CanvasNodeTrigger.vue'; -import { CONFIGURATION_NODE_OFFSET, GRID_SIZE } from '@/utils/nodeViewUtils'; +import { CONFIGURATION_NODE_RADIUS, GRID_SIZE } from '@/utils/nodeViewUtils'; type Props = NodeProps & { readOnly?: boolean; @@ -187,7 +187,7 @@ const createEndpointMappingFn = connectingHandle.value?.handleId === handleId; const offsetValue = position === Position.Bottom - ? `${GRID_SIZE * 2 * (1 + index * 2) + CONFIGURATION_NODE_OFFSET}px` + ? `${CONFIGURATION_NODE_RADIUS + GRID_SIZE * (3 * index)}px` : isExperimentalNdvActive.value && endpoints.length === 1 ? `${(1 + index) * (GRID_SIZE * 1.5)}px` : `${(100 / (endpoints.length + 1)) * (index + 1)}%`; diff --git a/packages/frontend/editor-ui/src/components/canvas/elements/nodes/render-types/CanvasNodeDefault.test.ts b/packages/frontend/editor-ui/src/components/canvas/elements/nodes/render-types/CanvasNodeDefault.test.ts index 142114de0c..e7d21afe20 100644 --- a/packages/frontend/editor-ui/src/components/canvas/elements/nodes/render-types/CanvasNodeDefault.test.ts +++ b/packages/frontend/editor-ui/src/components/canvas/elements/nodes/render-types/CanvasNodeDefault.test.ts @@ -209,7 +209,7 @@ describe('CanvasNodeDefault', () => { [ '1 required', [{ type: NodeConnectionTypes.AiLanguageModel, index: 0, required: true }], - '272px', + '224px', ], [ '2 required, 1 optional', @@ -218,7 +218,7 @@ describe('CanvasNodeDefault', () => { { type: NodeConnectionTypes.AiDocument, index: 0, required: true }, { type: NodeConnectionTypes.AiMemory, index: 0, required: true }, ], - '272px', + '224px', ], [ '2 required, 2 optional', @@ -228,7 +228,7 @@ describe('CanvasNodeDefault', () => { { type: NodeConnectionTypes.AiDocument, index: 0, required: true }, { type: NodeConnectionTypes.AiMemory, index: 0, required: true }, ], - '272px', + '224px', ], [ '1 required, 4 optional', @@ -239,7 +239,7 @@ describe('CanvasNodeDefault', () => { { type: NodeConnectionTypes.AiMemory, index: 0 }, { type: NodeConnectionTypes.AiMemory, index: 0 }, ], - '336px', + '272px', ], ])( 'should adjust width css variable based on the number of non-main inputs (%s)', diff --git a/packages/frontend/editor-ui/src/components/canvas/elements/nodes/render-types/__snapshots__/CanvasNodeDefault.test.ts.snap b/packages/frontend/editor-ui/src/components/canvas/elements/nodes/render-types/__snapshots__/CanvasNodeDefault.test.ts.snap index 4476565ba6..3fb6d36b50 100644 --- a/packages/frontend/editor-ui/src/components/canvas/elements/nodes/render-types/__snapshots__/CanvasNodeDefault.test.ts.snap +++ b/packages/frontend/editor-ui/src/components/canvas/elements/nodes/render-types/__snapshots__/CanvasNodeDefault.test.ts.snap @@ -4,7 +4,7 @@ exports[`CanvasNodeDefault > configurable > should render configurable node corr
configuration > should render configurable configur
{ const nonMainInputCount = 5; const mainInputCount = 3; const mainOutputCount = 2; - // width = max(4, 5) * 2 * 16 * 2 = 5 * 2 * 16 * 2 + offset = 336 + // width = 80 + 0 + (max(4, 5) - 1) * 16 * 3 = 272 // height = DEFAULT_NODE_SIZE[1] + max(0, max(3,2,1) - 2) * 16 * 2 // maxVerticalHandles = 3 // height = 96 + (3 - 2) * 32 = 96 + 32 = 128 expect( calculateNodeSize(false, true, mainInputCount, mainOutputCount, nonMainInputCount), - ).toEqual({ width: 336, height: 128 }); + ).toEqual({ width: 272, height: 128 }); }); it('should return configurable configuration node size when both isConfigurable and isConfiguration are true', () => { const nonMainInputCount = 2; - // width = max(4, 2) * 2 * 16 * 2 = 4 * 2 * 16 * 2 + offset = 272 + // width = 80 + 16 + (max(4, 2) - 1) * 16 * 3 = 240 // height = CONFIGURATION_NODE_SIZE[1] = 16 * 5 = 80 expect(calculateNodeSize(true, true, 1, 1, nonMainInputCount)).toEqual({ - width: 272, + width: 240, height: 80, }); }); @@ -524,12 +524,12 @@ describe('calculateNodeSize', () => { it('should respect the minimum width for configurable nodes', () => { const nonMainInputCount = 2; // less than NODE_MIN_INPUT_ITEMS_COUNT - // width = 4 * 2 * 16 * 2 + offset = 272 + // width = 80 + 0 + (max(2, 4) - 1) * 16 * 3 = 224 // height = default path, mainInputCount = 1, mainOutputCount = 1 // maxVerticalHandles = 1 // height = 96 + (1 - 2) * 32 = 96 + 0 = 96 expect(calculateNodeSize(false, true, 1, 1, nonMainInputCount)).toEqual({ - width: 272, + width: 224, height: 96, }); }); diff --git a/packages/frontend/editor-ui/src/utils/nodeViewUtils.ts b/packages/frontend/editor-ui/src/utils/nodeViewUtils.ts index 8e2938c20d..068988a6c3 100644 --- a/packages/frontend/editor-ui/src/utils/nodeViewUtils.ts +++ b/packages/frontend/editor-ui/src/utils/nodeViewUtils.ts @@ -35,7 +35,11 @@ import { export const GRID_SIZE = 16; export const DEFAULT_NODE_SIZE: [number, number] = [GRID_SIZE * 6, GRID_SIZE * 6]; -export const CONFIGURATION_NODE_SIZE: [number, number] = [GRID_SIZE * 5, GRID_SIZE * 5]; +export const CONFIGURATION_NODE_RADIUS = (GRID_SIZE * 5) / 2; +export const CONFIGURATION_NODE_SIZE: [number, number] = [ + CONFIGURATION_NODE_RADIUS * 2, + CONFIGURATION_NODE_RADIUS * 2, +]; // the node has circle shape export const CONFIGURABLE_NODE_SIZE: [number, number] = [GRID_SIZE * 16, GRID_SIZE * 6]; export const DEFAULT_START_POSITION_X = GRID_SIZE * 11; export const DEFAULT_START_POSITION_Y = GRID_SIZE * 15; @@ -48,10 +52,6 @@ export const DEFAULT_VIEWPORT_BOUNDARIES: ViewportBoundaries = { yMax: Infinity, }; -// The top-center of the configuration node is not a multiple of GRID_SIZE, -// therefore we need to offset non-main inputs to align with the nodes top-center -export const CONFIGURATION_NODE_OFFSET = (CONFIGURATION_NODE_SIZE[0] / 2) % GRID_SIZE; - /** * Utility functions for returning nodes found at the edges of a group */ @@ -619,10 +619,13 @@ export function calculateNodeSize( const height = DEFAULT_NODE_SIZE[1] + Math.max(0, maxVerticalHandles - 2) * GRID_SIZE * 2; if (isConfigurable) { + const portCount = Math.max(NODE_MIN_INPUT_ITEMS_COUNT, nonMainInputCount); + return { + // Configuration node has extra width so that its centered port aligns to the grid width: - Math.max(NODE_MIN_INPUT_ITEMS_COUNT, nonMainInputCount) * GRID_SIZE * 4 + - CONFIGURATION_NODE_OFFSET * 2, + CONFIGURATION_NODE_RADIUS * 2 + + GRID_SIZE * ((isConfiguration ? 1 : 0) + (portCount - 1) * 3), height: isConfiguration ? CONFIGURATION_NODE_SIZE[1] : height, }; }