fix(graph): resolve multi-node selection bug by enforcing unique concept IDs and hardening JS logic
This commit is contained in:
@@ -17,7 +17,8 @@ public static class PromptRegistry
|
||||
"You are an expert at information architecture. Extract key concepts and their relationships from the text to build a knowledge graph. " +
|
||||
"CRITICAL: Restrict 'label' to a maximum of 3 words. " +
|
||||
"CRITICAL: Extract a MAXIMUM of 15 key concepts/plot points and their relationships. " +
|
||||
"CRITICAL: Each paragraph in the user text starts with [ID: some-id]. You MUST use these exact IDs as the 'id' for the nodes representing those blocks. " +
|
||||
"CRITICAL: Each paragraph in the user text starts with [ID: some-id]. Use these IDs ONLY for nodes representing the blocks. " +
|
||||
"CRITICAL: All other extracted 'concept' nodes MUST have unique, slug-style IDs based on their labels (e.g., 'dependency-injection'). " +
|
||||
"Include a 'current' node representing the block content itself if applicable. " +
|
||||
"CRITICAL: Limit the result to a MAXIMUM of 15 most relevant connections. " +
|
||||
"Return ONLY minified JSON. Schema: { \"graph\": { \"nodes\": [ { \"id\": \"string\", \"label\": \"string\", \"group\": \"concept|current\" } ], \"links\": [ { \"source\": \"string\", \"target\": \"string\", \"value\": 1 } ] } }";
|
||||
|
||||
@@ -247,6 +247,7 @@ function drag(simulation) {
|
||||
export function setActiveNode(nodeId) {
|
||||
if (!svgElement || !node) return;
|
||||
|
||||
// Safety check: ensure we only target the first occurrence if IDs are duplicated
|
||||
const targetNode = node.filter(d => d.id === nodeId);
|
||||
if (targetNode.empty()) {
|
||||
dimNodes(null);
|
||||
@@ -254,20 +255,21 @@ export function setActiveNode(nodeId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const d = targetNode.datum();
|
||||
const firstMatch = targetNode.filter((d, i) => i === 0);
|
||||
const d = firstMatch.datum();
|
||||
|
||||
// Reset all active classes
|
||||
rootGroup.selectAll(".node-pill").classed("nexus-node-active", false);
|
||||
targetNode.select(".node-pill").classed("nexus-node-active", true);
|
||||
firstMatch.select(".node-pill").classed("nexus-node-active", true);
|
||||
|
||||
// Position badge
|
||||
badge.style("display", "block").datum(d);
|
||||
badge.attr("transform", `translate(${d.x},${d.y})`);
|
||||
|
||||
// Dim others
|
||||
// Dim others (only exact matches for nodeId will be fully opaque)
|
||||
dimNodes(nodeId);
|
||||
|
||||
// Smooth transition
|
||||
// Smooth transition to the first matching node
|
||||
svgElement.transition().duration(1000).call(
|
||||
zoomBehavior.transform,
|
||||
d3.zoomIdentity.translate(width / 2, height / 2).scale(1.2).translate(-d.x, -d.y)
|
||||
|
||||
Reference in New Issue
Block a user