From b722ccc5bc8f5ca3ec4a3a32243c9a5fd9144237 Mon Sep 17 00:00:00 2001 From: henrygd Date: Wed, 12 Nov 2025 14:15:45 -0500 Subject: [PATCH] show additional disk percentages in systems table (#1365) --- agent/agent.go | 6 ++ internal/entities/system/system.go | 5 +- .../systems-table/systems-table-columns.tsx | 76 ++++++++++++++++++- internal/site/src/types.d.ts | 2 + 4 files changed, 86 insertions(+), 3 deletions(-) diff --git a/agent/agent.go b/agent/agent.go index e1135b25..9f8ec78b 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -166,6 +166,7 @@ func (a *Agent) gatherStats(cacheTimeMs uint16) *system.CombinedData { } data.Stats.ExtraFs = make(map[string]*system.FsStats) + data.Info.ExtraFsPct = make(map[string]float64) for name, stats := range a.fsStats { if !stats.Root && stats.DiskTotal > 0 { // Use custom name if available, otherwise use device name @@ -174,6 +175,11 @@ func (a *Agent) gatherStats(cacheTimeMs uint16) *system.CombinedData { key = stats.Name } data.Stats.ExtraFs[key] = stats + // Add percentages to Info struct for dashboard + if stats.DiskTotal > 0 { + pct := twoDecimals((stats.DiskUsed / stats.DiskTotal) * 100) + data.Info.ExtraFsPct[key] = pct + } } } slog.Debug("Extra FS", "data", data.Stats.ExtraFs) diff --git a/internal/entities/system/system.go b/internal/entities/system/system.go index b467d892..c2f7728e 100644 --- a/internal/entities/system/system.go +++ b/internal/entities/system/system.go @@ -144,8 +144,9 @@ type Info struct { LoadAvg15 float64 `json:"l15,omitempty" cbor:"17,keyasint,omitempty"` BandwidthBytes uint64 `json:"bb" cbor:"18,keyasint"` // TODO: remove load fields in future release in favor of load avg array - LoadAvg [3]float64 `json:"la,omitempty" cbor:"19,keyasint"` - ConnectionType ConnectionType `json:"ct,omitempty" cbor:"20,keyasint,omitempty,omitzero"` + LoadAvg [3]float64 `json:"la,omitempty" cbor:"19,keyasint"` + ConnectionType ConnectionType `json:"ct,omitempty" cbor:"20,keyasint,omitempty,omitzero"` + ExtraFsPct map[string]float64 `json:"efs,omitempty" cbor:"21,keyasint,omitempty"` } // Final data structure to return to the hub diff --git a/internal/site/src/components/systems-table/systems-table-columns.tsx b/internal/site/src/components/systems-table/systems-table-columns.tsx index 3f23153f..145ba9ab 100644 --- a/internal/site/src/components/systems-table/systems-table-columns.tsx +++ b/internal/site/src/components/systems-table/systems-table-columns.tsx @@ -20,6 +20,7 @@ import { WifiIcon, } from "lucide-react" import { memo, useMemo, useRef, useState } from "react" +import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip" import { isReadOnlyUser, pb } from "@/lib/api" import { ConnectionType, connectionTypeLabels, MeterState, SystemStatus } from "@/lib/enums" import { $longestSystemNameLen, $userSettings } from "@/lib/stores" @@ -153,7 +154,7 @@ export default function SystemsTableColumns(viewMode: "table" | "grid"): ColumnD accessorFn: ({ info }) => info.dp, id: "disk", name: () => t`Disk`, - cell: TableCellWithMeter, + cell: DiskCellWithMultiple, Icon: HardDriveIcon, header: sortableHeader, }, @@ -354,6 +355,79 @@ function TableCellWithMeter(info: CellContext) { ) } +function DiskCellWithMultiple(info: CellContext) { + const { info: sysInfo, status, id } = info.row.original + const extraFs = Object.entries(sysInfo.efs ?? {}) + + // No extra disks - show basic meter + if (extraFs.length === 0) { + return TableCellWithMeter(info) + } + + const rootDiskPct = sysInfo.dp + + // sort extra disks by percentage descending + extraFs.sort((a, b) => b[1] - a[1]) + + function getMeterClass(pct: number) { + const threshold = getMeterState(pct) + return cn( + "h-full", + (status !== SystemStatus.Up && STATUS_COLORS.paused) || + (threshold === MeterState.Good && STATUS_COLORS.up) || + (threshold === MeterState.Warn && STATUS_COLORS.pending) || + STATUS_COLORS.down + ) + } + + return ( + + + +
+ {decimalString(rootDiskPct, rootDiskPct >= 10 ? 1 : 2)}% + + {/* Root disk */} + + {/* Extra disks */} + {extraFs.map(([_name, pct], index) => ( + + ))} + + +
+ +
+ +
+
+
{t`Root`}
+
+ {decimalString(rootDiskPct, rootDiskPct >= 10 ? 1 : 2)}% + + + +
+
+ {extraFs.map(([name, pct]) => { + return ( +
+
{name}
+
+ {decimalString(pct, pct >= 10 ? 1 : 2)}% + + + +
+
+ ) + })} +
+
+
+ ) +} + export function IndicatorDot({ system, className }: { system: SystemRecord; className?: ClassValue }) { className ||= STATUS_COLORS[system.status as keyof typeof STATUS_COLORS] || "" return ( diff --git a/internal/site/src/types.d.ts b/internal/site/src/types.d.ts index 75b2c51c..07dad0ac 100644 --- a/internal/site/src/types.d.ts +++ b/internal/site/src/types.d.ts @@ -77,6 +77,8 @@ export interface SystemInfo { os?: Os /** connection type */ ct?: ConnectionType + /** extra filesystem percentages */ + efs?: Record } export interface SystemStats {