From 87255071f4469e730d3c988057407cb15fbbedd7 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Sat, 31 Jan 2026 00:18:33 +0000 Subject: [PATCH] headers and actions --- .../Incidents/Components/IncidentTable.tsx | 161 +++++++++++++++++- client/src/locales/en.json | 3 + 2 files changed, 162 insertions(+), 2 deletions(-) diff --git a/client/src/Pages/Incidents/Components/IncidentTable.tsx b/client/src/Pages/Incidents/Components/IncidentTable.tsx index 93b09830b..f8346d2b9 100644 --- a/client/src/Pages/Incidents/Components/IncidentTable.tsx +++ b/client/src/Pages/Incidents/Components/IncidentTable.tsx @@ -1,17 +1,174 @@ import { Table } from "@/Components/v2/design-elements"; -import type { Header } from "@/Components/v2/design-elements"; +import type { Header } from "@/Components/v2/design-elements/Table"; +import { StatusLabel, ValueLabel } from "@/Components/v2/design-elements"; +import type { ValueType } from "@/Components/v2/design-elements/StatusLabel"; +import { ActionsMenu } from "@/Components/v2/actions-menu"; import type { Incident } from "@/Types/Incident"; import type { Monitor } from "@/Types/Monitor"; +import type { ActionMenuItem } from "@/Components/v2/actions-menu"; +import { useTranslation } from "react-i18next"; +import { useNavigate } from "react-router-dom"; +import { TypeToPathMap } from "@/Utils/monitorUtilsLegacy.js"; +import { formatDateWithTz } from "@/Utils/TimeUtils"; +import { useSelector } from "react-redux"; +import type { RootState } from "@/Types/state"; +import Typography from "@mui/material/Typography"; +import { useTheme } from "@mui/material/styles"; interface IncidentsTableProps { incidents?: Incident[]; monitors?: Monitor[]; + onOpenDetails?: (incidentId: string) => void; + onResolve?: (incidentId: string) => void; } -export const IncidentsTable = ({ incidents, monitors }: IncidentsTableProps) => { + +export const IncidentsTable = ({ + incidents, + monitors, + onOpenDetails, + onResolve, +}: IncidentsTableProps) => { + const { t } = useTranslation(); + const theme = useTheme(); + const navigate = useNavigate(); + const uiTimezone = useSelector((state: RootState) => state.ui.timezone); + + const getActions = (incident: Incident): ActionMenuItem[] => { + const monitor = monitors?.find((m) => m.id === incident.monitorId); + const isActive = incident.status === true; + + const actions: ActionMenuItem[] = [ + { + id: "details", + label: t("incidentsPage.incidentsTableActionDetails"), + action: () => onOpenDetails?.(incident.id), + closeMenu: true, + }, + { + id: "goToMonitor", + label: t("incidentsPage.incidentsTableActionGoToMonitor"), + action: () => { + if (monitor) { + const path = TypeToPathMap[monitor.type as keyof typeof TypeToPathMap]; + if (path && monitor.id) { + navigate(`/${path}/${monitor.id}`); + } + } + }, + closeMenu: true, + }, + ]; + + if (isActive) { + actions.push({ + id: "resolve", + label: t("incidentsPage.incidentsTableActionResolveManually"), + action: () => onResolve?.(incident.id), + closeMenu: true, + }); + } + + return actions; + }; + + const getHeaders = (): Header[] => { + return [ + { + id: "monitorName", + content: t("common.table.headers.monitor"), + render: (row) => { + const monitor = monitors?.find((m) => m.id === row.monitorId); + return monitor?.name || "N/A"; + }, + }, + { + id: "status", + content: t("common.table.headers.status"), + render: (row) => { + const status = row.status === true ? false : true; + return ; + }, + }, + { + id: "startTime", + content: t("incidentsPage.startTime"), + render: (row) => { + return formatDateWithTz( + row.createdAt, + "YYYY-MM-DD HH:mm:ss A", + uiTimezone + ); + }, + }, + { + id: "endTime", + content: t("incidentsPage.endTime"), + render: (row) => { + if (row.endTime) { + return formatDateWithTz( + row.endTime, + "YYYY-MM-DD HH:mm:ss A", + uiTimezone + ); + } + return "-"; + }, + }, + { + id: "resolutionType", + content: t("incidentsPage.resolutionType"), + render: (row) => { + if (row.resolutionType) { + return ( + + {row.resolutionType} + + ); + } + return "-"; + }, + }, + { + id: "statusCode", + content: t("incidentsPage.statusCode"), + 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 ; + }, + }, + { + id: "message", + content: t("common.table.headers.message"), + render: (row) => row.message || "-", + }, + { + id: "actions", + content: t("common.table.headers.actions"), + render: (row) => , + }, + ]; + }; + if (!incidents || !monitors) { return null; } + void getHeaders; + void Table; + // Headers: Monitor name, status, start time, end time, resolution type, status code, message, actions return "Table here"; }; diff --git a/client/src/locales/en.json b/client/src/locales/en.json index 725dc09fc..552447991 100644 --- a/client/src/locales/en.json +++ b/client/src/locales/en.json @@ -366,6 +366,9 @@ "mostAffectedMonitor": "Most affected monitor", "avgResolutionTime": "Average resolution time" } + }, + "table": { + "headers": {} } } },