MCPcopy Create free account
hub / github.com/Zleap-AI/SAG / ProjectGraphCanvas

Function ProjectGraphCanvas

web/src/components/ProjectGraphFlow.tsx:69–308  ·  view source on GitHub ↗
(props: {
  graph: ProjectGraphRecord;
  language: SupportedLanguage;
  onOpenEvent: (eventId: string) => void;
  onOpenEntity: (entityId: string) => void;
})

Source from the content-addressed store, hash-verified

67}
68
69function ProjectGraphCanvas(props: {
70 graph: ProjectGraphRecord;
71 language: SupportedLanguage;
72 onOpenEvent: (eventId: string) => void;
73 onOpenEntity: (entityId: string) => void;
74}) {
75 const initialEntityIds = useMemo(
76 () => new Set(props.graph.entities.slice(0, ROOT_ENTITY_LIMIT).map((entity) => entity.id)),
77 [props.graph.entities]
78 );
79 const [expandedEntityIds, setExpandedEntityIds] = useState<Set<string>>(
80 () => new Set(props.graph.entities[0] ? [props.graph.entities[0].id] : [])
81 );
82 const [expandedEventIds, setExpandedEventIds] = useState<Set<string>>(new Set());
83 const [selectedNodeId, setSelectedNodeId] = useState<string | null>(null);
84 const expandedEntityIdsRef = useRef(expandedEntityIds);
85 const expandedEventIdsRef = useRef(expandedEventIds);
86 const [nodes, setNodes, onNodesChange] = useNodesState<GraphNode>([]);
87 const [edges, setEdges, onEdgesChange] = useEdgesState<GraphEdge>([]);
88 const { fitView } = useReactFlow<GraphNode, GraphEdge>();
89 const clickTimerRef = useRef<number | null>(null);
90 const shouldFitViewRef = useRef(true);
91
92 const entityById = useMemo(
93 () => new Map(props.graph.entities.map((entity) => [entity.id, entity])),
94 [props.graph.entities]
95 );
96 const eventById = useMemo(
97 () => new Map(props.graph.events.map((event) => [event.id, event])),
98 [props.graph.events]
99 );
100 const eventIdsByEntityId = useMemo(() => {
101 const map = new Map<string, string[]>();
102 for (const edge of props.graph.edges) {
103 const eventIds = map.get(edge.entityId) ?? [];
104 eventIds.push(edge.eventId);
105 map.set(edge.entityId, eventIds);
106 }
107 for (const [entityId, eventIds] of map.entries()) {
108 eventIds.sort((a, b) => compareEvents(eventById.get(a), eventById.get(b)));
109 map.set(entityId, eventIds);
110 }
111 return map;
112 }, [eventById, props.graph.edges]);
113 const entityIdsByEventId = useMemo(() => {
114 const map = new Map<string, string[]>();
115 for (const edge of props.graph.edges) {
116 const entityIds = map.get(edge.eventId) ?? [];
117 entityIds.push(edge.entityId);
118 map.set(edge.eventId, entityIds);
119 }
120 for (const [eventId, entityIds] of map.entries()) {
121 entityIds.sort((a, b) => compareEntities(entityById.get(a), entityById.get(b)));
122 map.set(eventId, entityIds);
123 }
124 return map;
125 }, [entityById, props.graph.edges]);
126 const positionByNodeId = useMemo(

Callers

nothing calls this directly

Calls 6

compareEventsFunction · 0.85
compareEntitiesFunction · 0.85
buildCircularPositionMapFunction · 0.85
buildVisibleGraphFunction · 0.85
clearClickTimerFunction · 0.85
graphTextFunction · 0.85

Tested by

no test coverage detected