fix(widgets): clean up health monitoring disk and size display (#6019)

This commit is contained in:
Afonso Jorge Ramos authored and GitHub committed 2026-06-20 11:47:38 +02:00
1 parent a19c9d88ca
commit e29c79a902
1 file changed
+40 -47
@@ -13,7 +13,6 @@ import {
Progress,
Stack,
Text,
Tooltip,
} from "@mantine/core";
import { useDisclosure } from "@mantine/hooks";
import {
@@ -33,6 +32,7 @@ import duration from "dayjs/plugin/duration";
import { clientApi } from "@homarr/api/client";
import { useRequiredBoard } from "@homarr/boards/context";
import { humanFileSize } from "@homarr/common";
import type { TranslationFunction } from "@homarr/translation";
import { useI18n } from "@homarr/translation/client";
@@ -91,7 +91,7 @@ export const SystemHealthMonitoring = ({
return (
<Stack h="100%" gap="sm" className="health-monitoring">
{healthData.map(({ integrationId, integrationName, healthInfo, updatedAt }) => {
{healthData.map(({ integrationId, integrationName, healthInfo }) => {
const disksData = matchFileSystemAndSmart(healthInfo.fileSystem, healthInfo.smart);
const memoryUsage = formatMemoryUsage(healthInfo.memAvailableInBytes, healthInfo.memUsedInBytes);
return (
@@ -196,11 +196,6 @@ export const SystemHealthMonitoring = ({
<GpuRing key={gpu.gpuId} gpu={gpu} isTiny={isTiny} fahrenheit={options.fahrenheit} />
))}
</Flex>
{
<Text className="health-monitoring-status-update-time" c="dimmed" size="xs" ta="center">
{t("widget.healthMonitoring.popover.lastSeen", { lastSeen: dayjs(updatedAt).fromNow() })}
</Text>
}
{options.fileSystem &&
disksData.map((disk) => {
return (
@@ -214,7 +209,7 @@ export const SystemHealthMonitoring = ({
radius={board.itemRadius}
p="xs"
>
<Stack gap="sm">
<Stack gap="xs">
<Group
className="health-monitoring-disk-status"
justify="space-between"
@@ -228,14 +223,16 @@ export const SystemHealthMonitoring = ({
{disk.deviceName}
</Text>
</Group>
<Group gap={4} wrap="nowrap">
<IconTemperature className="health-monitoring-disk-temperature-icon" size="1rem" />
<Text className="health-monitoring-disk-temperature-value" size="xs">
{options.fahrenheit
? `${(disk.temperature * 1.8 + 32).toFixed(1)}°F`
: `${disk.temperature}°C`}
</Text>
</Group>
{disk.temperature !== null && (
<Group gap={4} wrap="nowrap">
<IconTemperature className="health-monitoring-disk-temperature-icon" size="1rem" />
<Text className="health-monitoring-disk-temperature-value" size="xs">
{options.fahrenheit
? `${(disk.temperature * 1.8 + 32).toFixed(1)}°F`
: `${disk.temperature}°C`}
</Text>
</Group>
)}
<Group gap={4} wrap="nowrap">
<IconFileReport className="health-monitoring-disk-status-icon" size="1rem" />
<Text className="health-monitoring-disk-status-value" size="xs">
@@ -243,37 +240,26 @@ export const SystemHealthMonitoring = ({
</Text>
</Group>
</Group>
<Progress.Root className="health-monitoring-disk-use" radius={board.itemRadius} h="md">
<Tooltip label={disk.used}>
<Progress.Section
value={disk.percentage}
color={progressColor(disk.percentage)}
className="health-monitoring-disk-use-percentage"
>
<Progress.Label className="health-monitoring-disk-use-value" fz="xs">
{t("widget.healthMonitoring.popover.used")}
</Progress.Label>
</Progress.Section>
</Tooltip>
<Tooltip
label={
Number(disk.available) / 1024 ** 4 >= 1
? `${(Number(disk.available) / 1024 ** 4).toFixed(2)} TiB`
: `${(Number(disk.available) / 1024 ** 3).toFixed(2)} GiB`
}
>
<Progress.Section
className="health-monitoring-disk-available-percentage"
value={100 - disk.percentage}
color="default"
>
<Progress.Label className="health-monitoring-disk-available-value" fz="xs">
{t("widget.healthMonitoring.popover.available")}
</Progress.Label>
</Progress.Section>
</Tooltip>
<Progress.Root className="health-monitoring-disk-use" radius={board.itemRadius} size="lg">
<Progress.Section
value={disk.percentage}
color={progressColor(disk.percentage)}
className="health-monitoring-disk-use-percentage"
/>
<Progress.Section
className="health-monitoring-disk-available-percentage"
value={100 - disk.percentage}
color="default"
/>
</Progress.Root>
<Group justify="space-between" gap={8} wrap="nowrap">
<Text className="health-monitoring-disk-use-value" size="xs" c="dimmed">
{t("widget.healthMonitoring.popover.used")} {formatFileSize(disk.used)}
</Text>
<Text className="health-monitoring-disk-available-value" size="xs" c="dimmed">
{formatFileSize(disk.available)} {t("widget.healthMonitoring.popover.available")}
</Text>
</Group>
</Stack>
</Card>
);
@@ -307,6 +293,13 @@ export const progressColor = (percentage: number) => {
else return "red";
};
// Some integrations report file sizes as raw bytes (e.g. TrueNAS, Glances) while others pre-format
// them (e.g. Unraid, dashdot). Format the former and pass the latter through untouched.
const formatFileSize = (value: string) => {
const bytes = Number(value);
return Number.isFinite(bytes) ? humanFileSize(Math.round(bytes)) : value;
};
interface FileSystem {
deviceName: string;
used: string;
@@ -331,7 +324,7 @@ export const matchFileSystemAndSmart = (fileSystems: FileSystem[], smartData: Sm
used: fileSystem.used,
available: fileSystem.available,
percentage: fileSystem.percentage,
temperature: smartDisk?.temperature ?? 0,
temperature: smartDisk?.temperature ?? null,
overallStatus: smartDisk?.overallStatus ?? "",
};
})