diff --git a/public/locales/en/modules/health-monitoring.json b/public/locales/en/modules/health-monitoring.json index be6e085e4..933386e80 100644 --- a/public/locales/en/modules/health-monitoring.json +++ b/public/locales/en/modules/health-monitoring.json @@ -86,7 +86,7 @@ }, "info": { "uptime": "Uptime", - "uptimeFormat": "{{days}} days, {{hours}} hours", + "uptimeFormat": "{{days}} days, {{hours}} hours, {{minutes}} minutes", "updates": "Updates Available", "reboot": "Reboot" }, diff --git a/src/widgets/health-monitoring/HealthMonitoringTile.tsx b/src/widgets/health-monitoring/HealthMonitoringTile.tsx index 71bddeeed..573ddd423 100644 --- a/src/widgets/health-monitoring/HealthMonitoringTile.tsx +++ b/src/widgets/health-monitoring/HealthMonitoringTile.tsx @@ -6,6 +6,8 @@ import { IconInfoSquare, IconStatusChange, } from '@tabler/icons-react'; +import dayjs from 'dayjs'; +import duration from 'dayjs/plugin/duration'; import { useTranslation } from 'next-i18next'; import { useConfigContext } from '~/config/provider'; import { api } from '~/utils/api'; @@ -18,6 +20,8 @@ import HealthMonitoringFileSystem from './HealthMonitoringFileSystem'; import HealthMonitoringMemory from './HealthMonitoringMemory'; import { ClusterStatusTile } from './cluster/HealthMonitoringClusterTile'; +dayjs.extend(duration); + const defaultViewStates = ['none', 'node', 'vm', 'lxc', 'storage'] as const; type DefaultViewState = (typeof defaultViewStates)[number]; @@ -186,12 +190,6 @@ function HealthMonitoringWidgetTile({ widget }: HealthMonitoringWidgetProps) { const SystemStatusTile = ({ data, properties }: { data: any; properties: any }) => { const { t } = useTranslation('modules/health-monitoring'); - const formatUptime = (uptime: number) => { - const days = Math.floor(uptime / (60 * 60 * 24)); - const remainingHours = Math.floor((uptime % (60 * 60 * 24)) / 3600); - return t('info.uptimeFormat', { days: days, hours: remainingHours}) - }; - return ( @@ -268,3 +266,13 @@ const useStatusQuery = (node: string, ignoreCerts: boolean) => { }; export default definition; + +export const formatUptime = (uptime: number) => { + const { t } = useTranslation('modules/health-monitoring'); + const time = dayjs.duration(uptime, 's'); + return t('info.uptimeFormat', { + days: Math.floor(time.asDays()), + hours: time.hours(), + minutes: time.minutes(), + }); +}; diff --git a/src/widgets/health-monitoring/cluster/HealthMonitoringClusterTile.tsx b/src/widgets/health-monitoring/cluster/HealthMonitoringClusterTile.tsx index 2ad96cb40..9b37d8f57 100644 --- a/src/widgets/health-monitoring/cluster/HealthMonitoringClusterTile.tsx +++ b/src/widgets/health-monitoring/cluster/HealthMonitoringClusterTile.tsx @@ -1,24 +1,20 @@ -import { Accordion, Center, Flex, Group, RingProgress, Stack, Text } from '@mantine/core'; +import { Accordion, Card, Center, Flex, Group, RingProgress, Stack, Text } from '@mantine/core'; import { IconBrain, IconCpu, IconCube, IconDatabase, IconDeviceLaptop, + IconInfoSquare, IconServer, } from '@tabler/icons-react'; import { useTranslation } from 'react-i18next'; -import { ResourceData, ResourceSummary } from '~/widgets/health-monitoring/cluster/types'; +import { ResourceData } from '~/widgets/health-monitoring/cluster/types'; +import { formatUptime } from '../HealthMonitoringTile'; import { ResourceType } from './HealthMonitoringClusterResourceRow'; -export const ClusterStatusTile = ({ - data, - properties, -}: { - data: ResourceSummary; - properties: any; -}) => { +export const ClusterStatusTile = ({ data, properties }: { data: any; properties: any }) => { const { t } = useTranslation('modules/health-monitoring'); const running = (total: number, current: ResourceData) => { @@ -46,12 +42,26 @@ export const ClusterStatusTile = ({ (sum: number, item: ResourceData) => (item.running ? item.cpu * item.maxCpu + sum : sum), 0 ); + const uptime = data.nodes.reduce( + (sum: number, { uptime }: ResourceData) => (sum > uptime ? sum : uptime), + 0 + ); const cpuPercent = (usedCpu / maxCpu) * 100; const memPercent = (usedMem / maxMem) * 100; return ( + + + + + {t('info.uptime')}: +
+ {formatUptime(uptime)} +
+
+
{ const { t } = useTranslation('modules/health-monitoring'); - if (!include) { - return null; - } + if (!include) return null; + return (
@@ -142,7 +151,7 @@ const SummaryHeader = ({ cpu, memory, include }: SummaryHeaderProps) => { sections={[{ value: cpu, color: cpu > 75 ? 'orange' : 'green' }]} /> - {t('cluster.summary.cpu')} + {t('cluster.summary.cpu')} {cpu.toFixed(1)}% @@ -159,7 +168,7 @@ const SummaryHeader = ({ cpu, memory, include }: SummaryHeaderProps) => { sections={[{ value: memory, color: memory > 75 ? 'orange' : 'green' }]} /> - {t('cluster.summary.ram')} + {t('cluster.summary.ram')} {memory.toFixed(1)}%