fix: implemented cycle check on isValidConnection (#8716)
* Implemented cycle check on isValidConnection * Implemented loop check if the loop done results in a loopcomponent loop
This commit is contained in:
parent
605928d308
commit
39af1ded5f
1 changed files with 64 additions and 15 deletions
|
|
@ -329,10 +329,11 @@ export function unselectAllNodesEdges(nodes: Node[], edges: Edge[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isValidConnection(
|
export function isValidConnection(
|
||||||
{ source, target, sourceHandle, targetHandle }: Connection,
|
connection: Connection,
|
||||||
nodes?: AllNodeType[],
|
nodes?: AllNodeType[],
|
||||||
edges?: EdgeType[],
|
edges?: EdgeType[],
|
||||||
): boolean {
|
): boolean {
|
||||||
|
const { source, target, sourceHandle, targetHandle } = connection;
|
||||||
if (source === target) {
|
if (source === target) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -342,6 +343,33 @@ export function isValidConnection(
|
||||||
|
|
||||||
const targetHandleObject: targetHandleType = scapeJSONParse(targetHandle!);
|
const targetHandleObject: targetHandleType = scapeJSONParse(targetHandle!);
|
||||||
const sourceHandleObject: sourceHandleType = scapeJSONParse(sourceHandle!);
|
const sourceHandleObject: sourceHandleType = scapeJSONParse(sourceHandle!);
|
||||||
|
|
||||||
|
// Helper to find the edge between two nodes
|
||||||
|
function findEdgeBetween(srcId: string, tgtId: string) {
|
||||||
|
return edgesArray.find((e) => e.source === srcId && e.target === tgtId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modified hasCycle to return the path of edges forming the loop
|
||||||
|
const findCyclePath = (
|
||||||
|
node: AllNodeType,
|
||||||
|
visited = new Set(),
|
||||||
|
path: EdgeType[] = [],
|
||||||
|
): EdgeType[] | null => {
|
||||||
|
if (visited.has(node.id)) return null;
|
||||||
|
visited.add(node.id);
|
||||||
|
for (const outgoer of getOutgoers(node, nodesArray, edgesArray)) {
|
||||||
|
const edge = findEdgeBetween(node.id, outgoer.id);
|
||||||
|
if (!edge) continue;
|
||||||
|
if (outgoer.id === source) {
|
||||||
|
// This edge would close the loop
|
||||||
|
return [...path, edge];
|
||||||
|
}
|
||||||
|
const result = findCyclePath(outgoer, visited, [...path, edge]);
|
||||||
|
if (result) return result;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
if (
|
if (
|
||||||
targetHandleObject.inputTypes?.some(
|
targetHandleObject.inputTypes?.some(
|
||||||
(n) => n === sourceHandleObject.dataType,
|
(n) => n === sourceHandleObject.dataType,
|
||||||
|
|
@ -359,22 +387,43 @@ export function isValidConnection(
|
||||||
t === targetHandleObject.type,
|
t === targetHandleObject.type,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
let targetNode = nodesArray.find((node) => node.id === target!)?.data?.node;
|
let targetNode = nodesArray.find((node) => node.id === target!);
|
||||||
if (!targetNode) {
|
let targetNodeDataNode = targetNode?.data?.node;
|
||||||
if (!edgesArray.find((e) => e.targetHandle === targetHandle)) {
|
if (
|
||||||
|
(!targetNodeDataNode &&
|
||||||
|
!edgesArray.find((e) => e.targetHandle === targetHandle)) ||
|
||||||
|
(targetNodeDataNode &&
|
||||||
|
targetHandleObject.output_types &&
|
||||||
|
!edgesArray.find((e) => e.targetHandle === targetHandle)) ||
|
||||||
|
(targetNodeDataNode &&
|
||||||
|
!targetHandleObject.output_types &&
|
||||||
|
((!targetNodeDataNode.template[targetHandleObject.fieldName].list &&
|
||||||
|
!edgesArray.find((e) => e.targetHandle === targetHandle)) ||
|
||||||
|
targetNodeDataNode.template[targetHandleObject.fieldName].list))
|
||||||
|
) {
|
||||||
|
// If the current target handle is a loop component, allow connection immediately
|
||||||
|
if (targetHandleObject.output_types) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (
|
// Check for loop and if any edge in the loop is a loop component
|
||||||
targetHandleObject.output_types &&
|
let cyclePath: EdgeType[] | null = null;
|
||||||
!edgesArray.find((e) => e.targetHandle === targetHandle)
|
if (targetNode) {
|
||||||
) {
|
cyclePath = findCyclePath(targetNode);
|
||||||
return true;
|
}
|
||||||
} else if (
|
if (cyclePath) {
|
||||||
!targetHandleObject.output_types &&
|
// Check if any edge in the cycle path is a loop component
|
||||||
((!targetNode.template[targetHandleObject.fieldName].list &&
|
const hasLoopComponent = cyclePath.some((edge) => {
|
||||||
!edgesArray.find((e) => e.targetHandle === targetHandle)) ||
|
try {
|
||||||
targetNode.template[targetHandleObject.fieldName].list)
|
const th = scapeJSONParse(edge.targetHandle!);
|
||||||
) {
|
return !!th.output_types;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!hasLoopComponent) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue