diff --git a/client/src/Components/monitors/MonitorStatBoxes.tsx b/client/src/Components/monitors/MonitorStatBoxes.tsx index 914e76ffb..58176dc04 100644 --- a/client/src/Components/monitors/MonitorStatBoxes.tsx +++ b/client/src/Components/monitors/MonitorStatBoxes.tsx @@ -1,12 +1,11 @@ import Stack from "@mui/material/Stack"; import { StatBox } from "@/Components/design-elements"; -import prettyMilliseconds from "pretty-ms"; import { useTheme } from "@mui/material/styles"; import type { MonitorStats, Monitor } from "@/Types/Monitor"; import { getStatusPalette } from "@/Utils/MonitorUtils"; import { useTranslation } from "react-i18next"; -import { formatMs } from "@/Utils/TimeUtils"; +import { formatMs, formatDuration } from "@/Utils/TimeUtils"; interface MonitorStatBoxesProps { monitor?: Monitor; @@ -32,14 +31,9 @@ export const MonitorStatBoxes = ({ const timeOfLastCheck = monitorStats?.lastCheckTimestamp || 0; const timeSinceLastCheck = Date.now() - timeOfLastCheck || 0; - const options = { - secondsDecimalDigits: 0, - millisecondsDecimalDigits: 0, - }; + const streakTime = formatDuration(timeSinceLastFailure); - const streakTime = prettyMilliseconds(timeSinceLastFailure, options); - - const lastCheckTime = prettyMilliseconds(timeSinceLastCheck, options); + const lastCheckTime = formatDuration(timeSinceLastCheck); const isActive = monitor?.status === "up" || monitor?.status === "paused" || diff --git a/client/src/Pages/Incidents/utils.ts b/client/src/Pages/Incidents/utils.ts index 6ff518a18..3407c40b4 100644 --- a/client/src/Pages/Incidents/utils.ts +++ b/client/src/Pages/Incidents/utils.ts @@ -1,5 +1,5 @@ import type { Incident, IncidentSummaryItem } from "@/Types/Incident"; -import prettyMilliseconds from "pretty-ms"; +import { formatDuration } from "@/Utils/TimeUtils"; type IncidentLike = Pick; @@ -24,8 +24,5 @@ export const getIncidentsDuration = (incident: IncidentLike | IncidentSummaryIte return "-"; } - return prettyMilliseconds(durationMs, { - secondsDecimalDigits: 0, - millisecondsDecimalDigits: 0, - }); + return formatDuration(durationMs); }; diff --git a/client/src/Pages/Logs/components/Stats.tsx b/client/src/Pages/Logs/components/Stats.tsx index 5cee4fe87..884fa9c18 100644 --- a/client/src/Pages/Logs/components/Stats.tsx +++ b/client/src/Pages/Logs/components/Stats.tsx @@ -6,7 +6,7 @@ import prettyMilliseconds from "pretty-ms"; import { useTheme } from "@mui/material"; import { useTranslation } from "react-i18next"; import type { Diagnostics } from "@/Types/Diagnostics"; -import { formatMs } from "@/Utils/TimeUtils"; +import { formatDuration, formatMs } from "@/Utils/TimeUtils"; interface StatsProps { diagnostics: Diagnostics | null; @@ -21,9 +21,7 @@ export const Stats = ({ diagnostics }: StatsProps) => { const eventLoopDelay = diagnostics ? formatMs(diagnostics.eventLoopDelayMs ?? 0) : PLACEHOLDER; - const uptime = diagnostics - ? prettyMilliseconds(diagnostics.uptimeMs ?? 0, { hideSeconds: true }) - : PLACEHOLDER; + const uptime = diagnostics ? formatDuration(diagnostics.uptimeMs ?? 0) : PLACEHOLDER; const usedHeap = diagnostics ? prettyBytes(diagnostics.v8HeapStats?.usedHeapSizeBytes ?? 0) : PLACEHOLDER; diff --git a/client/src/Pages/Logs/components/TableJobs.tsx b/client/src/Pages/Logs/components/TableJobs.tsx index 26fe62bb3..c8c287a9e 100644 --- a/client/src/Pages/Logs/components/TableJobs.tsx +++ b/client/src/Pages/Logs/components/TableJobs.tsx @@ -1,7 +1,6 @@ import { Table, Pagination } from "@/Components/design-elements"; import { Typography, useTheme } from "@mui/material"; -import prettyMilliseconds from "pretty-ms"; -import { formatTimestamp } from "@/Utils/TimeUtils"; +import { formatDuration, formatTimestamp } from "@/Utils/TimeUtils"; import { useTranslation } from "react-i18next"; import type { QueueJobFailure, QueueJobSummary, QueueMetrics } from "@/Types/Queue"; @@ -84,7 +83,7 @@ export const TableJobs = ({ id: "interval", content: t("common.table.headers.interval"), render: (row) => ( - {prettyMilliseconds(row.monitorInterval ?? 0)} + {formatDuration(row.monitorInterval ?? 0)} ), }, { diff --git a/client/src/Pages/Maintenance/MaintenanceWindowTable.tsx b/client/src/Pages/Maintenance/MaintenanceWindowTable.tsx index 6dadb5a9c..7cd543007 100644 --- a/client/src/Pages/Maintenance/MaintenanceWindowTable.tsx +++ b/client/src/Pages/Maintenance/MaintenanceWindowTable.tsx @@ -4,7 +4,6 @@ import { Pagination } from "@/Components/design-elements/Table"; import { ActionsMenu } from "@/Components/actions-menu"; import { DialogInput } from "@/Components/inputs/Dialog"; -import prettyMilliseconds from "pretty-ms"; import { useTheme } from "@mui/material"; import type { Header } from "@/Components/design-elements/Table"; import type { ActionMenuItem } from "@/Components/actions-menu"; @@ -18,6 +17,7 @@ import { setRowsPerPage } from "@/Features/UI/uiSlice"; import dayjs from "dayjs"; import { useState } from "react"; import { useDelete, usePatch } from "@/Hooks/UseApi"; +import { formatDuration } from "@/Utils/TimeUtils"; interface MaintenanceWindowTableProps { maintenanceWindows: MaintenanceWindow[]; @@ -51,7 +51,7 @@ const getTimeToNextWindow = ( // Window is in the future if (start.isAfter(now)) { - return prettyMilliseconds(start.diff(now), { unitCount: 2, hideSeconds: true }); + return formatDuration(start.diff(now)); } return "N/A"; @@ -152,9 +152,7 @@ export const MaintenanceWindowTable = ({ id: "repeat", content: t("pages.maintenanceWindow.table.headers.repeat"), render: (row) => - row.repeat === 0 - ? t("common.labels.na") - : prettyMilliseconds(row.repeat, { verbose: true }), + row.repeat === 0 ? t("common.labels.na") : formatDuration(row.repeat), }, { id: "actions", diff --git a/client/src/Utils/TimeUtils.ts b/client/src/Utils/TimeUtils.ts index 78bdc42a4..4112967ab 100644 --- a/client/src/Utils/TimeUtils.ts +++ b/client/src/Utils/TimeUtils.ts @@ -103,3 +103,20 @@ export const formatMs = (ms: number, hasSpace: boolean = true): string => { } return formatted; }; + +export const formatDuration = (ms: number, verbose: boolean = false, hasSpace = true) => { + if (verbose) { + return prettyMilliseconds(ms, { verbose: true }); + } + + const formatted = prettyMilliseconds(ms, { + unitCount: 2, + secondsDecimalDigits: 0, + millisecondsDecimalDigits: 0, + }); + + if (hasSpace) { + return formatted.replace(/^(\d+)(\D+)$/, "$1 $2"); + } + return formatted; +};