Skip to content

Commit a0c71c2

Browse files
authored
[DRAFT][Feature][Graph Render]Nodes and initial render implementation (#2)
* [Feature][Graph Render]Nodes and initial render implementation * [Fix][Validation] * [Fix][Validation] * [Fix][Validation] * [Fix][Validation] * [Fix][Validation] * [Feature] Links Render
1 parent 8657210 commit a0c71c2

File tree

7 files changed

+75
-210
lines changed

7 files changed

+75
-210
lines changed

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@
6565
]
6666
},
6767
"resolutions": {
68-
"postcss": "^8.4.31",
69-
"nth-check": "^2.0.1"
70-
}
68+
"postcss": "^8.4.31",
69+
"nth-check": "^2.0.1"
70+
}
71+
7172
}

src/design/Layouts/FullScreen.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ const FullScreen = () => {
206206
minHeight: "calc(100vh - 6rem)", // Ensure full height minus the AppBar height (6rem)
207207
boxSizing: "border-box",
208208
marginTop: "6rem",
209-
background: Colors.primary.light,
209+
background: "#f0f0f0",
210210
}}
211211
>
212212
<Outlet />

src/modules/universe/NeuroJsonGraph.tsx

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import ForceGraph3D, { ForceGraph3DInstance } from "3d-force-graph";
1+
import ForceGraph3D from "3d-force-graph";
2+
import { Colors } from "design/theme";
23
import React, { useEffect, useRef } from "react";
34
import * as THREE from "three";
45
import {
@@ -16,15 +17,18 @@ interface NodeObject {
1617
datatype: string[];
1718
support: string;
1819
url: string;
20+
datasets: number;
1921
}
2022

2123
const NeuroJsonGraph: React.FC<{ registry: Database[] }> = ({ registry }) => {
2224
const graphRef = useRef<HTMLDivElement>(null);
2325

24-
// Debug log for registry data
25-
useEffect(() => {
26-
console.log("From NeuroJsonGraph, registry:", registry);
27-
}, [registry]);
26+
// Function to determine color and size based on node size
27+
const size2colorAndSize = (size: number) => {
28+
if (size > 32) return { color: Colors.primary.dark, size: 10 };
29+
if (size > 3) return { color: Colors.primary.main, size: 7 };
30+
return { color: Colors.primary.light, size: 5 };
31+
};
2832

2933
useEffect(() => {
3034
// Ensure registry and graphRef are properly initialized
@@ -40,40 +44,61 @@ const NeuroJsonGraph: React.FC<{ registry: Database[] }> = ({ registry }) => {
4044

4145
// Prepare graph data
4246
const graphData = {
43-
nodes: registry.map((db) => ({
44-
id: db.id,
45-
name: db.fullname || db.name,
46-
dbname: db.name,
47-
color: "rgba(255,255,255,1)", // White color for nodes
48-
datatype: db.datatype,
49-
support: db.support,
50-
url: db.url,
51-
})),
52-
links: [], // Add links if needed
47+
nodes: registry.map((db) => {
48+
const { color, size } = size2colorAndSize(db.datasets);
49+
return {
50+
id: db.id,
51+
name: db.fullname || db.name,
52+
dbname: db.name,
53+
color: color,
54+
datatype: db.datatype,
55+
support: db.support,
56+
url: db.url,
57+
datasets: db.datasets,
58+
size: size,
59+
};
60+
}),
61+
links: registry.flatMap((db, index) => {
62+
const connections = [];
63+
const nextIndex = (index + 1) % registry.length;
64+
const { color } = size2colorAndSize(db.datasets);
65+
connections.push({
66+
source: db.id,
67+
target: registry[nextIndex].id,
68+
color: color,
69+
visible: true,
70+
});
71+
return connections;
72+
}),
5373
};
5474

5575
// Initialize 3D Force Graph
56-
const Graph: ForceGraph3DInstance = new ForceGraph3D(graphRef.current)
76+
const Graph = new ForceGraph3D(graphRef.current)
5777
.graphData(graphData)
5878
.nodeRelSize(2)
59-
.nodeColor((node) => (node as NodeObject).color || "rgba(255,255,255,1)") // White nodes
79+
.nodeColor((node) => (node as NodeObject).color)
80+
.linkWidth(2) // Set the thickness of the links
6081
.backgroundColor("rgba(0,0,0,0)") // Transparent background
6182
.nodeLabel("name")
6283
.nodeThreeObject((node) => {
6384
const castNode = node as NodeObject;
6485

6586
// Create a 3D sphere for the node
66-
const sphereGeometry = new THREE.SphereGeometry(5, 16, 16); // Radius 5
87+
const sphereGeometry = new THREE.SphereGeometry(
88+
(castNode as any).size,
89+
16,
90+
16
91+
); // Dynamic radius
6792
const sphereMaterial = new THREE.MeshBasicMaterial({
68-
color: "white",
93+
color: (castNode as any).color,
6994
});
7095
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
7196

7297
// Add label as CSS2DObject
7398
const label = new CSS2DObject(document.createElement("div"));
7499
label.element.textContent = castNode.dbname || "Unnamed";
75-
label.element.style.color = "white";
76-
label.element.style.fontSize = "10px";
100+
label.element.style.color = Colors.primary.main;
101+
label.element.style.fontSize = "12px";
77102
label.element.style.pointerEvents = "none"; // Prevent interaction
78103
label.position.set(0, 10, 0); // Position label above the node
79104
sphere.add(label);
@@ -86,7 +111,7 @@ const NeuroJsonGraph: React.FC<{ registry: Database[] }> = ({ registry }) => {
86111
labelRenderer.setSize(window.innerWidth, window.innerHeight);
87112
labelRenderer.domElement.style.position = "absolute";
88113
labelRenderer.domElement.style.top = "0px";
89-
labelRenderer.domElement.style.pointerEvents = "none"; // Prevent interaction
114+
labelRenderer.domElement.style.pointerEvents = "none";
90115
graphRef.current?.appendChild(labelRenderer.domElement);
91116

92117
// Animate label rendering

src/pages/Home.tsx

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { useAppDispatch } from "hooks/useAppDispatch";
33
import { useAppSelector } from "hooks/useAppSelector";
44
import NeuroJsonGraph from "modules/universe/NeuroJsonGraph";
55
import React, { useEffect } from "react";
6-
import { Link } from "react-router-dom";
76
import { fetchRegistry } from "redux/neurojson/neurojson.action";
87
import { NeurojsonSelector } from "redux/neurojson/neurojson.selector";
98

@@ -13,33 +12,15 @@ const Home: React.FC = () => {
1312

1413
useEffect(() => {
1514
dispatch(fetchRegistry());
16-
console.log(registry);
1715
}, [dispatch]);
18-
return (
19-
<Container>
20-
{registry && <NeuroJsonGraph registry={registry} />}
21-
22-
<Box sx={{ padding: 4, maxHeight: "100%", maxWidth: "30%" }}>
23-
{/* Header Section */}
24-
<Typography variant="h3" gutterBottom>
25-
Welcome to NeuroJSON IO
26-
</Typography>
27-
<Typography variant="body1">
28-
Manage and explore your CouchDB databases and datasets effortlessly.
29-
</Typography>
3016

31-
{/* Navigation to Database Page */}
32-
<Box mt={4}>
33-
<Button
34-
variant="contained"
35-
color="primary"
36-
component={Link}
37-
to="/databases"
38-
>
39-
View Databases
40-
</Button>
41-
</Box>
42-
</Box>
17+
return (
18+
<Container style={{ width: "100%", height: "100vh", padding: 0 }}>
19+
{registry && registry.length > 0 ? (
20+
<NeuroJsonGraph registry={registry} />
21+
) : (
22+
<div>No data available to display</div>
23+
)}
4324
</Container>
4425
);
4526
};

src/redux/neurojson/neurojson.action.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ export const fetchRegistry = createAsyncThunk(
1111
"neurojson/fetchRegistry",
1212
async () => {
1313
const response = await NeurojsonService.getRegistry();
14-
console.log(response);
1514
return response.database;
1615
}
1716
);

src/redux/neurojson/neurojson.slice.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {
22
fetchDocumentDetails,
3+
fetchRegistry,
34
loadAllDocuments,
45
loadPaginatedData,
56
} from "./neurojson.action";
@@ -96,6 +97,17 @@ const neurojsonSlice = createSlice({
9697
.addCase(fetchDocumentDetails.rejected, (state, action) => {
9798
state.loading = false;
9899
state.error = action.payload as string;
100+
})
101+
.addCase(fetchRegistry.fulfilled, (state, action: PayloadAction<any>) => {
102+
state.registry = action.payload;
103+
})
104+
.addCase(fetchRegistry.rejected, (state, action) => {
105+
state.registry = null;
106+
state.error = action.payload as string;
107+
})
108+
.addCase(fetchRegistry.pending, (state) => {
109+
state.loading = true;
110+
state.error = null;
99111
});
100112
},
101113
});

0 commit comments

Comments
 (0)