From 1f1a448aef917d5759462fc27d95471395ffba21 Mon Sep 17 00:00:00 2001 From: henrygd Date: Thu, 12 Feb 2026 18:40:16 -0500 Subject: [PATCH] ui: small refactoring / auto formatting --- .../containers-table/containers-table.tsx | 66 ++++++++--------- .../src/components/routes/system/info-bar.tsx | 12 +-- .../components/routes/system/smart-table.tsx | 73 +++++++++---------- .../systems-table/systems-table-columns.tsx | 27 ++----- .../systems-table/systems-table.tsx | 2 +- internal/site/src/lib/utils.ts | 11 +++ 6 files changed, 90 insertions(+), 101 deletions(-) diff --git a/internal/site/src/components/containers-table/containers-table.tsx b/internal/site/src/components/containers-table/containers-table.tsx index 92c63beb..773d478d 100644 --- a/internal/site/src/components/containers-table/containers-table.tsx +++ b/internal/site/src/components/containers-table/containers-table.tsx @@ -54,36 +54,34 @@ export default function ContainersTable({ systemId }: { systemId?: string }) { fields: "id,name,image,cpu,memory,net,health,status,system,updated", filter: systemId ? pb.filter("system={:system}", { system: systemId }) : undefined, }) - .then( - ({ items }) => { - if (items.length === 0) { - setData((curItems) => { - if (systemId) { - return curItems?.filter((item) => item.system !== systemId) ?? [] - } - return [] - }) - return - } + .then(({ items }) => { + if (items.length === 0) { setData((curItems) => { - const lastUpdated = Math.max(items[0].updated, items.at(-1)?.updated ?? 0) - const containerIds = new Set() - const newItems = [] - for (const item of items) { - if (Math.abs(lastUpdated - item.updated) < 70_000) { - containerIds.add(item.id) - newItems.push(item) - } + if (systemId) { + return curItems?.filter((item) => item.system !== systemId) ?? [] } - for (const item of curItems ?? []) { - if (!containerIds.has(item.id) && lastUpdated - item.updated < 70_000) { - newItems.push(item) - } - } - return newItems + return [] }) + return } - ) + setData((curItems) => { + const lastUpdated = Math.max(items[0].updated, items.at(-1)?.updated ?? 0) + const containerIds = new Set() + const newItems = [] + for (const item of items) { + if (Math.abs(lastUpdated - item.updated) < 70_000) { + containerIds.add(item.id) + newItems.push(item) + } + } + for (const item of curItems ?? []) { + if (!containerIds.has(item.id) && lastUpdated - item.updated < 70_000) { + newItems.push(item) + } + } + return newItems + }) + }) } // initial load @@ -285,7 +283,7 @@ async function getInfoHtml(container: ContainerRecord): Promise { ]) try { info = JSON.stringify(JSON.parse(info), null, 2) - } catch (_) { } + } catch (_) {} return info ? highlighter.codeToHtml(info, { lang: "json", theme: syntaxTheme }) : t`No results.` } catch (error) { console.error(error) @@ -342,12 +340,12 @@ function ContainerSheet({ setLogsDisplay("") setInfoDisplay("") if (!container) return - ; (async () => { - const [logsHtml, infoHtml] = await Promise.all([getLogsHtml(container), getInfoHtml(container)]) - setLogsDisplay(logsHtml) - setInfoDisplay(infoHtml) - setTimeout(scrollLogsToBottom, 20) - })() + ;(async () => { + const [logsHtml, infoHtml] = await Promise.all([getLogsHtml(container), getInfoHtml(container)]) + setLogsDisplay(logsHtml) + setInfoDisplay(infoHtml) + setTimeout(scrollLogsToBottom, 20) + })() }, [container]) return ( @@ -473,7 +471,7 @@ const ContainerTableRow = memo(function ContainerTableRow({ {row.getVisibleCells().map((cell) => ( [] = [ ), cell: ({ getValue }) => { - const hours = (getValue() ?? 0) as number - if (!hours && hours !== 0) { + const hours = getValue() as number | undefined + if (hours == null) { return
N/A
} const seconds = hours * 3600 @@ -195,7 +195,7 @@ export const columns: ColumnDef[] = [ ), cell: ({ getValue }) => { const cycles = getValue() as number | undefined - if (!cycles && cycles !== 0) { + if (cycles == null) { return
N/A
} return {cycles.toLocaleString()} @@ -206,9 +206,8 @@ export const columns: ColumnDef[] = [ invertSorting: true, header: ({ column }) => , cell: ({ getValue }) => { - const temp = getValue() as number | undefined | null - // Most devices won't report a real 0C temperature; treat 0 as "unknown". - if (temp == null || temp === 0) { + const temp = getValue() as number | null | undefined + if (!temp) { return
N/A
} const { value, unit } = formatTemperature(temp) @@ -309,41 +308,41 @@ export default function DisksTable({ systemId }: { systemId?: string }) { ? { fields: SMART_DEVICE_FIELDS, filter: pb.filter("system = {:system}", { system: systemId }) } : { fields: SMART_DEVICE_FIELDS } - ; (async () => { - try { - unsubscribe = await pb.collection("smart_devices").subscribe( - "*", - (event) => { - const record = event.record as SmartDeviceRecord - setSmartDevices((currentDevices) => { - const devices = currentDevices ?? [] - const matchesSystemScope = !systemId || record.system === systemId + ;(async () => { + try { + unsubscribe = await pb.collection("smart_devices").subscribe( + "*", + (event) => { + const record = event.record as SmartDeviceRecord + setSmartDevices((currentDevices) => { + const devices = currentDevices ?? [] + const matchesSystemScope = !systemId || record.system === systemId - if (event.action === "delete") { - return devices.filter((device) => device.id !== record.id) - } + if (event.action === "delete") { + return devices.filter((device) => device.id !== record.id) + } - if (!matchesSystemScope) { - // Record moved out of scope; ensure it disappears locally. - return devices.filter((device) => device.id !== record.id) - } + if (!matchesSystemScope) { + // Record moved out of scope; ensure it disappears locally. + return devices.filter((device) => device.id !== record.id) + } - const existingIndex = devices.findIndex((device) => device.id === record.id) - if (existingIndex === -1) { - return [record, ...devices] - } + const existingIndex = devices.findIndex((device) => device.id === record.id) + if (existingIndex === -1) { + return [record, ...devices] + } - const next = [...devices] - next[existingIndex] = record - return next - }) - }, - pbOptions - ) - } catch (error) { - console.error("Failed to subscribe to SMART device updates:", error) - } - })() + const next = [...devices] + next[existingIndex] = record + return next + }) + }, + pbOptions + ) + } catch (error) { + console.error("Failed to subscribe to SMART device updates:", error) + } + })() return () => { unsubscribe?.() 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 53807d4d..8afb02ea 100644 --- a/internal/site/src/components/systems-table/systems-table-columns.tsx +++ b/internal/site/src/components/systems-table/systems-table-columns.tsx @@ -35,7 +35,7 @@ import { formatTemperature, getMeterState, parseSemVer, - secondsToString, + secondsToUptimeString, } from "@/lib/utils" import { batteryStateTranslations } from "@/lib/i18n" import type { SystemRecord } from "@/types" @@ -154,11 +154,7 @@ export function SystemsTableColumns(viewMode: "table" | "grid"): ColumnDef - + ) }, @@ -382,20 +378,13 @@ export function SystemsTableColumns(viewMode: "table" | "grid"): ColumnDef{formatted} + return {secondsToUptimeString(uptime)} }, }, { @@ -479,9 +468,9 @@ function TableCellWithMeter(info: CellContext) { const meterClass = cn( "h-full", (info.row.original.status !== SystemStatus.Up && STATUS_COLORS.paused) || - (threshold === MeterState.Good && STATUS_COLORS.up) || - (threshold === MeterState.Warn && STATUS_COLORS.pending) || - STATUS_COLORS.down + (threshold === MeterState.Good && STATUS_COLORS.up) || + (threshold === MeterState.Warn && STATUS_COLORS.pending) || + STATUS_COLORS.down ) return (
@@ -593,7 +582,7 @@ export function IndicatorDot({ system, className }: { system: SystemRecord; clas return ( ) } diff --git a/internal/site/src/components/systems-table/systems-table.tsx b/internal/site/src/components/systems-table/systems-table.tsx index e30dc437..78438c5a 100644 --- a/internal/site/src/components/systems-table/systems-table.tsx +++ b/internal/site/src/components/systems-table/systems-table.tsx @@ -434,7 +434,7 @@ const SystemTableRow = memo( width: cell.column.getSize(), height: virtualRow.size, }} - className="py-0" + className="py-0 ps-4.5" > {flexRender(cell.column.columnDef.cell, cell.getContext())} diff --git a/internal/site/src/lib/utils.ts b/internal/site/src/lib/utils.ts index 6e52fb9e..4171b2f5 100644 --- a/internal/site/src/lib/utils.ts +++ b/internal/site/src/lib/utils.ts @@ -465,4 +465,15 @@ export function secondsToString(seconds: number, unit: "hour" | "minute" | "day" case "day": return plural(count, { one: `${countString} day`, other: `${countString} days` }) } +} + +/** Format seconds to uptime string - "X minutes", "X hours", "X days" */ +export function secondsToUptimeString(seconds: number): string { + if (seconds < 3600) { + return secondsToString(seconds, "minute") + } else if (seconds < 360000) { + return secondsToString(seconds, "hour") + } else { + return secondsToString(seconds, "day") + } } \ No newline at end of file