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,54 @@
function gb(value) {
return `${Number(value).toFixed(1)} GB`;
}
function diskTone(status) {
if (status === "critical" || status === "offline") return "danger";
if (status === "warning") return "warning";
return "online";
}
function pillLabel(status) {
if (status === "critical") return "Critical";
if (status === "warning") return "Warning";
if (status === "offline") return "Offline";
return "Stable";
}
export function renderStorage(state) {
const { storage } = state.data;
const rootTone = diskTone(storage.root.status);
const rootPill = document.getElementById("root-storage-pill");
rootPill.className = `status-pill ${rootTone === "danger" ? "offline" : rootTone}`;
rootPill.textContent = pillLabel(storage.root.status);
document.getElementById("root-storage-value").textContent = `${storage.root.usage_percent.toFixed(1)}%`;
document.getElementById("root-storage-value").className = `card-value value-${rootTone === "danger" ? "danger" : rootTone}`;
document.getElementById("root-storage-used").textContent = gb(storage.root.used_gb);
document.getElementById("root-storage-free").textContent = gb(storage.root.free_gb);
const rootBar = document.getElementById("root-storage-bar");
rootBar.className = `metric-bar${rootTone === "online" ? "" : ` ${rootTone === "danger" ? "danger" : rootTone}`}`;
document.getElementById("root-storage-bar-fill").style.width = `${storage.root.usage_percent}%`;
const signal = document.getElementById("disk-matrix-signal");
signal.className = `signal ${storage.summary.overall_status === "degraded" ? "warning" : storage.summary.overall_status === "offline" ? "offline" : "online"}`;
const list = document.getElementById("storage-list");
list.innerHTML = storage.disks
.map((disk) => {
const tone = diskTone(disk.status);
const pillClass = tone === "danger" ? "offline" : tone === "warning" ? "warning" : "online";
const barClass = tone === "online" ? "metric-bar" : `metric-bar ${tone === "danger" ? "danger" : tone}`;
return `
<div class="storage-row">
<strong>${disk.name}</strong>
<span>${disk.mount}</span>
<div class="${barClass}"><span style="width:${Math.max(0, Math.min(disk.usage_percent, 100))}%"></span></div>
<span class="status-pill ${pillClass}">${disk.usage_percent.toFixed(0)}%</span>
</div>
`;
})
.join("");
}