From 7c3a05077c6126b7e3bf697ef018bcfdd2e96b7d Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Mon, 6 Oct 2025 10:56:29 -0700 Subject: [PATCH] tooltip --- .../v2/Monitors/HistogramResponseTime.tsx | 50 +++++++++++-------- .../Monitors/HistogramResponseTimeTooltip.tsx | 29 +++++++++++ client/src/Types/Check.ts | 7 +++ client/src/Utils/TimeUtils.ts | 25 ++++++++++ 4 files changed, 90 insertions(+), 21 deletions(-) create mode 100644 client/src/Components/v2/Monitors/HistogramResponseTimeTooltip.tsx create mode 100644 client/src/Utils/TimeUtils.ts diff --git a/client/src/Components/v2/Monitors/HistogramResponseTime.tsx b/client/src/Components/v2/Monitors/HistogramResponseTime.tsx index 43e9a9677..d19ddbf53 100644 --- a/client/src/Components/v2/Monitors/HistogramResponseTime.tsx +++ b/client/src/Components/v2/Monitors/HistogramResponseTime.tsx @@ -2,6 +2,7 @@ import Stack from "@mui/material/Stack"; import Box from "@mui/material/Box"; import { useTheme } from "@mui/material/styles"; import type { Check } from "@/Types/Check"; +import { HistogramResponseTimeTooltip } from "@/Components/v2/Monitors/HistogramResponseTimeTooltip"; export const HistogramResponseTime = ({ checks }: { checks: Check[] }) => { let data = Array(); @@ -39,8 +40,11 @@ export const HistogramResponseTime = ({ checks }: { checks: Check[] }) => { {data.map((check, index) => { const safeResponse = Math.max(check.responseTime, 1); const logValue = Math.log10(safeResponse); + const minHeight = 10; const barHeight = - logMax === logMin ? 100 : ((logValue - logMin) / (logMax - logMin)) * 100; + logMax === logMin + ? 100 + : Math.max(minHeight, ((logValue - logMin) / (logMax - logMin)) * 100); if (check === "placeholder") { return ( @@ -57,32 +61,36 @@ export const HistogramResponseTime = ({ checks }: { checks: Check[] }) => { ); } else { return ( - - + > + + + ); } })} diff --git a/client/src/Components/v2/Monitors/HistogramResponseTimeTooltip.tsx b/client/src/Components/v2/Monitors/HistogramResponseTimeTooltip.tsx new file mode 100644 index 000000000..d704cf5d4 --- /dev/null +++ b/client/src/Components/v2/Monitors/HistogramResponseTimeTooltip.tsx @@ -0,0 +1,29 @@ +import Stack from "@mui/material/Stack"; +import Tooltip from "@mui/material/Tooltip"; +import Typography from "@mui/material/Typography"; +import { formatDateWithTz } from "@/Utils/TimeUtils"; +import { useSelector } from "react-redux"; +import type { LatestCheck } from "@/Types/Check"; + +export const HistogramResponseTimeTooltip: React.FC<{ + children: React.ReactElement; + check: LatestCheck; +}> = ({ children, check }) => { + const uiTimezone = useSelector((state: any) => state.ui.timezone); + return ( + + + {formatDateWithTz(check?.checkedAt, "ddd, MMMM D, YYYY, HH:mm A", uiTimezone)} + + {check?.responseTime && ( + Response Time: {check.responseTime} ms + )} + + } + > + {children} + + ); +}; diff --git a/client/src/Types/Check.ts b/client/src/Types/Check.ts index 0590069cc..c3c3712f0 100644 --- a/client/src/Types/Check.ts +++ b/client/src/Types/Check.ts @@ -10,3 +10,10 @@ export interface GroupedCheck { avgResponseTime: number; count: number; } + +export interface LatestCheck { + status: string; + responseTime: number; + checkedAt: string; + _id: string; +} diff --git a/client/src/Utils/TimeUtils.ts b/client/src/Utils/TimeUtils.ts new file mode 100644 index 000000000..5dc9b23c1 --- /dev/null +++ b/client/src/Utils/TimeUtils.ts @@ -0,0 +1,25 @@ +import dayjs from "dayjs"; +import duration from "dayjs/plugin/duration"; +import utc from "dayjs/plugin/utc"; +import timezone from "dayjs/plugin/timezone"; +import customParseFormat from "dayjs/plugin/customParseFormat"; + +dayjs.extend(utc); +dayjs.extend(timezone); +dayjs.extend(customParseFormat); +dayjs.extend(duration); + +export const MS_PER_SECOND = 1000; +export const MS_PER_MINUTE = 60 * MS_PER_SECOND; +export const MS_PER_HOUR = 60 * MS_PER_MINUTE; +export const MS_PER_DAY = 24 * MS_PER_HOUR; +export const MS_PER_WEEK = MS_PER_DAY * 7; + +export const formatDateWithTz = (timestamp: string, format: string, timezone: string) => { + if (!timestamp) { + return "Unknown time"; + } + + const formattedDate = dayjs(timestamp).tz(timezone).format(format); + return formattedDate; +};