70 lines
2.7 KiB
HTML
70 lines
2.7 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>Boday-IT cloudmon Dashboard</title>
|
|
<script src="https://d3js.org"></script>
|
|
<script src="https://tailwindcss.com"></script>
|
|
<style>
|
|
.node circle { fill: #fff; stroke: #4f46e5; stroke-width: 3px; }
|
|
.node text { font: 12px sans-serif; font-weight: 600; fill: #1f2937; }
|
|
.link { fill: none; stroke: #cbd5e1; stroke-width: 2px; }
|
|
</style>
|
|
</head>
|
|
<body class="bg-slate-50 min-h-screen">
|
|
|
|
<div class="p-6 max-w-7xl mx-auto">
|
|
<header class="mb-8 flex justify-between items-center">
|
|
<div>
|
|
<h1 class="text-2xl font-bold text-slate-800">cloudmon // Cluster Map</h1>
|
|
<p class="text-sm text-slate-500">Live Infrastructure Mindmap aus Terraform State-Daten</p>
|
|
</div>
|
|
<span class="px-3 py-1 bg-emerald-100 text-emerald-800 rounded-full text-xs font-semibold animate-pulse">Live API Stream</span>
|
|
</header>
|
|
|
|
<div class="bg-white rounded-xl shadow-md p-6 overflow-x-auto border border-slate-200 flex justify-center">
|
|
<svg id="mindmap" width="1000" height="500"></svg>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
d3.json("/api/cluster-data/").then(function(data) {
|
|
const svg = d3.select("#mindmap"),
|
|
width = +svg.attr("width"),
|
|
height = +svg.attr("height");
|
|
|
|
const g = svg.append("g").attr("transform", "translate(150,0)");
|
|
const tree = d3.tree().size([height - 50, width - 350]);
|
|
const root = d3.hierarchy(data, d => d.children);
|
|
tree(root);
|
|
|
|
g.selectAll(".link")
|
|
.data(root.links())
|
|
.enter().append("path")
|
|
.attr("class", "link")
|
|
.attr("d", d3.linkHorizontal().x(d => d.y).y(d => d.x));
|
|
|
|
const node = g.selectAll(".node")
|
|
.data(root.descendants())
|
|
.enter().append("g")
|
|
.attr("class", "node")
|
|
.attr("transform", d => `translate(${d.y},${d.x})`);
|
|
|
|
node.append("circle")
|
|
.attr("r", 8)
|
|
.style("stroke", d => {
|
|
if (d.data.type === "Root") return "#10b981";
|
|
if (d.data.type === "Ingress") return "#3b82f6";
|
|
if (d.data.type === "Service") return "#f59e0b";
|
|
return "#6366f1";
|
|
});
|
|
|
|
node.append("text")
|
|
.attr("dy", ".35em")
|
|
.attr("x", d => d.children ? -13 : 13)
|
|
.style("text-anchor", d => d.children ? "end" : "start")
|
|
.text(d => `[${d.data.type}] ${d.data.name}`);
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|