diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasEditable.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasEditable.tsx index 9baba86534..0747a2e47a 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasEditable.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasEditable.tsx @@ -14,6 +14,7 @@ import { import { getWorkflowVersionStatusTagProps } from '@/workflow/workflow-diagram/utils/getWorkflowVersionStatusTagProps'; import { WorkflowDiagramBlankEdge } from '@/workflow/workflow-diagram/workflow-edges/components/WorkflowDiagramBlankEdge'; import { WorkflowDiagramDefaultEdgeEditable } from '@/workflow/workflow-diagram/workflow-edges/components/WorkflowDiagramDefaultEdgeEditable'; +import { getConnectionOptionsForSourceHandle } from '@/workflow/workflow-diagram/workflow-edges/utils/getConnectionOptionsForSourceHandle'; import { WorkflowDiagramEmptyTriggerEditable } from '@/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramEmptyTriggerEditable'; import { WorkflowDiagramStepNodeEditable } from '@/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeEditable'; import { useCreateEdge } from '@/workflow/workflow-steps/hooks/useCreateEdge'; @@ -63,7 +64,13 @@ export const WorkflowDiagramCanvasEditable = () => { }; }); - createEdge(edgeConnect); + createEdge({ + source: edgeConnect.source, + target: edgeConnect.target, + connectionOptions: getConnectionOptionsForSourceHandle({ + sourceHandleId: edgeConnect.sourceHandle, + }), + }); }; const onDeleteEdge = async (edge: WorkflowDiagramEdge) => { diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-edges/hooks/useEdgeState.ts b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-edges/hooks/useEdgeState.ts index 1de33ebe69..63a08b49a8 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-edges/hooks/useEdgeState.ts +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-edges/hooks/useEdgeState.ts @@ -20,7 +20,7 @@ export const useEdgeState = () => { sourceHandle, }: { nodeId: string; - sourceHandle: string | null | undefined; + sourceHandle: string; }) => { return ( workflowSelectedEdge?.source === nodeId && @@ -33,7 +33,7 @@ export const useEdgeState = () => { sourceHandle, }: { nodeId: string; - sourceHandle: string | null | undefined; + sourceHandle: string; }) => { return ( workflowHoveredEdge?.source === nodeId && diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeEditableContent.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeEditableContent.tsx index 387a70f4a0..0de4daa8b3 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeEditableContent.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeEditableContent.tsx @@ -74,11 +74,13 @@ export const WorkflowDiagramStepNodeEditableContent = ({ const { isNodeCreationStarted } = useStartNodeCreation(); - const { isConnectable, isSourceConnected, isInProgressConnection } = + const { isConnectable, isConnectingSource, isConnectionInProgress } = useConnectionState(data.nodeType); const { isSourceSelected, isSourceHovered } = useEdgeState(); + const isNodeConnectable = isConnectable({ nodeId: id }); + const handleAddStepButtonContainerClick = ( event: React.MouseEvent, ) => { @@ -92,9 +94,9 @@ export const WorkflowDiagramStepNodeEditableContent = ({ onClick={onClick} onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave} - isConnectable={isConnectable(id)} + isConnectable={isNodeConnectable} > - + @@ -119,7 +121,7 @@ export const WorkflowDiagramStepNodeEditableContent = ({ )} - {!data.hasNextStepIds && !isInProgressConnection && ( + {!data.hasNextStepIds && !isConnectionInProgress && ( { const edges = useEdges(); - const isInProgressConnection = connection.inProgress; + const isConnectionInProgress = connection.inProgress; - const isConnectable = (nodeId: string) => { + const isConnectable = ({ nodeId }: { nodeId: string }) => { if (nodeType === 'trigger') { return false; } - if (!isInProgressConnection) { + if (!isConnectionInProgress) { return false; } @@ -20,17 +20,29 @@ export const useConnectionState = (nodeType: 'action' | 'trigger') => { return false; } - return !edges.some( + const edgeAlreadyExists = edges.some( (edge) => - edge.target === nodeId && - connection.fromNode?.id && - edge.source === connection.fromNode.id, + edge.source === connection.fromNode.id && + edge.sourceHandle === connection.fromHandle.id && + edge.target === nodeId, + ); + + return !edgeAlreadyExists; + }; + + const isConnectingSource = ({ + nodeId, + sourceHandleId, + }: { + nodeId: string; + sourceHandleId: string; + }) => { + return ( + connection.inProgress && + connection.fromNode.id === nodeId && + connection.fromHandle.id === sourceHandleId ); }; - const isSourceConnected = (nodeId: string) => { - return connection.inProgress && connection.fromNode.id === nodeId; - }; - - return { isConnectable, isSourceConnected, isInProgressConnection }; + return { isConnectable, isConnectingSource, isConnectionInProgress }; }; diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/hooks/useCreateEdge.ts b/packages/twenty-front/src/modules/workflow/workflow-steps/hooks/useCreateEdge.ts index 55adca2460..69fc828154 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-steps/hooks/useCreateEdge.ts +++ b/packages/twenty-front/src/modules/workflow/workflow-steps/hooks/useCreateEdge.ts @@ -1,8 +1,16 @@ import { useGetUpdatableWorkflowVersionOrThrow } from '@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow'; import { type WorkflowDiagramEdgeDescriptor } from '@/workflow/workflow-diagram/workflow-edges/types/WorkflowDiagramEdgeDescriptor'; +import { type WorkflowStepConnectionOptions } from '@/workflow/workflow-diagram/workflow-iterator/types/WorkflowStepConnectionOptions'; import { useCreateWorkflowVersionEdge } from '@/workflow/workflow-steps/hooks/useCreateWorkflowVersionEdge'; import { useState } from 'react'; +type CreateEdgeParams = Pick< + WorkflowDiagramEdgeDescriptor, + 'source' | 'target' +> & { + connectionOptions?: WorkflowStepConnectionOptions; +}; + export const useCreateEdge = () => { const [isLoading, setIsLoading] = useState(false); @@ -14,7 +22,8 @@ export const useCreateEdge = () => { const createEdge = async ({ source, target, - }: WorkflowDiagramEdgeDescriptor) => { + connectionOptions, + }: CreateEdgeParams) => { if (isLoading) { return; } @@ -29,6 +38,7 @@ export const useCreateEdge = () => { workflowVersionId, source, target, + sourceConnectionOptions: connectionOptions, }) )?.data?.createWorkflowVersionEdge;