AgentGraph / frontend /src /components /features /workspace /SimpleGraphVisualization.tsx
wu981526092's picture
feat: optimize graph visualization sizes for better UI layout
cc3c5e9
import React, { useEffect, useRef } from "react";
import { KnowledgeGraph, Entity, Relation } from "@/types";
import { detectSchemaType } from "@/lib/schema-detection";
interface SimpleGraphVisualizationProps {
knowledgeGraph: KnowledgeGraph;
width?: number;
height?: number;
graphData?: {
entities: Entity[];
relations: Relation[];
metadata?: Record<string, any>;
} | null;
}
export function SimpleGraphVisualization({
knowledgeGraph,
width = 500,
height = 350,
graphData,
}: SimpleGraphVisualizationProps) {
const svgRef = useRef<SVGSVGElement>(null);
useEffect(() => {
if (!svgRef.current) return;
// Clear previous content
const svg = svgRef.current;
svg.innerHTML = "";
// Only render if we have real data
if (!graphData || !graphData.entities || !graphData.relations) {
return; // Don't render anything if no data
}
// Detect schema type for future enhancements
const schemaType = detectSchemaType(graphData);
console.log("SimpleGraphVisualization: Detected schema type:", schemaType);
// Use real data
const nodes = graphData.entities.map((entity, index) => ({
id: entity.id,
name: entity.name,
type: entity.type,
x: 100 + (index % 4) * 120, // Simple grid layout
y: 100 + Math.floor(index / 4) * 100,
}));
const links = graphData.relations.map((relation) => ({
source: relation.source,
target: relation.target,
type: relation.type,
}));
// Create SVG elements
const g = document.createElementNS("http://www.w3.org/2000/svg", "g");
svg.appendChild(g);
// Draw links
links.forEach((link) => {
const sourceNode = nodes.find((n) => n.id === link.source);
const targetNode = nodes.find((n) => n.id === link.target);
if (sourceNode && targetNode) {
const line = document.createElementNS(
"http://www.w3.org/2000/svg",
"line"
);
line.setAttribute("x1", sourceNode.x.toString());
line.setAttribute("y1", sourceNode.y.toString());
line.setAttribute("x2", targetNode.x.toString());
line.setAttribute("y2", targetNode.y.toString());
line.setAttribute("stroke", "#94a3b8");
line.setAttribute("stroke-width", "2");
g.appendChild(line);
// Add link label
const text = document.createElementNS(
"http://www.w3.org/2000/svg",
"text"
);
text.setAttribute("x", ((sourceNode.x + targetNode.x) / 2).toString());
text.setAttribute("y", ((sourceNode.y + targetNode.y) / 2).toString());
text.setAttribute("text-anchor", "middle");
text.setAttribute("font-size", "10");
text.setAttribute("fill", "#6b7280");
text.textContent = link.type.replace("_", " ");
g.appendChild(text);
}
});
// Draw nodes
nodes.forEach((node) => {
const nodeGroup = document.createElementNS(
"http://www.w3.org/2000/svg",
"g"
);
// Node circle
const circle = document.createElementNS(
"http://www.w3.org/2000/svg",
"circle"
);
circle.setAttribute("cx", node.x.toString());
circle.setAttribute("cy", node.y.toString());
circle.setAttribute("r", "20");
circle.setAttribute("fill", getNodeColor(node.type));
circle.setAttribute("stroke", "#ffffff");
circle.setAttribute("stroke-width", "2");
nodeGroup.appendChild(circle);
// Node label
const text = document.createElementNS(
"http://www.w3.org/2000/svg",
"text"
);
text.setAttribute("x", node.x.toString());
text.setAttribute("y", (node.y + 35).toString());
text.setAttribute("text-anchor", "middle");
text.setAttribute("font-size", "12");
text.setAttribute("font-weight", "bold");
text.setAttribute("fill", "#1f2937");
text.textContent = node.name;
nodeGroup.appendChild(text);
// Node type
const typeText = document.createElementNS(
"http://www.w3.org/2000/svg",
"text"
);
typeText.setAttribute("x", node.x.toString());
typeText.setAttribute("y", (node.y + 50).toString());
typeText.setAttribute("text-anchor", "middle");
typeText.setAttribute("font-size", "10");
typeText.setAttribute("fill", "#6b7280");
typeText.textContent = node.type;
nodeGroup.appendChild(typeText);
g.appendChild(nodeGroup);
});
}, [knowledgeGraph, graphData]);
const getNodeColor = (type: string): string => {
switch (type) {
case "person":
return "#3b82f6";
case "organization":
return "#10b981";
case "location":
return "#f59e0b";
case "concept":
return "#8b5cf6";
case "event":
return "#ef4444";
default:
return "#6b7280";
}
};
// Use real counts if available
const entityCount =
graphData?.entities?.length || knowledgeGraph.entity_count || 0;
const relationCount =
graphData?.relations?.length || knowledgeGraph.relation_count || 0;
return (
<div className="flex flex-col items-center space-y-4">
<div className="text-center">
<h3 className="text-lg font-semibold">Agent Graph Visualization</h3>
<p className="text-sm text-muted-foreground">
{entityCount} entities, {relationCount} relationships
</p>
</div>
<div className="border rounded-lg p-4 bg-gray-50">
<svg
ref={svgRef}
width={width}
height={height}
className="bg-white rounded"
style={{ maxWidth: "100%", height: "auto" }}
>
{/* Content will be generated dynamically */}
</svg>
</div>
<div className="text-xs text-muted-foreground text-center">
<p>Interactive visualization - Click and drag nodes to explore</p>
<p>Colors represent different entity types</p>
</div>
</div>
);
}