114 lines
3.0 KiB
HTML
114 lines
3.0 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>Ruby's Brain Map</title>
|
|
<script src="https://cdn.jsdelivr.net/npm/force-graph"></script>
|
|
<style>
|
|
body {
|
|
margin: 0;
|
|
background-color: #121212;
|
|
color: #e0e0e0;
|
|
font-family: 'Segoe UI', Tahoma, sans-serif;
|
|
}
|
|
#graph {
|
|
width: 100vw;
|
|
height: 100vh;
|
|
}
|
|
.nav {
|
|
position: absolute;
|
|
top: 10px;
|
|
left: 10px;
|
|
background: rgba(0, 0, 0, 0.7);
|
|
padding: 8px 14px;
|
|
border-radius: 8px;
|
|
z-index: 1000;
|
|
}
|
|
.nav a {
|
|
color: #e0e0e0;
|
|
margin-right: 15px;
|
|
text-decoration: none;
|
|
font-weight: bold;
|
|
}
|
|
#searchBox {
|
|
position: absolute;
|
|
top: 10px;
|
|
right: 10px;
|
|
z-index: 1000;
|
|
padding: 6px 10px;
|
|
font-size: 14px;
|
|
border-radius: 6px;
|
|
border: none;
|
|
outline: none;
|
|
background-color: #1e1e1e;
|
|
color: #fff;
|
|
width: 200px;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<div class="nav">
|
|
<a href="/">📊 Dashboard</a>
|
|
<a href="/journal">📓 Journal</a>
|
|
<a href="/concepts">🧠 Concepts</a>
|
|
<a href="/brainmap">🕸️ Brain Map</a>
|
|
<a href="/growth">📈 Growth</a>
|
|
<a href="/dreams">🌃 Dreams</a>
|
|
<a href="/health">❤️ Health</a>
|
|
</div>
|
|
|
|
<input type="text" id="searchBox" placeholder="Search word...">
|
|
|
|
<div id="graph"></div>
|
|
|
|
<script>
|
|
const graphData = {
|
|
nodes: {{ nodes | safe }},
|
|
links: {{ links | safe }}
|
|
};
|
|
|
|
const degreeMap = {};
|
|
graphData.links.forEach(link => {
|
|
degreeMap[link.source] = (degreeMap[link.source] || 0) + 1;
|
|
degreeMap[link.target] = (degreeMap[link.target] || 0) + 1;
|
|
});
|
|
|
|
const Graph = ForceGraph()(document.getElementById("graph"))
|
|
.graphData(graphData)
|
|
.nodeId("id")
|
|
.nodeLabel(node => `${node.id} (${degreeMap[node.id] || 0} links)`)
|
|
.nodeAutoColorBy("group")
|
|
.nodeVal(node => Math.max(2, degreeMap[node.id] || 1))
|
|
.linkWidth(link => Math.log(link.value + 1))
|
|
.linkColor(() => "rgba(255,255,255,0.2)")
|
|
.backgroundColor("#121212");
|
|
|
|
// Search filter
|
|
document.getElementById("searchBox").addEventListener("input", e => {
|
|
const search = e.target.value.toLowerCase();
|
|
Graph.nodeVisibility(node => node.id.toLowerCase().includes(search));
|
|
});
|
|
|
|
// Click-to-highlight
|
|
Graph.onNodeClick(node => {
|
|
const neighbors = new Set();
|
|
graphData.links.forEach(link => {
|
|
if (link.source === node.id) neighbors.add(link.target);
|
|
else if (link.target === node.id) neighbors.add(link.source);
|
|
});
|
|
|
|
Graph.nodeColor(n =>
|
|
n.id === node.id ? "#ffff00" :
|
|
neighbors.has(n.id) ? "#ffa500" : "#333"
|
|
);
|
|
|
|
Graph.linkColor(l =>
|
|
l.source === node.id || l.target === node.id ? "#ffffff" : "rgba(255,255,255,0.05)"
|
|
);
|
|
});
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|