From b5dd3fd2c3a318ea8bad4dc45a58d87ed29ddf2b Mon Sep 17 00:00:00 2001 From: Curtis Bangert Date: Thu, 31 Jul 2025 15:34:32 -0400 Subject: [PATCH 1/2] fix: corrects issues with edge rendering on the graph view --- .../ui/src/components/Graph/useGraphLayout.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/airflow-core/src/airflow/ui/src/components/Graph/useGraphLayout.ts b/airflow-core/src/airflow/ui/src/components/Graph/useGraphLayout.ts index d34491612c16e..73d17c12355c6 100644 --- a/airflow-core/src/airflow/ui/src/components/Graph/useGraphLayout.ts +++ b/airflow-core/src/airflow/ui/src/components/Graph/useGraphLayout.ts @@ -210,7 +210,20 @@ const generateElkGraph = ({ const children = nodes.map(formatChildNode); - const edges = filteredEdges.map((fe) => formatElkEdge(fe, font)); + // Deduplicate edges that point to the same source/target + const edgeMap = new Map(); + + filteredEdges.forEach((edge) => { + const edgeKey = `${edge.source_id}-${edge.target_id}`; + + if (!edgeMap.has(edgeKey)) { + edgeMap.set(edgeKey, edge); + } + }); + + // Convert back to array and create formatted edges + const deduplicatedEdges = [...edgeMap.values()]; + const edges = deduplicatedEdges.map((fe) => formatElkEdge(fe, font)); return { children: children as Array, From f6a991a2d4f24afde33261ea7695a14cc5987917 Mon Sep 17 00:00:00 2001 From: Curtis Bangert Date: Sat, 9 Aug 2025 21:42:21 -0400 Subject: [PATCH 2/2] fix: moved edge deduplication logic to formatChildNode. --- .../ui/src/components/Graph/useGraphLayout.ts | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/airflow-core/src/airflow/ui/src/components/Graph/useGraphLayout.ts b/airflow-core/src/airflow/ui/src/components/Graph/useGraphLayout.ts index 73d17c12355c6..4dae977ff3c56 100644 --- a/airflow-core/src/airflow/ui/src/components/Graph/useGraphLayout.ts +++ b/airflow-core/src/airflow/ui/src/components/Graph/useGraphLayout.ts @@ -169,6 +169,8 @@ const generateElkGraph = ({ } if (!Boolean(isOpen) && node.children !== undefined) { + const seenEdges = new Set(); + filteredEdges = filteredEdges // Filter out internal group edges .filter((fe) => !(childIds.includes(fe.source_id) && childIds.includes(fe.target_id))) @@ -177,7 +179,18 @@ const generateElkGraph = ({ ...fe, source_id: childIds.includes(fe.source_id) ? node.id : fe.source_id, target_id: childIds.includes(fe.target_id) ? node.id : fe.target_id, - })); + })) + // Deduplicate edges based on source_id and target_id composite + .filter((fe) => { + const edgeKey = `${fe.source_id}-${fe.target_id}`; + + if (seenEdges.has(edgeKey)) { + return false; + } + seenEdges.add(edgeKey); + + return true; + }); closedGroupIds.push(node.id); } @@ -210,20 +223,7 @@ const generateElkGraph = ({ const children = nodes.map(formatChildNode); - // Deduplicate edges that point to the same source/target - const edgeMap = new Map(); - - filteredEdges.forEach((edge) => { - const edgeKey = `${edge.source_id}-${edge.target_id}`; - - if (!edgeMap.has(edgeKey)) { - edgeMap.set(edgeKey, edge); - } - }); - - // Convert back to array and create formatted edges - const deduplicatedEdges = [...edgeMap.values()]; - const edges = deduplicatedEdges.map((fe) => formatElkEdge(fe, font)); + const edges = filteredEdges.map((fe) => formatElkEdge(fe, font)); return { children: children as Array,