From 4ac0f1e87fbd755e6bb9ed8a8064faadc3e5dd05 Mon Sep 17 00:00:00 2001 From: Jannis Fedoruk-Betschki Date: Wed, 29 Oct 2025 20:16:39 +0100 Subject: [PATCH 1/2] feat: add detailed response time breakdown in Response Times table --- .../Components/ResponseTable/index.jsx | 126 ++++++++++++++++++ client/src/locales/en.json | 6 + 2 files changed, 132 insertions(+) diff --git a/client/src/Pages/v1/Uptime/Details/Components/ResponseTable/index.jsx b/client/src/Pages/v1/Uptime/Details/Components/ResponseTable/index.jsx index 948489ac1..a131092a0 100644 --- a/client/src/Pages/v1/Uptime/Details/Components/ResponseTable/index.jsx +++ b/client/src/Pages/v1/Uptime/Details/Components/ResponseTable/index.jsx @@ -7,6 +7,80 @@ import { StatusLabel } from "@/Components/v1/Label/index.jsx"; import { useTranslation } from "react-i18next"; import { formatDateWithTz } from "../../../../../../Utils/timeUtils.js"; import SkeletonLayout from "./skeleton.jsx"; +import Tooltip from "@mui/material/Tooltip"; +import Box from "@mui/material/Box"; +import Typography from "@mui/material/Typography"; +import Stack from "@mui/material/Stack"; +import { lighten, useTheme } from "@mui/material"; + +/** + * Creates tooltip content with detailed timing breakdown + * Following the pattern from IncidentTable's GetTooltip function + * @param {Object} timings - Timing object (guaranteed to have phases by caller) + * @param {Object} theme - MUI theme object + * @param {Function} t - Translation function + * @returns {JSX.Element} Tooltip content + */ +const GetTooltip = (timings, theme, t) => { + const phases = timings.phases; + const timingDetails = [ + { label: t("dnsLookup"), value: phases.dns }, + { label: t("tcpConnection"), value: phases.tcp }, + { label: t("tlsHandshake"), value: phases.tls }, + { label: t("waitTime"), value: phases.wait }, + { label: t("timeToFirstByte"), value: phases.firstByte }, + { label: t("download"), value: phases.download }, + { label: t("total"), value: phases.total }, + ].filter((item) => item.value > 0); + + return ( + + + {t("responseTimeBreakdown")} + + {timingDetails.map((detail, index) => ( + + + {detail.label}: + + + {Math.round(detail.value)} ms + + + ))} + + ); +}; + const ResponseTable = ({ isLoading = false, checks = [], @@ -18,6 +92,8 @@ const ResponseTable = ({ setRowsPerPage, }) => { const { t } = useTranslation(); + const theme = useTheme(); + if (isLoading) { return ; } @@ -54,6 +130,56 @@ const ResponseTable = ({ content: t("message"), render: (row) => row.message, }, + { + id: "responseTime", + content: t("responseTime"), + render: (row) => { + const hasTimings = row.timings && row.timings.phases; + const responseTime = row.responseTime; + const responseTimeDisplay = + responseTime !== null && responseTime !== undefined + ? `${Math.round(responseTime)} ms` + : "N/A"; + + if (!hasTimings) { + return responseTimeDisplay; + } + + return ( + + + {responseTimeDisplay} + + + ); + }, + }, ]; return ( diff --git a/client/src/locales/en.json b/client/src/locales/en.json index 13d4a7731..fc8e54a40 100644 --- a/client/src/locales/en.json +++ b/client/src/locales/en.json @@ -20,6 +20,12 @@ "delete": "Delete", "configure": "Configure", "responseTime": "Response time", + "responseTimeBreakdown": "Response Time Breakdown", + "dnsLookup": "DNS Lookup", + "tcpConnection": "TCP Connection", + "tlsHandshake": "TLS Handshake", + "waitTime": "Wait Time", + "timeToFirstByte": "Time to First Byte", "ms": "ms", "bar": "Bar", "area": "Area", From 87c549960ec64be42f35d69df5726843423d5abc Mon Sep 17 00:00:00 2001 From: Jannis Fedoruk-Betschki Date: Wed, 29 Oct 2025 20:32:21 +0100 Subject: [PATCH 2/2] fix: use array parameter instead of closure for i18n-safe bold styling --- .../v1/Uptime/Details/Components/ResponseTable/index.jsx | 6 +++--- client/src/locales/en.json | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/client/src/Pages/v1/Uptime/Details/Components/ResponseTable/index.jsx b/client/src/Pages/v1/Uptime/Details/Components/ResponseTable/index.jsx index a131092a0..0d0defc3b 100644 --- a/client/src/Pages/v1/Uptime/Details/Components/ResponseTable/index.jsx +++ b/client/src/Pages/v1/Uptime/Details/Components/ResponseTable/index.jsx @@ -50,14 +50,14 @@ const GetTooltip = (timings, theme, t) => { > {t("responseTimeBreakdown")} - {timingDetails.map((detail, index) => ( + {timingDetails.map((detail, index, array) => ( { diff --git a/client/src/locales/en.json b/client/src/locales/en.json index fc8e54a40..85b326917 100644 --- a/client/src/locales/en.json +++ b/client/src/locales/en.json @@ -26,6 +26,7 @@ "tlsHandshake": "TLS Handshake", "waitTime": "Wait Time", "timeToFirstByte": "Time to First Byte", + "download": "Download", "ms": "ms", "bar": "Bar", "area": "Area",