diff --git a/web/app/components/workflow/custom-edge.tsx b/web/app/components/workflow/custom-edge.tsx index 06e9d6aa59..c14c8e52c3 100644 --- a/web/app/components/workflow/custom-edge.tsx +++ b/web/app/components/workflow/custom-edge.tsx @@ -10,11 +10,17 @@ import { Position, getSimpleBezierPath, } from 'reactflow' +import { useNodesInteractions } from './hooks' import BlockSelector from './block-selector' +import type { OnSelectBlock } from './types' const CustomEdge = ({ id, data, + source, + sourceHandleId, + target, + targetHandleId, sourceX, sourceY, targetX, @@ -34,10 +40,26 @@ const CustomEdge = ({ targetPosition: Position.Left, }) const [open, setOpen] = useState(false) + const { handleNodeAdd } = useNodesInteractions() const handleOpenChange = useCallback((v: boolean) => { setOpen(v) }, []) + const handleInsert = useCallback((nodeType, toolDefaultValue) => { + handleNodeAdd( + { + nodeType, + toolDefaultValue, + }, + { + prevNodeId: source, + prevNodeSourceHandle: sourceHandleId || 'source', + nextNodeId: target, + nextNodeTargetHandle: targetHandleId || 'target', + }, + ) + }, [handleNodeAdd, source, sourceHandleId, target, targetHandleId]) + return ( <> {}} + onSelect={handleInsert} /> diff --git a/web/app/components/workflow/hooks/use-nodes-interactions.ts b/web/app/components/workflow/hooks/use-nodes-interactions.ts index 1fb90fa74b..3abed9caf9 100644 --- a/web/app/components/workflow/hooks/use-nodes-interactions.ts +++ b/web/app/components/workflow/hooks/use-nodes-interactions.ts @@ -6,29 +6,34 @@ import type { OnConnect, } from 'reactflow' import { - Position, getConnectedEdges, - getIncomers, getOutgoers, useStoreApi, } from 'reactflow' import type { ToolDefaultValue } from '../block-selector/types' import type { + BlockEnum, Node, + OnNodeAdd, } from '../types' -import { BlockEnum } from '../types' import { useStore } from '../store' import { NODE_WIDTH_X_OFFSET, Y_OFFSET, } from '../constants' +import { + generateNewNode, + getNodesConnectedSourceOrTargetHandleIdsMap, +} from '../utils' import { useNodesInitialData } from './use-nodes-data' import { useNodesSyncDraft } from './use-nodes-sync-draft' +import { useWorkflow } from './use-workflow' export const useNodesInteractions = () => { const store = useStoreApi() const nodesInitialData = useNodesInitialData() const { handleSyncWorkflowDraft } = useNodesSyncDraft() + const { getAfterNodesInSameBranch } = useWorkflow() const dragNodeStartPosition = useRef({ x: 0, y: 0 } as { x: number; y: number }) const handleNodeDragStart = useCallback((_, node) => { @@ -257,20 +262,44 @@ export const useNodesInteractions = () => { return const { + getNodes, + setNodes, edges, setEdges, } = store.getState() - const newEdges = produce(edges, (draft) => { - const filtered = draft.filter(edge => (edge.source !== source && edge.sourceHandle !== sourceHandle) || (edge.target !== target && edge.targetHandle !== targetHandle)) - - filtered.push({ - id: `${source}-${target}`, - type: 'custom', - source: source!, - target: target!, - sourceHandle, - targetHandle, + const needDeleteEdges = edges.filter(edge => (edge.source === source && edge.sourceHandle === sourceHandle) || (edge.target === target && edge.targetHandle === targetHandle)) + const needDeleteEdgesIds = needDeleteEdges.map(edge => edge.id) + const newEdge = { + id: `${source}-${target}`, + type: 'custom', + source: source!, + target: target!, + sourceHandle, + targetHandle, + } + const nodes = getNodes() + const nodesConnectedSourceOrTargetHandleIdsMap = getNodesConnectedSourceOrTargetHandleIdsMap( + [ + ...needDeleteEdges.map(edge => ({ type: 'remove', edge })), + { type: 'add', edge: newEdge }, + ], + nodes, + ) + const newNodes = produce(nodes, (draft: Node[]) => { + draft.forEach((node) => { + if (nodesConnectedSourceOrTargetHandleIdsMap[node.id]) { + node.data = { + ...node.data, + ...nodesConnectedSourceOrTargetHandleIdsMap[node.id], + } + } }) + }) + setNodes(newNodes) + const newEdges = produce(edges, (draft) => { + const filtered = draft.filter(edge => !needDeleteEdgesIds.includes(edge.id)) + + filtered.push(newEdge) return filtered }) @@ -293,19 +322,16 @@ export const useNodesInteractions = () => { const nodes = getNodes() const currentNodeIndex = nodes.findIndex(node => node.id === nodeId) - const currentNode = nodes[currentNodeIndex] - const incomersIds = getIncomers(currentNode, nodes, edges).map(incomer => incomer.id) - const outgoersIds = getOutgoers(currentNode, nodes, edges).map(outgoer => outgoer.id) const connectedEdges = getConnectedEdges([{ id: nodeId } as Node], edges) - const sourceEdgesHandleIds = connectedEdges.filter(edge => edge.target === nodeId).map(edge => edge.sourceHandle) - const targetEdgesHandleIds = connectedEdges.filter(edge => edge.source === nodeId).map(edge => edge.targetHandle) + const nodesConnectedSourceOrTargetHandleIdsMap = getNodesConnectedSourceOrTargetHandleIdsMap(connectedEdges.map(edge => ({ type: 'remove', edge })), nodes) const newNodes = produce(nodes, (draft: Node[]) => { draft.forEach((node) => { - if (incomersIds.includes(node.id)) - node.data._connectedSourceHandleIds = node.data._connectedSourceHandleIds?.filter(handleId => !sourceEdgesHandleIds.includes(handleId)) - - if (outgoersIds.includes(node.id)) - node.data._connectedTargetHandleIds = node.data._connectedTargetHandleIds?.filter(handleId => !targetEdgesHandleIds.includes(handleId)) + if (nodesConnectedSourceOrTargetHandleIdsMap[node.id]) { + node.data = { + ...node.data, + ...nodesConnectedSourceOrTargetHandleIdsMap[node.id], + } + } }) draft.splice(currentNodeIndex, 1) }) @@ -317,11 +343,19 @@ export const useNodesInteractions = () => { handleSyncWorkflowDraft() }, [store, handleSyncWorkflowDraft]) - const handleNodeAddNext = useCallback(( - currentNodeId: string, - nodeType: BlockEnum, - sourceHandle: string, - toolDefaultValue?: ToolDefaultValue, + const handleNodeAdd = useCallback(( + { + nodeType, + sourceHandle = 'source', + targetHandle = 'target', + toolDefaultValue, + }, + { + prevNodeId, + prevNodeSourceHandle, + nextNodeId, + nextNodeTargetHandle, + }, ) => { const { runningStatus } = useStore.getState() @@ -335,112 +369,150 @@ export const useNodesInteractions = () => { setEdges, } = store.getState() const nodes = getNodes() - const currentNodeIndex = nodes.findIndex(node => node.id === currentNodeId) - const currentNode = nodes[currentNodeIndex] - const outgoers = getOutgoers(currentNode, nodes, edges).sort((a, b) => a.position.y - b.position.y) - const lastOutgoer = outgoers[outgoers.length - 1] - const nextNode: Node = { - id: `${Date.now()}`, - type: 'custom', - data: { - ...nodesInitialData[nodeType], - ...(toolDefaultValue || {}), - _connectedTargetHandleIds: ['target'], - selected: true, - }, - position: { - x: lastOutgoer ? lastOutgoer.position.x : currentNode.position.x + NODE_WIDTH_X_OFFSET, - y: lastOutgoer ? lastOutgoer.position.y + lastOutgoer.height! + Y_OFFSET : currentNode.position.y, - }, - targetPosition: Position.Left, - } - const newEdge = { - id: `${currentNode.id}-${nextNode.id}`, - type: 'custom', - source: currentNode.id, - sourceHandle, - target: nextNode.id, - targetHandle: 'target', - } - const newNodes = produce(nodes, (draft: Node[]) => { - draft.forEach((node, index) => { - node.data.selected = false - - if (index === currentNodeIndex) - node.data._connectedSourceHandleIds?.push(sourceHandle) - }) - draft.push(nextNode) - }) - setNodes(newNodes) - const newEdges = produce(edges, (draft) => { - draft.push(newEdge) - }) - setEdges(newEdges) - handleSyncWorkflowDraft() - }, [store, nodesInitialData, handleSyncWorkflowDraft]) - - const handleNodeAddPrev = useCallback(( - currentNodeId: string, - nodeType: BlockEnum, - targetHandle: string, - toolDefaultValue?: ToolDefaultValue, - ) => { - const { runningStatus } = useStore.getState() - - if (runningStatus) - return - - const { - getNodes, - setNodes, - edges, - setEdges, - } = store.getState() - const nodes = getNodes() - const currentNodeIndex = nodes.findIndex(node => node.id === currentNodeId) - const currentNode = nodes[currentNodeIndex] - const prevNode: Node = { - id: `${Date.now()}`, - type: 'custom', + const newNode = generateNewNode({ data: { ...nodesInitialData[nodeType], ...(toolDefaultValue || {}), selected: true, }, position: { - x: currentNode.position.x, - y: currentNode.position.y, + x: 0, + y: 0, }, - targetPosition: Position.Left, - } - const newNodes = produce(nodes, (draft) => { - draft.forEach((node, index) => { - node.data.selected = false - - if (index === currentNodeIndex) - node.position.x += NODE_WIDTH_X_OFFSET - }) - draft.push(prevNode) }) - setNodes(newNodes) + if (prevNodeId && !nextNodeId) { + const prevNodeIndex = nodes.findIndex(node => node.id === prevNodeId) + const prevNode = nodes[prevNodeIndex] + const outgoers = getOutgoers(prevNode, nodes, edges).sort((a, b) => a.position.y - b.position.y) + const lastOutgoer = outgoers[outgoers.length - 1] + newNode.data._connectedTargetHandleIds = [targetHandle] + newNode.position = { + x: lastOutgoer ? lastOutgoer.position.x : prevNode.position.x + NODE_WIDTH_X_OFFSET, + y: lastOutgoer ? lastOutgoer.position.y + lastOutgoer.height! + Y_OFFSET : prevNode.position.y, + } - if (prevNode.type !== BlockEnum.IfElse && prevNode.type !== BlockEnum.QuestionClassifier) { const newEdge = { - id: `${prevNode.id}-${currentNode.id}`, + id: `${prevNodeId}-${newNode.id}`, type: 'custom', - source: prevNode.id, - sourceHandle: 'source', - target: currentNode.id, + source: prevNodeId, + sourceHandle: prevNodeSourceHandle, + target: newNode.id, targetHandle, } + const newNodes = produce(nodes, (draft: Node[]) => { + draft.forEach((node) => { + node.data.selected = false + + if (node.id === prevNode.id) + node.data._connectedSourceHandleIds?.push(prevNodeSourceHandle!) + }) + draft.push(newNode) + }) + setNodes(newNodes) const newEdges = produce(edges, (draft) => { draft.push(newEdge) }) setEdges(newEdges) } + if (!prevNodeId && nextNodeId) { + const nextNodeIndex = nodes.findIndex(node => node.id === nextNodeId) + const nextNode = nodes[nextNodeIndex]! + newNode.data._connectedSourceHandleIds = [sourceHandle] + newNode.position = { + x: nextNode.position.x, + y: nextNode.position.y, + } + const newEdge = { + id: `${newNode.id}-${nextNodeId}`, + type: 'custom', + source: newNode.id, + sourceHandle, + target: nextNodeId, + targetHandle: nextNodeTargetHandle, + } + const afterNodesInSameBranch = getAfterNodesInSameBranch(nextNodeId!) + const afterNodesInSameBranchIds = afterNodesInSameBranch.map(node => node.id) + const newNodes = produce(nodes, (draft) => { + draft.forEach((node) => { + node.data.selected = false + + if (afterNodesInSameBranchIds.includes(node.id)) + node.position.x += NODE_WIDTH_X_OFFSET + + if (node.id === nextNodeId) + node.data._connectedTargetHandleIds?.push(nextNodeTargetHandle!) + }) + draft.push(newNode) + }) + setNodes(newNodes) + const newEdges = produce(edges, (draft) => { + draft.push(newEdge) + }) + setEdges(newEdges) + } + if (prevNodeId && nextNodeId) { + const nextNode = nodes.find(node => node.id === nextNodeId)! + newNode.data._connectedTargetHandleIds = [targetHandle] + newNode.data._connectedSourceHandleIds = [sourceHandle] + newNode.position = { + x: nextNode.position.x, + y: nextNode.position.y, + } + + const currentEdgeIndex = edges.findIndex(edge => edge.source === prevNodeId && edge.target === nextNodeId) + const newPrevEdge = { + id: `${prevNodeId}-${newNode.id}`, + type: 'custom', + source: prevNodeId, + sourceHandle: prevNodeSourceHandle, + target: newNode.id, + targetHandle, + } + const newNextEdge = { + id: `${newNode.id}-${nextNodeId}`, + type: 'custom', + source: newNode.id, + sourceHandle, + target: nextNodeId, + targetHandle: nextNodeTargetHandle, + } + const nodesConnectedSourceOrTargetHandleIdsMap = getNodesConnectedSourceOrTargetHandleIdsMap( + [ + { type: 'remove', edge: edges[currentEdgeIndex] }, + { type: 'add', edge: newPrevEdge }, + { type: 'add', edge: newNextEdge }, + ], + nodes, + ) + + const afterNodesInSameBranch = getAfterNodesInSameBranch(nextNodeId!) + const afterNodesInSameBranchIds = afterNodesInSameBranch.map(node => node.id) + const newNodes = produce(nodes, (draft) => { + draft.forEach((node) => { + node.data.selected = false + + if (nodesConnectedSourceOrTargetHandleIdsMap[node.id]) { + node.data = { + ...node.data, + ...nodesConnectedSourceOrTargetHandleIdsMap[node.id], + } + } + if (afterNodesInSameBranchIds.includes(node.id)) + node.position.x += NODE_WIDTH_X_OFFSET + }) + draft.push(newNode) + }) + setNodes(newNodes) + const newEdges = produce(edges, (draft) => { + draft.splice(currentEdgeIndex, 1) + draft.push(newPrevEdge) + draft.push(newNextEdge) + }) + setEdges(newEdges) + } handleSyncWorkflowDraft() - }, [store, nodesInitialData, handleSyncWorkflowDraft]) + }, [store, nodesInitialData, handleSyncWorkflowDraft, getAfterNodesInSameBranch]) const handleNodeChange = useCallback(( currentNodeId: string, @@ -461,11 +533,8 @@ export const useNodesInteractions = () => { } = 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()}`, - type: 'custom', + const newCurrentNode = generateNewNode({ data: { ...nodesInitialData[nodeType], ...(toolDefaultValue || {}), @@ -475,35 +544,36 @@ export const useNodesInteractions = () => { x: currentNode.position.x, y: currentNode.position.y, }, - targetPosition: Position.Left, - } + }) + const nodesConnectedSourceOrTargetHandleIdsMap = getNodesConnectedSourceOrTargetHandleIdsMap( + [ + ...connectedEdges.map(edge => ({ type: 'remove', edge })), + ], + nodes, + ) const newNodes = produce(nodes, (draft) => { + draft.forEach((node) => { + node.data.selected = false + + if (nodesConnectedSourceOrTargetHandleIdsMap[node.id]) { + node.data = { + ...node.data, + ...nodesConnectedSourceOrTargetHandleIdsMap[node.id], + } + } + }) const index = draft.findIndex(node => node.id === currentNodeId) draft.splice(index, 1, newCurrentNode) }) setNodes(newNodes) - if (incomers.length === 1) { - const parentNodeId = incomers[0].id + const newEdges = produce(edges, (draft) => { + const filtered = draft.filter(edge => !connectedEdges.find(connectedEdge => connectedEdge.id === edge.id)) - const newEdge = { - id: `${parentNodeId}-${newCurrentNode.id}`, - type: 'custom', - source: parentNodeId, - sourceHandle, - 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) - handleSyncWorkflowDraft() - } + return filtered + }) + setEdges(newEdges) + handleSyncWorkflowDraft() }, [store, nodesInitialData, handleSyncWorkflowDraft]) return { @@ -516,8 +586,7 @@ export const useNodesInteractions = () => { handleNodeClick, handleNodeConnect, handleNodeDelete, - handleNodeAddNext, - handleNodeAddPrev, handleNodeChange, + handleNodeAdd, } } diff --git a/web/app/components/workflow/hooks/use-workflow.ts b/web/app/components/workflow/hooks/use-workflow.ts index 6a4d98b070..76f9758764 100644 --- a/web/app/components/workflow/hooks/use-workflow.ts +++ b/web/app/components/workflow/hooks/use-workflow.ts @@ -118,9 +118,41 @@ export const useWorkflow = () => { return [] }, [store]) + const getAfterNodesInSameBranch = useCallback((nodeId: string) => { + const { + getNodes, + edges, + } = store.getState() + const nodes = getNodes() + const currentNode = nodes.find(node => node.id === nodeId)! + + if (!currentNode) + return [] + const list: Node[] = [currentNode] + + const traverse = (root: Node, callback: (node: Node) => void) => { + if (root) { + const outgoers = getOutgoers(root, nodes, edges) + + if (outgoers.length) { + outgoers.forEach((node) => { + callback(node) + traverse(node, callback) + }) + } + } + } + traverse(currentNode, (node) => { + list.push(node) + }) + + return list + }, [store]) + return { handleLayout, getTreeLeafNodes, getBeforeNodesInSameBranch, + getAfterNodesInSameBranch, } } diff --git a/web/app/components/workflow/index.tsx b/web/app/components/workflow/index.tsx index c43b2b2474..5f3cd7d921 100644 --- a/web/app/components/workflow/index.tsx +++ b/web/app/components/workflow/index.tsx @@ -40,6 +40,7 @@ import { } from './utils' import { START_INITIAL_POSITION } from './constants' import { + fetchNodesDefaultConfigs, fetchWorkflowDraft, syncWorkflowDraft, } from '@/service/workflow' @@ -158,6 +159,7 @@ const WorkflowWrap: FC = ({ }) => { const appDetail = useAppStore(state => state.appDetail) const { data, isLoading, error, mutate } = useSWR(appDetail?.id ? `/apps/${appDetail.id}/workflows/draft` : null, fetchWorkflowDraft) + const { data: nodesDefaultConfigs } = useSWR(appDetail?.id ? `/apps/${appDetail?.id}/workflows/default-workflow-block-configs` : null, fetchNodesDefaultConfigs) const nodesInitialData = useNodesInitialData() useEffect(() => { diff --git a/web/app/components/workflow/nodes/_base/components/node-handle.tsx b/web/app/components/workflow/nodes/_base/components/node-handle.tsx index f2955c8932..7b87e7e0ef 100644 --- a/web/app/components/workflow/nodes/_base/components/node-handle.tsx +++ b/web/app/components/workflow/nodes/_base/components/node-handle.tsx @@ -30,7 +30,7 @@ export const NodeTargetHandle = memo(({ nodeSelectorClassName, }: NodeHandleProps) => { const [open, setOpen] = useState(false) - const { handleNodeAddPrev } = useNodesInteractions() + const { handleNodeAdd } = useNodesInteractions() const connected = data._connectedTargetHandleIds?.includes(handleId) const handleOpenChange = useCallback((v: boolean) => { @@ -42,8 +42,17 @@ export const NodeTargetHandle = memo(({ setOpen(v => !v) }, [connected]) const handleSelect = useCallback((type: BlockEnum, toolDefaultValue?: ToolDefaultValue) => { - handleNodeAddPrev(id, type, handleId, toolDefaultValue) - }, [handleNodeAddPrev, id, handleId]) + handleNodeAdd( + { + nodeType: type, + toolDefaultValue, + }, + { + nextNodeId: id, + nextNodeTargetHandle: handleId, + }, + ) + }, [handleNodeAdd, id, handleId]) return ( <> @@ -93,7 +102,7 @@ export const NodeSourceHandle = memo(({ }: NodeHandleProps) => { const notInitialWorkflow = useStore(s => s.notInitialWorkflow) const [open, setOpen] = useState(false) - const { handleNodeAddNext } = useNodesInteractions() + const { handleNodeAdd } = useNodesInteractions() const connected = data._connectedSourceHandleIds?.includes(handleId) const handleOpenChange = useCallback((v: boolean) => { setOpen(v) @@ -104,8 +113,17 @@ export const NodeSourceHandle = memo(({ setOpen(v => !v) }, [connected]) const handleSelect = useCallback((type: BlockEnum, toolDefaultValue?: ToolDefaultValue) => { - handleNodeAddNext(id, type, handleId, toolDefaultValue) - }, [handleNodeAddNext, id, handleId]) + handleNodeAdd( + { + nodeType: type, + toolDefaultValue, + }, + { + prevNodeId: id, + prevNodeSourceHandle: handleId, + }, + ) + }, [handleNodeAdd, id, handleId]) useEffect(() => { if (notInitialWorkflow && data.type === BlockEnum.Start) diff --git a/web/app/components/workflow/types.ts b/web/app/components/workflow/types.ts index 7b71e2f5e5..ed05bba221 100644 --- a/web/app/components/workflow/types.ts +++ b/web/app/components/workflow/types.ts @@ -180,3 +180,18 @@ export enum NodeRunningStatus { Succeeded = 'succeeded', Failed = 'failed', } + +export type OnNodeAdd = ( + newNodePayload: { + nodeType: BlockEnum + sourceHandle?: string + targetHandle?: string + toolDefaultValue?: ToolDefaultValue + }, + oldNodesPayload: { + prevNodeId?: string + prevNodeSourceHandle?: string + nextNodeId?: string + nextNodeTargetHandle?: string + } +) => void diff --git a/web/app/components/workflow/utils.ts b/web/app/components/workflow/utils.ts index 0e0161ea19..3af92ee62c 100644 --- a/web/app/components/workflow/utils.ts +++ b/web/app/components/workflow/utils.ts @@ -1,4 +1,5 @@ import { + Position, getConnectedEdges, getOutgoers, } from 'reactflow' @@ -176,8 +177,60 @@ export const canRunBySingle = (nodeType: BlockEnum) => { } type ConnectedSourceOrTargetNodesChange = { - type: 'add' | 'remove' + type: string edge: Edge }[] -export const getConnectedSourceOrTargetNodesChangeList = (changes: ConnectedSourceOrTargetNodesChange, nodes: Node[], edges: Edge[]) => { +export const getNodesConnectedSourceOrTargetHandleIdsMap = (changes: ConnectedSourceOrTargetNodesChange, nodes: Node[]) => { + const nodesConnectedSourceOrTargetHandleIdsMap = {} as Record + + changes.forEach((change) => { + const { + edge, + type, + } = change + const sourceNode = nodes.find(node => node.id === edge.source) + const sourceNodeConnectedSourceHandleIds = sourceNode?.data._connectedSourceHandleIds || [] + const targetNode = nodes.find(node => node.id === edge.target) + const targetNodeConnectedTargetHandleIds = targetNode?.data._connectedTargetHandleIds || [] + + if (sourceNode) { + const newSourceNodeConnectedSourceHandleIds = type === 'remove' + ? sourceNodeConnectedSourceHandleIds.filter(handleId => handleId !== edge.sourceHandle) + : sourceNodeConnectedSourceHandleIds.concat(edge.sourceHandle || 'source') + if (!nodesConnectedSourceOrTargetHandleIdsMap[sourceNode.id]) { + nodesConnectedSourceOrTargetHandleIdsMap[sourceNode.id] = { + _connectedSourceHandleIds: newSourceNodeConnectedSourceHandleIds, + } + } + else { + nodesConnectedSourceOrTargetHandleIdsMap[sourceNode.id]._connectedSourceHandleIds = newSourceNodeConnectedSourceHandleIds + } + } + if (targetNode) { + const newTargetNodeConnectedTargetHandleIds = type === 'remove' + ? targetNodeConnectedTargetHandleIds.filter(handleId => handleId !== edge.targetHandle) + : targetNodeConnectedTargetHandleIds.concat(edge.targetHandle || 'target') + if (!nodesConnectedSourceOrTargetHandleIdsMap[targetNode.id]) { + nodesConnectedSourceOrTargetHandleIdsMap[targetNode.id] = { + _connectedTargetHandleIds: newTargetNodeConnectedTargetHandleIds, + } + } + else { + nodesConnectedSourceOrTargetHandleIdsMap[targetNode.id]._connectedTargetHandleIds = newTargetNodeConnectedTargetHandleIds + } + } + }) + + return nodesConnectedSourceOrTargetHandleIdsMap +} + +export const generateNewNode = ({ data, position }: Pick) => { + return { + id: `${Date.now()}`, + type: 'custom', + data, + position, + targetPosition: Position.Left, + sourcePosition: Position.Right, + } as Node } diff --git a/web/service/workflow.ts b/web/service/workflow.ts index c7a76c1e37..06cdeaef0f 100644 --- a/web/service/workflow.ts +++ b/web/service/workflow.ts @@ -3,6 +3,7 @@ import { get, post } from './base' import type { CommonResponse } from '@/models/common' import type { FetchWorkflowDraftResponse, + NodesDefaultConfigsResponse, WorkflowRunHistoryResponse, } from '@/types/workflow' @@ -14,8 +15,8 @@ export const syncWorkflowDraft = ({ url, params }: { url: string; params: Pick(url, { body: params }) } -export const fetchNodesDefaultConfigs: Fetcher = (url) => { - return get(url) +export const fetchNodesDefaultConfigs: Fetcher = (url) => { + return get(url) } export const fetchWorkflowRunHistory: Fetcher = (url) => { diff --git a/web/types/workflow.ts b/web/types/workflow.ts index 93d13cbb8d..7e77bdba5d 100644 --- a/web/types/workflow.ts +++ b/web/types/workflow.ts @@ -160,3 +160,10 @@ export type WorkflowRunHistory = { export type WorkflowRunHistoryResponse = { data: WorkflowRunHistory[] } + +export type NodesDefaultConfigsResponse = { + blocks: { + type: string + config: any + }[] +}