Spaces:
Sleeping
Sleeping
Commit ·
d737dbb
1
Parent(s): aa9b339
feat: implement 3D visualization toggle and Retrieval Context Preview
Browse files- frontend/package-lock.json +204 -0
- frontend/package.json +12 -9
- frontend/src/components/dashboard/MainQueryView.tsx +3 -0
- frontend/src/components/graph/ForceGraphWrapper.tsx +12 -2
- frontend/src/components/graph/GraphControls.tsx +11 -0
- frontend/src/components/graph/GraphVisualization.tsx +11 -5
- frontend/src/components/query/SourceToggle.tsx +22 -12
- frontend/src/store/graph.ts +4 -0
frontend/package-lock.json
CHANGED
|
@@ -16,9 +16,11 @@
|
|
| 16 |
"react": "^18.3.1",
|
| 17 |
"react-dom": "^18.3.1",
|
| 18 |
"react-force-graph-2d": "^1.25.5",
|
|
|
|
| 19 |
"react-markdown": "^9.0.1",
|
| 20 |
"recharts": "^2.12.7",
|
| 21 |
"tailwind-merge": "^2.4.0",
|
|
|
|
| 22 |
"zustand": "^4.5.4"
|
| 23 |
},
|
| 24 |
"devDependencies": {
|
|
@@ -26,6 +28,7 @@
|
|
| 26 |
"@types/node": "^20.14.13",
|
| 27 |
"@types/react": "^18.3.3",
|
| 28 |
"@types/react-dom": "^18.3.0",
|
|
|
|
| 29 |
"autoprefixer": "^10.4.19",
|
| 30 |
"eslint": "^8.57.0",
|
| 31 |
"eslint-config-next": "14.2.5",
|
|
@@ -57,6 +60,13 @@
|
|
| 57 |
"node": ">=6.9.0"
|
| 58 |
}
|
| 59 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 60 |
"node_modules/@eslint-community/eslint-utils": {
|
| 61 |
"version": "4.9.1",
|
| 62 |
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
|
|
@@ -661,12 +671,48 @@
|
|
| 661 |
"@types/react": "^18.0.0"
|
| 662 |
}
|
| 663 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 664 |
"node_modules/@types/unist": {
|
| 665 |
"version": "3.0.3",
|
| 666 |
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
|
| 667 |
"integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
|
| 668 |
"license": "MIT"
|
| 669 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 670 |
"node_modules/@typescript-eslint/parser": {
|
| 671 |
"version": "7.2.0",
|
| 672 |
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.2.0.tgz",
|
|
@@ -821,6 +867,22 @@
|
|
| 821 |
"linux"
|
| 822 |
]
|
| 823 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 824 |
"node_modules/accessor-fn": {
|
| 825 |
"version": "1.5.3",
|
| 826 |
"resolved": "https://registry.npmjs.org/accessor-fn/-/accessor-fn-1.5.3.tgz",
|
|
@@ -1923,6 +1985,18 @@
|
|
| 1923 |
"dev": true,
|
| 1924 |
"license": "BSD-2-Clause"
|
| 1925 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1926 |
"node_modules/data-view-buffer": {
|
| 1927 |
"version": "1.0.2",
|
| 1928 |
"resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
|
|
@@ -2911,6 +2985,13 @@
|
|
| 2911 |
"reusify": "^1.0.4"
|
| 2912 |
}
|
| 2913 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2914 |
"node_modules/file-entry-cache": {
|
| 2915 |
"version": "6.0.1",
|
| 2916 |
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
|
|
@@ -4610,6 +4691,13 @@
|
|
| 4610 |
"node": ">= 8"
|
| 4611 |
}
|
| 4612 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4613 |
"node_modules/micromark": {
|
| 4614 |
"version": "4.0.2",
|
| 4615 |
"resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz",
|
|
@@ -5258,6 +5346,44 @@
|
|
| 5258 |
"node": "^10 || ^12 || >=14"
|
| 5259 |
}
|
| 5260 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5261 |
"node_modules/node-exports-info": {
|
| 5262 |
"version": "1.6.2",
|
| 5263 |
"resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.2.tgz",
|
|
@@ -5690,6 +5816,18 @@
|
|
| 5690 |
"node": ">=18"
|
| 5691 |
}
|
| 5692 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5693 |
"node_modules/possible-typed-array-names": {
|
| 5694 |
"version": "1.1.0",
|
| 5695 |
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
|
|
@@ -6016,6 +6154,23 @@
|
|
| 6016 |
"react": "*"
|
| 6017 |
}
|
| 6018 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6019 |
"node_modules/react-is": {
|
| 6020 |
"version": "16.13.1",
|
| 6021 |
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
|
@@ -7096,6 +7251,55 @@
|
|
| 7096 |
"node": ">=0.8"
|
| 7097 |
}
|
| 7098 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7099 |
"node_modules/tiny-invariant": {
|
| 7100 |
"version": "1.3.3",
|
| 7101 |
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
|
|
|
|
| 16 |
"react": "^18.3.1",
|
| 17 |
"react-dom": "^18.3.1",
|
| 18 |
"react-force-graph-2d": "^1.25.5",
|
| 19 |
+
"react-force-graph-3d": "^1.29.1",
|
| 20 |
"react-markdown": "^9.0.1",
|
| 21 |
"recharts": "^2.12.7",
|
| 22 |
"tailwind-merge": "^2.4.0",
|
| 23 |
+
"three": "^0.185.1",
|
| 24 |
"zustand": "^4.5.4"
|
| 25 |
},
|
| 26 |
"devDependencies": {
|
|
|
|
| 28 |
"@types/node": "^20.14.13",
|
| 29 |
"@types/react": "^18.3.3",
|
| 30 |
"@types/react-dom": "^18.3.0",
|
| 31 |
+
"@types/three": "^0.185.1",
|
| 32 |
"autoprefixer": "^10.4.19",
|
| 33 |
"eslint": "^8.57.0",
|
| 34 |
"eslint-config-next": "14.2.5",
|
|
|
|
| 60 |
"node": ">=6.9.0"
|
| 61 |
}
|
| 62 |
},
|
| 63 |
+
"node_modules/@dimforge/rapier3d-compat": {
|
| 64 |
+
"version": "0.12.0",
|
| 65 |
+
"resolved": "https://registry.npmjs.org/@dimforge/rapier3d-compat/-/rapier3d-compat-0.12.0.tgz",
|
| 66 |
+
"integrity": "sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow==",
|
| 67 |
+
"dev": true,
|
| 68 |
+
"license": "Apache-2.0"
|
| 69 |
+
},
|
| 70 |
"node_modules/@eslint-community/eslint-utils": {
|
| 71 |
"version": "4.9.1",
|
| 72 |
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
|
|
|
|
| 671 |
"@types/react": "^18.0.0"
|
| 672 |
}
|
| 673 |
},
|
| 674 |
+
"node_modules/@types/stats.js": {
|
| 675 |
+
"version": "0.17.4",
|
| 676 |
+
"resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.4.tgz",
|
| 677 |
+
"integrity": "sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA==",
|
| 678 |
+
"dev": true,
|
| 679 |
+
"license": "MIT"
|
| 680 |
+
},
|
| 681 |
+
"node_modules/@types/three": {
|
| 682 |
+
"version": "0.185.1",
|
| 683 |
+
"resolved": "https://registry.npmjs.org/@types/three/-/three-0.185.1.tgz",
|
| 684 |
+
"integrity": "sha512-db1xTb+EgYF2didW+eudSvVPtn75zo+fGsY8ShQrJY/B5ZBmC2Fiaykv3aImHAlCNEGuMPkPGXBJGLwzu5mC7A==",
|
| 685 |
+
"dev": true,
|
| 686 |
+
"license": "MIT",
|
| 687 |
+
"dependencies": {
|
| 688 |
+
"@dimforge/rapier3d-compat": "~0.12.0",
|
| 689 |
+
"@tweenjs/tween.js": "~23.1.3",
|
| 690 |
+
"@types/stats.js": "*",
|
| 691 |
+
"@types/webxr": ">=0.5.17",
|
| 692 |
+
"fflate": "~0.8.2",
|
| 693 |
+
"meshoptimizer": "~1.1.1"
|
| 694 |
+
}
|
| 695 |
+
},
|
| 696 |
+
"node_modules/@types/three/node_modules/@tweenjs/tween.js": {
|
| 697 |
+
"version": "23.1.3",
|
| 698 |
+
"resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-23.1.3.tgz",
|
| 699 |
+
"integrity": "sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==",
|
| 700 |
+
"dev": true,
|
| 701 |
+
"license": "MIT"
|
| 702 |
+
},
|
| 703 |
"node_modules/@types/unist": {
|
| 704 |
"version": "3.0.3",
|
| 705 |
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
|
| 706 |
"integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
|
| 707 |
"license": "MIT"
|
| 708 |
},
|
| 709 |
+
"node_modules/@types/webxr": {
|
| 710 |
+
"version": "0.5.24",
|
| 711 |
+
"resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.24.tgz",
|
| 712 |
+
"integrity": "sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg==",
|
| 713 |
+
"dev": true,
|
| 714 |
+
"license": "MIT"
|
| 715 |
+
},
|
| 716 |
"node_modules/@typescript-eslint/parser": {
|
| 717 |
"version": "7.2.0",
|
| 718 |
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.2.0.tgz",
|
|
|
|
| 867 |
"linux"
|
| 868 |
]
|
| 869 |
},
|
| 870 |
+
"node_modules/3d-force-graph": {
|
| 871 |
+
"version": "1.80.0",
|
| 872 |
+
"resolved": "https://registry.npmjs.org/3d-force-graph/-/3d-force-graph-1.80.0.tgz",
|
| 873 |
+
"integrity": "sha512-tzI353gW1nXPpnC7VTa3JjMg+3cp77qOLUFO0vucPTfF+q5R6sQsNsIqVTbRIb7RSypn14nBa4yfkOe9ThxASw==",
|
| 874 |
+
"license": "MIT",
|
| 875 |
+
"dependencies": {
|
| 876 |
+
"accessor-fn": "1",
|
| 877 |
+
"kapsule": "^1.16",
|
| 878 |
+
"three": ">=0.179 <1",
|
| 879 |
+
"three-forcegraph": "1",
|
| 880 |
+
"three-render-objects": "^1.41"
|
| 881 |
+
},
|
| 882 |
+
"engines": {
|
| 883 |
+
"node": ">=12"
|
| 884 |
+
}
|
| 885 |
+
},
|
| 886 |
"node_modules/accessor-fn": {
|
| 887 |
"version": "1.5.3",
|
| 888 |
"resolved": "https://registry.npmjs.org/accessor-fn/-/accessor-fn-1.5.3.tgz",
|
|
|
|
| 1985 |
"dev": true,
|
| 1986 |
"license": "BSD-2-Clause"
|
| 1987 |
},
|
| 1988 |
+
"node_modules/data-bind-mapper": {
|
| 1989 |
+
"version": "1.0.3",
|
| 1990 |
+
"resolved": "https://registry.npmjs.org/data-bind-mapper/-/data-bind-mapper-1.0.3.tgz",
|
| 1991 |
+
"integrity": "sha512-QmU3lyEnbENQPo0M1F9BMu4s6cqNNp8iJA+b/HP2sSb7pf3dxwF3+EP1eO69rwBfH9kFJ1apmzrtogAmVt2/Xw==",
|
| 1992 |
+
"license": "MIT",
|
| 1993 |
+
"dependencies": {
|
| 1994 |
+
"accessor-fn": "1"
|
| 1995 |
+
},
|
| 1996 |
+
"engines": {
|
| 1997 |
+
"node": ">=12"
|
| 1998 |
+
}
|
| 1999 |
+
},
|
| 2000 |
"node_modules/data-view-buffer": {
|
| 2001 |
"version": "1.0.2",
|
| 2002 |
"resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
|
|
|
|
| 2985 |
"reusify": "^1.0.4"
|
| 2986 |
}
|
| 2987 |
},
|
| 2988 |
+
"node_modules/fflate": {
|
| 2989 |
+
"version": "0.8.3",
|
| 2990 |
+
"resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.3.tgz",
|
| 2991 |
+
"integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==",
|
| 2992 |
+
"dev": true,
|
| 2993 |
+
"license": "MIT"
|
| 2994 |
+
},
|
| 2995 |
"node_modules/file-entry-cache": {
|
| 2996 |
"version": "6.0.1",
|
| 2997 |
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
|
|
|
|
| 4691 |
"node": ">= 8"
|
| 4692 |
}
|
| 4693 |
},
|
| 4694 |
+
"node_modules/meshoptimizer": {
|
| 4695 |
+
"version": "1.1.1",
|
| 4696 |
+
"resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-1.1.1.tgz",
|
| 4697 |
+
"integrity": "sha512-oRFNWJRDA/WTrVj7NWvqa5HqE1t9MYDj2VaWirQCzCCrAd2GHrqR/sQezCxiWATPNlKTcRaPRHPJwIRoPBAp5g==",
|
| 4698 |
+
"dev": true,
|
| 4699 |
+
"license": "MIT"
|
| 4700 |
+
},
|
| 4701 |
"node_modules/micromark": {
|
| 4702 |
"version": "4.0.2",
|
| 4703 |
"resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz",
|
|
|
|
| 5346 |
"node": "^10 || ^12 || >=14"
|
| 5347 |
}
|
| 5348 |
},
|
| 5349 |
+
"node_modules/ngraph.events": {
|
| 5350 |
+
"version": "1.4.0",
|
| 5351 |
+
"resolved": "https://registry.npmjs.org/ngraph.events/-/ngraph.events-1.4.0.tgz",
|
| 5352 |
+
"integrity": "sha512-NeDGI4DSyjBNBRtA86222JoYietsmCXbs8CEB0dZ51Xeh4lhVl1y3wpWLumczvnha8sFQIW4E0vvVWwgmX2mGw==",
|
| 5353 |
+
"license": "BSD-3-Clause"
|
| 5354 |
+
},
|
| 5355 |
+
"node_modules/ngraph.forcelayout": {
|
| 5356 |
+
"version": "3.3.1",
|
| 5357 |
+
"resolved": "https://registry.npmjs.org/ngraph.forcelayout/-/ngraph.forcelayout-3.3.1.tgz",
|
| 5358 |
+
"integrity": "sha512-MKBuEh1wujyQHFTW57y5vd/uuEOK0XfXYxm3lC7kktjJLRdt/KEKEknyOlc6tjXflqBKEuYBBcu7Ax5VY+S6aw==",
|
| 5359 |
+
"license": "BSD-3-Clause",
|
| 5360 |
+
"dependencies": {
|
| 5361 |
+
"ngraph.events": "^1.0.0",
|
| 5362 |
+
"ngraph.merge": "^1.0.0",
|
| 5363 |
+
"ngraph.random": "^1.0.0"
|
| 5364 |
+
}
|
| 5365 |
+
},
|
| 5366 |
+
"node_modules/ngraph.graph": {
|
| 5367 |
+
"version": "20.1.2",
|
| 5368 |
+
"resolved": "https://registry.npmjs.org/ngraph.graph/-/ngraph.graph-20.1.2.tgz",
|
| 5369 |
+
"integrity": "sha512-W/G3GBR3Y5UxMLHTUCPP9v+pbtpzwuAEIqP5oZV+9IwgxAIEZwh+Foc60iPc1idlnK7Zxu0p3puxAyNmDvBd0Q==",
|
| 5370 |
+
"license": "BSD-3-Clause",
|
| 5371 |
+
"dependencies": {
|
| 5372 |
+
"ngraph.events": "^1.4.0"
|
| 5373 |
+
}
|
| 5374 |
+
},
|
| 5375 |
+
"node_modules/ngraph.merge": {
|
| 5376 |
+
"version": "1.0.0",
|
| 5377 |
+
"resolved": "https://registry.npmjs.org/ngraph.merge/-/ngraph.merge-1.0.0.tgz",
|
| 5378 |
+
"integrity": "sha512-5J8YjGITUJeapsomtTALYsw7rFveYkM+lBj3QiYZ79EymQcuri65Nw3knQtFxQBU1r5iOaVRXrSwMENUPK62Vg==",
|
| 5379 |
+
"license": "MIT"
|
| 5380 |
+
},
|
| 5381 |
+
"node_modules/ngraph.random": {
|
| 5382 |
+
"version": "1.2.0",
|
| 5383 |
+
"resolved": "https://registry.npmjs.org/ngraph.random/-/ngraph.random-1.2.0.tgz",
|
| 5384 |
+
"integrity": "sha512-4EUeAGbB2HWX9njd6bP6tciN6ByJfoaAvmVL9QTaZSeXrW46eNGA9GajiXiPBbvFqxUWFkEbyo6x5qsACUuVfA==",
|
| 5385 |
+
"license": "BSD-3-Clause"
|
| 5386 |
+
},
|
| 5387 |
"node_modules/node-exports-info": {
|
| 5388 |
"version": "1.6.2",
|
| 5389 |
"resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.2.tgz",
|
|
|
|
| 5816 |
"node": ">=18"
|
| 5817 |
}
|
| 5818 |
},
|
| 5819 |
+
"node_modules/polished": {
|
| 5820 |
+
"version": "4.3.1",
|
| 5821 |
+
"resolved": "https://registry.npmjs.org/polished/-/polished-4.3.1.tgz",
|
| 5822 |
+
"integrity": "sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==",
|
| 5823 |
+
"license": "MIT",
|
| 5824 |
+
"dependencies": {
|
| 5825 |
+
"@babel/runtime": "^7.17.8"
|
| 5826 |
+
},
|
| 5827 |
+
"engines": {
|
| 5828 |
+
"node": ">=10"
|
| 5829 |
+
}
|
| 5830 |
+
},
|
| 5831 |
"node_modules/possible-typed-array-names": {
|
| 5832 |
"version": "1.1.0",
|
| 5833 |
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
|
|
|
|
| 6154 |
"react": "*"
|
| 6155 |
}
|
| 6156 |
},
|
| 6157 |
+
"node_modules/react-force-graph-3d": {
|
| 6158 |
+
"version": "1.29.1",
|
| 6159 |
+
"resolved": "https://registry.npmjs.org/react-force-graph-3d/-/react-force-graph-3d-1.29.1.tgz",
|
| 6160 |
+
"integrity": "sha512-5Vp+PGpYnO+zLwgK2NvNqdXHvsWLrFzpDfJW1vUA1twjo9SPvXqfUYQrnRmAbD+K2tOxkZw1BkbH31l5b4TWHg==",
|
| 6161 |
+
"license": "MIT",
|
| 6162 |
+
"dependencies": {
|
| 6163 |
+
"3d-force-graph": "^1.79",
|
| 6164 |
+
"prop-types": "15",
|
| 6165 |
+
"react-kapsule": "^2.5"
|
| 6166 |
+
},
|
| 6167 |
+
"engines": {
|
| 6168 |
+
"node": ">=12"
|
| 6169 |
+
},
|
| 6170 |
+
"peerDependencies": {
|
| 6171 |
+
"react": "*"
|
| 6172 |
+
}
|
| 6173 |
+
},
|
| 6174 |
"node_modules/react-is": {
|
| 6175 |
"version": "16.13.1",
|
| 6176 |
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
|
|
|
| 7251 |
"node": ">=0.8"
|
| 7252 |
}
|
| 7253 |
},
|
| 7254 |
+
"node_modules/three": {
|
| 7255 |
+
"version": "0.185.1",
|
| 7256 |
+
"resolved": "https://registry.npmjs.org/three/-/three-0.185.1.tgz",
|
| 7257 |
+
"integrity": "sha512-5aojFCXKwnjBRZvUnt3WFfEcvUJgkN5LlijRFN95hMy8WVkG4I0QNcJE+OuWvuJ0bOdStrbfXn0pkd6/QyiAlg==",
|
| 7258 |
+
"license": "MIT"
|
| 7259 |
+
},
|
| 7260 |
+
"node_modules/three-forcegraph": {
|
| 7261 |
+
"version": "1.43.4",
|
| 7262 |
+
"resolved": "https://registry.npmjs.org/three-forcegraph/-/three-forcegraph-1.43.4.tgz",
|
| 7263 |
+
"integrity": "sha512-FtmiZP/T16ZQaHza3JDaDn0YTXFtg9e7pGnTeU8nzu0NNkx7MpWbF/GvmpbQsWHx3rukHtkRv1fTorLPB3FDEA==",
|
| 7264 |
+
"license": "MIT",
|
| 7265 |
+
"dependencies": {
|
| 7266 |
+
"accessor-fn": "1",
|
| 7267 |
+
"d3-array": "1 - 3",
|
| 7268 |
+
"d3-force-3d": "2 - 3",
|
| 7269 |
+
"d3-scale": "1 - 4",
|
| 7270 |
+
"d3-scale-chromatic": "1 - 3",
|
| 7271 |
+
"data-bind-mapper": "1",
|
| 7272 |
+
"kapsule": "^1.16",
|
| 7273 |
+
"ngraph.forcelayout": "3",
|
| 7274 |
+
"ngraph.graph": "20",
|
| 7275 |
+
"tinycolor2": "1"
|
| 7276 |
+
},
|
| 7277 |
+
"engines": {
|
| 7278 |
+
"node": ">=12"
|
| 7279 |
+
},
|
| 7280 |
+
"peerDependencies": {
|
| 7281 |
+
"three": ">=0.118.3"
|
| 7282 |
+
}
|
| 7283 |
+
},
|
| 7284 |
+
"node_modules/three-render-objects": {
|
| 7285 |
+
"version": "1.42.0",
|
| 7286 |
+
"resolved": "https://registry.npmjs.org/three-render-objects/-/three-render-objects-1.42.0.tgz",
|
| 7287 |
+
"integrity": "sha512-KYfkPrYGEbIK8ChFocWqOF1aAN80FBUBWVYB8mB2oBpVuVN+52FvvngVYB5ieFANQu7Rt21rPYZ/xKaAgVWWRQ==",
|
| 7288 |
+
"license": "MIT",
|
| 7289 |
+
"dependencies": {
|
| 7290 |
+
"@tweenjs/tween.js": "18 - 25",
|
| 7291 |
+
"accessor-fn": "1",
|
| 7292 |
+
"float-tooltip": "^1.7",
|
| 7293 |
+
"kapsule": "^1.16",
|
| 7294 |
+
"polished": "4"
|
| 7295 |
+
},
|
| 7296 |
+
"engines": {
|
| 7297 |
+
"node": ">=12"
|
| 7298 |
+
},
|
| 7299 |
+
"peerDependencies": {
|
| 7300 |
+
"three": ">=0.179"
|
| 7301 |
+
}
|
| 7302 |
+
},
|
| 7303 |
"node_modules/tiny-invariant": {
|
| 7304 |
"version": "1.3.3",
|
| 7305 |
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
|
frontend/package.json
CHANGED
|
@@ -11,30 +11,33 @@
|
|
| 11 |
"test:e2e:install": "playwright install --with-deps chromium"
|
| 12 |
},
|
| 13 |
"dependencies": {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
"next": "14.2.5",
|
| 15 |
"react": "^18.3.1",
|
| 16 |
"react-dom": "^18.3.1",
|
| 17 |
-
"zustand": "^4.5.4",
|
| 18 |
-
"axios": "^1.7.3",
|
| 19 |
"react-force-graph-2d": "^1.25.5",
|
| 20 |
-
"
|
| 21 |
"react-markdown": "^9.0.1",
|
| 22 |
-
"
|
| 23 |
-
"clsx": "^2.1.1",
|
| 24 |
"tailwind-merge": "^2.4.0",
|
| 25 |
-
"
|
|
|
|
| 26 |
},
|
| 27 |
"devDependencies": {
|
| 28 |
"@playwright/test": "^1.47.0",
|
| 29 |
"@types/node": "^20.14.13",
|
| 30 |
"@types/react": "^18.3.3",
|
| 31 |
"@types/react-dom": "^18.3.0",
|
|
|
|
| 32 |
"autoprefixer": "^10.4.19",
|
|
|
|
|
|
|
| 33 |
"postcss": "^8.4.40",
|
| 34 |
"tailwindcss": "^3.4.7",
|
| 35 |
"tailwindcss-animate": "^1.0.7",
|
| 36 |
-
"typescript": "^5.5.4"
|
| 37 |
-
"eslint": "^8.57.0",
|
| 38 |
-
"eslint-config-next": "14.2.5"
|
| 39 |
}
|
| 40 |
}
|
|
|
|
| 11 |
"test:e2e:install": "playwright install --with-deps chromium"
|
| 12 |
},
|
| 13 |
"dependencies": {
|
| 14 |
+
"axios": "^1.7.3",
|
| 15 |
+
"class-variance-authority": "^0.7.0",
|
| 16 |
+
"clsx": "^2.1.1",
|
| 17 |
+
"lucide-react": "^0.417.0",
|
| 18 |
"next": "14.2.5",
|
| 19 |
"react": "^18.3.1",
|
| 20 |
"react-dom": "^18.3.1",
|
|
|
|
|
|
|
| 21 |
"react-force-graph-2d": "^1.25.5",
|
| 22 |
+
"react-force-graph-3d": "^1.29.1",
|
| 23 |
"react-markdown": "^9.0.1",
|
| 24 |
+
"recharts": "^2.12.7",
|
|
|
|
| 25 |
"tailwind-merge": "^2.4.0",
|
| 26 |
+
"three": "^0.185.1",
|
| 27 |
+
"zustand": "^4.5.4"
|
| 28 |
},
|
| 29 |
"devDependencies": {
|
| 30 |
"@playwright/test": "^1.47.0",
|
| 31 |
"@types/node": "^20.14.13",
|
| 32 |
"@types/react": "^18.3.3",
|
| 33 |
"@types/react-dom": "^18.3.0",
|
| 34 |
+
"@types/three": "^0.185.1",
|
| 35 |
"autoprefixer": "^10.4.19",
|
| 36 |
+
"eslint": "^8.57.0",
|
| 37 |
+
"eslint-config-next": "14.2.5",
|
| 38 |
"postcss": "^8.4.40",
|
| 39 |
"tailwindcss": "^3.4.7",
|
| 40 |
"tailwindcss-animate": "^1.0.7",
|
| 41 |
+
"typescript": "^5.5.4"
|
|
|
|
|
|
|
| 42 |
}
|
| 43 |
}
|
frontend/src/components/dashboard/MainQueryView.tsx
CHANGED
|
@@ -23,6 +23,7 @@ interface QueryResult {
|
|
| 23 |
entities?: string[];
|
| 24 |
paths?: string[];
|
| 25 |
hops?: Hop[];
|
|
|
|
| 26 |
}
|
| 27 |
|
| 28 |
export function MainQueryView() {
|
|
@@ -68,6 +69,7 @@ export function MainQueryView() {
|
|
| 68 |
entities: res.highlighted_entities,
|
| 69 |
paths: res.paths,
|
| 70 |
hops: res.hops,
|
|
|
|
| 71 |
};
|
| 72 |
setResult(mapped);
|
| 73 |
setHighlighted(mapped.entities || [], mapped.paths || []);
|
|
@@ -142,6 +144,7 @@ export function MainQueryView() {
|
|
| 142 |
method={result.method || mode}
|
| 143 |
entityCount={result.entities?.length || 0}
|
| 144 |
chunkCount={result.citations?.length || 0}
|
|
|
|
| 145 |
/>
|
| 146 |
)}
|
| 147 |
</div>
|
|
|
|
| 23 |
entities?: string[];
|
| 24 |
paths?: string[];
|
| 25 |
hops?: Hop[];
|
| 26 |
+
context?: string;
|
| 27 |
}
|
| 28 |
|
| 29 |
export function MainQueryView() {
|
|
|
|
| 69 |
entities: res.highlighted_entities,
|
| 70 |
paths: res.paths,
|
| 71 |
hops: res.hops,
|
| 72 |
+
context: res.context,
|
| 73 |
};
|
| 74 |
setResult(mapped);
|
| 75 |
setHighlighted(mapped.entities || [], mapped.paths || []);
|
|
|
|
| 144 |
method={result.method || mode}
|
| 145 |
entityCount={result.entities?.length || 0}
|
| 146 |
chunkCount={result.citations?.length || 0}
|
| 147 |
+
context={result.context}
|
| 148 |
/>
|
| 149 |
)}
|
| 150 |
</div>
|
frontend/src/components/graph/ForceGraphWrapper.tsx
CHANGED
|
@@ -2,9 +2,19 @@
|
|
| 2 |
|
| 3 |
import React, { forwardRef } from 'react';
|
| 4 |
import ForceGraph2D from 'react-force-graph-2d';
|
|
|
|
| 5 |
|
| 6 |
-
|
| 7 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
});
|
| 9 |
|
| 10 |
ForceGraphWrapper.displayName = 'ForceGraphWrapper';
|
|
|
|
| 2 |
|
| 3 |
import React, { forwardRef } from 'react';
|
| 4 |
import ForceGraph2D from 'react-force-graph-2d';
|
| 5 |
+
import ForceGraph3D from 'react-force-graph-3d';
|
| 6 |
|
| 7 |
+
interface ForceGraphWrapperProps {
|
| 8 |
+
dim?: 2 | 3;
|
| 9 |
+
[key: string]: any;
|
| 10 |
+
}
|
| 11 |
+
|
| 12 |
+
const ForceGraphWrapper = forwardRef<any, ForceGraphWrapperProps>((props, ref) => {
|
| 13 |
+
const { dim = 2, ...rest } = props;
|
| 14 |
+
if (dim === 3) {
|
| 15 |
+
return <ForceGraph3D {...rest} ref={ref as any} />;
|
| 16 |
+
}
|
| 17 |
+
return <ForceGraph2D {...rest} ref={ref as any} />;
|
| 18 |
});
|
| 19 |
|
| 20 |
ForceGraphWrapper.displayName = 'ForceGraphWrapper';
|
frontend/src/components/graph/GraphControls.tsx
CHANGED
|
@@ -2,10 +2,21 @@
|
|
| 2 |
|
| 3 |
import { Plus, Minus, Maximize, Crosshair } from 'lucide-react';
|
| 4 |
import { graphController } from './graphController';
|
|
|
|
| 5 |
|
| 6 |
export function GraphControls() {
|
|
|
|
|
|
|
|
|
|
| 7 |
return (
|
| 8 |
<div className="absolute right-3 top-3 flex flex-col gap-1.5">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
<button
|
| 10 |
onClick={() => graphController.zoomIn?.()}
|
| 11 |
className="flex h-9 w-9 items-center justify-center rounded-md border border-border bg-bg-elevated/90 text-text-secondary shadow-sm backdrop-blur hover:text-text-primary"
|
|
|
|
| 2 |
|
| 3 |
import { Plus, Minus, Maximize, Crosshair } from 'lucide-react';
|
| 4 |
import { graphController } from './graphController';
|
| 5 |
+
import { useGraphStore } from '@/store/graph';
|
| 6 |
|
| 7 |
export function GraphControls() {
|
| 8 |
+
const dim = useGraphStore((s) => s.dim);
|
| 9 |
+
const setDim = useGraphStore((s) => s.setDim);
|
| 10 |
+
|
| 11 |
return (
|
| 12 |
<div className="absolute right-3 top-3 flex flex-col gap-1.5">
|
| 13 |
+
<button
|
| 14 |
+
onClick={() => setDim(dim === 2 ? 3 : 2)}
|
| 15 |
+
className="flex h-9 w-9 items-center justify-center rounded-md border border-border bg-bg-elevated/90 text-xs font-bold text-accent-cyan shadow-sm backdrop-blur hover:bg-bg-surface hover:text-text-primary transition-all duration-200"
|
| 16 |
+
aria-label="Toggle 2D/3D"
|
| 17 |
+
>
|
| 18 |
+
{dim === 2 ? '3D' : '2D'}
|
| 19 |
+
</button>
|
| 20 |
<button
|
| 21 |
onClick={() => graphController.zoomIn?.()}
|
| 22 |
className="flex h-9 w-9 items-center justify-center rounded-md border border-border bg-bg-elevated/90 text-text-secondary shadow-sm backdrop-blur hover:text-text-primary"
|
frontend/src/components/graph/GraphVisualization.tsx
CHANGED
|
@@ -34,6 +34,7 @@ export function GraphVisualization({ height = '100%' }: { height?: string | numb
|
|
| 34 |
const visibleRelationships = useGraphStore((s) => s.visibleRelationships);
|
| 35 |
const selectEntity = useGraphStore((s) => s.selectEntity);
|
| 36 |
const setHighlighted = useGraphStore((s) => s.setHighlighted);
|
|
|
|
| 37 |
|
| 38 |
const fgRef = useRef<any>(null);
|
| 39 |
const [hoverNode, setHoverNode] = useState<FGNode | null>(null);
|
|
@@ -42,10 +43,10 @@ export function GraphVisualization({ height = '100%' }: { height?: string | numb
|
|
| 42 |
const closeContextMenu = useCallback(() => setContextMenu(null), []);
|
| 43 |
|
| 44 |
useEffect(() => {
|
| 45 |
-
graphController.zoomIn = () => fgRef.current?.zoom(fgRef.current.zoom() * 1.4, 300);
|
| 46 |
-
graphController.zoomOut = () => fgRef.current?.zoom(fgRef.current.zoom() / 1.4, 300);
|
| 47 |
graphController.resetView = () => {
|
| 48 |
-
fgRef.current?.zoomToFit(400, 40);
|
| 49 |
};
|
| 50 |
}, []);
|
| 51 |
|
|
@@ -99,8 +100,12 @@ export function GraphVisualization({ height = '100%' }: { height?: string | numb
|
|
| 99 |
);
|
| 100 |
setSearchHit(match ? (match as any).id : null);
|
| 101 |
if (match && fgRef.current) {
|
| 102 |
-
fgRef.current.centerAt
|
| 103 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 104 |
}
|
| 105 |
}, [searchTerm, graphData.nodes]);
|
| 106 |
|
|
@@ -108,6 +113,7 @@ export function GraphVisualization({ height = '100%' }: { height?: string | numb
|
|
| 108 |
<div className="graph-canvas relative h-full w-full" style={{ height }}>
|
| 109 |
<ForceGraph2D
|
| 110 |
ref={fgRef}
|
|
|
|
| 111 |
graphData={graphData}
|
| 112 |
width={undefined}
|
| 113 |
backgroundColor="transparent"
|
|
|
|
| 34 |
const visibleRelationships = useGraphStore((s) => s.visibleRelationships);
|
| 35 |
const selectEntity = useGraphStore((s) => s.selectEntity);
|
| 36 |
const setHighlighted = useGraphStore((s) => s.setHighlighted);
|
| 37 |
+
const dim = useGraphStore((s) => s.dim);
|
| 38 |
|
| 39 |
const fgRef = useRef<any>(null);
|
| 40 |
const [hoverNode, setHoverNode] = useState<FGNode | null>(null);
|
|
|
|
| 43 |
const closeContextMenu = useCallback(() => setContextMenu(null), []);
|
| 44 |
|
| 45 |
useEffect(() => {
|
| 46 |
+
graphController.zoomIn = () => fgRef.current?.zoom?.(fgRef.current.zoom() * 1.4, 300);
|
| 47 |
+
graphController.zoomOut = () => fgRef.current?.zoom?.(fgRef.current.zoom() / 1.4, 300);
|
| 48 |
graphController.resetView = () => {
|
| 49 |
+
fgRef.current?.zoomToFit?.(400, 40);
|
| 50 |
};
|
| 51 |
}, []);
|
| 52 |
|
|
|
|
| 100 |
);
|
| 101 |
setSearchHit(match ? (match as any).id : null);
|
| 102 |
if (match && fgRef.current) {
|
| 103 |
+
if (fgRef.current.centerAt) {
|
| 104 |
+
fgRef.current.centerAt((match as any).x, (match as any).y, 600);
|
| 105 |
+
}
|
| 106 |
+
if (fgRef.current.zoom) {
|
| 107 |
+
fgRef.current.zoom(2.5, 600);
|
| 108 |
+
}
|
| 109 |
}
|
| 110 |
}, [searchTerm, graphData.nodes]);
|
| 111 |
|
|
|
|
| 113 |
<div className="graph-canvas relative h-full w-full" style={{ height }}>
|
| 114 |
<ForceGraph2D
|
| 115 |
ref={fgRef}
|
| 116 |
+
dim={dim}
|
| 117 |
graphData={graphData}
|
| 118 |
width={undefined}
|
| 119 |
backgroundColor="transparent"
|
frontend/src/components/query/SourceToggle.tsx
CHANGED
|
@@ -3,14 +3,16 @@
|
|
| 3 |
import { useState } from 'react';
|
| 4 |
import { Network, Type, Layers, ChevronDown } from 'lucide-react';
|
| 5 |
import { cn } from '@/lib/utils';
|
|
|
|
| 6 |
|
| 7 |
interface SourceToggleProps {
|
| 8 |
method: string;
|
| 9 |
entityCount: number;
|
| 10 |
chunkCount: number;
|
|
|
|
| 11 |
}
|
| 12 |
|
| 13 |
-
export function SourceToggle({ method, entityCount, chunkCount }: SourceToggleProps) {
|
| 14 |
const [open, setOpen] = useState(false);
|
| 15 |
return (
|
| 16 |
<div className="border-t border-border bg-bg-surface px-4 py-2">
|
|
@@ -19,9 +21,9 @@ export function SourceToggle({ method, entityCount, chunkCount }: SourceTogglePr
|
|
| 19 |
<span
|
| 20 |
className={cn(
|
| 21 |
'inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium',
|
| 22 |
-
method === 'Graph'
|
| 23 |
? 'bg-accent-violet/15 text-accent-violet'
|
| 24 |
-
: method === 'Vector'
|
| 25 |
? 'bg-accent-indigo/15 text-accent-indigo'
|
| 26 |
: 'bg-accent-cyan/15 text-accent-cyan'
|
| 27 |
)}
|
|
@@ -39,19 +41,27 @@ export function SourceToggle({ method, entityCount, chunkCount }: SourceTogglePr
|
|
| 39 |
onClick={() => setOpen((o) => !o)}
|
| 40 |
className="inline-flex items-center gap-1 text-xs text-text-secondary hover:text-text-primary"
|
| 41 |
>
|
| 42 |
-
<Layers className="h-3.5 w-3.5" /> Context
|
| 43 |
<ChevronDown className={cn('h-3.5 w-3.5 transition-transform', open && 'rotate-180')} />
|
| 44 |
</button>
|
| 45 |
</div>
|
| 46 |
{open && (
|
| 47 |
-
<div className="mt-2 rounded-md border border-border bg-bg-base p-3 text-xs text-text-secondary">
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
</div>
|
| 56 |
)}
|
| 57 |
</div>
|
|
|
|
| 3 |
import { useState } from 'react';
|
| 4 |
import { Network, Type, Layers, ChevronDown } from 'lucide-react';
|
| 5 |
import { cn } from '@/lib/utils';
|
| 6 |
+
import ReactMarkdown from 'react-markdown';
|
| 7 |
|
| 8 |
interface SourceToggleProps {
|
| 9 |
method: string;
|
| 10 |
entityCount: number;
|
| 11 |
chunkCount: number;
|
| 12 |
+
context?: string;
|
| 13 |
}
|
| 14 |
|
| 15 |
+
export function SourceToggle({ method, entityCount, chunkCount, context }: SourceToggleProps) {
|
| 16 |
const [open, setOpen] = useState(false);
|
| 17 |
return (
|
| 18 |
<div className="border-t border-border bg-bg-surface px-4 py-2">
|
|
|
|
| 21 |
<span
|
| 22 |
className={cn(
|
| 23 |
'inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium',
|
| 24 |
+
method === 'Graph' || method === 'GRAPH_ONLY'
|
| 25 |
? 'bg-accent-violet/15 text-accent-violet'
|
| 26 |
+
: method === 'Vector' || method === 'VECTOR_ONLY'
|
| 27 |
? 'bg-accent-indigo/15 text-accent-indigo'
|
| 28 |
: 'bg-accent-cyan/15 text-accent-cyan'
|
| 29 |
)}
|
|
|
|
| 41 |
onClick={() => setOpen((o) => !o)}
|
| 42 |
className="inline-flex items-center gap-1 text-xs text-text-secondary hover:text-text-primary"
|
| 43 |
>
|
| 44 |
+
<Layers className="h-3.5 w-3.5" /> Context Preview
|
| 45 |
<ChevronDown className={cn('h-3.5 w-3.5 transition-transform', open && 'rotate-180')} />
|
| 46 |
</button>
|
| 47 |
</div>
|
| 48 |
{open && (
|
| 49 |
+
<div className="mt-2 max-h-[300px] overflow-y-auto rounded-md border border-border bg-bg-base p-3 text-xs text-text-secondary scrollbar-thin">
|
| 50 |
+
{context ? (
|
| 51 |
+
<div className="prose prose-invert max-w-none text-xs leading-relaxed text-text-secondary space-y-2">
|
| 52 |
+
<ReactMarkdown>{context}</ReactMarkdown>
|
| 53 |
+
</div>
|
| 54 |
+
) : (
|
| 55 |
+
<div>
|
| 56 |
+
<p className="mb-1 font-medium text-text-primary">Retrieval context</p>
|
| 57 |
+
<p>
|
| 58 |
+
GRAPH CONTEXT: {entityCount} entities and their relationships were traversed in Neo4j.
|
| 59 |
+
</p>
|
| 60 |
+
<p>
|
| 61 |
+
TEXT CONTEXT: {chunkCount} semantically similar text chunks were retrieved from the vector store.
|
| 62 |
+
</p>
|
| 63 |
+
</div>
|
| 64 |
+
)}
|
| 65 |
</div>
|
| 66 |
)}
|
| 67 |
</div>
|
frontend/src/store/graph.ts
CHANGED
|
@@ -32,6 +32,7 @@ interface GraphState {
|
|
| 32 |
visibleTypes: Record<string, boolean>;
|
| 33 |
visibleRelationships: Record<string, boolean>;
|
| 34 |
selectedEntity: GraphNode | null;
|
|
|
|
| 35 |
setData: (data: GraphData) => void;
|
| 36 |
setHighlighted: (entities: string[], paths?: string[]) => void;
|
| 37 |
clearHighlighted: () => void;
|
|
@@ -39,6 +40,7 @@ interface GraphState {
|
|
| 39 |
toggleType: (type: string) => void;
|
| 40 |
toggleRelationship: (rel: string) => void;
|
| 41 |
selectEntity: (entity: GraphNode | null) => void;
|
|
|
|
| 42 |
}
|
| 43 |
|
| 44 |
export const useGraphStore = create<GraphState>((set) => ({
|
|
@@ -49,6 +51,7 @@ export const useGraphStore = create<GraphState>((set) => ({
|
|
| 49 |
visibleTypes: {},
|
| 50 |
visibleRelationships: {},
|
| 51 |
selectedEntity: null,
|
|
|
|
| 52 |
setData: (data) => set({ data }),
|
| 53 |
setHighlighted: (entities, paths = []) =>
|
| 54 |
set({ highlightedEntities: entities, highlightedPaths: paths }),
|
|
@@ -66,4 +69,5 @@ export const useGraphStore = create<GraphState>((set) => ({
|
|
| 66 |
},
|
| 67 |
})),
|
| 68 |
selectEntity: (entity) => set({ selectedEntity: entity }),
|
|
|
|
| 69 |
}));
|
|
|
|
| 32 |
visibleTypes: Record<string, boolean>;
|
| 33 |
visibleRelationships: Record<string, boolean>;
|
| 34 |
selectedEntity: GraphNode | null;
|
| 35 |
+
dim: 2 | 3;
|
| 36 |
setData: (data: GraphData) => void;
|
| 37 |
setHighlighted: (entities: string[], paths?: string[]) => void;
|
| 38 |
clearHighlighted: () => void;
|
|
|
|
| 40 |
toggleType: (type: string) => void;
|
| 41 |
toggleRelationship: (rel: string) => void;
|
| 42 |
selectEntity: (entity: GraphNode | null) => void;
|
| 43 |
+
setDim: (dim: 2 | 3) => void;
|
| 44 |
}
|
| 45 |
|
| 46 |
export const useGraphStore = create<GraphState>((set) => ({
|
|
|
|
| 51 |
visibleTypes: {},
|
| 52 |
visibleRelationships: {},
|
| 53 |
selectedEntity: null,
|
| 54 |
+
dim: 2,
|
| 55 |
setData: (data) => set({ data }),
|
| 56 |
setHighlighted: (entities, paths = []) =>
|
| 57 |
set({ highlightedEntities: entities, highlightedPaths: paths }),
|
|
|
|
| 69 |
},
|
| 70 |
})),
|
| 71 |
selectEntity: (entity) => set({ selectedEntity: entity }),
|
| 72 |
+
setDim: (dim) => set({ dim }),
|
| 73 |
}));
|