Skip to content

Commit 7a923f3

Browse files
committed
Split TaskInput and TaskOutput Node Ids from Input and Output Node Ids
1 parent 281533c commit 7a923f3

File tree

6 files changed

+166
-103
lines changed

6 files changed

+166
-103
lines changed

src/components/shared/ReactFlow/FlowCanvas/IONode/IONode.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,12 @@ interface IONodeProps {
2727
}
2828

2929
const IONode = ({ type, data, selected = false }: IONodeProps) => {
30-
const { getInputNodeId, getOutputNodeId } = useNodeManager();
30+
const {
31+
getInputNodeId,
32+
getOutputNodeId,
33+
getTaskInputNodeId,
34+
getTaskOutputNodeId,
35+
} = useNodeManager();
3136
const { graphSpec, componentSpec } = useComponentSpec();
3237
const { setContent, clearContent } = useContextPanel();
3338

@@ -63,13 +68,13 @@ const IONode = ({ type, data, selected = false }: IONodeProps) => {
6368
: getOutputNodeId(outputNameToOutputId(spec.name));
6469

6570
const nodeHandleId = isInput
66-
? getInputNodeId(inputNameToInputId(spec.name + "handle"))
67-
: getOutputNodeId(outputNameToOutputId(spec.name + "handle"));
71+
? getTaskOutputNodeId(inputNameToInputId(spec.name))
72+
: getTaskInputNodeId(outputNameToOutputId(spec.name));
6873

6974
const handleHandleClick = useCallback(() => {
7075
if (ENABLE_DEBUG_MODE) {
71-
console.log(`${isInput ? "Input" : "Output"} Handle clicked:`, {
72-
name: isInput ? input?.name : output?.name,
76+
console.log(`${isInput ? "Output" : "Input"} Handle clicked:`, {
77+
nodeName: isInput ? input?.name : output?.name,
7378
nodeId,
7479
handleId: nodeHandleId,
7580
});

src/components/shared/ReactFlow/FlowCanvas/TaskNode/TaskNodeCard/Handles.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export const InputHandle = ({
3838
onLabelClick,
3939
onHandleSelectionChange,
4040
}: InputHandleProps) => {
41-
const { getInputNodeId } = useNodeManager();
41+
const { getTaskInputNodeId } = useNodeManager();
4242
const { nodeId, state, name } = useTaskNode();
4343

4444
const fromHandle = useConnection((connection) => connection.fromHandle?.id);
@@ -51,7 +51,7 @@ export const InputHandle = ({
5151
const [selected, setSelected] = useState(false);
5252
const [active, setActive] = useState(false);
5353

54-
const handleId = getInputNodeId(inputNameToInputId(input.name));
54+
const handleId = getTaskInputNodeId(inputNameToInputId(input.name));
5555

5656
const missing = invalid ? "bg-red-700!" : "bg-gray-500!";
5757
const hasValue = value !== undefined && value !== null;
@@ -234,7 +234,7 @@ export const OutputHandle = ({
234234
onLabelClick,
235235
onHandleSelectionChange,
236236
}: OutputHandleProps) => {
237-
const { getOutputNodeId } = useNodeManager();
237+
const { getTaskOutputNodeId } = useNodeManager();
238238
const { nodeId, state, name } = useTaskNode();
239239

240240
const fromHandle = useConnection((connection) => connection.fromHandle?.id);
@@ -247,7 +247,7 @@ export const OutputHandle = ({
247247
const [selected, setSelected] = useState(false);
248248
const [active, setActive] = useState(false);
249249

250-
const handleId = getOutputNodeId(outputNameToOutputId(output.name));
250+
const handleId = getTaskOutputNodeId(outputNameToOutputId(output.name));
251251
const hasValue = value !== undefined && value !== "" && value !== null;
252252

253253
const handleHandleClick = useCallback(

src/components/shared/ReactFlow/FlowCanvas/TaskNode/TaskNodeCard/TaskNodeOutputs.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export function TaskNodeOutputs({
2424
expanded,
2525
onBackgroundClick,
2626
}: TaskNodeOutputsProps) {
27-
const { getOutputNodeId } = useNodeManager();
27+
const { getTaskOutputNodeId } = useNodeManager();
2828
const { nodeId, outputs, state, select } = useTaskNode();
2929
const {
3030
highlightSearchFilter,
@@ -43,7 +43,7 @@ export function TaskNodeOutputs({
4343
(edge) =>
4444
edge.source === nodeId &&
4545
edge.sourceHandle ===
46-
getOutputNodeId(outputNameToOutputId(output.name)),
46+
getTaskOutputNodeId(outputNameToOutputId(output.name)),
4747
),
4848
);
4949

@@ -141,7 +141,8 @@ export function TaskNodeOutputs({
141141
}
142142

143143
const output = outputs.find(
144-
(o) => getOutputNodeId(outputNameToOutputId(o.name)) === fromHandle?.id,
144+
(o) =>
145+
getTaskOutputNodeId(outputNameToOutputId(o.name)) === fromHandle?.id,
145146
);
146147

147148
if (!output) return;

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ export function addAndConnectNode({
118118
}
119119

120120
const inputId = inputNameToInputId(handleName);
121-
targetHandleId = nodeManager.getNodeId(inputId, "input");
121+
targetHandleId = nodeManager.getNodeId(inputId, "taskInput");
122122
} else if (toHandleType === "output") {
123123
const handleName = componentRef.spec?.outputs?.find(
124124
(io) => io.type === connectionType,
@@ -128,7 +128,7 @@ export function addAndConnectNode({
128128
}
129129

130130
const outputId = outputNameToOutputId(handleName);
131-
targetHandleId = nodeManager.getNodeId(outputId, "output");
131+
targetHandleId = nodeManager.getNodeId(outputId, "taskOutput");
132132
}
133133

134134
// 4. Build a Connection object and use handleConnection to add the edge
Lines changed: 137 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,107 +1,159 @@
11
import type { Connection } from "@xyflow/react";
22

3-
import type { NodeManager } from "@/nodeManager";
3+
import type { NodeManager, NodeType } from "@/nodeManager";
44
import type {
55
GraphInputArgument,
66
GraphSpec,
77
TaskOutputArgument,
88
} from "@/utils/componentSpec";
9-
import { inputIdToInputName } from "@/utils/nodes/nodeIdUtils";
9+
import {
10+
inputIdToInputName,
11+
outputIdToOutputName,
12+
} from "@/utils/nodes/nodeIdUtils";
1013

1114
import { setGraphOutputValue } from "./setGraphOutputValue";
1215
import { setTaskArgument } from "./setTaskArgument";
1316

17+
type NodeInfo = {
18+
id: string;
19+
handle?: string;
20+
type?: NodeType;
21+
};
22+
1423
export const handleConnection = (
1524
graphSpec: GraphSpec,
1625
connection: Connection,
1726
nodeManager: NodeManager,
1827
) => {
19-
const targetTaskInputName = connection.targetHandle?.replace(/^input_/, "");
20-
const sourceTaskOutputName = connection.sourceHandle?.replace(/^output_/, "");
21-
22-
const targetId = nodeManager.getTaskId(connection.target);
2328
const sourceId = nodeManager.getTaskId(connection.source);
29+
const targetId = nodeManager.getTaskId(connection.target);
2430

25-
if (sourceTaskOutputName !== undefined) {
26-
if (!sourceId) {
27-
console.error(
28-
"addConnection: Could not find task ID for source node: ",
29-
connection.source,
30-
);
31-
return graphSpec;
32-
}
33-
34-
const taskOutputArgument: TaskOutputArgument = {
35-
taskOutput: {
36-
taskId: sourceId,
37-
outputName: sourceTaskOutputName,
38-
},
39-
};
40-
41-
if (targetTaskInputName !== undefined) {
42-
if (!targetId) {
43-
console.error(
44-
"addConnection: Could not find Input ID for target node: ",
45-
connection.target,
46-
);
47-
return graphSpec;
48-
}
49-
50-
return setTaskArgument(
51-
graphSpec,
52-
targetId,
53-
targetTaskInputName,
54-
taskOutputArgument,
55-
);
56-
} else {
57-
if (!targetId) {
58-
console.error(
59-
"addConnection: Could not find Output ID for target node: ",
60-
connection.target,
61-
);
62-
return graphSpec;
63-
}
64-
65-
return setGraphOutputValue(graphSpec, targetId, taskOutputArgument);
66-
// TODO: Perhaps propagate type information
67-
}
68-
} else {
69-
if (!sourceId) {
70-
console.error(
71-
"addConnection: Could not find task ID for source node: ",
72-
connection.source,
73-
);
31+
if (!sourceId || !targetId) {
32+
console.warn("Source or Target ID is missing in the connection.");
33+
return graphSpec;
34+
}
35+
36+
if (sourceId === targetId) {
37+
console.warn(
38+
"Source and Target IDs are the same. Self-connections are not allowed.",
39+
);
40+
return graphSpec;
41+
}
42+
43+
const sourceHandleId = connection.sourceHandle
44+
? nodeManager.getTaskId(connection.sourceHandle)
45+
: undefined;
46+
47+
const targetHandleId = connection.targetHandle
48+
? nodeManager.getTaskId(connection.targetHandle)
49+
: undefined;
50+
51+
const source: NodeInfo = {
52+
id: sourceId,
53+
handle: sourceHandleId,
54+
type: nodeManager.getNodeType(connection.source),
55+
};
56+
57+
const target: NodeInfo = {
58+
id: targetId,
59+
handle: targetHandleId,
60+
type: nodeManager.getNodeType(connection.target),
61+
};
62+
63+
const connectionType = `${source.type}_to_${target.type}` as const;
64+
65+
switch (connectionType) {
66+
case "input_to_task":
67+
return handleGraphInputToTask(graphSpec, source, target);
68+
69+
case "task_to_task":
70+
return handleTaskToTask(graphSpec, source, target);
71+
72+
case "task_to_output":
73+
return handleTaskToGraphOutput(graphSpec, source, target);
74+
75+
default:
76+
console.warn("Unsupported connection pattern:", connectionType);
7477
return graphSpec;
75-
}
76-
const inputName = inputIdToInputName(sourceId);
77-
const graphInputArgument: GraphInputArgument = {
78-
graphInput: {
79-
inputName: inputName,
80-
},
81-
};
82-
if (targetTaskInputName !== undefined) {
83-
if (!targetId) {
84-
console.error(
85-
"addConnection: Could not find Output ID for target node: ",
86-
connection.target,
87-
);
88-
return graphSpec;
89-
}
90-
91-
return setTaskArgument(
92-
graphSpec,
93-
targetId,
94-
targetTaskInputName,
95-
graphInputArgument,
96-
);
97-
} else {
98-
console.error(
99-
"addConnection: Cannot directly connect graph input to graph output: ",
100-
connection,
101-
);
102-
}
10378
}
79+
};
80+
81+
const handleGraphInputToTask = (
82+
graphSpec: GraphSpec,
83+
source: NodeInfo,
84+
target: NodeInfo,
85+
): GraphSpec => {
86+
if (!target.handle) {
87+
console.warn("Handle ID is missing for target task node.");
88+
return graphSpec;
89+
}
90+
91+
const sourceInputName = inputIdToInputName(source.id);
92+
const targetInputName = inputIdToInputName(target.handle);
93+
94+
const graphInputArgument: GraphInputArgument = {
95+
graphInput: { inputName: sourceInputName },
96+
};
97+
98+
return setTaskArgument(
99+
graphSpec,
100+
target.id,
101+
targetInputName,
102+
graphInputArgument,
103+
);
104+
};
105+
106+
const handleTaskToTask = (
107+
graphSpec: GraphSpec,
108+
source: NodeInfo,
109+
target: NodeInfo,
110+
): GraphSpec => {
111+
if (!source.handle) {
112+
console.warn("Handle ID is missing for source task node.");
113+
return graphSpec;
114+
}
115+
116+
if (!target.handle) {
117+
console.warn("Handle ID is missing for target task node.");
118+
return graphSpec;
119+
}
120+
121+
const sourceOutputName = outputIdToOutputName(source.handle);
122+
const targetInputName = inputIdToInputName(target.handle);
123+
124+
const taskOutputArgument: TaskOutputArgument = {
125+
taskOutput: {
126+
taskId: source.id,
127+
outputName: sourceOutputName,
128+
},
129+
};
130+
131+
return setTaskArgument(
132+
graphSpec,
133+
target.id,
134+
targetInputName,
135+
taskOutputArgument,
136+
);
137+
};
138+
139+
const handleTaskToGraphOutput = (
140+
graphSpec: GraphSpec,
141+
source: NodeInfo,
142+
target: NodeInfo,
143+
): GraphSpec => {
144+
if (!source.handle) {
145+
console.warn("Handle ID is missing for source task node.");
146+
return graphSpec;
147+
}
148+
149+
const sourceOutputName = outputIdToOutputName(source.handle);
150+
151+
const taskOutputArgument: TaskOutputArgument = {
152+
taskOutput: {
153+
taskId: source.id,
154+
outputName: sourceOutputName,
155+
},
156+
};
104157

105-
// GraphSpec was not updated (due to an error or other reason)
106-
return graphSpec;
158+
return setGraphOutputValue(graphSpec, target.id, taskOutputArgument);
107159
};

src/hooks/useComponentSpecToEdges.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,13 @@ const createTaskOutputEdge = (
111111
): Edge => {
112112
const sourceNodeId = nodeManager.getNodeId(taskOutput.taskId, "task");
113113
const sourceOutputId = outputNameToOutputId(taskOutput.outputName);
114-
const sourceHandleNodeId = nodeManager.getNodeId(sourceOutputId, "output");
114+
const sourceHandleNodeId = nodeManager.getNodeId(
115+
sourceOutputId,
116+
"taskOutput",
117+
);
115118
const targetNodeId = nodeManager.getNodeId(taskId, "task");
116119
const targetInputId = inputNameToInputId(inputName);
117-
const targetHandleNodeId = nodeManager.getNodeId(targetInputId, "input");
120+
const targetHandleNodeId = nodeManager.getNodeId(targetInputId, "taskInput");
118121

119122
return {
120123
id: `${taskOutput.taskId}_${sourceOutputId}-${taskId}_${targetInputId}`,
@@ -137,7 +140,7 @@ const createGraphInputEdge = (
137140
const sourceNodeId = nodeManager.getNodeId(inputId, "input");
138141
const targetNodeId = nodeManager.getNodeId(taskId, "task");
139142
const targetInputId = inputNameToInputId(inputName);
140-
const targetHandleNodeId = nodeManager.getNodeId(targetInputId, "input");
143+
const targetHandleNodeId = nodeManager.getNodeId(targetInputId, "taskInput");
141144

142145
return {
143146
id: `Input_${inputId}-${taskId}_${targetInputId}`,
@@ -162,11 +165,13 @@ const createOutputEdgesFromGraphSpec = (
162165
const sourceOutputId = outputNameToOutputId(taskOutput.outputName);
163166
const sourceHandleNodeId = nodeManager.getNodeId(
164167
sourceOutputId,
165-
"output",
168+
"taskOutput",
166169
);
167170
const targetOutputId = outputNameToOutputId(outputName);
168171
const targetNodeId = nodeManager.getNodeId(targetOutputId, "output");
169172

173+
// console.log({ sourceNodeId, targetNodeId, sourceHandleNodeId });
174+
170175
const edge: Edge = {
171176
id: `${taskOutput.taskId}_${sourceOutputId}-Output_${targetOutputId}`,
172177
source: sourceNodeId,

0 commit comments

Comments
 (0)