From b61077bd3f997ab610d120137d8a8b904070d748 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Mon, 26 Jan 2026 21:14:04 +0000 Subject: [PATCH 1/4] remove unsued strings, initial commit --- .../v2/monitors/charts/PiePagespeed.tsx | 159 ++++++++++++++++++ client/src/Components/v2/monitors/index.tsx | 1 + client/src/Pages/PageSpeed/Details/index.tsx | 7 + .../PageSpeed/Details/{index.jsx => old.jsx} | 0 client/src/Routes/index.jsx | 2 +- client/src/locales/en.json | 40 ----- 6 files changed, 168 insertions(+), 41 deletions(-) create mode 100644 client/src/Components/v2/monitors/charts/PiePagespeed.tsx create mode 100644 client/src/Pages/PageSpeed/Details/index.tsx rename client/src/Pages/PageSpeed/Details/{index.jsx => old.jsx} (100%) diff --git a/client/src/Components/v2/monitors/charts/PiePagespeed.tsx b/client/src/Components/v2/monitors/charts/PiePagespeed.tsx new file mode 100644 index 000000000..cbc6b3106 --- /dev/null +++ b/client/src/Components/v2/monitors/charts/PiePagespeed.tsx @@ -0,0 +1,159 @@ +import { BaseChart } from "@/Components/v2/design-elements"; +import { FileText } from "lucide-react"; +import { Pie, PieChart, ResponsiveContainer, Label } from "recharts"; +import Typography from "@mui/material/Typography"; +import Box from "@mui/material/Box"; +import { getPageSpeedPalette } from "@/Utils/MonitorUtils"; +import { useTheme } from "@mui/material/styles"; +import { alpha } from "@mui/material/styles"; +import { useState } from "react"; +import Tooltip from "@mui/material/Tooltip"; +import { useTranslation } from "react-i18next"; + +const CenterLabel = ({ viewBox, value }: any) => { + const { cx, cy } = viewBox; + return ( + + + {value} + + + ); +}; + +export const PiePageSpeed = ({ latestCheck }: { latestCheck: any }) => { + const { t } = useTranslation(); + const theme = useTheme(); + const [hoverTitle, setHoverTitle] = useState(null); + + const LABELS: Record = { + FCP: t("common.charts.pageSpeed.fcp"), + SI: t("common.charts.pageSpeed.si"), + LCP: t("common.charts.pageSpeed.lcp"), + TBT: t("common.charts.pageSpeed.tbt"), + CLS: t("common.charts.pageSpeed.cls"), + }; + const metrics = [ + { key: "fcp", color: alpha("#1DE9B6", 0.6), weight: 0.1 }, + { key: "si", color: alpha("#7C4DFF", 0.6), weight: 0.1 }, + { key: "lcp", color: alpha("#FFB200", 0.6), weight: 0.25 }, + { key: "tbt", color: alpha("#00AFFE", 0.6), weight: 0.3 }, + { key: "cls", color: alpha("#FF4181", 0.6), weight: 0.25 }, + ]; + + const scores = metrics.flatMap(({ key, color, weight }) => { + const val = Math.floor((latestCheck?.[key] ?? 0) * 100); + const inverse = 100 - val; + return [ + { + name: `${key.toUpperCase()} Inverse`, + value: inverse * weight, + fill: "transparent", + stroke: color, + weight, + }, + { + name: key.toUpperCase(), + value: val * weight, + fill: color, + stroke: color, + weight, + }, + ]; + }); + + const totalScore = + (latestCheck?.fcp || 0) * 0.1 + + (latestCheck?.si || 0) * 0.1 + + (latestCheck?.lcp || 0) * 0.25 + + (latestCheck?.tbt || 0) * 0.3 + + (latestCheck?.cls || 0) * 0.25; + + const pageSpeedPalette = getPageSpeedPalette(Math.floor(totalScore * 100)); + + const score = [ + { + value: 100, + fill: alpha(theme.palette[pageSpeedPalette].light || "#ffffff", 0.6), + stroke: "none", + }, + ]; + + return ( + + } + title={t("common.charts.pageSpeed.title")} + > + + + + + + + `${name}: ${Math.round(value)}`} + dataKey="value" + stroke="none" + onMouseEnter={(_, index: number) => { + const d = scores[index]; + if (!d) return; + const isInverse = String(d.name).includes("Inverse"); + const pair = isInverse && scores[index + 1] ? scores[index + 1] : d; + const base = String(pair.name).replace(" Inverse", ""); + const full = LABELS[base] ?? base; + const displayVal = Math.round(Number(pair.value) || 0); + setHoverTitle(`${full}: ${displayVal}`); + }} + onMouseLeave={() => setHoverTitle(null)} + /> + + + + + + ); +}; diff --git a/client/src/Components/v2/monitors/index.tsx b/client/src/Components/v2/monitors/index.tsx index ca0aaa15e..f8e59270d 100644 --- a/client/src/Components/v2/monitors/index.tsx +++ b/client/src/Components/v2/monitors/index.tsx @@ -5,3 +5,4 @@ export * from "./charts/RadialAvgResponse"; export * from "./charts/HistogramDetails"; export * from "./charts/HistogramPageSpeed"; export * from "./charts/HistogramPageSpeedTooltip"; +export * from "./charts/PiePagespeed"; diff --git a/client/src/Pages/PageSpeed/Details/index.tsx b/client/src/Pages/PageSpeed/Details/index.tsx new file mode 100644 index 000000000..ce40d9b2f --- /dev/null +++ b/client/src/Pages/PageSpeed/Details/index.tsx @@ -0,0 +1,7 @@ +import { BasePage } from "@/Components/v2/design-elements"; + +const PageSpeedDetails = () => { + return PageSpeed Details - Work in Progress; +}; + +export default PageSpeedDetails; diff --git a/client/src/Pages/PageSpeed/Details/index.jsx b/client/src/Pages/PageSpeed/Details/old.jsx similarity index 100% rename from client/src/Pages/PageSpeed/Details/index.jsx rename to client/src/Pages/PageSpeed/Details/old.jsx diff --git a/client/src/Routes/index.jsx b/client/src/Routes/index.jsx index c9a1084d6..3c2873ffa 100644 --- a/client/src/Routes/index.jsx +++ b/client/src/Routes/index.jsx @@ -21,7 +21,7 @@ import UptimeCreate from "../Pages/Uptime/Create/index.jsx"; // PageSpeed import PageSpeed from "../Pages/PageSpeed/Monitors/index"; -import PageSpeedDetails from "../Pages/PageSpeed/Details/index.jsx"; +import PageSpeedDetails from "../Pages/PageSpeed/Details/"; import PageSpeedCreate from "../Pages/PageSpeed/Create/index.jsx"; // Infrastructure diff --git a/client/src/locales/en.json b/client/src/locales/en.json index 928ace54c..78d05ff0e 100644 --- a/client/src/locales/en.json +++ b/client/src/locales/en.json @@ -53,8 +53,6 @@ }, "submit": "Submit", "title": "Title", - "distributedStatusHeaderText": "Real-time, real-device coverage", - "distributedStatusSubHeaderText": "Powered by millions devices worldwide, view a system performance by global region, country or city", "settingsDisabled": "Disabled", "settingsSuccessSaved": "Settings saved successfully", "settingsFailedToSave": "Failed to save settings", @@ -90,18 +88,11 @@ "webhookSendSuccess": "Webhook notification sent successfully", "webhookSendError": "Error sending webhook notification to {platform}", "webhookUnsupportedPlatform": "Unsupported platform: {platform}", - "distributedRightCategoryTitle": "Monitor", - "distributedStatusServerMonitors": "Server Monitors", - "distributedStatusServerMonitorsDescription": "Monitor status of related servers", "distributedUptimeCreateSelectURL": "Here you can select the URL of the host, together with the type of monitor.", "distributedUptimeCreateChecks": "Checks to perform", "distributedUptimeCreateChecksDescription": "You can always add or remove checks after adding your site.", - "distributedUptimeCreateIncidentNotification": "Incident notifications", - "distributedUptimeCreateIncidentDescription": "When there is an incident, notify users.", "distributedUptimeCreateAdvancedSettings": "Advanced settings", "distributedUptimeDetailsNoMonitorHistory": "There is no check history for this monitor yet.", - "distributedUptimeDetailsStatusHeaderUptime": "Uptime:", - "distributedUptimeDetailsStatusHeaderLastUpdate": "Last updated", "notifications": { "enableNotifications": "Enable {{platform}} notifications", "testNotification": "Test notification", @@ -174,7 +165,6 @@ "failed": "Failed to send test notification" } }, - "testLocale": "testLocale", "add": "Add", "monitors": "monitors", "pages": { @@ -241,34 +231,6 @@ } } }, - "distributedUptimeStatusCreateStatusPage": "status page", - "distributedUptimeStatusCreateStatusPageAccess": "Access", - "distributedUptimeStatusCreateStatusPageReady": "If your status page is ready, you can mark it as published.", - "distributedUptimeStatusBasicInfoHeader": "Basic Information", - "distributedUptimeStatusBasicInfoDescription": "Define company name and the subdomain that your status page points to.", - "distributedUptimeStatusLogoHeader": "Logo", - "distributedUptimeStatusLogoDescription": "Upload a logo for your status page", - "distributedUptimeStatusLogoUploadButton": "Upload logo", - "distributedUptimeStatusStandardMonitorsHeader": "Standard Monitors", - "distributedUptimeStatusStandardMonitorsDescription": "Attach standard monitors to your status page.", - "distributedUptimeStatusCreateYour": "Create your", - "distributedUptimeStatusEditYour": "Edit your", - "distributedUptimeStatusPublishedLabel": "Published and visible to the public", - "distributedUptimeStatusCompanyNameLabel": "Company name", - "distributedUptimeStatusPageAddressLabel": "Your status page address", - "distributedUptimeStatus30Days": "30 days", - "distributedUptimeStatus60Days": "60 days", - "distributedUptimeStatus90Days": "90 days", - "distributedUptimeStatusPageNotSetUp": "A status page is not set up.", - "distributedUptimeStatusContactAdmin": "Please contact your administrator", - "distributedUptimeStatusPageNotPublic": "This status page is not public.", - "distributedUptimeStatusPageDeleteDialog": "Do you want to delete this status page?", - "distributedUptimeStatusPageDeleteConfirm": "Yes, delete status page", - "distributedUptimeStatusPageDeleteDescription": "Once deleted, your status page cannot be retrieved.", - "distributedUptimeStatusDevices": "Devices", - "distributedUptimeStatusUpt": "UPT", - "distributedUptimeStatusUptBurned": "UPT Burned", - "distributedUptimeStatusUptLogo": "Upt Logo", "incidentsTableNoIncidents": "No incidents recorded", "incidentsTablePaginationLabel": "incidents", "incidentsTableMonitorName": "Monitor Name", @@ -279,7 +241,6 @@ "incidentsOptionsHeader": "Incidents for:", "incidentsOptionsHeaderFilterBy": "Filter by:", "incidentsOptionsHeaderFilterAll": "All", - "incidentsOptionsHeaderFilterActive": "Active", "incidentsOptionsHeaderFilterDown": "Down", "incidentsOptionsHeaderFilterCannotResolve": "Cannot Resolve", "incidentsOptionsHeaderShow": "Show:", @@ -625,7 +586,6 @@ "game": "Enter the IP address or hostname and the port number to ping (e.g., 192.168.1.100 or example.com) and choose game type.", "https": "Enter the URL or IP to monitor (e.g., https://example.com/ or 192.168.1.100) and add a clear display name that appears on the dashboard." }, - "auth": { "common": { "navigation": { From 1bcb2ddf9164a28266af9134873d437ecf1f35ea Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Mon, 26 Jan 2026 22:28:02 +0000 Subject: [PATCH 2/4] pagespeed v2 refactor --- client/package-lock.json | 30 +--- client/package.json | 1 - .../v2/design-elements/MonitorStatus.tsx | 1 - .../charts/HistogramPageSpeedDetails.tsx | 144 ++++++++++++++++++ .../HistogramPageSpeedDetailsTooltip.tsx | 78 ++++++++++ .../{PiePagespeed.tsx => PiePageSpeed.tsx} | 32 ++-- .../v2/monitors/charts/PiePageSpeedLegend.tsx | 105 +++++++++++++ client/src/Components/v2/monitors/index.tsx | 5 +- client/src/Pages/PageSpeed/Details/index.tsx | 59 ++++++- client/src/Routes/index.jsx | 8 +- client/src/Types/Monitor.ts | 5 + client/src/locales/en.json | 17 ++- 12 files changed, 434 insertions(+), 51 deletions(-) create mode 100644 client/src/Components/v2/monitors/charts/HistogramPageSpeedDetails.tsx create mode 100644 client/src/Components/v2/monitors/charts/HistogramPageSpeedDetailsTooltip.tsx rename client/src/Components/v2/monitors/charts/{PiePagespeed.tsx => PiePageSpeed.tsx} (80%) create mode 100644 client/src/Components/v2/monitors/charts/PiePageSpeedLegend.tsx diff --git a/client/package-lock.json b/client/package-lock.json index 7f5397b7f..a378fa5c2 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -26,7 +26,6 @@ "joi": "17.13.3", "lucide-react": "^0.562.0", "mui-color-input": "^6.0.0", - "pretty-ms": "9.3.0", "react": "18.3.1", "react-dom": "^18.2.0", "react-hook-form": "7.63.0", @@ -38,7 +37,7 @@ "react-toastify": "^10.0.5", "recharts": "2.15.2", "redux-persist": "6.0.0", - "swr": "2.3.6", + "swr": "^2.3.6", "vite-plugin-svgr": "^4.2.0", "zod": "4.1.11" }, @@ -5780,18 +5779,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parse-ms": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", - "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -5919,21 +5906,6 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/pretty-ms": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz", - "integrity": "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==", - "license": "MIT", - "dependencies": { - "parse-ms": "^4.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", diff --git a/client/package.json b/client/package.json index 7c5acb441..360e4911d 100644 --- a/client/package.json +++ b/client/package.json @@ -31,7 +31,6 @@ "joi": "17.13.3", "lucide-react": "^0.562.0", "mui-color-input": "^6.0.0", - "pretty-ms": "9.3.0", "react": "18.3.1", "react-dom": "^18.2.0", "react-hook-form": "7.63.0", diff --git a/client/src/Components/v2/design-elements/MonitorStatus.tsx b/client/src/Components/v2/design-elements/MonitorStatus.tsx index 0ecb77df8..3d5e81845 100644 --- a/client/src/Components/v2/design-elements/MonitorStatus.tsx +++ b/client/src/Components/v2/design-elements/MonitorStatus.tsx @@ -34,7 +34,6 @@ export const MonitorStatus = ({ monitor }: { monitor: Monitor }) => { > ; + +export interface ConfigItem { + id: string; + text: string; + palette: PaletteColorKey; +} + +const config: Record = { + seo: { + id: "seo", + text: "SEO", + palette: "primary", + }, + performance: { + id: "performance", + text: "performance", + palette: "success", + }, + bestPractices: { + id: "bestPractices", + text: "best practices", + palette: "warning", + }, + accessibility: { + id: "accessibility", + text: "accessibility", + palette: "error", + }, +}; + +export const HistogramPageSpeedDetails = ({ + checks, + range, +}: { + checks: Check[]; + range: string; +}) => { + const theme = useTheme(); + return ( + + } + title="Score history" + > + + + ( + + )} + /> + + } + /> + + {Object.values(config).map(({ id, palette }) => { + const startColor = theme.palette[palette].main; + const endColor = theme.palette[palette].light; + + return ( + + + + + ); + })} + + {Object.keys(config).map((key) => { + const { palette } = config[key]; + const strokeColor = theme.palette[palette].main; + const bgColor = theme.palette.primary.main; + + return ( + + ); + })} + + + + ); +}; diff --git a/client/src/Components/v2/monitors/charts/HistogramPageSpeedDetailsTooltip.tsx b/client/src/Components/v2/monitors/charts/HistogramPageSpeedDetailsTooltip.tsx new file mode 100644 index 000000000..7219ba821 --- /dev/null +++ b/client/src/Components/v2/monitors/charts/HistogramPageSpeedDetailsTooltip.tsx @@ -0,0 +1,78 @@ +import Box from "@mui/material/Box"; +import Stack from "@mui/material/Stack"; +import Typography from "@mui/material/Typography"; +import { useTheme } from "@mui/material/styles"; +import { formatDateWithTz } from "@/Utils/TimeUtils"; +import type { ConfigItem } from "@/Components/v2/monitors"; +import type { TooltipProps } from "recharts"; +import { useSelector } from "react-redux"; +import type { RootState } from "@/Types/state"; + +interface HistogramPageSpeedScoresTooltipProps + extends Partial> { + config: Record; +} +export const HistogramPageSpeedScoresTooltip = ({ + active, + payload, + label, + config, +}: HistogramPageSpeedScoresTooltipProps) => { + const theme = useTheme(); + const uiTimezone = useSelector((state: RootState) => state.ui.timezone); + + if (active && payload && payload.length) { + return ( + + + {formatDateWithTz(label, "ddd, MMMM D, YYYY, h:mm A", uiTimezone)} + + {Object.keys(config) + .reverse() + .map((key) => { + const { palette } = config[key]; + const dotColor = theme.palette[palette].main; + + return ( + + + + {config[key].text} + + {Math.floor(payload[0].payload[key])} + + ); + })} + + ); + } + return null; +}; diff --git a/client/src/Components/v2/monitors/charts/PiePagespeed.tsx b/client/src/Components/v2/monitors/charts/PiePageSpeed.tsx similarity index 80% rename from client/src/Components/v2/monitors/charts/PiePagespeed.tsx rename to client/src/Components/v2/monitors/charts/PiePageSpeed.tsx index cbc6b3106..1c58bb3f7 100644 --- a/client/src/Components/v2/monitors/charts/PiePagespeed.tsx +++ b/client/src/Components/v2/monitors/charts/PiePageSpeed.tsx @@ -1,5 +1,6 @@ import { BaseChart } from "@/Components/v2/design-elements"; import { FileText } from "lucide-react"; +import type { Check, CheckAudits } from "@/Types/Check"; import { Pie, PieChart, ResponsiveContainer, Label } from "recharts"; import Typography from "@mui/material/Typography"; import Box from "@mui/material/Box"; @@ -29,19 +30,20 @@ const CenterLabel = ({ viewBox, value }: any) => { ); }; -export const PiePageSpeed = ({ latestCheck }: { latestCheck: any }) => { +export const PiePageSpeed = ({ latestCheck }: { latestCheck?: Check }) => { const { t } = useTranslation(); const theme = useTheme(); const [hoverTitle, setHoverTitle] = useState(null); + if (!latestCheck) return null; const LABELS: Record = { - FCP: t("common.charts.pageSpeed.fcp"), - SI: t("common.charts.pageSpeed.si"), - LCP: t("common.charts.pageSpeed.lcp"), - TBT: t("common.charts.pageSpeed.tbt"), - CLS: t("common.charts.pageSpeed.cls"), + FCP: t("pages.pageSpeed.charts.common.fcp"), + SI: t("pages.pageSpeed.charts.common.si"), + LCP: t("pages.pageSpeed.charts.common.lcp"), + TBT: t("pages.pageSpeed.charts.common.tbt"), + CLS: t("pages.pageSpeed.charts.common.cls"), }; - const metrics = [ + const metrics: { key: keyof CheckAudits; color: string; weight: number }[] = [ { key: "fcp", color: alpha("#1DE9B6", 0.6), weight: 0.1 }, { key: "si", color: alpha("#7C4DFF", 0.6), weight: 0.1 }, { key: "lcp", color: alpha("#FFB200", 0.6), weight: 0.25 }, @@ -50,7 +52,8 @@ export const PiePageSpeed = ({ latestCheck }: { latestCheck: any }) => { ]; const scores = metrics.flatMap(({ key, color, weight }) => { - const val = Math.floor((latestCheck?.[key] ?? 0) * 100); + const audit = latestCheck?.audits?.[key]; + const val = Math.floor((audit?.score ?? 0) * 100); const inverse = 100 - val; return [ { @@ -71,12 +74,11 @@ export const PiePageSpeed = ({ latestCheck }: { latestCheck: any }) => { }); const totalScore = - (latestCheck?.fcp || 0) * 0.1 + - (latestCheck?.si || 0) * 0.1 + - (latestCheck?.lcp || 0) * 0.25 + - (latestCheck?.tbt || 0) * 0.3 + - (latestCheck?.cls || 0) * 0.25; - + (latestCheck.audits?.fcp?.score || 0) * 0.1 + + (latestCheck.audits?.si?.score || 0) * 0.1 + + (latestCheck.audits?.lcp?.score || 0) * 0.25 + + (latestCheck.audits?.tbt?.score || 0) * 0.3 + + (latestCheck.audits?.cls?.score || 0) * 0.25; const pageSpeedPalette = getPageSpeedPalette(Math.floor(totalScore * 100)); const score = [ @@ -95,7 +97,7 @@ export const PiePageSpeed = ({ latestCheck }: { latestCheck: any }) => { strokeWidth={1.5} /> } - title={t("common.charts.pageSpeed.title")} + title={t("pages.pageSpeed.charts.pie.title")} > { + const { t } = useTranslation(); + const theme = useTheme(); + const palette = getPageSpeedPalette(value); + return ( + + + {label} + + {`${value}%`} + {`${t("pages.pageSpeed.charts.legend.weight")}: ${weight}%`} + + + + + ); +}; + +export const PiePageSpeedLegend = ({ latestCheck }: { latestCheck?: Check }) => { + const theme = useTheme(); + const { t } = useTranslation(); + + if (!latestCheck) { + return null; + } + return ( + + } + title={t("pages.pageSpeed.charts.legend.title")} + > + + + + + + + + + ); +}; diff --git a/client/src/Components/v2/monitors/index.tsx b/client/src/Components/v2/monitors/index.tsx index f8e59270d..4efaae65c 100644 --- a/client/src/Components/v2/monitors/index.tsx +++ b/client/src/Components/v2/monitors/index.tsx @@ -5,4 +5,7 @@ export * from "./charts/RadialAvgResponse"; export * from "./charts/HistogramDetails"; export * from "./charts/HistogramPageSpeed"; export * from "./charts/HistogramPageSpeedTooltip"; -export * from "./charts/PiePagespeed"; +export * from "./charts/PiePageSpeed"; +export * from "./charts/PiePageSpeedLegend"; +export * from "./charts/HistogramPageSpeedDetails"; +export * from "./charts/HistogramPageSpeedDetailsTooltip"; diff --git a/client/src/Pages/PageSpeed/Details/index.tsx b/client/src/Pages/PageSpeed/Details/index.tsx index ce40d9b2f..f6c672e77 100644 --- a/client/src/Pages/PageSpeed/Details/index.tsx +++ b/client/src/Pages/PageSpeed/Details/index.tsx @@ -1,7 +1,62 @@ import { BasePage } from "@/Components/v2/design-elements"; +import type { PageSpeedDetailsResponse } from "@/Types/Monitor"; +import { HeaderMonitorControls } from "@/Components/v2/common"; +import Stack from "@mui/material/Stack"; +import { + HistogramPageSpeedDetails, + PiePageSpeed, + PiePageSpeedLegend, + MonitorStatBoxes, +} from "@/Components/v2/monitors"; + +import { useIsAdmin } from "@/Hooks/useIsAdmin"; +import { useGet } from "@/Hooks/UseApi"; +import { useParams } from "react-router-dom"; +import { useTheme } from "@mui/material"; const PageSpeedDetails = () => { - return PageSpeed Details - Work in Progress; -}; + const { monitorId } = useParams(); + const isAdmin = useIsAdmin(); + const theme = useTheme(); + const { + data: monitorData, + isLoading, + error, + refetch, + } = useGet( + monitorId ? `/monitors/pagespeed/details/${monitorId}?dateRange=day` : null + ); + const monitor = monitorData?.monitor; + const monitorStats = monitorData?.monitorStats || null; + + return ( + + + + + + + + + + ); +}; export default PageSpeedDetails; diff --git a/client/src/Routes/index.jsx b/client/src/Routes/index.jsx index 3c2873ffa..45715a488 100644 --- a/client/src/Routes/index.jsx +++ b/client/src/Routes/index.jsx @@ -133,7 +133,13 @@ const Routes = () => { /> } + element={ + <> + + + + + } /> Date: Mon, 26 Jan 2026 22:29:28 +0000 Subject: [PATCH 3/4] pretty-ms --- client/package-lock.json | 28 ++++++++++++++++++++++++++++ client/package.json | 1 + 2 files changed, 29 insertions(+) diff --git a/client/package-lock.json b/client/package-lock.json index a378fa5c2..b4ad9f73c 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -26,6 +26,7 @@ "joi": "17.13.3", "lucide-react": "^0.562.0", "mui-color-input": "^6.0.0", + "pretty-ms": "^9.3.0", "react": "18.3.1", "react-dom": "^18.2.0", "react-hook-form": "7.63.0", @@ -5779,6 +5780,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parse-ms": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", + "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -5906,6 +5919,21 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/pretty-ms": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.3.0.tgz", + "integrity": "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==", + "license": "MIT", + "dependencies": { + "parse-ms": "^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", diff --git a/client/package.json b/client/package.json index 360e4911d..a5c17e343 100644 --- a/client/package.json +++ b/client/package.json @@ -31,6 +31,7 @@ "joi": "17.13.3", "lucide-react": "^0.562.0", "mui-color-input": "^6.0.0", + "pretty-ms": "^9.3.0", "react": "18.3.1", "react-dom": "^18.2.0", "react-hook-form": "7.63.0", From d71d16ecd0718953faa6f02713ee176d607e48c9 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Mon, 26 Jan 2026 22:32:08 +0000 Subject: [PATCH 4/4] refresh interval --- client/src/Pages/PageSpeed/Details/index.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/src/Pages/PageSpeed/Details/index.tsx b/client/src/Pages/PageSpeed/Details/index.tsx index f6c672e77..2028f47c0 100644 --- a/client/src/Pages/PageSpeed/Details/index.tsx +++ b/client/src/Pages/PageSpeed/Details/index.tsx @@ -24,7 +24,9 @@ const PageSpeedDetails = () => { error, refetch, } = useGet( - monitorId ? `/monitors/pagespeed/details/${monitorId}?dateRange=day` : null + monitorId ? `/monitors/pagespeed/details/${monitorId}?dateRange=day` : null, + {}, + { keepPreviousData: true, refreshInterval: 30000 } ); const monitor = monitorData?.monitor;