mirror of
https://github.com/langgenius/dify.git
synced 2026-03-26 13:51:05 +08:00
feat: keep connections when change node (#31982)
This commit is contained in:
parent
8b1ea3a8f5
commit
ec5409756e
@ -1422,21 +1422,136 @@ export const useNodesInteractions = () => {
|
||||
extent: currentNode.extent,
|
||||
zIndex: currentNode.zIndex,
|
||||
})
|
||||
const nodesConnectedSourceOrTargetHandleIdsMap
|
||||
= getNodesConnectedSourceOrTargetHandleIdsMap(
|
||||
connectedEdges.map(edge => ({ type: 'remove', edge })),
|
||||
nodes,
|
||||
)
|
||||
const newNodes = produce(nodes, (draft) => {
|
||||
const parentNode = nodes.find(node => node.id === currentNode.parentId)
|
||||
const newNodeIsInIteration
|
||||
= !!parentNode && parentNode.data.type === BlockEnum.Iteration
|
||||
const newNodeIsInLoop
|
||||
= !!parentNode && parentNode.data.type === BlockEnum.Loop
|
||||
const outgoingEdges = connectedEdges.filter(
|
||||
edge => edge.source === currentNodeId,
|
||||
)
|
||||
const normalizedSourceHandle = sourceHandle || 'source'
|
||||
const outgoingHandles = new Set(
|
||||
outgoingEdges.map(edge => edge.sourceHandle || 'source'),
|
||||
)
|
||||
const branchSourceHandle = currentNode.data._targetBranches?.[0]?.id
|
||||
let outgoingHandleToPreserve = normalizedSourceHandle
|
||||
if (!outgoingHandles.has(outgoingHandleToPreserve)) {
|
||||
if (branchSourceHandle && outgoingHandles.has(branchSourceHandle))
|
||||
outgoingHandleToPreserve = branchSourceHandle
|
||||
else if (outgoingHandles.has('source'))
|
||||
outgoingHandleToPreserve = 'source'
|
||||
else
|
||||
outgoingHandleToPreserve = outgoingEdges[0]?.sourceHandle || 'source'
|
||||
}
|
||||
const outgoingEdgesToPreserve = outgoingEdges.filter(
|
||||
edge => (edge.sourceHandle || 'source') === outgoingHandleToPreserve,
|
||||
)
|
||||
const outgoingEdgeIds = new Set(
|
||||
outgoingEdgesToPreserve.map(edge => edge.id),
|
||||
)
|
||||
const newNodeSourceHandle = newCurrentNode.data._targetBranches?.[0]?.id || 'source'
|
||||
const reconnectedEdges = connectedEdges.reduce<Edge[]>(
|
||||
(acc, edge) => {
|
||||
if (outgoingEdgeIds.has(edge.id)) {
|
||||
const originalTargetNode = nodes.find(
|
||||
node => node.id === edge.target,
|
||||
)
|
||||
const targetNodeForEdge
|
||||
= originalTargetNode && originalTargetNode.id !== currentNodeId
|
||||
? originalTargetNode
|
||||
: newCurrentNode
|
||||
if (!targetNodeForEdge)
|
||||
return acc
|
||||
|
||||
const targetHandle = edge.targetHandle || 'target'
|
||||
const targetParentNode
|
||||
= targetNodeForEdge.id === newCurrentNode.id
|
||||
? parentNode || null
|
||||
: nodes.find(node => node.id === targetNodeForEdge.parentId)
|
||||
|| null
|
||||
const isInIteration
|
||||
= !!targetParentNode
|
||||
&& targetParentNode.data.type === BlockEnum.Iteration
|
||||
const isInLoop
|
||||
= !!targetParentNode
|
||||
&& targetParentNode.data.type === BlockEnum.Loop
|
||||
|
||||
acc.push({
|
||||
...edge,
|
||||
id: `${newCurrentNode.id}-${newNodeSourceHandle}-${targetNodeForEdge.id}-${targetHandle}`,
|
||||
source: newCurrentNode.id,
|
||||
sourceHandle: newNodeSourceHandle,
|
||||
target: targetNodeForEdge.id,
|
||||
targetHandle,
|
||||
type: CUSTOM_EDGE,
|
||||
data: {
|
||||
...(edge.data || {}),
|
||||
sourceType: newCurrentNode.data.type,
|
||||
targetType: targetNodeForEdge.data.type,
|
||||
isInIteration,
|
||||
iteration_id: isInIteration
|
||||
? targetNodeForEdge.parentId
|
||||
: undefined,
|
||||
isInLoop,
|
||||
loop_id: isInLoop ? targetNodeForEdge.parentId : undefined,
|
||||
_connectedNodeIsSelected: false,
|
||||
},
|
||||
zIndex: targetNodeForEdge.parentId
|
||||
? isInIteration
|
||||
? ITERATION_CHILDREN_Z_INDEX
|
||||
: LOOP_CHILDREN_Z_INDEX
|
||||
: 0,
|
||||
})
|
||||
}
|
||||
|
||||
if (
|
||||
edge.target === currentNodeId
|
||||
&& edge.source !== currentNodeId
|
||||
&& !outgoingEdgeIds.has(edge.id)
|
||||
) {
|
||||
const sourceNode = nodes.find(node => node.id === edge.source)
|
||||
if (!sourceNode)
|
||||
return acc
|
||||
|
||||
const targetHandle = edge.targetHandle || 'target'
|
||||
const sourceHandle = edge.sourceHandle || 'source'
|
||||
|
||||
acc.push({
|
||||
...edge,
|
||||
id: `${sourceNode.id}-${sourceHandle}-${newCurrentNode.id}-${targetHandle}`,
|
||||
source: sourceNode.id,
|
||||
sourceHandle,
|
||||
target: newCurrentNode.id,
|
||||
targetHandle,
|
||||
type: CUSTOM_EDGE,
|
||||
data: {
|
||||
...(edge.data || {}),
|
||||
sourceType: sourceNode.data.type,
|
||||
targetType: newCurrentNode.data.type,
|
||||
isInIteration: newNodeIsInIteration,
|
||||
iteration_id: newNodeIsInIteration
|
||||
? newCurrentNode.parentId
|
||||
: undefined,
|
||||
isInLoop: newNodeIsInLoop,
|
||||
loop_id: newNodeIsInLoop ? newCurrentNode.parentId : undefined,
|
||||
_connectedNodeIsSelected: false,
|
||||
},
|
||||
zIndex: newCurrentNode.parentId
|
||||
? newNodeIsInIteration
|
||||
? ITERATION_CHILDREN_Z_INDEX
|
||||
: LOOP_CHILDREN_Z_INDEX
|
||||
: 0,
|
||||
})
|
||||
}
|
||||
|
||||
return acc
|
||||
},
|
||||
[],
|
||||
)
|
||||
const nodesWithNewNode = 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)
|
||||
|
||||
@ -1446,18 +1561,32 @@ export const useNodesInteractions = () => {
|
||||
if (newLoopStartNode)
|
||||
draft.push(newLoopStartNode)
|
||||
})
|
||||
setNodes(newNodes)
|
||||
const newEdges = produce(edges, (draft) => {
|
||||
const filtered = draft.filter(
|
||||
edge =>
|
||||
!connectedEdges.find(
|
||||
connectedEdge => connectedEdge.id === edge.id,
|
||||
),
|
||||
const nodesConnectedSourceOrTargetHandleIdsMap
|
||||
= getNodesConnectedSourceOrTargetHandleIdsMap(
|
||||
[
|
||||
...connectedEdges.map(edge => ({ type: 'remove', edge })),
|
||||
...reconnectedEdges.map(edge => ({ type: 'add', edge })),
|
||||
],
|
||||
nodesWithNewNode,
|
||||
)
|
||||
|
||||
return filtered
|
||||
const newNodes = produce(nodesWithNewNode, (draft) => {
|
||||
draft.forEach((node) => {
|
||||
if (nodesConnectedSourceOrTargetHandleIdsMap[node.id]) {
|
||||
node.data = {
|
||||
...node.data,
|
||||
...nodesConnectedSourceOrTargetHandleIdsMap[node.id],
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
setEdges(newEdges)
|
||||
setNodes(newNodes)
|
||||
const remainingEdges = edges.filter(
|
||||
edge =>
|
||||
!connectedEdges.find(
|
||||
connectedEdge => connectedEdge.id === edge.id,
|
||||
),
|
||||
)
|
||||
setEdges([...remainingEdges, ...reconnectedEdges])
|
||||
if (nodeType === BlockEnum.TriggerWebhook) {
|
||||
handleSyncWorkflowDraft(true, true, {
|
||||
onSuccess: () => autoGenerateWebhookUrl(newCurrentNode.id),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user