diff --git a/packages/editor-ui/src/composables/__tests__/useCanvasOperations.spec.ts b/packages/editor-ui/src/composables/__tests__/useCanvasOperations.spec.ts index e59cffa552..dcb8499bf7 100644 --- a/packages/editor-ui/src/composables/__tests__/useCanvasOperations.spec.ts +++ b/packages/editor-ui/src/composables/__tests__/useCanvasOperations.spec.ts @@ -708,6 +708,24 @@ describe('useCanvasOperations', () => { }); }); + describe('revertCreateConnection', () => { + it('deletes connection if both source and target nodes exist', () => { + const connection: [IConnection, IConnection] = [ + { node: 'sourceNode', type: NodeConnectionType.Main, index: 0 }, + { node: 'targetNode', type: NodeConnectionType.Main, index: 0 }, + ]; + const testNode = createTestNode(); + + const removeConnectionSpy = vi.spyOn(workflowsStore, 'removeConnection'); + vi.spyOn(workflowsStore, 'getNodeByName').mockReturnValue(testNode); + vi.spyOn(workflowsStore, 'getNodeById').mockReturnValue(testNode); + + canvasOperations.revertCreateConnection(connection); + + expect(removeConnectionSpy).toHaveBeenCalled(); + }); + }); + describe('isConnectionAllowed', () => { it('should return false if source and target nodes are the same', () => { const node = mockNode({ id: '1', type: 'testType', name: 'Test Node' }); diff --git a/packages/editor-ui/src/composables/useCanvasOperations.ts b/packages/editor-ui/src/composables/useCanvasOperations.ts index b467a7238f..973faad1fa 100644 --- a/packages/editor-ui/src/composables/useCanvasOperations.ts +++ b/packages/editor-ui/src/composables/useCanvasOperations.ts @@ -30,6 +30,7 @@ import { WEBHOOK_NODE_TYPE, } from '@/constants'; import { + AddConnectionCommand, AddNodeCommand, MoveNodeCommand, RemoveConnectionCommand, @@ -55,6 +56,7 @@ import { getUniqueNodeName, mapCanvasConnectionToLegacyConnection, mapLegacyConnectionsToCanvasConnections, + mapLegacyConnectionToCanvasConnection, parseCanvasConnectionHandleString, } from '@/utils/canvasUtilsV2'; import * as NodeViewUtils from '@/utils/nodeViewUtils'; @@ -949,13 +951,21 @@ export function useCanvasOperations({ * Connection operations */ - function createConnection(connection: Connection) { + function createConnection(connection: Connection, { trackHistory = false } = {}) { const sourceNode = workflowsStore.getNodeById(connection.source); const targetNode = workflowsStore.getNodeById(connection.target); if (!sourceNode || !targetNode) { return; } + if (trackHistory) { + historyStore.pushCommandToUndo( + new AddConnectionCommand( + mapCanvasConnectionToLegacyConnection(sourceNode, targetNode, connection), + ), + ); + } + const mappedConnection = mapCanvasConnectionToLegacyConnection( sourceNode, targetNode, @@ -976,6 +986,19 @@ export function useCanvasOperations({ uiStore.stateIsDirty = true; } + function revertCreateConnection(connection: [IConnection, IConnection]) { + const sourceNodeName = connection[0].node; + const sourceNode = workflowsStore.getNodeByName(sourceNodeName); + const targetNodeName = connection[1].node; + const targetNode = workflowsStore.getNodeByName(targetNodeName); + + if (!sourceNode || !targetNode) { + return; + } + + deleteConnection(mapLegacyConnectionToCanvasConnection(sourceNode, targetNode, connection)); + } + function deleteConnection( connection: Connection, { trackHistory = false, trackBulk = true } = {}, @@ -1607,6 +1630,7 @@ export function useCanvasOperations({ revertDeleteNode, addConnections, createConnection, + revertCreateConnection, deleteConnection, revertDeleteConnection, isConnectionAllowed, diff --git a/packages/editor-ui/src/utils/canvasUtilsV2.ts b/packages/editor-ui/src/utils/canvasUtilsV2.ts index 79c7b998f9..321db4cf26 100644 --- a/packages/editor-ui/src/utils/canvasUtilsV2.ts +++ b/packages/editor-ui/src/utils/canvasUtilsV2.ts @@ -74,6 +74,32 @@ export function mapLegacyConnectionsToCanvasConnections( return mappedConnections; } +export function mapLegacyConnectionToCanvasConnection( + sourceNode: INodeUi, + targetNode: INodeUi, + legacyConnection: [IConnection, IConnection], +): Connection { + const source = sourceNode.id; + const sourceHandle = createCanvasConnectionHandleString({ + mode: CanvasConnectionMode.Output, + type: legacyConnection[0].type, + index: legacyConnection[0].index, + }); + const target = targetNode.id; + const targetHandle = createCanvasConnectionHandleString({ + mode: CanvasConnectionMode.Input, + type: legacyConnection[1].type, + index: legacyConnection[1].index, + }); + + return { + source, + sourceHandle, + target, + targetHandle, + }; +} + export function parseCanvasConnectionHandleString(handle: string | null | undefined) { const [mode, type, index] = (handle ?? '').split('/'); diff --git a/packages/editor-ui/src/views/NodeView.v2.vue b/packages/editor-ui/src/views/NodeView.v2.vue index 3ae627d1dc..606202e425 100644 --- a/packages/editor-ui/src/views/NodeView.v2.vue +++ b/packages/editor-ui/src/views/NodeView.v2.vue @@ -149,6 +149,7 @@ const { revertDeleteNode, addNodes, createConnection, + revertCreateConnection, deleteConnection, revertDeleteConnection, setNodeActiveByName, @@ -689,7 +690,11 @@ async function loadCredentials() { */ function onCreateConnection(connection: Connection) { - createConnection(connection); + createConnection(connection, { trackHistory: true }); +} + +function onRevertCreateConnection({ connection }: { connection: [IConnection, IConnection] }) { + revertCreateConnection(connection); } function onCreateConnectionCancelled(event: ConnectStartEvent) { @@ -974,7 +979,7 @@ function addUndoRedoEventBindings() { // historyBus.on('nodeMove', onMoveNode); // historyBus.on('revertAddNode', onRevertAddNode); historyBus.on('revertRemoveNode', onRevertDeleteNode); - // historyBus.on('revertAddConnection', onRevertAddConnection); + historyBus.on('revertAddConnection', onRevertCreateConnection); historyBus.on('revertRemoveConnection', onRevertDeleteConnection); historyBus.on('revertRenameNode', onRevertRenameNode); // historyBus.on('enableNodeToggle', onRevertEnableToggle); @@ -984,7 +989,7 @@ function removeUndoRedoEventBindings() { // historyBus.off('nodeMove', onMoveNode); // historyBus.off('revertAddNode', onRevertAddNode); historyBus.off('revertRemoveNode', onRevertDeleteNode); - // historyBus.off('revertAddConnection', onRevertAddConnection); + historyBus.off('revertAddConnection', onRevertCreateConnection); historyBus.off('revertRemoveConnection', onRevertDeleteConnection); historyBus.off('revertRenameNode', onRevertRenameNode); // historyBus.off('enableNodeToggle', onRevertEnableToggle);