diff --git a/client/src/Pages/StatusPage/Create/index.tsx b/client/src/Pages/StatusPage/Create/index.tsx index 1574c21c1..ea4452dae 100644 --- a/client/src/Pages/StatusPage/Create/index.tsx +++ b/client/src/Pages/StatusPage/Create/index.tsx @@ -29,6 +29,7 @@ import type { StatusPageFormData } from "@/Validation/statusPage"; import { useGet, usePost, usePut, useDelete } from "@/Hooks/UseApi"; import type { Monitor } from "@/Types/Monitor"; import type { MonitorDisplayType, StatusPageResponse } from "@/Types/StatusPage"; +import { getMonitorTypeLabel } from "@/Types/StatusPage"; import timezones from "@/Utils/timezones.json"; import { useNavigate, useParams } from "react-router-dom"; import axios from "axios"; @@ -39,22 +40,6 @@ interface TimezoneOption { name: string; } -const MONITOR_TYPE_KEYS: Record = { - http: "pages.common.monitors.monitorTypes.optionHttp", - ping: "pages.common.monitors.monitorTypes.optionPing", - docker: "pages.common.monitors.monitorTypes.optionDocker", - port: "pages.common.monitors.monitorTypes.optionPort", - game: "pages.common.monitors.monitorTypes.optionGame", - grpc: "pages.common.monitors.monitorTypes.optionGrpc", - websocket: "pages.common.monitors.monitorTypes.optionWebSocket", - hardware: "pages.common.monitors.monitorTypes.optionHardware", -}; - -const getMonitorTypeLabel = (type: string, t: (key: string) => string): string => { - const i18nMonitorKey = MONITOR_TYPE_KEYS[type]; - return i18nMonitorKey ? t(i18nMonitorKey) : type; -}; - const CreateStatusPage = () => { const theme = useTheme(); const { t } = useTranslation(); @@ -111,7 +96,7 @@ const CreateStatusPage = () => { }); return typesSet.size ? Array.from(typesSet) : ["uptime"]; - }, [JSON.stringify(watchedMonitorIds), monitors]); + }, [watchedMonitorIds, monitors]); useEffect(() => { form.setValue("type", computedTypes); diff --git a/client/src/Pages/StatusPage/Status/Components/MonitorsList.tsx b/client/src/Pages/StatusPage/Status/Components/MonitorsList.tsx index c9212f0c4..248a69c9b 100644 --- a/client/src/Pages/StatusPage/Status/Components/MonitorsList.tsx +++ b/client/src/Pages/StatusPage/Status/Components/MonitorsList.tsx @@ -12,6 +12,7 @@ import { useSelector } from "react-redux"; import { useState } from "react"; import type { Monitor } from "@/Types/Monitor"; import type { StatusPage } from "@/Types/StatusPage"; +import { getMonitorTypeLabel } from "@/Types/StatusPage"; import type { RootState } from "@/Types/state"; import { LAYOUT, SPACING } from "@/Utils/Theme/constants"; @@ -25,81 +26,98 @@ interface MonitorsListProps { } const getMonitorBadgeStyles = (monitorType: string, theme: Theme) => { - // for future: specific badge styles can be defined here based on monitor type - const badgeConfig: Record = { - hardware: { - color: theme.palette.background.paper, - bg: theme.palette.info.light, - }, - http: { - color: theme.palette.background.paper, - bg: theme.palette.success.light, - }, - ping: { - color: theme.palette.background.paper, - bg: theme.palette.success.light, - }, - port: { - color: theme.palette.background.paper, - bg: theme.palette.success.light, - }, - docker: { - color: theme.palette.background.paper, - bg: theme.palette.success.light, - }, - pagespeed: { - color: theme.palette.background.paper, - bg: theme.palette.success.light, - }, - game: { - color: theme.palette.background.paper, - bg: theme.palette.success.light, - }, - }; - - const config = badgeConfig[monitorType] ?? badgeConfig.http; + const bg = + monitorType === "hardware" ? theme.palette.info.light : theme.palette.success.light; return { - backgroundColor: config.bg, - color: config.color, + backgroundColor: bg, + color: theme.palette.background.paper, padding: `${theme.spacing(SPACING.SM)} ${theme.spacing(SPACING.LG)}`, borderRadius: theme.shape.borderRadius, }; }; -// Extracted component for monitor content below the header row +const MonitorHeader = ({ + monitor, + showURL, +}: { + monitor: StatusPageMonitor; + showURL: boolean; +}) => { + const theme = useTheme(); + const { t } = useTranslation(); + + return ( + + + + + {monitor.name} + + + {getMonitorTypeLabel(monitor.type, t)} + + + {showURL && monitor.url && ( + + {monitor.url} + + )} + + + + ); +}; + const MonitorContent = ({ monitor, statusPage, chartType, }: { - monitor: Monitor & { checks?: Monitor["recentChecks"] }; + monitor: StatusPageMonitor; statusPage: StatusPage; chartType: string; }) => { const theme = useTheme(); - const isInfrastructureMonitor = monitor?.type === "hardware"; - if (isInfrastructureMonitor) { - if (statusPage.showInfrastructure === false) { - return null; - } + if (monitor.type === "hardware") { + if (statusPage.showInfrastructure === false) return null; return ; } - if (statusPage.showCharts === false) { - return null; - } + if (statusPage.showCharts === false) return null; + const checks = monitor.checks?.slice().reverse() ?? []; return ( {chartType === "histogram" ? ( ) : ( - + )} ); @@ -108,17 +126,15 @@ const MonitorContent = ({ export const MonitorsList = ({ statusPage, monitors }: MonitorsListProps) => { const theme = useTheme(); const { t } = useTranslation(); - const showURL = useSelector((state: RootState) => state.ui?.showURL); - const [chartType, setChartType] = useState<"histogram" | "heatmap">("histogram"); return ( {statusPage.showCharts && ( {t("pages.statusPages.monitorsList.chartTypeHeatmap")} @@ -126,9 +142,7 @@ export const MonitorsList = ({ statusPage, monitors }: MonitorsListProps) => { dualOption value={chartType} checked={chartType === "histogram"} - onChange={(e) => { - setChartType(e.target.checked ? "histogram" : "heatmap"); - }} + onChange={(e) => setChartType(e.target.checked ? "histogram" : "heatmap")} /> {t("pages.statusPages.monitorsList.chartTypeHistogram")} @@ -136,69 +150,22 @@ export const MonitorsList = ({ statusPage, monitors }: MonitorsListProps) => { )} - {monitors?.map((monitor) => { - return ( - - - - - - {monitor.name} - - - {t( - `pages.common.monitors.monitorTypes.option${monitor?.type.charAt(0).toUpperCase() + monitor?.type.slice(1)}` - )} - - - {showURL && monitor?.url && ( - - {monitor.url} - - )} - - - - - - ); - })} + {monitors.map((monitor) => ( + + + + + ))} ); }; diff --git a/client/src/Types/StatusPage.ts b/client/src/Types/StatusPage.ts index 370cc23b5..9b4ee313f 100644 --- a/client/src/Types/StatusPage.ts +++ b/client/src/Types/StatusPage.ts @@ -1,6 +1,26 @@ -import type { Monitor } from "@/Types/Monitor"; +import type { Monitor, MonitorType } from "@/Types/Monitor"; export type MonitorDisplayType = "uptime" | "infrastructure"; +export const MONITOR_TYPE_KEYS: Partial> = { + http: "pages.common.monitors.monitorTypes.optionHttp", + ping: "pages.common.monitors.monitorTypes.optionPing", + docker: "pages.common.monitors.monitorTypes.optionDocker", + port: "pages.common.monitors.monitorTypes.optionPort", + game: "pages.common.monitors.monitorTypes.optionGame", + grpc: "pages.common.monitors.monitorTypes.optionGrpc", + websocket: "pages.common.monitors.monitorTypes.optionWebSocket", + hardware: "pages.common.monitors.monitorTypes.optionHardware", + pagespeed: "pages.common.monitors.monitorTypes.optionPagespeed", +}; + +export const getMonitorTypeLabel = ( + type: MonitorType, + t: (key: string) => string +): string => { + const key = MONITOR_TYPE_KEYS[type]; + return key ? t(key) : type; +}; + export interface StatusPage { id: string; userId: string; diff --git a/client/src/locales/en.json b/client/src/locales/en.json index dbe037447..92a21939f 100644 --- a/client/src/locales/en.json +++ b/client/src/locales/en.json @@ -551,7 +551,8 @@ "optionWebSocketDescription": "Monitor WebSocket endpoints for connection health and response time.", "optionHttpDescription": "Use HTTP(S) to monitor your website or API endpoint.", "optionPingDescription": "Use ICMP Ping to monitor if a server is online.", - "optionPortDescription": "Monitor if a specific port on a server is open." + "optionPortDescription": "Monitor if a specific port on a server is open.", + "title": "Type" }, "thresholds": { "title": "Alert thresholds",