Skip to content

Commit ed6dac3

Browse files
committed
Fix inability to delete edges
1 parent 0e9abbe commit ed6dac3

File tree

2 files changed

+112
-100
lines changed

2 files changed

+112
-100
lines changed

src/components/shared/ReactFlow/FlowCanvas/utils/addAndConnectNode.ts

Lines changed: 55 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { Connection, Handle } from "@xyflow/react";
22

3-
import type { NodeManager } from "@/nodeManager";
3+
import type { NodeManager, NodeType } from "@/nodeManager";
44
import {
55
type ComponentReference,
66
type ComponentSpec,
@@ -48,57 +48,44 @@ export function addAndConnectNode({
4848
return componentSpec;
4949
}
5050

51-
const isTaskHandle = nodeManager.isManaged(fromHandle.id);
52-
let fromHandleType: "input" | "output";
53-
let fromHandleName: string | undefined;
54-
let fromTaskId: string | undefined;
51+
const fromNodeId = fromHandle.nodeId;
52+
const fromNodeType = nodeManager.getNodeType(fromNodeId);
53+
const fromTaskId = nodeManager.getTaskId(fromNodeId);
5554

56-
if (isTaskHandle) {
57-
// Handle is managed by NodeManager (task handle)
58-
const fromHandleInfo = nodeManager.getHandleInfo(fromHandle.id);
59-
const fromNodeType = nodeManager.getNodeType(fromHandle.id);
55+
if (!fromTaskId) {
56+
return componentSpec;
57+
}
6058

61-
if (!fromHandleInfo || !fromNodeType) {
62-
return componentSpec;
63-
}
59+
let fromHandleType: NodeType | undefined;
60+
let fromHandleName: string | undefined;
6461

65-
fromHandleType = fromNodeType === "taskInput" ? "input" : "output";
66-
fromHandleName = fromHandleInfo.handleName;
67-
fromTaskId = fromHandleInfo.taskId;
62+
if (fromNodeType === "task") {
63+
const fromHandleInfo = nodeManager.getHandleInfo(fromHandle.id);
64+
fromHandleName = fromHandleInfo?.handleName;
65+
fromHandleType = nodeManager.getNodeType(fromHandle.id);
66+
} else if (fromNodeType === "input") {
67+
fromHandleType = "taskOutput";
68+
fromHandleName = inputIdToInputName(fromTaskId);
69+
} else if (fromNodeType === "output") {
70+
fromHandleType = "taskInput";
71+
fromHandleName = outputIdToOutputName(fromTaskId);
6872
} else {
69-
// Simple IO node handle - get info from the source node, not the handle
70-
const fromNodeId = fromHandle.nodeId;
71-
const fromNodeType = nodeManager.getNodeType(fromNodeId);
72-
73-
if (!fromNodeType) {
74-
return componentSpec;
75-
}
76-
77-
if (fromNodeType === "input") {
78-
fromHandleType = "output";
79-
const inputId = nodeManager.getTaskId(fromNodeId);
80-
if (inputId) {
81-
fromHandleName = inputIdToInputName(inputId);
82-
fromTaskId = inputId;
83-
}
84-
} else if (fromNodeType === "output") {
85-
fromHandleType = "input";
86-
const outputId = nodeManager.getTaskId(fromNodeId);
87-
if (outputId) {
88-
fromHandleName = outputIdToOutputName(outputId);
89-
fromTaskId = outputId;
90-
}
91-
} else {
92-
return componentSpec;
93-
}
73+
return componentSpec;
74+
}
75+
76+
if (!fromHandleName) {
77+
return componentSpec;
9478
}
9579

96-
if (!fromTaskId || !fromHandleName) {
80+
if (
81+
!fromHandleType ||
82+
(fromHandleType !== "taskInput" && fromHandleType !== "taskOutput")
83+
) {
9784
return componentSpec;
9885
}
9986

10087
const adjustedPosition =
101-
fromHandleType === "input"
88+
fromHandleType === "taskInput"
10289
? { ...position, x: position.x - DEFAULT_NODE_DIMENSIONS.w }
10390
: position;
10491

@@ -129,7 +116,7 @@ export function addAndConnectNode({
129116
// 3. Determine the connection data type and find the first matching handle on the new node
130117
let fromComponentSpec: ComponentSpec | undefined;
131118

132-
if (isTaskHandle) {
119+
if (fromNodeType === "task") {
133120
// Get spec from task
134121
const fromTaskSpec = graphSpec.tasks[fromTaskId];
135122
fromComponentSpec = fromTaskSpec?.componentRef.spec;
@@ -139,55 +126,48 @@ export function addAndConnectNode({
139126
}
140127

141128
let connectionType: TypeSpecType | undefined;
142-
if (fromHandleType === "input") {
129+
if (fromHandleType === "taskInput") {
143130
connectionType = fromComponentSpec?.inputs?.find(
144131
(io) => io.name === fromHandleName,
145132
)?.type;
146-
} else if (fromHandleType === "output") {
133+
} else if (fromHandleType === "taskOutput") {
147134
connectionType = fromComponentSpec?.outputs?.find(
148135
(io) => io.name === fromHandleName,
149136
)?.type;
150137
}
151138

152139
// Find the first matching handle on the new node
153-
const toHandleType = fromHandleType === "input" ? "output" : "input";
154-
let targetHandleId: string | undefined;
155-
156-
if (toHandleType === "input") {
157-
const handleName = componentRef.spec?.inputs?.find(
158-
(io) => io.type === connectionType,
159-
)?.name;
160-
if (!handleName) {
161-
return newComponentSpec;
162-
}
163-
164-
targetHandleId = nodeManager.getTaskHandleNodeId(
165-
newTaskId,
166-
handleName,
167-
"taskInput",
168-
);
169-
} else if (toHandleType === "output") {
170-
const handleName = componentRef.spec?.outputs?.find(
171-
(io) => io.type === connectionType,
172-
)?.name;
173-
if (!handleName) {
174-
return newComponentSpec;
175-
}
176-
177-
targetHandleId = nodeManager.getTaskHandleNodeId(
178-
newTaskId,
179-
handleName,
180-
"taskOutput",
181-
);
140+
const toHandleType =
141+
fromHandleType === "taskInput" ? "taskOutput" : "taskInput";
142+
143+
const inputHandleName = componentRef.spec?.inputs?.find(
144+
(io) => io.type === connectionType,
145+
)?.name;
146+
147+
const outputHandleName = componentRef.spec?.outputs?.find(
148+
(io) => io.type === connectionType,
149+
)?.name;
150+
151+
const toHandleName =
152+
toHandleType === "taskInput" ? inputHandleName : outputHandleName;
153+
154+
if (!toHandleName) {
155+
return newComponentSpec;
182156
}
183157

158+
const targetHandleId = nodeManager.getTaskHandleNodeId(
159+
newTaskId,
160+
toHandleName,
161+
toHandleType,
162+
);
163+
184164
// 4. Build a Connection object and use handleConnection to add the edge
185165
if (targetHandleId) {
186166
const fromNodeId = fromHandle.nodeId;
187167
const fromHandleId = fromHandle.id;
188168

189169
const isReversedConnection =
190-
fromHandleType === "input" && toHandleType === "output";
170+
fromHandleType === "taskInput" && toHandleType === "taskOutput";
191171

192172
const connection: Connection = isReversedConnection
193173
? // Drawing from an input handle to a new output handle
Lines changed: 57 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import type { Edge } from "@xyflow/react";
22

33
import type { NodeManager } from "@/nodeManager";
4-
import type { ComponentSpec, GraphImplementation } from "@/utils/componentSpec";
4+
import {
5+
type ComponentSpec,
6+
isGraphImplementation,
7+
} from "@/utils/componentSpec";
58
import { outputIdToOutputName } from "@/utils/nodes/conversions";
69

710
import { setGraphOutputValue } from "./setGraphOutputValue";
@@ -12,38 +15,67 @@ export const removeEdge = (
1215
componentSpec: ComponentSpec,
1316
nodeManager: NodeManager,
1417
) => {
15-
const graphSpec = (componentSpec.implementation as GraphImplementation)
16-
?.graph;
18+
if (!isGraphImplementation(componentSpec.implementation)) {
19+
return componentSpec;
20+
}
21+
22+
const graphSpec = componentSpec.implementation.graph;
23+
const updatedComponentSpec = { ...componentSpec };
1724

18-
if (!edge.targetHandle) {
25+
const targetNodeId = edge.target;
26+
const targetTaskId = nodeManager.getTaskId(targetNodeId);
27+
const targetNodeType = nodeManager.getNodeType(targetNodeId);
28+
29+
if (!targetTaskId || !targetNodeType) {
30+
console.error("Could not resolve target node information:", {
31+
targetNodeId,
32+
targetTaskId,
33+
targetNodeType,
34+
});
1935
return componentSpec;
2036
}
2137

22-
const inputName = nodeManager.getHandleInfo(edge.targetHandle)?.handleName;
38+
switch (targetNodeType) {
39+
case "task": {
40+
if (!edge.targetHandle) {
41+
console.error("No target handle found for task connection");
42+
return componentSpec;
43+
}
44+
45+
const targetHandleInfo = nodeManager.getHandleInfo(edge.targetHandle);
46+
if (!targetHandleInfo) {
47+
console.error("Could not resolve target handle info");
48+
return componentSpec;
49+
}
2350

24-
const updatedComponentSpec = {
25-
...componentSpec,
26-
};
51+
const inputName = targetHandleInfo.handleName;
52+
const newGraphSpec = setTaskArgument(graphSpec, targetTaskId, inputName);
2753

28-
const taskId = nodeManager.getTaskId(edge.target);
29-
if (!taskId) return componentSpec;
54+
updatedComponentSpec.implementation = {
55+
...updatedComponentSpec.implementation,
56+
graph: newGraphSpec,
57+
};
58+
break;
59+
}
3060

31-
if (inputName !== undefined && graphSpec) {
32-
const newGraphSpec = setTaskArgument(graphSpec, taskId, inputName);
33-
updatedComponentSpec.implementation = {
34-
...updatedComponentSpec.implementation,
35-
graph: newGraphSpec,
36-
};
61+
case "output": {
62+
const outputName = outputIdToOutputName(targetTaskId);
63+
const newGraphSpec = setGraphOutputValue(graphSpec, outputName);
3764

38-
return updatedComponentSpec;
39-
} else {
40-
const outputName = outputIdToOutputName(taskId);
41-
const newGraphSpec = setGraphOutputValue(graphSpec, outputName);
42-
updatedComponentSpec.implementation = {
43-
...updatedComponentSpec.implementation,
44-
graph: newGraphSpec,
45-
};
65+
updatedComponentSpec.implementation = {
66+
...updatedComponentSpec.implementation,
67+
graph: newGraphSpec,
68+
};
69+
break;
70+
}
4671

47-
return updatedComponentSpec;
72+
default:
73+
console.error(
74+
"Unsupported target node type for edge removal:",
75+
targetNodeType,
76+
);
77+
return componentSpec;
4878
}
79+
80+
return updatedComponentSpec;
4981
};

0 commit comments

Comments
 (0)