diff --git a/src/healthchecksio.tsx b/src/healthchecksio.tsx index dd173f9..f82c233 100644 --- a/src/healthchecksio.tsx +++ b/src/healthchecksio.tsx @@ -1,6 +1,6 @@ import { useState } from "react"; import useSWR from "swr"; -import { groupBy, healthchecksioFetcher, removePrefix, removeSuffix } from "./utils"; +import { groupBy, healthchecksioFetcher, removePrefix, removeSuffix, timeSinceShort } from "./utils"; import { STATUS_SYMBOLS } from "./constants"; import { StatusSummary } from "./summary"; import { OptionGroup } from "./option-group"; @@ -76,7 +76,7 @@ function shortenCheckName(groupKey: typeof GROUP_KEYS[number], groupName: string export function HealthchecksioStatus({ showInternal, initialGroupKey = "" }: { showInternal?: boolean, initialGroupKey?: string }) { const [groupKey, setGroupKey] = useState((GROUP_KEYS.includes(initialGroupKey as any) ? initialGroupKey : GROUP_KEYS[0]) as typeof GROUP_KEYS[number]); - const { data: dataRaw, error, isLoading } = useSWR('/api/v3/checks/', healthchecksioFetcher, { refreshInterval: 10000 }); + const { data: dataRaw, error, isLoading } = useSWR('/api/v3/checks/', healthchecksioFetcher, { refreshInterval: 5000 }); const checks = (processHCData(dataRaw) || []).filter(check => check.tags_dict.public !== 'False' || showInternal); const groupedChecks = groupBy(checks, c => c.tags_dict[groupKey]); @@ -99,14 +99,15 @@ export function HealthchecksioStatus({ showInternal, initialGroupKey = "" }: { s selectedClassName="bg-blue-500 text-white" /> -
+
{Object.entries(groupedChecks).sort().map(([group, checks]) => (

{group}

    {checks.map(check => (
  • - {shortenCheckName(groupKey, group, check.name)} + {shortenCheckName(groupKey, group, check.name)} {timeSinceShort(new Date(check.last_ping))} ago
  • ))} diff --git a/src/utils.ts b/src/utils.ts index 189973a..9570218 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -74,4 +74,43 @@ export function removeSuffix(str: string, suffix: string) { export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) +} + +export function timeSince(date: Date): string { + let v: number = Math.floor((new Date().getTime() - date.getTime()) / 1000); + + if (v < 60) { + // v is seconds + return v + ' second' + (v === 1 ? '' : 's'); + } + + v = Math.floor(v / 60); // v is now minutes + if (v < 60) { + return v + ' minute' + (v === 1 ? '' : 's'); + } + + v = Math.floor(v / 60); // v is now hours + if (v < 24) { + return v + ' hour' + (v === 1 ? '' : 's'); + } + + v = Math.floor(v / 24); // v is now days + return v + ' day' + (v === 1 ? '' : 's'); +} + +export function timeSinceShort(date: Date): string { + const seconds = Math.floor((new Date().getTime() - date.getTime()) / 1000); + const units: [number, string][] = [ + [60, 's'], + [60, 'm'], + [24, 'h'], + [Number.MAX_SAFE_INTEGER, 'd'] + ]; + + let value = seconds; + for (const [unit, suffix] of units) { + if (value < unit) return `${value}${suffix}`; + value = Math.floor(value / unit); + } + return `${value}d`; } \ No newline at end of file