bigwolfe commited on
Commit
044ec7f
·
1 Parent(s): 40fe67e

graph working

Browse files
frontend/package-lock.json CHANGED
@@ -21,6 +21,7 @@
21
  "@radix-ui/react-tooltip": "^1.2.8",
22
  "@tailwindcss/typography": "^0.5.19",
23
  "cmdk": "^1.1.1",
 
24
  "react": "^19.2.0",
25
  "react-dom": "^19.2.0",
26
  "react-force-graph-2d": "^1.29.0",
@@ -4629,6 +4630,20 @@
4629
  "node": ">=12"
4630
  }
4631
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4632
  "node_modules/d3-force-3d": {
4633
  "version": "3.0.6",
4634
  "resolved": "https://registry.npmjs.org/d3-force-3d/-/d3-force-3d-3.0.6.tgz",
 
21
  "@radix-ui/react-tooltip": "^1.2.8",
22
  "@tailwindcss/typography": "^0.5.19",
23
  "cmdk": "^1.1.1",
24
+ "d3-force": "^3.0.0",
25
  "react": "^19.2.0",
26
  "react-dom": "^19.2.0",
27
  "react-force-graph-2d": "^1.29.0",
 
4630
  "node": ">=12"
4631
  }
4632
  },
4633
+ "node_modules/d3-force": {
4634
+ "version": "3.0.0",
4635
+ "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz",
4636
+ "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==",
4637
+ "license": "ISC",
4638
+ "dependencies": {
4639
+ "d3-dispatch": "1 - 3",
4640
+ "d3-quadtree": "1 - 3",
4641
+ "d3-timer": "1 - 3"
4642
+ },
4643
+ "engines": {
4644
+ "node": ">=12"
4645
+ }
4646
+ },
4647
  "node_modules/d3-force-3d": {
4648
  "version": "3.0.6",
4649
  "resolved": "https://registry.npmjs.org/d3-force-3d/-/d3-force-3d-3.0.6.tgz",
frontend/package.json CHANGED
@@ -23,6 +23,7 @@
23
  "@radix-ui/react-tooltip": "^1.2.8",
24
  "@tailwindcss/typography": "^0.5.19",
25
  "cmdk": "^1.1.1",
 
26
  "react": "^19.2.0",
27
  "react-dom": "^19.2.0",
28
  "react-force-graph-2d": "^1.29.0",
 
23
  "@radix-ui/react-tooltip": "^1.2.8",
24
  "@tailwindcss/typography": "^0.5.19",
25
  "cmdk": "^1.1.1",
26
+ "d3-force": "^3.0.0",
27
  "react": "^19.2.0",
28
  "react-dom": "^19.2.0",
29
  "react-force-graph-2d": "^1.29.0",
frontend/src/components/GraphView.tsx CHANGED
@@ -1,5 +1,6 @@
1
  import { useEffect, useRef, useState, useMemo } from 'react';
2
  import ForceGraph2D, { type ForceGraphMethods } from 'react-force-graph-2d';
 
3
  import type { GraphData, GraphNode } from '@/types/graph';
4
  import { getGraphData } from '@/services/api';
5
  import { Loader2, AlertCircle } from 'lucide-react';
@@ -72,6 +73,33 @@ export function GraphView({ onSelectNote }: GraphViewProps) {
72
  fetchData();
73
  }, []);
74
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  // Simple hash for categorical colors
76
  const getGroupColor = (group: string) => {
77
  let hash = 0;
@@ -124,15 +152,16 @@ export function GraphView({ onSelectNote }: GraphViewProps) {
124
  nodeLabel="label"
125
  nodeColor={(node: any) => node.group && node.group !== 'root' ? getGroupColor(node.group) : defaultNodeColor}
126
  linkColor={() => linkColor}
 
127
  backgroundColor={backgroundColor}
128
  onNodeClick={handleNodeClick}
129
  nodeRelSize={6}
130
  linkDirectionalParticles={2}
131
- linkDirectionalParticleSpeed={0.005}
 
132
  width={window.innerWidth * 0.75} // Approximate width, needs resize observer for true responsiveness
 
133
  height={window.innerHeight - 60} // Approximate height minus header
134
- // Basic forces to keep structure
135
- d3Force={('charge', -120)}
136
  />
137
  </div>
138
  );
 
1
  import { useEffect, useRef, useState, useMemo } from 'react';
2
  import ForceGraph2D, { type ForceGraphMethods } from 'react-force-graph-2d';
3
+ import { forceRadial } from 'd3-force';
4
  import type { GraphData, GraphNode } from '@/types/graph';
5
  import { getGraphData } from '@/services/api';
6
  import { Loader2, AlertCircle } from 'lucide-react';
 
73
  fetchData();
74
  }, []);
75
 
76
+ // Configure forces when data is loaded
77
+ useEffect(() => {
78
+ if (!isLoading && graphRef.current) {
79
+ // Configure forces
80
+ // Increase repulsion to spread out clusters
81
+ graphRef.current.d3Force('charge')?.strength(-400);
82
+ // Adjust link distance
83
+ graphRef.current.d3Force('link')?.distance(60);
84
+
85
+ // Add "valence shell" for orphans (nodes with val=1)
86
+ // Pulls them to a ring at radius 300
87
+ graphRef.current.d3Force(
88
+ 'valence',
89
+ forceRadial(300, 0, 0).strength((node: any) => node.val === 1 ? 0.1 : 0)
90
+ );
91
+
92
+ // Add collision detection to prevent overlap
93
+ // @ts-ignore - d3 types might not be fully exposed
94
+ if (!graphRef.current.d3Force('collide')) {
95
+ // dynamic import of d3 would be needed to create new forces if not default
96
+ }
97
+
98
+ // Warmup the engine
99
+ graphRef.current.d3ReheatSimulation();
100
+ }
101
+ }, [data, isLoading]);
102
+
103
  // Simple hash for categorical colors
104
  const getGroupColor = (group: string) => {
105
  let hash = 0;
 
152
  nodeLabel="label"
153
  nodeColor={(node: any) => node.group && node.group !== 'root' ? getGroupColor(node.group) : defaultNodeColor}
154
  linkColor={() => linkColor}
155
+ linkWidth={3} //width of links between nodes
156
  backgroundColor={backgroundColor}
157
  onNodeClick={handleNodeClick}
158
  nodeRelSize={6}
159
  linkDirectionalParticles={2}
160
+ linkDirectionalParticleWidth={7}
161
+ linkDirectionalParticleSpeed={0.0025}
162
  width={window.innerWidth * 0.75} // Approximate width, needs resize observer for true responsiveness
163
+
164
  height={window.innerHeight - 60} // Approximate height minus header
 
 
165
  />
166
  </div>
167
  );