Split Proxmox node card into system info (left) / storage (right)

Was a single stacked column (uptime/CPU/memory/swap, then the storage
table below); now a two-column layout within the card body — system
stats on the left, storage table (or the missing-permission hint) on
the right — so the card reads more like a dashboard tile at a glance.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
bobbanandClaude Sonnet 5 committed 2026-09-17 20:50:16 +02:00
1 parent 846953194c
commit 7b39b7be4d
1 file changed
+13 -11
+13 -11
View File
@@ -186,11 +186,12 @@ export default function Proxmox({ user }: { user: CurrentUser }) {
<div className="card-body">
{n.error && <div className="alert alert-danger">{n.error}</div>}
<div className="row g-3">
<div className="col-sm-6">
<div className="col-md-6">
<div className="mb-3">
<div className="text-secondary small">Uptime</div>
<div>{formatUptime(n.uptime)}</div>
</div>
<div className="col-sm-6">
<div className="mb-3">
<div className="text-secondary small">CPU</div>
<div>
{n.cpuUsagePercent !== null ? `${n.cpuUsagePercent.toFixed(1)}%` : "—"}
@@ -200,7 +201,7 @@ export default function Proxmox({ user }: { user: CurrentUser }) {
<div className="text-secondary small">Load: {n.loadAverage.map((l) => l.toFixed(2)).join(", ")}</div>
)}
</div>
<div className="col-sm-6">
<div className={n.swapTotalBytes ? "mb-3" : ""}>
<div className="text-secondary small">Memory</div>
<div>
{formatBytes(n.memUsedBytes)} / {formatBytes(n.memTotalBytes)}
@@ -208,7 +209,7 @@ export default function Proxmox({ user }: { user: CurrentUser }) {
{usageBar(n.memUsedBytes, n.memTotalBytes)}
</div>
{!!n.swapTotalBytes && (
<div className="col-sm-6">
<div>
<div className="text-secondary small">Swap</div>
<div>
{formatBytes(n.swapUsedBytes)} / {formatBytes(n.swapTotalBytes)}
@@ -218,9 +219,9 @@ export default function Proxmox({ user }: { user: CurrentUser }) {
)}
</div>
{n.storages.length > 0 ? (
<div className="mt-3">
<div className="col-md-6">
<div className="text-secondary small mb-1">Storage</div>
{n.storages.length > 0 ? (
<table className="table table-sm table-vcenter mb-0">
<tbody>
{n.storages.map((s) => (
@@ -238,19 +239,20 @@ export default function Proxmox({ user }: { user: CurrentUser }) {
))}
</tbody>
</table>
</div>
) : (
!n.error && (
<div className="text-secondary small mt-3">
No storage visible to this API token. Proxmox filters the storage list per-token —
grant it <code>Datastore.Audit</code> (e.g. on <code>/storage</code>) to see disk
usage here.
<div className="text-secondary small">
No storage visible to this API token. Proxmox filters the storage list
per-token — grant it <code>Datastore.Audit</code> (e.g. on{" "}
<code>/storage</code>) to see disk usage here.
</div>
)
)}
</div>
</div>
</div>
</div>
</div>
))}
{nodeStats?.length === 0 && (
<div className="col-12">