yangdx commited on
Commit
88fc1cb
·
1 Parent(s): 366bdb7

refactor: remove legacy node expansion and pruning methods from graph store

Browse files
Files changed (1) hide show
  1. lightrag_webui/src/stores/graph.ts +2 -252
lightrag_webui/src/stores/graph.ts CHANGED
@@ -107,7 +107,7 @@ interface GraphState {
107
  nodeToPrune: string | null
108
  }
109
 
110
- const useGraphStoreBase = create<GraphState>()((set, get) => ({
111
  selectedNode: null,
112
  focusedNode: null,
113
  selectedEdge: null,
@@ -148,7 +148,7 @@ const useGraphStoreBase = create<GraphState>()((set, get) => ({
148
  selectedEdge: null,
149
  focusedEdge: null,
150
  rawGraph: null,
151
- sigmaGraph: null, // 完全清除图形实例
152
  moveToSelectedNode: false,
153
  shouldRender: false
154
  });
@@ -195,256 +195,6 @@ const useGraphStoreBase = create<GraphState>()((set, get) => ({
195
  triggerNodeExpand: (nodeId: string | null) => set({ nodeToExpand: nodeId }),
196
  triggerNodePrune: (nodeId: string | null) => set({ nodeToPrune: nodeId }),
197
 
198
- // Legacy node expansion and pruning methods - will be removed after refactoring
199
- expandNode: async (nodeId: string) => {
200
- const state = get();
201
- if (!state.sigmaGraph || !state.rawGraph || !nodeId) {
202
- console.error('Cannot expand node: graph or node not available');
203
- return;
204
- }
205
-
206
- try {
207
- // Set fetching state
208
- state.setIsFetching(true);
209
-
210
- // Import queryGraphs dynamically to avoid circular dependency
211
- const { queryGraphs } = await import('@/api/lightrag');
212
-
213
- // Get the node to expand
214
- const nodeToExpand = state.rawGraph.getNode(nodeId);
215
- if (!nodeToExpand) {
216
- console.error('Node not found:', nodeId);
217
- state.setIsFetching(false);
218
- return;
219
- }
220
-
221
- // Get the label of the node to expand
222
- const label = nodeToExpand.labels[0];
223
- if (!label) {
224
- console.error('Node has no label:', nodeId);
225
- state.setIsFetching(false);
226
- return;
227
- }
228
-
229
- // Fetch the extended subgraph with depth 2
230
- const extendedGraph = await queryGraphs(label, 2, 0);
231
-
232
- if (!extendedGraph || !extendedGraph.nodes || !extendedGraph.edges) {
233
- console.error('Failed to fetch extended graph');
234
- state.setIsFetching(false);
235
- return;
236
- }
237
-
238
- // Process nodes to add required properties for RawNodeType
239
- const processedNodes: RawNodeType[] = [];
240
- for (const node of extendedGraph.nodes) {
241
- // Generate random color
242
- const randomColorValue = () => Math.floor(Math.random() * 256);
243
- const color = `rgb(${randomColorValue()}, ${randomColorValue()}, ${randomColorValue()})`;
244
-
245
- // Create a properly typed RawNodeType
246
- processedNodes.push({
247
- id: node.id,
248
- labels: node.labels,
249
- properties: node.properties,
250
- size: 10, // Default size
251
- x: Math.random(), // Random position
252
- y: Math.random(), // Random position
253
- color: color, // Random color
254
- degree: 0 // Initial degree
255
- });
256
- }
257
-
258
- // Process edges to add required properties for RawEdgeType
259
- const processedEdges: RawEdgeType[] = [];
260
- for (const edge of extendedGraph.edges) {
261
- // Create a properly typed RawEdgeType
262
- processedEdges.push({
263
- id: edge.id,
264
- source: edge.source,
265
- target: edge.target,
266
- type: edge.type,
267
- properties: edge.properties,
268
- dynamicId: '' // Will be set when adding to sigma graph
269
- });
270
- }
271
-
272
- // Store current node positions
273
- const nodePositions: Record<string, {x: number, y: number}> = {};
274
- state.sigmaGraph.forEachNode((node) => {
275
- nodePositions[node] = {
276
- x: state.sigmaGraph!.getNodeAttribute(node, 'x'),
277
- y: state.sigmaGraph!.getNodeAttribute(node, 'y')
278
- };
279
- });
280
-
281
- // Get existing node IDs
282
- const existingNodeIds = new Set(state.sigmaGraph.nodes());
283
-
284
- // Create a map from id to processed node for quick lookup
285
- const processedNodeMap = new Map<string, RawNodeType>();
286
- for (const node of processedNodes) {
287
- processedNodeMap.set(node.id, node);
288
- }
289
-
290
- // Create a map from id to processed edge for quick lookup
291
- const processedEdgeMap = new Map<string, RawEdgeType>();
292
- for (const edge of processedEdges) {
293
- processedEdgeMap.set(edge.id, edge);
294
- }
295
-
296
- // Add new nodes from the processed nodes
297
- for (const newNode of processedNodes) {
298
- // Skip if node already exists
299
- if (existingNodeIds.has(newNode.id)) {
300
- continue;
301
- }
302
-
303
- // Check if this node is connected to the selected node
304
- const isConnected = processedEdges.some(
305
- edge => (edge.source === nodeId && edge.target === newNode.id) ||
306
- (edge.target === nodeId && edge.source === newNode.id)
307
- );
308
-
309
- if (isConnected) {
310
- // Add the new node to the graph
311
- state.sigmaGraph.addNode(newNode.id, {
312
- label: newNode.labels.join(', '),
313
- color: newNode.color,
314
- x: nodePositions[nodeId].x + (Math.random() - 0.5) * 0.5,
315
- y: nodePositions[nodeId].y + (Math.random() - 0.5) * 0.5,
316
- size: newNode.size,
317
- borderColor: '#000',
318
- borderSize: 0.2
319
- });
320
-
321
- // Add the node to the raw graph
322
- if (!state.rawGraph.getNode(newNode.id)) {
323
- // Add to nodes array
324
- state.rawGraph.nodes.push(newNode);
325
- // Update nodeIdMap
326
- state.rawGraph.nodeIdMap[newNode.id] = state.rawGraph.nodes.length - 1;
327
- }
328
- }
329
- }
330
-
331
- // Add new edges
332
- for (const newEdge of processedEdges) {
333
- // Only add edges where both source and target exist in the graph
334
- if (state.sigmaGraph.hasNode(newEdge.source) && state.sigmaGraph.hasNode(newEdge.target)) {
335
- // Skip if edge already exists
336
- if (state.sigmaGraph.hasEdge(newEdge.source, newEdge.target)) {
337
- continue;
338
- }
339
-
340
- // Add the edge to the sigma graph
341
- newEdge.dynamicId = state.sigmaGraph.addDirectedEdge(newEdge.source, newEdge.target, {
342
- label: newEdge.type || undefined
343
- });
344
-
345
- // Add the edge to the raw graph
346
- if (!state.rawGraph.getEdge(newEdge.id, false)) {
347
- // Add to edges array
348
- state.rawGraph.edges.push(newEdge);
349
- // Update edgeIdMap
350
- state.rawGraph.edgeIdMap[newEdge.id] = state.rawGraph.edges.length - 1;
351
- // Update dynamic edge map
352
- state.rawGraph.edgeDynamicIdMap[newEdge.dynamicId] = state.rawGraph.edges.length - 1;
353
- }
354
- }
355
- }
356
-
357
- // Update the dynamic edge map
358
- state.rawGraph.buildDynamicMap();
359
-
360
- // Restore positions for existing nodes
361
- Object.entries(nodePositions).forEach(([nodeId, position]) => {
362
- if (state.sigmaGraph!.hasNode(nodeId)) {
363
- state.sigmaGraph!.setNodeAttribute(nodeId, 'x', position.x);
364
- state.sigmaGraph!.setNodeAttribute(nodeId, 'y', position.y);
365
- }
366
- });
367
-
368
- } catch (error) {
369
- console.error('Error expanding node:', error);
370
- } finally {
371
- // Reset fetching state
372
- state.setIsFetching(false);
373
- }
374
- },
375
-
376
- pruneNode: (nodeId: string) => {
377
- const state = get();
378
- if (!state.sigmaGraph || !state.rawGraph || !nodeId) {
379
- console.error('Cannot prune node: graph or node not available');
380
- return;
381
- }
382
-
383
- try {
384
- // Check if the node exists
385
- if (!state.sigmaGraph.hasNode(nodeId)) {
386
- console.error('Node not found:', nodeId);
387
- return;
388
- }
389
-
390
- // If the node is selected or focused, clear selection
391
- if (state.selectedNode === nodeId || state.focusedNode === nodeId) {
392
- state.clearSelection();
393
- }
394
-
395
- // Remove the node from the sigma graph (this will also remove connected edges)
396
- state.sigmaGraph.dropNode(nodeId);
397
-
398
- // Remove the node from the raw graph
399
- const nodeIndex = state.rawGraph.nodeIdMap[nodeId];
400
- if (nodeIndex !== undefined) {
401
- // Find all edges connected to this node
402
- const edgesToRemove = state.rawGraph.edges.filter(
403
- edge => edge.source === nodeId || edge.target === nodeId
404
- );
405
-
406
- // Remove edges from raw graph
407
- for (const edge of edgesToRemove) {
408
- const edgeIndex = state.rawGraph.edgeIdMap[edge.id];
409
- if (edgeIndex !== undefined) {
410
- // Remove from edges array
411
- state.rawGraph.edges.splice(edgeIndex, 1);
412
- // Update edgeIdMap for all edges after this one
413
- for (const [id, idx] of Object.entries(state.rawGraph.edgeIdMap)) {
414
- if (idx > edgeIndex) {
415
- state.rawGraph.edgeIdMap[id] = idx - 1;
416
- }
417
- }
418
- // Remove from edgeIdMap
419
- delete state.rawGraph.edgeIdMap[edge.id];
420
- // Remove from edgeDynamicIdMap
421
- delete state.rawGraph.edgeDynamicIdMap[edge.dynamicId];
422
- }
423
- }
424
-
425
- // Remove node from nodes array
426
- state.rawGraph.nodes.splice(nodeIndex, 1);
427
-
428
- // Update nodeIdMap for all nodes after this one
429
- for (const [id, idx] of Object.entries(state.rawGraph.nodeIdMap)) {
430
- if (idx > nodeIndex) {
431
- state.rawGraph.nodeIdMap[id] = idx - 1;
432
- }
433
- }
434
-
435
- // Remove from nodeIdMap
436
- delete state.rawGraph.nodeIdMap[nodeId];
437
-
438
- // Rebuild the dynamic edge map
439
- state.rawGraph.buildDynamicMap();
440
- }
441
-
442
- // 图形更新后会自动触发重新布局
443
-
444
- } catch (error) {
445
- console.error('Error pruning node:', error);
446
- }
447
- }
448
  }))
449
 
450
  const useGraphStore = createSelectors(useGraphStoreBase)
 
107
  nodeToPrune: string | null
108
  }
109
 
110
+ const useGraphStoreBase = create<GraphState>()((set) => ({
111
  selectedNode: null,
112
  focusedNode: null,
113
  selectedEdge: null,
 
148
  selectedEdge: null,
149
  focusedEdge: null,
150
  rawGraph: null,
151
+ sigmaGraph: null, // to avoid other components from acccessing graph objects
152
  moveToSelectedNode: false,
153
  shouldRender: false
154
  });
 
195
  triggerNodeExpand: (nodeId: string | null) => set({ nodeToExpand: nodeId }),
196
  triggerNodePrune: (nodeId: string | null) => set({ nodeToPrune: nodeId }),
197
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
  }))
199
 
200
  const useGraphStore = createSelectors(useGraphStoreBase)