Scaffold homelab-monitor: Fastify API + React dashboard + CI
Vertical slice for Phase 1 (v1-dashboard milestone): Proxmox collector, SQLite storage, local auth, and a dashboard UI showing host/container status cards. Config-driven collector registry so future data sources (SSH-based hosts, Zabbix, network discovery) plug in without rewiring. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
import type { HostSummary } from "../api";
|
||||
|
||||
function Bar({ label, pct }: { label: string; pct: number | null }) {
|
||||
const value = pct ?? 0;
|
||||
const color = value > 90 ? "#e5484d" : value > 75 ? "#f5a623" : "#3fb950";
|
||||
return (
|
||||
<div className="bar-row">
|
||||
<span className="bar-label">{label}</span>
|
||||
<div className="bar-track">
|
||||
<div className="bar-fill" style={{ width: `${Math.min(value, 100)}%`, background: color }} />
|
||||
</div>
|
||||
<span className="bar-value">{pct === null ? "—" : `${pct.toFixed(0)}%`}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function formatUptime(sec: number | null): string {
|
||||
if (sec === null) return "—";
|
||||
const days = Math.floor(sec / 86400);
|
||||
const hours = Math.floor((sec % 86400) / 3600);
|
||||
if (days > 0) return `${days}d ${hours}h`;
|
||||
const minutes = Math.floor((sec % 3600) / 60);
|
||||
return `${hours}h ${minutes}m`;
|
||||
}
|
||||
|
||||
export function HostCard({ host }: { host: HostSummary }) {
|
||||
return (
|
||||
<div className={`host-card status-${host.status}`}>
|
||||
<div className="host-card-header">
|
||||
<span className={`status-dot status-${host.status}`} />
|
||||
<span className="host-name">{host.displayName}</span>
|
||||
<span className="host-uptime">{formatUptime(host.uptimeSec)}</span>
|
||||
</div>
|
||||
<Bar label="CPU" pct={host.cpuPct} />
|
||||
<Bar label="Mem" pct={host.memPct} />
|
||||
<Bar label="Disk" pct={host.diskPct} />
|
||||
{(host.cpuPressurePct !== null || host.memPressurePct !== null) && (
|
||||
<div className="pressure-row">
|
||||
{host.cpuPressurePct !== null && <span>CPU pressure {host.cpuPressurePct.toFixed(1)}%</span>}
|
||||
{host.memPressurePct !== null && <span>Mem pressure {host.memPressurePct.toFixed(1)}%</span>}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user