From 602769b3e7c04e313ad9c137a44c90ce45e6a9af Mon Sep 17 00:00:00 2001 From: gorkem-bwl Date: Thu, 7 May 2026 01:13:09 -0400 Subject: [PATCH 1/6] feat(checks): render status code 5000 as "Down" with subtype tooltip MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Status code 5000 is Checkmate's internal sentinel for "no HTTP response received" (DNS failure, connection refused, timeout, TLS error, etc.). Showing the raw number to admins is confusing — the value isn't a real HTTP code and means nothing without context. This change replaces "5000" with "Down" across all check/incident surfaces, and adds a hover tooltip that explains the underlying cause based on the stored error message. Real HTTP codes (2xx/3xx/4xx/5xx) are unchanged. ## Changes - Add client/src/Utils/statusCode.ts with formatStatusCode, getStatusCodeTooltip, getStatusCodeValueType, extractErrorCode, and a message-to-subtype parser (timeout / dns / refused / tls / reset). - Wire into 6 render sites: Checks table, Uptime details Checks table, GeoChecks table + map popup, Incidents table, Incident details dialog. - Add common.statusCode.* i18n keys in en.json with subtype-specific descriptions. Tooltip appends the raw error code (ECONNREFUSED, ETIMEDOUT, CERT_HAS_EXPIRED, etc.) when present in the message. ## Tooltip examples - "queryA ECONNREFUSED www.example.com" → "The server refused the connection (port closed or service not listening). (ECONNREFUSED)" - "connect ETIMEDOUT 1.2.3.4:443" → "The server didn't respond in time (request timed out). (ETIMEDOUT)" ## Notes - No DB or server changes; statusCode field stays 5000 in storage. - Other locales fall back to English keys until translated. --- .../src/Components/monitors/GeoChecksMap.tsx | 5 +- .../Pages/Checks/Components/ChecksTable.tsx | 31 ++++++-- .../Incidents/Components/CardDetails.tsx | 21 ++++- .../Incidents/Components/IncidentTable.tsx | 27 ++++--- .../Uptime/Details/Components/ChecksTable.tsx | 16 +++- .../Details/Components/GeoChecksTable.tsx | 16 +++- client/src/Utils/statusCode.ts | 78 +++++++++++++++++++ client/src/locales/en.json | 11 +++ 8 files changed, 181 insertions(+), 24 deletions(-) create mode 100644 client/src/Utils/statusCode.ts diff --git a/client/src/Components/monitors/GeoChecksMap.tsx b/client/src/Components/monitors/GeoChecksMap.tsx index 3f9429853..e013f2235 100644 --- a/client/src/Components/monitors/GeoChecksMap.tsx +++ b/client/src/Components/monitors/GeoChecksMap.tsx @@ -3,6 +3,8 @@ import { Box, Typography, Stack, useTheme, GlobalStyles } from "@mui/material"; import Map, { Marker, Popup } from "react-map-gl/maplibre"; import type { MapRef } from "react-map-gl/maplibre"; import type { FlatGeoCheck } from "@/Types/GeoCheck"; +import { useTranslation } from "react-i18next"; +import { formatStatusCode } from "@/Utils/statusCode"; import "maplibre-gl/dist/maplibre-gl.css"; interface GeoChecksMapProps { @@ -14,6 +16,7 @@ export const GeoChecksMap = ({ geoChecks }: GeoChecksMapProps) => { const [selectedCheck, setSelectedCheck] = useState(null); const theme = useTheme(); const isDarkMode = theme.palette.mode === "dark"; + const { t } = useTranslation(); const mapPopupStyles = ( { > Status Code: {" "} - {selectedCheck.statusCode} + {formatStatusCode(selectedCheck.statusCode, t)} state.ui.timezone); - const getHeaders = (t: Function, uiTimezone: string) => { + const getHeaders = (t: (key: string) => string, uiTimezone: string) => { const headers: Header[] = [ { id: "monitorName", @@ -65,13 +76,21 @@ export const ChecksTable = ({ render: (row) => { const code = row.statusCode; if (!code) return "N/A"; - const value = code < 300 ? "positive" : code < 400 ? "neutral" : "negative"; - return ( + const text = formatStatusCode(code, t); + const tooltip = getStatusCodeTooltip(code, row.message, t); + const label = ( ); + return tooltip ? ( + + {label} + + ) : ( + label + ); }, }, { diff --git a/client/src/Pages/Incidents/Components/CardDetails.tsx b/client/src/Pages/Incidents/Components/CardDetails.tsx index b6c1288dd..2cd8fbde4 100644 --- a/client/src/Pages/Incidents/Components/CardDetails.tsx +++ b/client/src/Pages/Incidents/Components/CardDetails.tsx @@ -2,7 +2,7 @@ import Stack from "@mui/material/Stack"; import Grid from "@mui/material/Grid"; import Divider from "@mui/material/Divider"; import Typography from "@mui/material/Typography"; -import { BaseBox, ValueLabel } from "@/Components/design-elements"; +import { BaseBox, ValueLabel, Tooltip } from "@/Components/design-elements"; import { LAYOUT } from "@/Utils/Theme/constants"; import { useTranslation } from "react-i18next"; @@ -13,6 +13,7 @@ import { useSelector } from "react-redux"; import type { RootState } from "@/Types/state"; import { formatDateWithTz } from "@/Utils/TimeUtils"; import { getIncidentsDuration } from "@/Pages/Incidents/utils"; +import { formatStatusCode, getStatusCodeTooltip } from "@/Utils/statusCode"; interface CardDetailsProps { incident: Incident | null; @@ -46,6 +47,14 @@ export const CardDetails = ({ incident, monitor, sx }: CardDetailsProps) => { if (!incident) { return null; } + + const statusCodeText = formatStatusCode(incident.statusCode, t); + const statusCodeTooltip = getStatusCodeTooltip( + incident.statusCode, + incident.message, + t + ); + return ( { {t("pages.incidents.dialog.details.statusCode")} - {incident.statusCode ?? "N/A"} + + {statusCodeTooltip ? ( + + {statusCodeText} + + ) : ( + statusCodeText + )} + {t("pages.incidents.dialog.details.downtime")} diff --git a/client/src/Pages/Incidents/Components/IncidentTable.tsx b/client/src/Pages/Incidents/Components/IncidentTable.tsx index bb1759dcd..c66cdb0ed 100644 --- a/client/src/Pages/Incidents/Components/IncidentTable.tsx +++ b/client/src/Pages/Incidents/Components/IncidentTable.tsx @@ -1,8 +1,6 @@ -import { Table } from "@/Components/design-elements"; +import { Table, ValueLabel, Tooltip } from "@/Components/design-elements"; import { Pagination } from "@/Components/design-elements/Table"; import type { Header } from "@/Components/design-elements/Table"; -import { ValueLabel } from "@/Components/design-elements"; -import type { ValueType } from "@/Components/design-elements/StatusLabel"; import { ActionsMenu } from "@/Components/actions-menu"; import type { Incident } from "@/Types/Incident"; import type { Monitor } from "@/Types/Monitor"; @@ -16,6 +14,11 @@ import Typography from "@mui/material/Typography"; import { useTheme } from "@mui/material/styles"; import Box from "@mui/material/Box"; import { getMonitorPath } from "@/Utils/MonitorUtils"; +import { + formatStatusCode, + getStatusCodeTooltip, + getStatusCodeValueType, +} from "@/Utils/statusCode"; interface IncidentsTableProps { title?: string; @@ -157,15 +160,21 @@ export const IncidentsTable = ({ render: (row) => { const code = row.statusCode; if (!code) return "N/A"; - let value: ValueType = "neutral"; - if (code < 300) value = "positive"; - else if (code >= 400) value = "negative"; - return ( + const text = formatStatusCode(code, t); + const tooltip = getStatusCodeTooltip(code, row.message, t); + const label = ( ); + return tooltip ? ( + + {label} + + ) : ( + label + ); }, }, { diff --git a/client/src/Pages/Uptime/Details/Components/ChecksTable.tsx b/client/src/Pages/Uptime/Details/Components/ChecksTable.tsx index 0aaede394..0ab9a7a7c 100644 --- a/client/src/Pages/Uptime/Details/Components/ChecksTable.tsx +++ b/client/src/Pages/Uptime/Details/Components/ChecksTable.tsx @@ -1,4 +1,4 @@ -import { Table, Pagination, StatusLabel } from "@/Components/design-elements"; +import { Table, Pagination, StatusLabel, Tooltip } from "@/Components/design-elements"; import Box from "@mui/material/Box"; import type { Header } from "@/Components/design-elements"; import type { Check } from "@/Types/Check"; @@ -6,10 +6,11 @@ import type { Check } from "@/Types/Check"; import { useNavigate } from "react-router"; import { useTranslation } from "react-i18next"; import { formatDateWithTz } from "@/Utils/TimeUtils"; +import { formatStatusCode, getStatusCodeTooltip } from "@/Utils/statusCode"; import type { RootState } from "@/Types/state"; import { useSelector } from "react-redux"; -const getHeaders = (t: Function, uiTimezone: string) => { +const getHeaders = (t: (key: string) => string, uiTimezone: string) => { const headers: Header[] = [ { id: "status", @@ -36,7 +37,16 @@ const getHeaders = (t: Function, uiTimezone: string) => { id: "statusCode", content: t("pages.checks.table.headers.statusCode"), render: (row) => { - return row.statusCode || "N/A"; + if (!row.statusCode) return "N/A"; + const text = formatStatusCode(row.statusCode, t); + const tooltip = getStatusCodeTooltip(row.statusCode, row.message, t); + return tooltip ? ( + + {text} + + ) : ( + text + ); }, }, ]; diff --git a/client/src/Pages/Uptime/Details/Components/GeoChecksTable.tsx b/client/src/Pages/Uptime/Details/Components/GeoChecksTable.tsx index 31ad6a3dd..ae56e037e 100644 --- a/client/src/Pages/Uptime/Details/Components/GeoChecksTable.tsx +++ b/client/src/Pages/Uptime/Details/Components/GeoChecksTable.tsx @@ -1,14 +1,15 @@ -import { Table, Pagination, StatusLabel } from "@/Components/design-elements"; +import { Table, Pagination, StatusLabel, Tooltip } from "@/Components/design-elements"; import Box from "@mui/material/Box"; import type { Header } from "@/Components/design-elements"; import type { FlatGeoCheck } from "@/Types/GeoCheck"; import { useTranslation } from "react-i18next"; import { formatDateWithTz } from "@/Utils/TimeUtils"; +import { formatStatusCode, getStatusCodeTooltip } from "@/Utils/statusCode"; import type { RootState } from "@/Types/state"; import { useSelector } from "react-redux"; import prettyMilliseconds from "pretty-ms"; -const getHeaders = (t: Function, uiTimezone: string) => { +const getHeaders = (t: (key: string) => string, uiTimezone: string) => { const headers: Header[] = [ { id: "status", @@ -29,7 +30,16 @@ const getHeaders = (t: Function, uiTimezone: string) => { id: "statusCode", content: t("pages.checks.table.headers.statusCode"), render: (row) => { - return row.statusCode || "N/A"; + if (!row.statusCode) return "N/A"; + const text = formatStatusCode(row.statusCode, t); + const tooltip = getStatusCodeTooltip(row.statusCode, undefined, t); + return tooltip ? ( + + {text} + + ) : ( + text + ); }, }, { diff --git a/client/src/Utils/statusCode.ts b/client/src/Utils/statusCode.ts new file mode 100644 index 000000000..75e4a9b19 --- /dev/null +++ b/client/src/Utils/statusCode.ts @@ -0,0 +1,78 @@ +import type { ValueType } from "@/Components/design-elements/StatusLabel"; + +export const NETWORK_ERROR_CODE = 5000; + +export const NETWORK_ERROR_SUBTYPES = [ + "timeout", + "dns", + "refused", + "tls", + "reset", + "unknown", +] as const; +export type NetworkErrorSubtype = (typeof NETWORK_ERROR_SUBTYPES)[number]; + +type TranslateFn = (key: string) => string; + +export const isNetworkError = (code?: number | null): boolean => + code === NETWORK_ERROR_CODE; + +const ERROR_CODE_PATTERN = + /\b(E[A-Z_]{2,}|CERT_[A-Z_]+|UNABLE_TO_VERIFY[A-Z_]*|DEPTH_ZERO_SELF_SIGNED[A-Z_]*|SELF_SIGNED[A-Z_]*)\b/; + +export const extractErrorCode = (message?: string | null): string | null => { + if (!message) return null; + const match = message.match(ERROR_CODE_PATTERN); + return match ? match[1] : null; +}; + +export const getNetworkErrorSubtype = (message?: string | null): NetworkErrorSubtype => { + if (!message) return "unknown"; + const m = message.toUpperCase(); + if (m.includes("ETIMEDOUT") || m.includes("TIMEOUT") || m.includes("ESOCKETTIMEDOUT")) + return "timeout"; + if (m.includes("ENOTFOUND") || m.includes("EAI_AGAIN") || m.includes("DNS")) + return "dns"; + if (m.includes("ECONNREFUSED")) return "refused"; + if ( + m.includes("CERT_") || + m.includes("UNABLE_TO_VERIFY") || + m.includes("DEPTH_ZERO_SELF_SIGNED") || + m.includes("SELF_SIGNED") || + m.includes("TLS") || + m.includes("SSL") + ) + return "tls"; + if (m.includes("ECONNRESET")) return "reset"; + return "unknown"; +}; + +export const formatStatusCode = ( + code: number | null | undefined, + t: TranslateFn, + fallback: string = "N/A" +): string => { + if (code == null) return fallback; + if (isNetworkError(code)) return t("common.statusCode.down"); + return String(code); +}; + +export const getStatusCodeTooltip = ( + code: number | null | undefined, + message: string | null | undefined, + t: TranslateFn +): string | null => { + if (!isNetworkError(code)) return null; + const description = t( + `common.statusCode.networkError.${getNetworkErrorSubtype(message)}` + ); + const errorCode = extractErrorCode(message); + return errorCode ? `${description} (${errorCode})` : description; +}; + +export const getStatusCodeValueType = (code: number): ValueType => { + if (isNetworkError(code)) return "negative"; + if (code < 300) return "positive"; + if (code < 400) return "neutral"; + return "negative"; +}; diff --git a/client/src/locales/en.json b/client/src/locales/en.json index 211021276..587e25df1 100644 --- a/client/src/locales/en.json +++ b/client/src/locales/en.json @@ -14,6 +14,17 @@ } }, "appName": "Checkmate", + "statusCode": { + "down": "Down", + "networkError": { + "timeout": "The server didn't respond in time (request timed out).", + "dns": "Couldn't resolve the hostname (DNS lookup failed).", + "refused": "The server refused the connection (port closed or service not listening).", + "tls": "TLS or SSL handshake failed (certificate or encryption issue).", + "reset": "The connection was reset before a response was received.", + "unknown": "No HTTP response was received from the target." + } + }, "breadcrumbs": { "details": "Details", "home": "Home" From 7906f2f615a8f28cabce0d573ae9b57fb04c7cf8 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 7 May 2026 09:54:03 -0700 Subject: [PATCH 2/6] add stauts code label component --- .../design-elements/StatusCodeLabel.tsx | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 client/src/Components/design-elements/StatusCodeLabel.tsx diff --git a/client/src/Components/design-elements/StatusCodeLabel.tsx b/client/src/Components/design-elements/StatusCodeLabel.tsx new file mode 100644 index 000000000..b1500d42b --- /dev/null +++ b/client/src/Components/design-elements/StatusCodeLabel.tsx @@ -0,0 +1,36 @@ +import { useTranslation } from "react-i18next"; +import { + formatStatusCode, + getStatusCodeTooltip, + getStatusCodeValueType, +} from "@/Utils/statusCode"; +import { ValueLabel } from "./StatusLabel"; +import { Tooltip } from "./Tooltip"; + +export type StatusCodeLabelProps = { + statusCode: number | null | undefined; + message?: string | null; + fallback?: string; +}; + +export const StatusCodeLabel = ({ + statusCode, + message, + fallback = "N/A", +}: StatusCodeLabelProps) => { + const { t } = useTranslation(); + if (!statusCode) { + return <>{fallback}; + } + + const text = formatStatusCode(statusCode, t); + const tooltip = getStatusCodeTooltip(statusCode, message, t); + const body = ( + + ); + if (!tooltip) return body; + return {body}; +}; From 7c14d81a2428c99df99ac27517d5aa866bb165bf Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 7 May 2026 09:54:22 -0700 Subject: [PATCH 3/6] refactor utils --- client/src/Utils/statusCode.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/client/src/Utils/statusCode.ts b/client/src/Utils/statusCode.ts index 75e4a9b19..33a5f3de1 100644 --- a/client/src/Utils/statusCode.ts +++ b/client/src/Utils/statusCode.ts @@ -49,10 +49,8 @@ export const getNetworkErrorSubtype = (message?: string | null): NetworkErrorSub export const formatStatusCode = ( code: number | null | undefined, - t: TranslateFn, - fallback: string = "N/A" + t: TranslateFn ): string => { - if (code == null) return fallback; if (isNetworkError(code)) return t("common.statusCode.down"); return String(code); }; From 0827d4f5285abbd80231d155be347f02b91807f5 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 7 May 2026 09:54:50 -0700 Subject: [PATCH 4/6] add new component to barrel export --- client/src/Components/design-elements/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/client/src/Components/design-elements/index.tsx b/client/src/Components/design-elements/index.tsx index f6e2771ec..557f3bfc2 100644 --- a/client/src/Components/design-elements/index.tsx +++ b/client/src/Components/design-elements/index.tsx @@ -25,3 +25,4 @@ export * from "./TextLink"; export * from "./NoticeBanner"; export * from "./OfflineBanner"; export * from "./Avatar"; +export * from "./StatusCodeLabel"; From 1d90b8d8d9032ce98b0e9450a598bbee0163304a Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 7 May 2026 09:54:58 -0700 Subject: [PATCH 5/6] refactor all call sites --- .../Pages/Checks/Components/ChecksTable.tsx | 32 ++-------- .../Incidents/Components/CardDetails.tsx | 21 ++---- .../Incidents/Components/IncidentTable.tsx | 39 ++++------- .../Uptime/Details/Components/ChecksTable.tsx | 64 +++++++++---------- .../Details/Components/GeoChecksTable.tsx | 59 ++++++++--------- 5 files changed, 78 insertions(+), 137 deletions(-) diff --git a/client/src/Pages/Checks/Components/ChecksTable.tsx b/client/src/Pages/Checks/Components/ChecksTable.tsx index bd7170572..31737f4bb 100644 --- a/client/src/Pages/Checks/Components/ChecksTable.tsx +++ b/client/src/Pages/Checks/Components/ChecksTable.tsx @@ -1,21 +1,14 @@ import { Table, Pagination, - ValueLabel, StatusLabel, - Tooltip, + StatusCodeLabel, } from "@/Components/design-elements"; import Box from "@mui/material/Box"; import type { Header } from "@/Components/design-elements/Table"; import type { Monitor } from "@/Types/Monitor"; - import { useTranslation } from "react-i18next"; import { formatDateWithTz } from "@/Utils/TimeUtils"; -import { - formatStatusCode, - getStatusCodeTooltip, - getStatusCodeValueType, -} from "@/Utils/statusCode"; import type { Check } from "@/Types/Check"; import type { RootState } from "@/Types/state"; import { useSelector } from "react-redux"; @@ -40,7 +33,7 @@ export const ChecksTable = ({ const { t } = useTranslation(); const uiTimezone = useSelector((state: RootState) => state.ui.timezone); - const getHeaders = (t: (key: string) => string, uiTimezone: string) => { + const getHeaders = () => { const headers: Header[] = [ { id: "monitorName", @@ -74,23 +67,12 @@ export const ChecksTable = ({ id: "statusCode", content: t("pages.checks.table.headers.statusCode"), render: (row) => { - const code = row.statusCode; - if (!code) return "N/A"; - const text = formatStatusCode(code, t); - const tooltip = getStatusCodeTooltip(code, row.message, t); - const label = ( - ); - return tooltip ? ( - - {label} - - ) : ( - label - ); }, }, { @@ -104,7 +86,7 @@ export const ChecksTable = ({ return headers; }; - const headers = getHeaders(t, uiTimezone); + const headers = getHeaders(); const handlePageChange = ( _e: React.MouseEvent | null, diff --git a/client/src/Pages/Incidents/Components/CardDetails.tsx b/client/src/Pages/Incidents/Components/CardDetails.tsx index 2cd8fbde4..b2d72d08c 100644 --- a/client/src/Pages/Incidents/Components/CardDetails.tsx +++ b/client/src/Pages/Incidents/Components/CardDetails.tsx @@ -2,7 +2,7 @@ import Stack from "@mui/material/Stack"; import Grid from "@mui/material/Grid"; import Divider from "@mui/material/Divider"; import Typography from "@mui/material/Typography"; -import { BaseBox, ValueLabel, Tooltip } from "@/Components/design-elements"; +import { BaseBox, ValueLabel, StatusCodeLabel } from "@/Components/design-elements"; import { LAYOUT } from "@/Utils/Theme/constants"; import { useTranslation } from "react-i18next"; @@ -13,7 +13,6 @@ import { useSelector } from "react-redux"; import type { RootState } from "@/Types/state"; import { formatDateWithTz } from "@/Utils/TimeUtils"; import { getIncidentsDuration } from "@/Pages/Incidents/utils"; -import { formatStatusCode, getStatusCodeTooltip } from "@/Utils/statusCode"; interface CardDetailsProps { incident: Incident | null; @@ -48,13 +47,6 @@ export const CardDetails = ({ incident, monitor, sx }: CardDetailsProps) => { return null; } - const statusCodeText = formatStatusCode(incident.statusCode, t); - const statusCodeTooltip = getStatusCodeTooltip( - incident.statusCode, - incident.message, - t - ); - return ( { - {statusCodeTooltip ? ( - - {statusCodeText} - - ) : ( - statusCodeText - )} + diff --git a/client/src/Pages/Incidents/Components/IncidentTable.tsx b/client/src/Pages/Incidents/Components/IncidentTable.tsx index c66cdb0ed..399f4d8f8 100644 --- a/client/src/Pages/Incidents/Components/IncidentTable.tsx +++ b/client/src/Pages/Incidents/Components/IncidentTable.tsx @@ -1,4 +1,4 @@ -import { Table, ValueLabel, Tooltip } from "@/Components/design-elements"; +import { Table, ValueLabel, StatusCodeLabel } from "@/Components/design-elements"; import { Pagination } from "@/Components/design-elements/Table"; import type { Header } from "@/Components/design-elements/Table"; import { ActionsMenu } from "@/Components/actions-menu"; @@ -14,11 +14,6 @@ import Typography from "@mui/material/Typography"; import { useTheme } from "@mui/material/styles"; import Box from "@mui/material/Box"; import { getMonitorPath } from "@/Utils/MonitorUtils"; -import { - formatStatusCode, - getStatusCodeTooltip, - getStatusCodeValueType, -} from "@/Utils/statusCode"; interface IncidentsTableProps { title?: string; @@ -139,13 +134,12 @@ export const IncidentsTable = ({ return ( {row.resolutionType} @@ -158,23 +152,12 @@ export const IncidentsTable = ({ id: "statusCode", content: t("pages.incidents.table.headers.statusCode"), render: (row) => { - const code = row.statusCode; - if (!code) return "N/A"; - const text = formatStatusCode(code, t); - const tooltip = getStatusCodeTooltip(code, row.message, t); - const label = ( - ); - return tooltip ? ( - - {label} - - ) : ( - label - ); }, }, { diff --git a/client/src/Pages/Uptime/Details/Components/ChecksTable.tsx b/client/src/Pages/Uptime/Details/Components/ChecksTable.tsx index 0ab9a7a7c..b100c28c4 100644 --- a/client/src/Pages/Uptime/Details/Components/ChecksTable.tsx +++ b/client/src/Pages/Uptime/Details/Components/ChecksTable.tsx @@ -1,4 +1,9 @@ -import { Table, Pagination, StatusLabel, Tooltip } from "@/Components/design-elements"; +import { + Table, + Pagination, + StatusLabel, + StatusCodeLabel, +} from "@/Components/design-elements"; import Box from "@mui/material/Box"; import type { Header } from "@/Components/design-elements"; import type { Check } from "@/Types/Check"; @@ -6,11 +11,28 @@ import type { Check } from "@/Types/Check"; import { useNavigate } from "react-router"; import { useTranslation } from "react-i18next"; import { formatDateWithTz } from "@/Utils/TimeUtils"; -import { formatStatusCode, getStatusCodeTooltip } from "@/Utils/statusCode"; import type { RootState } from "@/Types/state"; import { useSelector } from "react-redux"; -const getHeaders = (t: (key: string) => string, uiTimezone: string) => { +export const ChecksTable = ({ + checks, + count, + page, + setPage, + rowsPerPage, + setRowsPerPage, +}: { + checks: Check[]; + count: number; + page: number; + setPage: (page: number) => void; + rowsPerPage: number; + setRowsPerPage: (rowsPerPage: number) => void; +}) => { + const navigate = useNavigate(); + const { t } = useTranslation(); + const uiTimezone = useSelector((state: RootState) => state.ui.timezone); + const headers: Header[] = [ { id: "status", @@ -37,41 +59,15 @@ const getHeaders = (t: (key: string) => string, uiTimezone: string) => { id: "statusCode", content: t("pages.checks.table.headers.statusCode"), render: (row) => { - if (!row.statusCode) return "N/A"; - const text = formatStatusCode(row.statusCode, t); - const tooltip = getStatusCodeTooltip(row.statusCode, row.message, t); - return tooltip ? ( - - {text} - - ) : ( - text + return ( + ); }, }, ]; - return headers; -}; - -export const ChecksTable = ({ - checks, - count, - page, - setPage, - rowsPerPage, - setRowsPerPage, -}: { - checks: Check[]; - count: number; - page: number; - setPage: (page: number) => void; - rowsPerPage: number; - setRowsPerPage: (rowsPerPage: number) => void; -}) => { - const navigate = useNavigate(); - const { t } = useTranslation(); - const uiTimezone = useSelector((state: RootState) => state.ui.timezone); - const headers = getHeaders(t, uiTimezone); const handlePageChange = ( _e: React.MouseEvent | null, diff --git a/client/src/Pages/Uptime/Details/Components/GeoChecksTable.tsx b/client/src/Pages/Uptime/Details/Components/GeoChecksTable.tsx index ae56e037e..373e09da2 100644 --- a/client/src/Pages/Uptime/Details/Components/GeoChecksTable.tsx +++ b/client/src/Pages/Uptime/Details/Components/GeoChecksTable.tsx @@ -1,15 +1,36 @@ -import { Table, Pagination, StatusLabel, Tooltip } from "@/Components/design-elements"; +import { + Table, + Pagination, + StatusLabel, + StatusCodeLabel, +} from "@/Components/design-elements"; import Box from "@mui/material/Box"; import type { Header } from "@/Components/design-elements"; import type { FlatGeoCheck } from "@/Types/GeoCheck"; import { useTranslation } from "react-i18next"; import { formatDateWithTz } from "@/Utils/TimeUtils"; -import { formatStatusCode, getStatusCodeTooltip } from "@/Utils/statusCode"; import type { RootState } from "@/Types/state"; import { useSelector } from "react-redux"; import prettyMilliseconds from "pretty-ms"; -const getHeaders = (t: (key: string) => string, uiTimezone: string) => { +export const GeoChecksTable = ({ + geoChecks, + count, + page, + setPage, + rowsPerPage, + setRowsPerPage, +}: { + geoChecks: FlatGeoCheck[]; + count: number; + page: number; + setPage: (page: number) => void; + rowsPerPage: number; + setRowsPerPage: (rowsPerPage: number) => void; +}) => { + const { t } = useTranslation(); + const uiTimezone = useSelector((state: RootState) => state.ui.timezone); + const headers: Header[] = [ { id: "status", @@ -30,16 +51,7 @@ const getHeaders = (t: (key: string) => string, uiTimezone: string) => { id: "statusCode", content: t("pages.checks.table.headers.statusCode"), render: (row) => { - if (!row.statusCode) return "N/A"; - const text = formatStatusCode(row.statusCode, t); - const tooltip = getStatusCodeTooltip(row.statusCode, undefined, t); - return tooltip ? ( - - {text} - - ) : ( - text - ); + return ; }, }, { @@ -61,27 +73,6 @@ const getHeaders = (t: (key: string) => string, uiTimezone: string) => { }, }, ]; - return headers; -}; - -export const GeoChecksTable = ({ - geoChecks, - count, - page, - setPage, - rowsPerPage, - setRowsPerPage, -}: { - geoChecks: FlatGeoCheck[]; - count: number; - page: number; - setPage: (page: number) => void; - rowsPerPage: number; - setRowsPerPage: (rowsPerPage: number) => void; -}) => { - const { t } = useTranslation(); - const uiTimezone = useSelector((state: RootState) => state.ui.timezone); - const headers = getHeaders(t, uiTimezone); const handlePageChange = ( _e: React.MouseEvent | null, From 713c3ea34fe6c7629af5db46a75200cee628b990 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 7 May 2026 09:56:56 -0700 Subject: [PATCH 6/6] add span for ref --- client/src/Components/design-elements/StatusCodeLabel.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/client/src/Components/design-elements/StatusCodeLabel.tsx b/client/src/Components/design-elements/StatusCodeLabel.tsx index b1500d42b..f088550f0 100644 --- a/client/src/Components/design-elements/StatusCodeLabel.tsx +++ b/client/src/Components/design-elements/StatusCodeLabel.tsx @@ -32,5 +32,9 @@ export const StatusCodeLabel = ({ /> ); if (!tooltip) return body; - return {body}; + return ( + + {body} + + ); };