From 396d5b369bd2202f3abbd510732fdf31e1bc0e25 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Wed, 28 Jan 2026 20:20:18 +0000 Subject: [PATCH] remove unused --- .../Details/Components/Charts/AreaChart.jsx | 330 ----------------- .../Components/Charts/AreaChartLegend.jsx | 62 ---- .../Details/Components/Charts/PieChart.jsx | 327 ----------------- .../Components/Charts/PieChartLegend.jsx | 101 ------ .../Components/PageSpeedAreaChart/index.jsx | 60 ---- .../PageSpeedAreaChart/skeleton.jsx | 17 - .../Components/PageSpeedStatusBoxes/index.jsx | 49 --- .../Components/PerformanceReport/index.jsx | 61 ---- .../Components/PerformanceReport/skeleton.jsx | 17 - client/src/Pages/PageSpeed/Details/old.jsx | 120 ------- .../Monitors/Components/Card/index.jsx | 331 ------------------ .../Monitors/Components/MonitorGrid/index.jsx | 22 -- client/src/Pages/PageSpeed/Monitors/old.jsx | 86 ----- .../Details/Hooks/useCertificateFetch.jsx | 44 --- client/src/Pages/Uptime/Details/old.jsx | 190 ---------- .../Monitors/Components/Filter/index.jsx | 162 --------- .../Monitors/Components/Skeleton/index.jsx | 61 ---- .../Monitors/Components/StatusBoxes/index.jsx | 42 --- .../Components/StatusBoxes/skeleton.jsx | 31 -- .../Components/StatusBoxes/statusBox.jsx | 115 ------ .../Components/UptimeDataTable/index.jsx | 241 ------------- client/src/Pages/Uptime/Monitors/old.jsx | 225 ------------ 22 files changed, 2694 deletions(-) delete mode 100644 client/src/Pages/PageSpeed/Details/Components/Charts/AreaChart.jsx delete mode 100644 client/src/Pages/PageSpeed/Details/Components/Charts/AreaChartLegend.jsx delete mode 100644 client/src/Pages/PageSpeed/Details/Components/Charts/PieChart.jsx delete mode 100644 client/src/Pages/PageSpeed/Details/Components/Charts/PieChartLegend.jsx delete mode 100644 client/src/Pages/PageSpeed/Details/Components/PageSpeedAreaChart/index.jsx delete mode 100644 client/src/Pages/PageSpeed/Details/Components/PageSpeedAreaChart/skeleton.jsx delete mode 100644 client/src/Pages/PageSpeed/Details/Components/PageSpeedStatusBoxes/index.jsx delete mode 100644 client/src/Pages/PageSpeed/Details/Components/PerformanceReport/index.jsx delete mode 100644 client/src/Pages/PageSpeed/Details/Components/PerformanceReport/skeleton.jsx delete mode 100644 client/src/Pages/PageSpeed/Details/old.jsx delete mode 100644 client/src/Pages/PageSpeed/Monitors/Components/Card/index.jsx delete mode 100644 client/src/Pages/PageSpeed/Monitors/Components/MonitorGrid/index.jsx delete mode 100644 client/src/Pages/PageSpeed/Monitors/old.jsx delete mode 100644 client/src/Pages/Uptime/Details/Hooks/useCertificateFetch.jsx delete mode 100644 client/src/Pages/Uptime/Details/old.jsx delete mode 100644 client/src/Pages/Uptime/Monitors/Components/Filter/index.jsx delete mode 100644 client/src/Pages/Uptime/Monitors/Components/Skeleton/index.jsx delete mode 100644 client/src/Pages/Uptime/Monitors/Components/StatusBoxes/index.jsx delete mode 100644 client/src/Pages/Uptime/Monitors/Components/StatusBoxes/skeleton.jsx delete mode 100644 client/src/Pages/Uptime/Monitors/Components/StatusBoxes/statusBox.jsx delete mode 100644 client/src/Pages/Uptime/Monitors/Components/UptimeDataTable/index.jsx delete mode 100644 client/src/Pages/Uptime/Monitors/old.jsx diff --git a/client/src/Pages/PageSpeed/Details/Components/Charts/AreaChart.jsx b/client/src/Pages/PageSpeed/Details/Components/Charts/AreaChart.jsx deleted file mode 100644 index d8c118237..000000000 --- a/client/src/Pages/PageSpeed/Details/Components/Charts/AreaChart.jsx +++ /dev/null @@ -1,330 +0,0 @@ -import PropTypes from "prop-types"; -import { - AreaChart, - Area, - XAxis, - Tooltip, - CartesianGrid, - ResponsiveContainer, - Text, -} from "recharts"; -import { useTheme } from "@emotion/react"; -import { useMemo, useState } from "react"; -import { Box, Stack, Typography } from "@mui/material"; -import { formatDateWithTz } from "../../../../../Utils/timeUtilsLegacy.js"; -import { useSelector } from "react-redux"; - -const config = { - seo: { - id: "seo", - text: "SEO", - color: "secondary", - }, - performance: { - id: "performance", - text: "performance", - color: "success", - }, - bestPractices: { - id: "bestPractices", - text: "best practices", - color: "warning", - }, - accessibility: { - id: "accessibility", - text: "accessibility", - color: "accent", - }, -}; - -/** - * Custom tooltip for the area chart. - * @param {Object} props - * @param {boolean} props.active - Whether the tooltip is active. - * @param {Array} props.payload - The payload data for the tooltip. - * @param {string} props.label - The label for the tooltip. - * @returns {JSX.Element|null} The tooltip element or null if not active. - */ - -const CustomToolTip = ({ active, payload, label, config }) => { - const theme = useTheme(); - const uiTimezone = useSelector((state) => 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 { color } = config[key]; - const dotColor = theme.palette[color].main; - - return ( - - - - {config[key].text} - {" "} - {payload[0].payload[key]} - - ); - })} - - ); - } - return null; -}; - -CustomToolTip.propTypes = { - active: PropTypes.bool, - payload: PropTypes.array, - label: PropTypes.string, - config: PropTypes.object, -}; - -/** - * Processes data to insert gaps with null values based on the interval. - * @param {Array} data - * @param {number} interval - The interval in milliseconds for gaps. - * @returns {Array} The formatted data with gaps. - */ -const processDataWithGaps = (data, interval) => { - if (data.length === 0) return []; - let formattedData = []; - let last = new Date(data[0].createdAt).getTime(); - - // Helper function to add a null entry - const addNullEntry = (timestamp) => { - formattedData.push({ - accessibility: "N/A", - bestPractices: "N/A", - performance: "N/A", - seo: "N/A", - createdAt: timestamp, - }); - }; - - data.forEach((entry) => { - const current = new Date(entry.createdAt).getTime(); - - if (current - last > interval * 2) { - // Insert null entries for each interval - let temp = last + interval; - while (temp < current) { - addNullEntry(new Date(temp).toISOString()); - temp += interval; - } - } - - formattedData.push(entry); - last = current; - }); - - return formattedData; -}; - -/** - * Custom tick component to render ticks on the XAxis. - * - * @param {Object} props - * @param {number} props.x - The x coordinate for the tick. - * @param {number} props.y - The y coordinate for the tick. - * @param {Object} props.payload - The data object containing the tick value. - * @param {number} props.index - The index of the tick in the array of ticks. - * - * @returns {JSX.Element|null} The tick element or null if the tick should be hidden. - */ -const CustomTick = ({ x, y, payload, index }) => { - const theme = useTheme(); - const uiTimezone = useSelector((state) => state.ui.timezone); - - // Render nothing for the first tick - if (index === 0) return null; - - return ( - - {formatDateWithTz(payload?.value, "h:mm a", uiTimezone)} - - ); -}; -CustomTick.propTypes = { - x: PropTypes.number, - y: PropTypes.number, - payload: PropTypes.shape({ - value: PropTypes.string.isRequired, - }), - index: PropTypes.number, -}; - -/** - * A chart displaying pagespeed details over time. - * @param {Object} props - * @param {Array} props.data - The data to display in the chart. - * @param {number} props.interval - The interval in milliseconds for processing gaps. - * @returns {JSX.Element} The area chart component. - */ - -const PageSpeedAreaChart = ({ data, monitor, metrics }) => { - const theme = useTheme(); - const [isHovered, setIsHovered] = useState(false); - const memoizedData = useMemo( - () => processDataWithGaps(data, monitor.interval), - [data[0]] - ); - - const filteredConfig = Object.keys(config).reduce((result, key) => { - if (metrics[key]) { - result[key] = config[key]; - } - return result; - }, {}); - - return ( - - setIsHovered(true)} - onMouseLeave={() => setIsHovered(false)} - > - - } - axisLine={false} - tickLine={false} - height={18} - minTickGap={0} - interval="equidistantPreserveStart" - /> - } - /> - - {Object.values(filteredConfig).map(({ id, color }) => { - /* TODO not working? */ - const startColor = theme.palette[color].main; - const endColor = theme.palette[color].lowContrast; - - return ( - - - - - ); - })} - - {Object.keys(filteredConfig).map((key) => { - const { color } = filteredConfig[key]; - const strokeColor = theme.palette[color].main; - const bgColor = theme.palette.primary.main; - - return ( - - ); - })} - - - ); -}; - -PageSpeedAreaChart.propTypes = { - data: PropTypes.arrayOf( - PropTypes.shape({ - createdAt: PropTypes.string.isRequired, - accessibility: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, - bestPractices: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, - performance: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, - seo: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, - }) - ).isRequired, - monitor: PropTypes.object.isRequired, - metrics: PropTypes.object, -}; - -export default PageSpeedAreaChart; diff --git a/client/src/Pages/PageSpeed/Details/Components/Charts/AreaChartLegend.jsx b/client/src/Pages/PageSpeed/Details/Components/Charts/AreaChartLegend.jsx deleted file mode 100644 index 525e4d0d2..000000000 --- a/client/src/Pages/PageSpeed/Details/Components/Charts/AreaChartLegend.jsx +++ /dev/null @@ -1,62 +0,0 @@ -import { Box, Typography, Divider } from "@mui/material"; -import Checkbox from "@/Components/v1/Inputs/Checkbox/index.jsx"; -import Icon from "@/Components/v1/Icon"; -import LegendBox from "@/Components/v1/Charts/LegendBox/index.jsx"; -import { useTranslation } from "react-i18next"; -import { useTheme } from "@emotion/react"; - -const AreaChartLegend = ({ metrics, handleMetrics }) => { - const theme = useTheme(); - const { t } = useTranslation(); - return ( - - } - header="Metrics" - > - - - {t("shown")} - - - - handleMetrics("accessibility")} - /> - - handleMetrics("bestPractices")} - /> - - handleMetrics("performance")} - /> - - handleMetrics("seo")} - /> - - - ); -}; - -export default AreaChartLegend; diff --git a/client/src/Pages/PageSpeed/Details/Components/Charts/PieChart.jsx b/client/src/Pages/PageSpeed/Details/Components/Charts/PieChart.jsx deleted file mode 100644 index eec075684..000000000 --- a/client/src/Pages/PageSpeed/Details/Components/Charts/PieChart.jsx +++ /dev/null @@ -1,327 +0,0 @@ -import PropTypes from "prop-types"; -import { PieChart as MuiPieChart } from "@mui/x-charts/PieChart"; -import { useDrawingArea } from "@mui/x-charts"; -import { useState } from "react"; -import { useTheme } from "@emotion/react"; -import { Box } from "@mui/material"; - -/** - * Renders a centered label within a pie chart. - * - * @param {Object} props - * @param {string | number} props.value - The value to display in the label. - * @param {string} props.color - The color of the text. - * @returns {JSX.Element} - */ -const PieCenterLabel = ({ value, color, setExpand }) => { - const { width, height } = useDrawingArea(); - return ( - setExpand(true)} - > - - - {value} - - - ); -}; - -PieCenterLabel.propTypes = { - value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - color: PropTypes.string, - setExpand: PropTypes.func, -}; - -/** - * A component that renders a label on a pie chart slice. - * The label is positioned relative to the center of the pie chart and is optionally highlighted. - * - * @param {Object} props - * @param {number} props.value - The value to display inside the pie slice. - * @param {number} props.startAngle - The starting angle of the pie slice in degrees. - * @param {number} props.endAngle - The ending angle of the pie slice in degrees. - * @param {string} props.color - The color of the label text when highlighted. - * @param {boolean} props.highlighted - Determines if the label should be highlighted or not. - * @returns {JSX.Element} - */ -const PieValueLabel = ({ value, startAngle, endAngle, color, highlighted }) => { - const { width, height } = useDrawingArea(); - - // Compute the midpoint angle in radians - const angle = (((startAngle + endAngle) / 2) * Math.PI) / 180; - const radius = height / 4; // length from center of the circle to where the text is positioned - - // Calculate x and y positions - const x = Math.sin(angle) * radius; - const y = -Math.cos(angle) * radius; - - return ( - - - +{value} - - - ); -}; - -// Validate props using PropTypes -PieValueLabel.propTypes = { - value: PropTypes.number.isRequired, - startAngle: PropTypes.number.isRequired, - endAngle: PropTypes.number.isRequired, - color: PropTypes.string.isRequired, - highlighted: PropTypes.bool.isRequired, -}; - -/** - * Weight constants for different performance metrics. - * @type {Object} - */ -const weights = { - fcp: 10, - si: 10, - lcp: 25, - tbt: 30, - cls: 25, -}; - -const PieChart = ({ audits }) => { - const theme = useTheme(); - const [highlightedItem, setHighLightedItem] = useState(null); - const [expand, setExpand] = useState(false); - - /** - * Retrieves color properties based on the performance value. - * - * @param {number} value - The performance score used to determine the color properties. - * @returns {{stroke: string, strokeBg: string, text: string, bg: string}} The color properties for the given performance value. - */ - const getColors = (value) => { - if (value >= 90 && value <= 100) - return { - stroke: theme.palette.success.main, - strokeBg: theme.palette.success.lowContrast, - text: theme.palette.success.contrastText, - bg: theme.palette.success.lowContrast, - }; - else if (value >= 50 && value < 90) - return { - stroke: theme.palette.warning.main, - strokeBg: theme.palette.warning.lowContrast, - text: theme.palette.warning.contrastText, - bg: theme.palette.warning.lowContrast, - }; - else if (value >= 0 && value < 50) - return { - stroke: theme.palette.error.contrastText, - strokeBg: theme.palette.error.lowContrast, - text: theme.palette.error.contrastText, - bg: theme.palette.error.lowContrast, - }; - return { - stroke: theme.palette.tertiary.contrastText, - strokeBg: theme.palette.tertiary.contrastText, - text: theme.palette.tertiary.contrastText, - bg: theme.palette.tertiary.main, - }; - }; - - /** - * Calculates and formats the data needed for rendering a pie chart based on audit scores and weights. - * This function generates properties for each pie slice, including angles, radii, and colors. - * It also calculates performance based on the weighted values. - * - * @returns {Array} An array of objects, each representing the properties for a slice of the pie chart. - * @returns {number} performance - A variable updated with the rounded sum of weighted values. - */ - let performance = 0; - const getPieData = (audits) => { - if (typeof audits === "undefined") return undefined; - - let data = []; - let startAngle = 0; - const padding = 3; // padding between arcs - const max = 360 - padding * (Object.keys(audits).length - 1); // _id is a child of audits - - Object.keys(audits).forEach((key) => { - if (audits[key].score) { - let value = audits[key].score * weights[key]; - let endAngle = startAngle + (weights[key] * max) / 100; - - let theme = getColors(audits[key].score * 100); - data.push({ - id: key, - data: [ - { - value: value, - color: theme.stroke, - label: key.toUpperCase(), - }, - { - value: weights[key] - value, - color: theme.strokeBg, - label: "", - }, - ], - arcLabel: (item) => `${item.label}`, - arcLabelRadius: 95, - startAngle: startAngle, - endAngle: endAngle, - innerRadius: 73, - outerRadius: 80, - cornerRadius: 2, - highlightScope: { faded: "global", highlighted: "series" }, - faded: { - innerRadius: 73, - outerRadius: 80, - additionalRadius: -20, - arcLabelRadius: 5, - }, - cx: pieSize.width / 2, - }); - - performance += Math.floor(value); - startAngle = endAngle + padding; - } - }); - - return data; - }; - - const pieSize = { width: 230, height: 230 }; - const pieData = getPieData(audits); - const colorMap = getColors(performance); - - return ( - setExpand(false)} - sx={{ - display: "flex", - justifyContent: "center", - alignItems: "center", - width: "100%", - }} - > - {expand ? ( - - - {pieData?.map((pie) => ( - - ))} - - ) : ( - - - - )} - - ); -}; - -PieChart.propTypes = { - audits: PropTypes.object, -}; - -export default PieChart; diff --git a/client/src/Pages/PageSpeed/Details/Components/Charts/PieChartLegend.jsx b/client/src/Pages/PageSpeed/Details/Components/Charts/PieChartLegend.jsx deleted file mode 100644 index 5cfdad608..000000000 --- a/client/src/Pages/PageSpeed/Details/Components/Charts/PieChartLegend.jsx +++ /dev/null @@ -1,101 +0,0 @@ -import { Stack, Box, Typography } from "@mui/material"; -import { useTheme } from "@emotion/react"; -import LegendBox from "@/Components/v1/Charts/LegendBox/index.jsx"; -import Icon from "@/Components/v1/Icon"; -import PropTypes from "prop-types"; - -const PieChartLegend = ({ audits }) => { - const theme = useTheme(); - - return ( - - } - header="Performance metrics" - sx={{ flex: 1 }} - > - {typeof audits !== "undefined" && - Object.keys(audits).map((key) => { - if (key === "_id") return; - - let audit = audits[key]; - let score = audit.score * 100; - let bg = - score >= 90 - ? theme.palette.success.main - : score >= 50 - ? theme.palette.warning.main - : score >= 0 - ? theme.palette.error.main - : theme.palette.tertiary.main; - - // Find the position where the number ends and the unit begins - const match = audit?.displayValue?.match(/(\d+\.?\d*)\s*([a-zA-Z]+)/); - let value; - let unit; - if (match) { - value = match[1]; - match[2] === "s" ? (unit = "seconds") : (unit = match[2]); - } else { - value = audit.displayValue; - } - - return ( - - - - {audit.title} - - - {value} - - {unit} - - - - - - ); - })} - - ); -}; - -PieChartLegend.propTypes = { - audits: PropTypes.object, -}; - -export default PieChartLegend; diff --git a/client/src/Pages/PageSpeed/Details/Components/PageSpeedAreaChart/index.jsx b/client/src/Pages/PageSpeed/Details/Components/PageSpeedAreaChart/index.jsx deleted file mode 100644 index 9020ddd6d..000000000 --- a/client/src/Pages/PageSpeed/Details/Components/PageSpeedAreaChart/index.jsx +++ /dev/null @@ -1,60 +0,0 @@ -import ChartBox from "@/Components/v1/Charts/ChartBox/index.jsx"; -import AreaChart from "../Charts/AreaChart.jsx"; -import AreaChartLegend from "../Charts/AreaChartLegend.jsx"; -import SkeletonLayout from "./skeleton.jsx"; -import Icon from "@/Components/v1/Icon"; -import { Stack } from "@mui/material"; -import PropTypes from "prop-types"; - -import { useTheme } from "@emotion/react"; - -const PageSpeedAreaChart = ({ shouldRender, monitor, metrics, handleMetrics }) => { - const theme = useTheme(); - - if (!shouldRender) { - return ; - } - - const data = monitor?.checks ? [...monitor.checks].reverse() : []; - - return ( - - - } - header="Score history" - height="100%" - borderRadiusRight={16} - Legend={ - - } - > - - - - ); -}; - -PageSpeedAreaChart.propTypes = { - shouldRender: PropTypes.bool, - monitor: PropTypes.object, - metrics: PropTypes.object, - handleMetrics: PropTypes.func, -}; - -export default PageSpeedAreaChart; diff --git a/client/src/Pages/PageSpeed/Details/Components/PageSpeedAreaChart/skeleton.jsx b/client/src/Pages/PageSpeed/Details/Components/PageSpeedAreaChart/skeleton.jsx deleted file mode 100644 index b793908d4..000000000 --- a/client/src/Pages/PageSpeed/Details/Components/PageSpeedAreaChart/skeleton.jsx +++ /dev/null @@ -1,17 +0,0 @@ -import { Box, Skeleton } from "@mui/material"; - -const SkeletonLayout = () => { - return ( - - - - ); -}; - -export default SkeletonLayout; diff --git a/client/src/Pages/PageSpeed/Details/Components/PageSpeedStatusBoxes/index.jsx b/client/src/Pages/PageSpeed/Details/Components/PageSpeedStatusBoxes/index.jsx deleted file mode 100644 index 6ff26c739..000000000 --- a/client/src/Pages/PageSpeed/Details/Components/PageSpeedStatusBoxes/index.jsx +++ /dev/null @@ -1,49 +0,0 @@ -import StatusBoxes from "@/Components/v1/StatusBoxes/index.jsx"; -import StatBox from "@/Components/v1/StatBox/index.jsx"; -import { Typography } from "@mui/material"; -import { getHumanReadableDuration } from "../../../../../Utils/timeUtilsLegacy.js"; -import { useTranslation } from "react-i18next"; - -const PageSpeedStatusBoxes = ({ shouldRender, monitorStats }) => { - const lastChecked = monitorStats?.lastCheckTimestamp - ? Date.now() - monitorStats.lastCheckTimestamp - : 0; - - // Determine time since last failure - const timeOfLastFailure = monitorStats?.timeOfLastFailure; - const timeSinceLastFailure = - timeOfLastFailure > 0 - ? Date.now() - timeOfLastFailure - : Date.now() - new Date(monitorStats?.createdAt); - - const streakTime = getHumanReadableDuration(timeSinceLastFailure); - - const time = getHumanReadableDuration(lastChecked); - - const { t } = useTranslation(); - - return ( - - - {streakTime} - {t("ago")} - - } - /> - - {time} - {t("ago")} - - } - /> - - ); -}; - -export default PageSpeedStatusBoxes; diff --git a/client/src/Pages/PageSpeed/Details/Components/PerformanceReport/index.jsx b/client/src/Pages/PageSpeed/Details/Components/PerformanceReport/index.jsx deleted file mode 100644 index a2e1b5f96..000000000 --- a/client/src/Pages/PageSpeed/Details/Components/PerformanceReport/index.jsx +++ /dev/null @@ -1,61 +0,0 @@ -import ChartBox from "@/Components/v1/Charts/ChartBox/index.jsx"; -import Icon from "@/Components/v1/Icon"; -import PieChart from "../Charts/PieChart.jsx"; -import { Typography } from "@mui/material"; -import { useTheme } from "@emotion/react"; -import PieChartLegend from "../Charts/PieChartLegend.jsx"; -import SkeletonLayout from "./skeleton.jsx"; -import { useTranslation } from "react-i18next"; - -const PerformanceReport = ({ shouldRender, audits }) => { - const theme = useTheme(); - const { t } = useTranslation(); - - if (!shouldRender) { - return ; - } - - return ( - - } - header="Performance report" - Legend={} - borderRadiusRight={16} - > - - - {t("pageSpeedDetailsPerformanceReport")}{" "} - - {t("pageSpeedDetailsPerformanceReportCalculator")} - - - - ); -}; - -export default PerformanceReport; diff --git a/client/src/Pages/PageSpeed/Details/Components/PerformanceReport/skeleton.jsx b/client/src/Pages/PageSpeed/Details/Components/PerformanceReport/skeleton.jsx deleted file mode 100644 index b793908d4..000000000 --- a/client/src/Pages/PageSpeed/Details/Components/PerformanceReport/skeleton.jsx +++ /dev/null @@ -1,17 +0,0 @@ -import { Box, Skeleton } from "@mui/material"; - -const SkeletonLayout = () => { - return ( - - - - ); -}; - -export default SkeletonLayout; diff --git a/client/src/Pages/PageSpeed/Details/old.jsx b/client/src/Pages/PageSpeed/Details/old.jsx deleted file mode 100644 index 3190787b3..000000000 --- a/client/src/Pages/PageSpeed/Details/old.jsx +++ /dev/null @@ -1,120 +0,0 @@ -// Components -import { Stack, Typography } from "@mui/material"; -import Breadcrumbs from "@/Components/v1/Breadcrumbs/index.jsx"; -import MonitorTimeFrameHeader from "@/Components/v1/MonitorTimeFrameHeader/index.jsx"; -import PageSpeedStatusBoxes from "./Components/PageSpeedStatusBoxes/index.jsx"; -import MonitorDetailsControlHeader from "@/Components/v1/MonitorDetailsControlHeader/index.jsx"; -import PageSpeedAreaChart from "./Components/PageSpeedAreaChart/index.jsx"; -import PerformanceReport from "./Components/PerformanceReport/index.jsx"; -import GenericFallback from "@/Components/v1/GenericFallback/index.jsx"; -// Utils -import { useTheme } from "@emotion/react"; -import { useIsAdmin } from "@/Hooks/useIsAdmin.js"; -import { useParams } from "react-router-dom"; -import { useFetchPageSpeedMonitorById } from "../../../Hooks/monitorHooks.js"; -import { useState } from "react"; -import { useTranslation } from "react-i18next"; -// Constants -const BREADCRUMBS = [ - { name: "pagespeed", path: "/pagespeed" }, - { name: "details", path: `` }, -]; - -const PageSpeedDetails = () => { - const theme = useTheme(); - const { t } = useTranslation(); - const isAdmin = useIsAdmin(); - const { monitorId } = useParams(); - - // Local state - const [metrics, setMetrics] = useState({ - accessibility: true, - bestPractices: true, - performance: true, - seo: true, - }); - const [trigger, setTrigger] = useState(false); - // Network - const [monitor, monitorStats, isLoading, networkError] = useFetchPageSpeedMonitorById({ - monitorId, - dateRange: "day", - updateTrigger: trigger, - }); - - // Handlers - const handleMetrics = (id) => { - setMetrics((prev) => ({ ...prev, [id]: !prev[id] })); - }; - - const triggerUpdate = () => { - setTrigger(!trigger); - }; - if (networkError === true) { - return ( - - - {t("common.toasts.networkError")} - - {t("common.toasts.checkConnection")} - - ); - } - - // Empty view, displayed when loading is complete and there are no checks - if (!isLoading && monitor?.checks?.length === 0) { - return ( - - - - - {t("distributedUptimeDetailsNoMonitorHistory")} - - - ); - } - - return ( - - - - - - - - - - ); -}; - -export default PageSpeedDetails; diff --git a/client/src/Pages/PageSpeed/Monitors/Components/Card/index.jsx b/client/src/Pages/PageSpeed/Monitors/Components/Card/index.jsx deleted file mode 100644 index 4a85863c4..000000000 --- a/client/src/Pages/PageSpeed/Monitors/Components/Card/index.jsx +++ /dev/null @@ -1,331 +0,0 @@ -import PropTypes from "prop-types"; -import Icon from "@/Components/v1/Icon"; -import { StatusLabel } from "@/Components/v1/Label/index.jsx"; -import { Box, Grid, Stack, Typography } from "@mui/material"; -import { useNavigate } from "react-router-dom"; -import { useTheme } from "@emotion/react"; -import { Area, AreaChart, CartesianGrid, ResponsiveContainer, Tooltip } from "recharts"; -import { useSelector } from "react-redux"; -import { formatDateWithTz, formatDurationSplit } from "@/Utils/timeUtilsLegacy.js"; -import { useMonitorUtils } from "@/Hooks/useMonitorUtils.js"; -import { useState } from "react"; -import { useTranslation } from "react-i18next"; -import IconBox from "@/Components/v1/IconBox/index.jsx"; -/** - * CustomToolTip displays a tooltip with formatted date and score information. - * @param {Object} props - * @param {Array} props.payload - Data to display in the tooltip - * @returns {JSX.Element} The rendered tooltip component - */ -const CustomToolTip = ({ payload }) => { - const theme = useTheme(); - const uiTimezone = useSelector((state) => state.ui.timezone); - - return ( - - - {formatDateWithTz( - payload[0]?.payload.createdAt, - "ddd, MMMM D, YYYY, h:mm A", - uiTimezone - )} - - - - - - {payload[0]?.name} - {" "} - {payload[0]?.payload.score} - - - ); -}; - -CustomToolTip.propTypes = { - payload: PropTypes.array, -}; - -/* TODO separate utils in folder*/ -/** - * Processes the raw data to include a score for each entry. - * @param {Array} data - The raw data array. - * @returns {Array} - The formatted data array with scores. - */ -const processData = (data) => { - if (data.length === 0) return []; - let formattedData = []; - - const calculateScore = (entry) => { - return ( - (entry.accessibility + entry.bestPractices + entry.performance + entry.seo) / 4 - ); - }; - - data.forEach((entry) => { - entry = { ...entry, score: calculateScore(entry) }; - formattedData.push(entry); - }); - - return formattedData; -}; - -/* TODO separate component*/ -/** - * Renders an area chart displaying page speed scores. - * @param {Object} props - * @param {Array} props.data - The raw data to be displayed in the chart. - * @param {string} props.status - The status of the page speed which determines the chart's color scheme. - * @returns {JSX.Element} - The rendered area chart. - */ -const PagespeedAreaChart = ({ data, status }) => { - const theme = useTheme(); - const [isHovered, setIsHovered] = useState(false); - const { statusToTheme } = useMonitorUtils(); - - const themeColor = statusToTheme[status]; - - const formattedData = processData(data); - - return ( - - setIsHovered(true)} - onMouseLeave={() => setIsHovered(false)} - > - - } - /> - - - - - - - - - - ); -}; - -PagespeedAreaChart.propTypes = { - data: PropTypes.arrayOf( - PropTypes.shape({ - accessibility: PropTypes.number.isRequired, - bestPractices: PropTypes.number.isRequired, - performance: PropTypes.number.isRequired, - seo: PropTypes.number.isRequired, - }) - ).isRequired, - status: PropTypes.string.isRequired, -}; - -/* TODO separate component */ -/** - * Renders a card displaying monitor details and an area chart. - * @param {Object} props - * @param {Object} props.monitor - The monitor data to be displayed in the card. - * @returns {JSX.Element} - The rendered card. - */ -const Card = ({ monitor }) => { - const { determineState, pagespeedStatusMsg } = useMonitorUtils(); - const theme = useTheme(); - const { t } = useTranslation(); - const navigate = useNavigate(); - const monitorState = determineState(monitor); - - return ( - - navigate(`/pagespeed/${monitor.id}`)} - border={1} - borderColor={theme.palette.primary.lowContrast} - borderRadius={theme.shape.borderRadius} - backgroundColor={theme.palette.primary.main} - sx={{ - display: "grid", - gridTemplateColumns: "34px 2fr 1fr", - columnGap: theme.spacing(5), - gridTemplateRows: "34px 1fr 3fr", - cursor: "pointer", - "&:hover": { - backgroundColor: theme.palette.tertiary.main, - }, - "& path": { - transition: "stroke-width 400ms ease", - }, - }} - > - - - - - {monitor.name} - - - - {monitor.url} - - - - - - - {t("checkingEvery")}{" "} - {(() => { - const { time, format } = formatDurationSplit(monitor?.interval); - return ( - <> - - {time}{" "} - - {format} - - ); - })()} - - - - - ); -}; - -Card.propTypes = { - monitor: PropTypes.object.isRequired, -}; - -export default Card; diff --git a/client/src/Pages/PageSpeed/Monitors/Components/MonitorGrid/index.jsx b/client/src/Pages/PageSpeed/Monitors/Components/MonitorGrid/index.jsx deleted file mode 100644 index 9df5f7577..000000000 --- a/client/src/Pages/PageSpeed/Monitors/Components/MonitorGrid/index.jsx +++ /dev/null @@ -1,22 +0,0 @@ -import { Grid } from "@mui/material"; -import Card from "../Card/index.jsx"; - -const MonitorGrid = ({ monitors, shouldRender = true }) => { - if (!shouldRender) return null; - - return ( - - {monitors?.map((monitor) => ( - - ))} - - ); -}; - -export default MonitorGrid; diff --git a/client/src/Pages/PageSpeed/Monitors/old.jsx b/client/src/Pages/PageSpeed/Monitors/old.jsx deleted file mode 100644 index f1bfcd0dd..000000000 --- a/client/src/Pages/PageSpeed/Monitors/old.jsx +++ /dev/null @@ -1,86 +0,0 @@ -// Components -import { useState } from "react"; -import Breadcrumbs from "@/Components/v1/Breadcrumbs/index.jsx"; -import { Stack } from "@mui/material"; -import CreateMonitorHeader from "@/Components/v1/MonitorCreateHeader/index.jsx"; -import MonitorCountHeader from "@/Components/v1/MonitorCountHeader/index.jsx"; -import MonitorGrid from "./Components/MonitorGrid/index.jsx"; -import PageStateWrapper from "@/Components/v1/PageStateWrapper/index.jsx"; -import FallbackPageSpeedWarning from "@/Components/v1/Fallback/FallbackPageSpeedWarning.jsx"; - -// Utils -import { useTheme } from "@emotion/react"; -import { useIsAdmin } from "@/Hooks/useIsAdmin.js"; -import { useFetchMonitorsWithChecks } from "@/Hooks/monitorHooks.js"; -import { useFetchSettings } from "@/Hooks/settingsHooks.js"; -// Constants -const BREADCRUMBS = [{ name: `pagespeed`, path: "/pagespeed" }]; -const TYPES = ["pagespeed"]; -const PageSpeed = () => { - const theme = useTheme(); - const isAdmin = useIsAdmin(); - - const [ - summary, - monitorsWithChecks, - monitorsWithChecksCount, - monitorsWithChecksIsLoading, - monitorsWithChecksNetworkError, - ] = useFetchMonitorsWithChecks({ - types: TYPES, - limit: 10, - page: null, - rowsPerPage: null, - filter: null, - field: null, - order: null, - monitorUpdateTrigger: null, - }); - - const [settingsData, setSettingsData] = useState(undefined); - const [isSettingsLoading, settingsError] = useFetchSettings({ - setSettingsData, - setIsApiKeySet: () => {}, - setIsEmailPasswordSet: () => {}, - }); - - return ( - <> - - ) - } - > - - - - - - - - - ); -}; - -export default PageSpeed; diff --git a/client/src/Pages/Uptime/Details/Hooks/useCertificateFetch.jsx b/client/src/Pages/Uptime/Details/Hooks/useCertificateFetch.jsx deleted file mode 100644 index 8912438d8..000000000 --- a/client/src/Pages/Uptime/Details/Hooks/useCertificateFetch.jsx +++ /dev/null @@ -1,44 +0,0 @@ -import { logger } from "../../../../Utils/Logger.js"; -import { useEffect, useState } from "react"; -import { networkService } from "../../../../main.jsx"; -import { formatDateWithTz } from "../../../../Utils/timeUtilsLegacy.js"; - -const useCertificateFetch = ({ - monitor, - monitorId, - certificateDateFormat, - uiTimezone, -}) => { - const [certificateExpiry, setCertificateExpiry] = useState(undefined); - const [isLoading, setIsLoading] = useState(false); - - useEffect(() => { - const fetchCertificate = async () => { - if (monitor?.type !== "http") { - return; - } - - try { - setIsLoading(true); - const res = await networkService.getCertificateExpiry({ - monitorId: monitorId, - }); - if (res?.data?.data?.certificateDate) { - const date = res.data.data.certificateDate; - setCertificateExpiry( - formatDateWithTz(date, certificateDateFormat, uiTimezone) ?? "N/A" - ); - } - } catch (error) { - setCertificateExpiry("N/A"); - logger.error(error); - } finally { - setIsLoading(false); - } - }; - fetchCertificate(); - }, [monitorId, certificateDateFormat, uiTimezone, monitor]); - return [certificateExpiry, isLoading]; -}; - -export default useCertificateFetch; diff --git a/client/src/Pages/Uptime/Details/old.jsx b/client/src/Pages/Uptime/Details/old.jsx deleted file mode 100644 index 144ceb4dc..000000000 --- a/client/src/Pages/Uptime/Details/old.jsx +++ /dev/null @@ -1,190 +0,0 @@ -// Components -import Breadcrumbs from "@/Components/v1/Breadcrumbs/index.jsx"; -import MonitorDetailsControlHeader from "@/Components/v1/MonitorDetailsControlHeader/index.jsx"; -import MonitorTimeFrameHeader from "@/Components/v1/MonitorTimeFrameHeader/index.jsx"; -import ChartBoxes from "./Components/ChartBoxes/index.jsx"; -import ResponseTimeChart from "./Components/Charts/ResponseTimeChart.jsx"; -import ResponseTable from "./Components/ResponseTable/index.jsx"; -import UptimeStatusBoxes from "./Components/UptimeStatusBoxes/index.jsx"; -import GenericFallback from "@/Components/v1/GenericFallback/index.jsx"; -import Stack from "@mui/material/Stack"; -import Typography from "@mui/material/Typography"; - -// Utils -import { useState } from "react"; -import { useParams } from "react-router-dom"; -import { useSelector } from "react-redux"; -import { useTheme } from "@emotion/react"; -import { useIsAdmin } from "@/Hooks/useIsAdmin.js"; -import { useFetchUptimeMonitorById } from "../../../Hooks/monitorHooks.js"; -import useCertificateFetch from "./Hooks/useCertificateFetch.jsx"; -import { useFetchChecksByMonitor } from "../../../Hooks/checkHooks.js"; -import { useTranslation } from "react-i18next"; - -// Constants -const BREADCRUMBS = [ - { name: "uptime", path: "/uptime" }, - { name: "details", path: "" }, - // { name: "details", path: `/uptime/${monitorId}` }, Is this needed? We can't click on this anywy -]; - -const certificateDateFormat = "MMM D, YYYY h A"; - -const UptimeDetails = () => { - // Redux state - const uiTimezone = useSelector((state) => state.ui.timezone); - - // Local state - const [dateRange, setDateRange] = useState("recent"); - const [page, setPage] = useState(0); - const [rowsPerPage, setRowsPerPage] = useState(5); - const [trigger, setTrigger] = useState(false); - - // Utils - const dateFormat = - dateRange === "day" || dateRange === "recent" ? "MMM D, h A" : "MMM D"; - const { monitorId } = useParams(); - const theme = useTheme(); - const isAdmin = useIsAdmin(); - const { t } = useTranslation(); - - const [monitorData, monitorStats, monitorIsLoading, monitorNetworkError] = - useFetchUptimeMonitorById({ - monitorId, - dateRange, - trigger, - }); - - const monitor = monitorData?.monitor; - - const [certificateExpiry, certificateIsLoading] = useCertificateFetch({ - monitor, - monitorId, - certificateDateFormat, - uiTimezone, - }); - - const monitorType = monitor?.type; - - const [checks, checksCount, checksAreLoading, checksNetworkError] = - useFetchChecksByMonitor({ - monitorId, - type: monitorType, - sortOrder: "desc", - limit: null, - dateRange, - filter: null, - page, - rowsPerPage, - }); - - // Handlers - const triggerUpdate = () => { - setTrigger(!trigger); - }; - - const handlePageChange = (_, newPage) => { - setPage(newPage); - }; - - const handleChangeRowsPerPage = (event) => { - setRowsPerPage(event.target.value); - }; - - if (monitorNetworkError || checksNetworkError) { - return ( - - - {t("common.toasts.networkError")} - - {t("common.toasts.checkConnection")} - - ); - } - - // Empty view, displayed when loading is complete and there are no checks - if (!monitorIsLoading && !checksAreLoading && checksCount === 0) { - return ( - - - - - - - - - {t("distributedUptimeDetailsNoMonitorHistory")} - - - ); - } - - return ( - - - - - - - - - - ); -}; - -export default UptimeDetails; diff --git a/client/src/Pages/Uptime/Monitors/Components/Filter/index.jsx b/client/src/Pages/Uptime/Monitors/Components/Filter/index.jsx deleted file mode 100644 index 62ba0be13..000000000 --- a/client/src/Pages/Uptime/Monitors/Components/Filter/index.jsx +++ /dev/null @@ -1,162 +0,0 @@ -import { useTheme } from "@emotion/react"; -import PropTypes from "prop-types"; -import FilterHeader from "@/Components/v1/FilterHeader/index.jsx"; -import { useMemo } from "react"; -import { Box, Button } from "@mui/material"; -import Icon from "@/Components/v1/Icon"; -import { useTranslation } from "react-i18next"; - -/** - * Filter Component - * - * A high-level component that provides filtering options for type, status, and state. - * It allows users to select multiple options for each filter and reset the filters. - * - * @component - * @param {Object} props - The component props. - * @param {string[]} props.selectedTypes - An array of selected type values. - * @param {function} props.setSelectedTypes - A function to set the selected type values. - * @param {string[]} props.selectedStatus - An array of selected status values. - * @param {function} props.setSelectedStatus - A function to set the selected status values. - * @param {string[]} props.selectedState - An array of selected state values. - * @param {function} props.setSelectedState - A function to set the selected state values. - * @param {function} props.setToFilterStatus - A function to set the filter status based on selected status values. - * @param {function} props.setToFilterActive - A function to set the filter active state based on selected state values. - * @param {function} props.handleReset - A function to reset all filters. - * - * @returns {JSX.Element} The rendered Filter component. - */ - -const getTypeOptions = () => [ - { value: "http", label: "HTTP(S)" }, - { value: "ping", label: "Ping" }, - { value: "docker", label: "Docker" }, - { value: "port", label: "Port" }, - { value: "game", label: "Game" }, -]; - -// These functions were moved inline to ensure translations are applied correctly - -const Filter = ({ - selectedTypes, - setSelectedTypes, - selectedStatus, - setSelectedStatus, - selectedState, - setSelectedState, - setToFilterStatus, - setToFilterActive, - handleReset, -}) => { - const theme = useTheme(); - const { t } = useTranslation(); - - const typeOptions = getTypeOptions(); - // Create status options with translations - const statusOptions = [ - { value: "Up", label: t("monitorStatus.up") }, - { value: "Down", label: t("monitorStatus.down") }, - ]; - // Create state options with translations - const stateOptions = [ - { value: "Active", label: t("monitorState.active") }, - { value: "Paused", label: t("monitorState.paused") }, - ]; - - const handleTypeChange = (event) => { - const selectedValues = event.target.value; - setSelectedTypes(selectedValues.length > 0 ? selectedValues : undefined); - }; - - const handleStatusChange = (event) => { - const selectedValues = event.target.value; - setSelectedStatus(selectedValues.length > 0 ? selectedValues : undefined); - - if (selectedValues.length === 0 || selectedValues.length === 2) { - setToFilterStatus(undefined); - } else { - setToFilterStatus(selectedValues[0] === "Up" ? "true" : "false"); - } - }; - - const handleStateChange = (event) => { - const selectedValues = event.target.value; - setSelectedState(selectedValues); - - if (selectedValues.length === 0 || selectedValues.length === 2) { - setToFilterActive(undefined); - } else { - setToFilterActive(selectedValues[0] === "Active" ? "true" : "false"); - } - }; - - const isFilterActive = useMemo(() => { - return ( - (selectedTypes?.length ?? 0) > 0 || - (selectedState?.length ?? 0) > 0 || - (selectedStatus?.length ?? 0) > 0 - ); - }, [selectedState, selectedTypes, selectedStatus]); - - return ( - - - - - - - ); -}; - -Filter.propTypes = { - selectedTypes: PropTypes.arrayOf(PropTypes.string), - setSelectedTypes: PropTypes.func.isRequired, - selectedStatus: PropTypes.arrayOf(PropTypes.string), - setSelectedStatus: PropTypes.func.isRequired, - selectedState: PropTypes.arrayOf(PropTypes.string), - setSelectedState: PropTypes.func.isRequired, - setToFilterStatus: PropTypes.func.isRequired, - setToFilterActive: PropTypes.func.isRequired, - handleReset: PropTypes.func.isRequired, -}; - -export default Filter; diff --git a/client/src/Pages/Uptime/Monitors/Components/Skeleton/index.jsx b/client/src/Pages/Uptime/Monitors/Components/Skeleton/index.jsx deleted file mode 100644 index 4e55be536..000000000 --- a/client/src/Pages/Uptime/Monitors/Components/Skeleton/index.jsx +++ /dev/null @@ -1,61 +0,0 @@ -import { Skeleton, Stack } from "@mui/material"; -import { useTheme } from "@emotion/react"; - -/** - * Renders a skeleton layout. - * - * @returns {JSX.Element} - */ -const SkeletonLayout = () => { - const theme = useTheme(); - - return ( - <> - - - - - - - - - - - - ); -}; - -export default SkeletonLayout; diff --git a/client/src/Pages/Uptime/Monitors/Components/StatusBoxes/index.jsx b/client/src/Pages/Uptime/Monitors/Components/StatusBoxes/index.jsx deleted file mode 100644 index 5cba9e3b1..000000000 --- a/client/src/Pages/Uptime/Monitors/Components/StatusBoxes/index.jsx +++ /dev/null @@ -1,42 +0,0 @@ -import PropTypes from "prop-types"; -import { Stack } from "@mui/material"; -import StatusBox from "./statusBox.jsx"; -import { useTheme } from "@emotion/react"; -import { useTranslation } from "react-i18next"; -import SkeletonLayout from "./skeleton.jsx"; - -const StatusBoxes = ({ shouldRender, monitorsSummary }) => { - const theme = useTheme(); - const { t } = useTranslation(); - if (!shouldRender) return ; - return ( - - - - - - ); -}; - -StatusBoxes.propTypes = { - monitorsSummary: PropTypes.object, - shouldRender: PropTypes.bool, -}; - -export default StatusBoxes; diff --git a/client/src/Pages/Uptime/Monitors/Components/StatusBoxes/skeleton.jsx b/client/src/Pages/Uptime/Monitors/Components/StatusBoxes/skeleton.jsx deleted file mode 100644 index df6e08ccd..000000000 --- a/client/src/Pages/Uptime/Monitors/Components/StatusBoxes/skeleton.jsx +++ /dev/null @@ -1,31 +0,0 @@ -import { Skeleton, Stack } from "@mui/material"; -import { useTheme } from "@emotion/react"; - -const SkeletonLayout = () => { - const theme = useTheme(); - return ( - - - - - - ); -}; - -export default SkeletonLayout; diff --git a/client/src/Pages/Uptime/Monitors/Components/StatusBoxes/statusBox.jsx b/client/src/Pages/Uptime/Monitors/Components/StatusBoxes/statusBox.jsx deleted file mode 100644 index 136c3575d..000000000 --- a/client/src/Pages/Uptime/Monitors/Components/StatusBoxes/statusBox.jsx +++ /dev/null @@ -1,115 +0,0 @@ -import PropTypes from "prop-types"; -import { useTheme } from "@emotion/react"; -import { Box, Stack, Typography } from "@mui/material"; -import Icon from "@/Components/v1/Icon"; -import Background from "@/assets/Images/background-grid.svg?react"; - -const StatusBox = ({ title, value, status }) => { - const theme = useTheme(); - let sharedStyles = { - position: "absolute", - right: 8, - opacity: 0.5, - "& svg path": { stroke: theme.palette.primary.contrastTextTertiary }, - }; - - let color; - let icon; - if (status === "up") { - color = theme.palette.success.lowContrast; - icon = ( - - - - ); - } else if (status === "down") { - color = theme.palette.error.lowContrast; - icon = ( - - - - ); - } else if (status === "paused") { - color = theme.palette.warning.lowContrast; - icon = ( - - - - ); - } - - return ( - - - - - - - - {title} - - {icon} - - - {value} - - - # - - - - - ); -}; - -StatusBox.propTypes = { - title: PropTypes.string, - value: PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired, - status: PropTypes.string, -}; - -export default StatusBox; diff --git a/client/src/Pages/Uptime/Monitors/Components/UptimeDataTable/index.jsx b/client/src/Pages/Uptime/Monitors/Components/UptimeDataTable/index.jsx deleted file mode 100644 index 8c3239dd3..000000000 --- a/client/src/Pages/Uptime/Monitors/Components/UptimeDataTable/index.jsx +++ /dev/null @@ -1,241 +0,0 @@ -// Components -import { Box, Stack } from "@mui/material"; -import DataTable from "@/Components/v1/Table/index.jsx"; -import Icon from "@/Components/v1/Icon"; -import Host from "@/Components/v1/Host/index.jsx"; -import { StatusLabel } from "@/Components/v1/Label/index.jsx"; -import BarChart from "@/Components/v1/Charts/BarChart/index.jsx"; -import ActionsMenu from "@/Components/v1/ActionsMenu/index.jsx"; - -import LoadingSpinner from "../LoadingSpinner/index.jsx"; -import TableSkeleton from "@/Components/v1/Table/skeleton.jsx"; - -// Utils -import { useTheme } from "@emotion/react"; -import { useMonitorUtils } from "../../../../../Hooks/useMonitorUtils.js"; -import { useNavigate } from "react-router-dom"; -import PropTypes from "prop-types"; -import { useTranslation } from "react-i18next"; - -/** - * UptimeDataTable displays a table of uptime monitors with sorting, searching, and action capabilities - * @param {Object} props - Component props - * @param {boolean} props.isAdmin - Whether the current user has admin privileges - * @param {boolean} props.isLoading - Loading state of the table - * @param {Array<{ - * id: string, - * url: string, - * title: string, - * percentage: number, - * percentageColor: string, - * monitor: { - * id: string, - * type: string, - * checks: Array - * } - * }>} props.monitors - Array of monitor objects to display - * @param {number} props.monitorCount - Total count of monitors - * @param {Object} props.sort - Current sort configuration - * @param {string} props.sort.field - Field to sort by - * @param {'asc'|'desc'} props.sort.order - Sort direction - * @param {Function} props.setSort - Callback to update sort configuration - * @param {string} props.search - Current search query - * @param {Function} props.setSearch - Callback to update search query - * @param {boolean} props.isSearching - Whether a search is in progress - * @param {Function} props.setIsLoading - Callback to update loading state - * @param {Function} props.triggerUpdate - Callback to trigger a data refresh - * @returns {JSX.Element} Rendered component - */ -const UptimeDataTable = ({ - isAdmin, - isSearching, - filteredMonitors, - sort, - setSort, - triggerUpdate, - monitorsAreLoading, -}) => { - // Utils - const navigate = useNavigate(); - const { determineState } = useMonitorUtils(); - const theme = useTheme(); - const { t } = useTranslation(); - - // Local state - // Handlers - const handleSort = (field) => { - let order = ""; - if (sort?.field !== field) { - order = "desc"; - } else { - order = sort?.order === "asc" ? "desc" : "asc"; - } - setSort({ field, order }); - }; - - const headers = [ - { - id: "name", - content: ( - handleSort("name")} - > - {t("host")} - - {sort?.order === "asc" ? ( - - ) : ( - - )} - - - ), - render: (row) => ( - - ), - }, - { - id: "status", - content: ( - handleSort("status")} - > - {" "} - {t("status")} - - {sort?.order === "asc" ? ( - - ) : ( - - )} - - - ), - render: (row) => { - const status = determineState(row.monitor); - return ( - - ); - }, - }, - { - id: "responseTime", - content: t("responseTime"), - render: (row) => ( - - - - ), - }, - { - id: "type", - content: t("type"), - render: (row) => ( - - {row.monitor.type === "http" ? "HTTP(s)" : row.monitor.type} - - ), - }, - { - id: "actions", - content: t("actions"), - render: (row) => ( - - ), - }, - ]; - - if (monitorsAreLoading) { - return ; - } - - return ( - - - { - navigate(`/uptime/${row.id}`); - }, - emptyView: "No monitors found", - }} - /> - - ); -}; - -UptimeDataTable.propTypes = { - isSearching: PropTypes.bool, - setSort: PropTypes.func, - setSearch: PropTypes.func, - triggerUpdate: PropTypes.func, - debouncedSearch: PropTypes.string, - onSearchChange: PropTypes.func, - isAdmin: PropTypes.bool, - monitors: PropTypes.array, - filteredMonitors: PropTypes.array, - monitorCount: PropTypes.number, - monitorsAreLoading: PropTypes.bool, - sort: PropTypes.shape({ - field: PropTypes.string, - order: PropTypes.oneOf(["asc", "desc"]), - }), -}; - -export default UptimeDataTable; diff --git a/client/src/Pages/Uptime/Monitors/old.jsx b/client/src/Pages/Uptime/Monitors/old.jsx deleted file mode 100644 index 67019362f..000000000 --- a/client/src/Pages/Uptime/Monitors/old.jsx +++ /dev/null @@ -1,225 +0,0 @@ -// Required Data -// 1. Monitor summary -// 2. List of monitors filtered by search term with 25 checks each -// 2a.List of monitors must have the total number of monitors that match. - -// Components -import Breadcrumbs from "@/Components/v1/Breadcrumbs/index.jsx"; -import Greeting from "../../../Utils/greeting.jsx"; -import StatusBoxes from "./Components/StatusBoxes/index.jsx"; -import UptimeDataTable from "./Components/UptimeDataTable/index.jsx"; -import Pagination from "@/Components/v1/Table/TablePagination/index.jsx"; -import CreateMonitorHeader from "@/Components/v1/MonitorCreateHeader/index.jsx"; -import SearchComponent from "./Components/SearchComponent/index.jsx"; -import Filter from "./Components/Filter/index.jsx"; -import PageStateWrapper from "@/Components/v1/PageStateWrapper/index.jsx"; - -import MonitorCountHeader from "@/Components/v1/MonitorCountHeader/index.jsx"; - -// MUI Components -import { Stack, Box, Button } from "@mui/material"; -// Utils -import { useState, useCallback, useEffect } from "react"; -import { useIsAdmin } from "@/Hooks/useIsAdmin.js"; -import { useTheme } from "@emotion/react"; -import { useNavigate } from "react-router-dom"; -import { useSelector, useDispatch } from "react-redux"; -import { setRowsPerPage } from "../../../Features/UI/uiSlice.js"; -import PropTypes from "prop-types"; -import { - useFetchMonitorsWithChecks, - useFetchMonitorsByTeamId, -} from "@/Hooks/monitorHooks.js"; -import { useTranslation } from "react-i18next"; - -const TYPES = ["http", "ping", "docker", "port", "game"]; -const CreateMonitorButton = ({ shouldRender }) => { - // Utils - const navigate = useNavigate(); - const { t } = useTranslation(); - if (shouldRender === false) { - return; - } - - return ( - - - - ); -}; - -CreateMonitorButton.propTypes = { - shouldRender: PropTypes.bool, -}; - -const UptimeMonitors = () => { - // Redux state - const rowsPerPage = useSelector((state) => state.ui?.monitors?.rowsPerPage ?? 10); - - // Local state - const [search, setSearch] = useState(undefined); - const [page, setPage] = useState(undefined); - const [sort, setSort] = useState(undefined); - const [isSearching, setIsSearching] = useState(false); - const [monitorUpdateTrigger, setMonitorUpdateTrigger] = useState(false); - const [selectedTypes, setSelectedTypes] = useState(undefined); - const [selectedState, setSelectedState] = useState(undefined); - const [selectedStatus, setSelectedStatus] = useState(undefined); - const [toFilterStatus, setToFilterStatus] = useState(undefined); - const [toFilterActive, setToFilterActive] = useState(undefined); - - // Utils - const theme = useTheme(); - const isAdmin = useIsAdmin(); - const dispatch = useDispatch(); - const { t } = useTranslation(); - - const BREADCRUMBS = [{ name: t("menu.uptime"), path: "/uptime" }]; - - // Handlers - const handleChangePage = (event, newPage) => { - setPage(newPage); - }; - - const handleChangeRowsPerPage = (event) => { - dispatch( - setRowsPerPage({ - value: parseInt(event.target.value, 10), - table: "monitors", - }) - ); - setPage(0); - }; - - const triggerUpdate = useCallback(() => { - setMonitorUpdateTrigger((prev) => !prev); - }, []); - - const handleReset = () => { - setSelectedState(undefined); - setSelectedTypes(undefined); - setSelectedStatus(undefined); - setToFilterStatus(undefined); - setToFilterActive(undefined); - }; - - const filterLookup = new Map([ - [toFilterStatus, "status"], - [toFilterActive, "isActive"], - ]); - - const activeFilter = [...filterLookup].find(([key]) => key !== undefined); - const field = activeFilter?.[1] || (search ? "name" : sort?.field); - const filter = activeFilter?.[0] || search; - - const effectiveTypes = selectedTypes?.length ? selectedTypes : TYPES; - - const [ - summary, - monitorsWithChecks, - monitorsWithChecksCount, - monitorsWithChecksIsLoading, - networkError, - ] = useFetchMonitorsWithChecks({ - types: effectiveTypes, - limit: 25, - page: page, - rowsPerPage: rowsPerPage, - filter: filter, - field: field, - order: sort?.order, - monitorUpdateTrigger, - }); - - const [monitors, listIsLoading, listNetworkError] = useFetchMonitorsByTeamId({ - type: ["http", "ping", "docker", "port", "game"], - }); - - useEffect(() => { - if (isSearching) { - setPage(undefined); - } - }, [isSearching]); - - const isLoading = monitorsWithChecksIsLoading; - - return ( - <> - - - - - - - - - - - - - - - - - - ); -}; - -export default UptimeMonitors;