diff --git a/web/app/components/workflow/hooks.ts b/web/app/components/workflow/hooks.ts index 30134c26bf..9a4a45c2d7 100644 --- a/web/app/components/workflow/hooks.ts +++ b/web/app/components/workflow/hooks.ts @@ -3,9 +3,11 @@ import produce from 'immer' import type { EdgeMouseHandler, NodeMouseHandler, + OnConnect, } from 'reactflow' import { getConnectedEdges, + getIncomers, useStoreApi, } from 'reactflow' import type { @@ -88,6 +90,33 @@ export const useWorkflow = () => { setNodes(newNodes) }, [store]) + const handleConnectNode = useCallback(({ + source, + sourceHandle, + target, + targetHandle, + }) => { + const { + edges, + setEdges, + } = store.getState() + + const newEdges = produce(edges, (draft) => { + const filtered = draft.filter(edge => edge.source !== source && edge.target !== target) + + filtered.push({ + id: `${source}-${target}`, + source: source!, + target: target!, + sourceHandle, + targetHandle, + }) + + return filtered + }) + setEdges(newEdges) + }, [store]) + const handleEnterEdge = useCallback((_, edge) => { const { edges, @@ -158,6 +187,7 @@ export const useWorkflow = () => { x: currentNode.position.x + 304, y: currentNode.position.y, }, + selected: true, } const newEdge = { id: `${currentNode.id}-${nextNode.id}`, @@ -169,7 +199,7 @@ export const useWorkflow = () => { } const newNodes = produce(nodes, (draft) => { draft.forEach((node) => { - node.data = { ...node.data, selected: false } + node.selected = false }) draft.push(nextNode) }) @@ -180,7 +210,7 @@ export const useWorkflow = () => { setEdges(newEdges) }, [store]) - const handleChangeCurrentNode = useCallback((parentNodeId: string, currentNodeId: string, nodeType: BlockEnum, sourceHandle: string) => { + const handleChangeCurrentNode = useCallback((currentNodeId: string, nodeType: BlockEnum, sourceHandle?: string) => { const { getNodes, setNodes, @@ -189,6 +219,7 @@ export const useWorkflow = () => { } = store.getState() const nodes = getNodes() const currentNode = nodes.find(node => node.id === currentNodeId)! + const incomers = getIncomers(currentNode, nodes, edges) const connectedEdges = getConnectedEdges([currentNode], edges) const newCurrentNode: Node = { id: `${Date.now()}`, @@ -199,27 +230,32 @@ export const useWorkflow = () => { y: currentNode.position.y, }, } - const newEdge = { - id: `${parentNodeId}-${newCurrentNode.id}`, - type: 'custom', - source: parentNodeId, - sourceHandle, - target: newCurrentNode.id, - targetHandle: 'target', - } const newNodes = produce(nodes, (draft) => { const index = draft.findIndex(node => node.id === currentNodeId) draft.splice(index, 1, newCurrentNode) }) setNodes(newNodes) - const newEdges = produce(edges, (draft) => { - const filtered = draft.filter(edge => !connectedEdges.find(connectedEdge => connectedEdge.id === edge.id)) - filtered.push(newEdge) + if (incomers.length === 1) { + const parentNodeId = incomers[0].id - return filtered - }) - setEdges(newEdges) + const newEdge = { + id: `${parentNodeId}-${newCurrentNode.id}`, + type: 'custom', + source: parentNodeId, + sourceHandle: sourceHandle || 'source', + target: newCurrentNode.id, + targetHandle: 'target', + } + + const newEdges = produce(edges, (draft) => { + const filtered = draft.filter(edge => !connectedEdges.find(connectedEdge => connectedEdge.id === edge.id)) + filtered.push(newEdge) + + return filtered + }) + setEdges(newEdges) + } }, [store]) const handleDeleteNode = useCallback((nodeId: string) => { @@ -303,6 +339,7 @@ export const useWorkflow = () => { handleSelectNode, handleEnterEdge, handleLeaveEdge, + handleConnectNode, handleDeleteEdge, handleUpdateNodeData, handleAddNextNode, diff --git a/web/app/components/workflow/index.tsx b/web/app/components/workflow/index.tsx index 4e7d3836b0..8c8752f875 100644 --- a/web/app/components/workflow/index.tsx +++ b/web/app/components/workflow/index.tsx @@ -41,6 +41,7 @@ const Workflow: FC = memo(({ const { handleEnterNode, handleLeaveNode, + handleConnectNode, handleEnterEdge, handleLeaveEdge, handleDeleteEdge, @@ -58,6 +59,7 @@ const Workflow: FC = memo(({ edgeTypes={edgeTypes} nodes={nodes} edges={edges} + onConnect={handleConnectNode} onNodeMouseEnter={handleEnterNode} onNodeMouseLeave={handleLeaveNode} onEdgeMouseEnter={handleEnterEdge} diff --git a/web/app/components/workflow/nodes/_base/components/next-step/index.tsx b/web/app/components/workflow/nodes/_base/components/next-step/index.tsx index c8db263f94..8b41025184 100644 --- a/web/app/components/workflow/nodes/_base/components/next-step/index.tsx +++ b/web/app/components/workflow/nodes/_base/components/next-step/index.tsx @@ -33,9 +33,7 @@ const NextStep = ({ { !branches && !!outgoers.length && ( ) @@ -63,7 +61,6 @@ const NextStep = ({ connected && ( { const { handleChangeCurrentNode } = useWorkflow() const handleSelect = useCallback((type: BlockEnum) => { - handleChangeCurrentNode(parentNodeId, nodeId, type, sourceHandle) - }, [parentNodeId, nodeId, sourceHandle, handleChangeCurrentNode]) + handleChangeCurrentNode(nodeId, type, sourceHandle) + }, [nodeId, sourceHandle, handleChangeCurrentNode]) const renderTrigger = useCallback((open: boolean) => { return (