Add custom homelab dashboard stack

This commit is contained in:
2026-04-05 13:43:03 +02:00
parent 450a04a7d3
commit 89b9173c25
38 changed files with 3539 additions and 0 deletions
@@ -0,0 +1,65 @@
function pct(value) {
return `${Math.round(value)}%`;
}
function gb(value) {
return `${Number(value).toFixed(1)} GB`;
}
function toneForPercent(value) {
if (value >= 85) return "danger";
if (value >= 60) return "warning";
return "online";
}
function setSignal(id, tone) {
const node = document.getElementById(id);
node.className = `signal ${tone === "danger" ? "offline" : tone === "warning" ? "warning" : tone === "info" ? "info" : "online"}`;
}
function setBar(id, fillId, percent, tone) {
const bar = document.getElementById(id);
const fill = document.getElementById(fillId);
bar.className = `metric-bar${tone === "online" ? "" : ` ${tone === "danger" ? "danger" : tone}`}`;
fill.style.width = `${Math.max(0, Math.min(percent, 100))}%`;
}
export function renderStats(state) {
const { system } = state.data;
const cpuTone = toneForPercent(system.cpu.usage_percent);
const ramTone = toneForPercent(system.memory.usage_percent);
const networkTone = "info";
const uptimeTone = system.source.status === "online" ? "online" : "danger";
setSignal("cpu-signal", cpuTone);
document.getElementById("cpu-value").textContent = pct(system.cpu.usage_percent);
document.getElementById("cpu-value").className = `card-value value-${cpuTone}`;
document.getElementById("cpu-cores").textContent = `${system.cpu.cores} CORES`;
document.getElementById("cpu-cores").className = `metric-accent ${cpuTone === "danger" ? "warning" : "online"}`;
document.getElementById("cpu-load").textContent = system.cpu.load_1.toFixed(2);
setBar("cpu-bar", "cpu-bar-fill", system.cpu.usage_percent, cpuTone);
setSignal("ram-signal", ramTone);
document.getElementById("ram-value").textContent = pct(system.memory.usage_percent);
document.getElementById("ram-value").className = `card-value value-${ramTone}`;
document.getElementById("ram-used").textContent = gb(system.memory.used_gb);
document.getElementById("ram-used").className = `metric-accent ${ramTone}`;
document.getElementById("ram-free").textContent = gb(system.memory.available_gb);
document.getElementById("ram-free").className = "metric-accent info";
setBar("ram-bar", "ram-bar-fill", system.memory.usage_percent, ramTone);
setSignal("network-signal", networkTone);
document.getElementById("network-value").textContent = system.network.rx_mbps.toFixed(1);
document.getElementById("network-value").className = "card-value value-info";
document.getElementById("network-tx").textContent = `${system.network.tx_mbps.toFixed(1)} MBPS`;
setBar("network-bar", "network-bar-fill", Math.min(system.network.rx_mbps * 4, 100), networkTone);
const uptimeDays = Math.max(0, Math.floor(system.host.uptime_seconds / 86400));
const uptimeHours = Math.max(0, Math.floor(system.host.uptime_seconds / 3600));
setSignal("uptime-signal", uptimeTone);
document.getElementById("uptime-value").textContent = `${uptimeDays}D`;
document.getElementById("uptime-value").className = `card-value value-${uptimeTone === "danger" ? "danger" : "online"}`;
document.getElementById("uptime-host").textContent = system.source.host_name.toUpperCase();
document.getElementById("uptime-hours").textContent = String(uptimeHours);
setBar("uptime-bar", "uptime-bar-fill", system.source.status === "online" ? 84 : 10, uptimeTone === "danger" ? "danger" : "online");
}