From 2bdf01abd6c5f7f1c5ae9d3faed0fe083a4ad7b5 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Thu, 12 Sep 2024 12:17:31 +0800 Subject: [PATCH] refactor formating to utils file --- .../Charts/MonitorDetailsAreaChart/index.jsx | 26 +++----- .../Pages/Incidents/IncidentTable/index.jsx | 14 ++--- .../Pages/Monitors/Details/Charts/index.jsx | 61 +++++++++++++++---- .../Details/PaginationTable/index.jsx | 14 ++--- Client/src/Pages/Monitors/Details/index.jsx | 33 +++++----- Client/src/Utils/timeUtils.js | 11 ++++ 6 files changed, 95 insertions(+), 64 deletions(-) diff --git a/Client/src/Components/Charts/MonitorDetailsAreaChart/index.jsx b/Client/src/Components/Charts/MonitorDetailsAreaChart/index.jsx index fd28b6e7e..6742f9d90 100644 --- a/Client/src/Components/Charts/MonitorDetailsAreaChart/index.jsx +++ b/Client/src/Components/Charts/MonitorDetailsAreaChart/index.jsx @@ -11,10 +11,13 @@ import { Box, Stack, Typography } from "@mui/material"; import { useTheme } from "@emotion/react"; import { useMemo } from "react"; import "./index.css"; +import { useSelector } from "react-redux"; +import { formatDateWithTz } from "../../../Utils/timeUtils"; const CustomToolTip = ({ active, payload, label }) => { - const theme = useTheme(); + const uiTimezone = useSelector((state) => state.ui.timezone); + const theme = useTheme(); if (active && payload && payload.length) { return ( { fontWeight: 500, }} > - {new Date(label).toLocaleDateString("en-US", { - weekday: "short", // Mon - month: "long", // July - day: "numeric", // 17 - }) + - ", " + - new Date(label).toLocaleTimeString("en-US", { - hour: "numeric", // 12 - minute: "2-digit", // 15 - hour12: true, // AM/PM format - })} + {formatDateWithTz(label, "ddd, MMMM D, YYYY, h:mm A", uiTimezone)} { }; const MonitorDetailsAreaChart = ({ checks }) => { + const uiTimezone = useSelector((state) => state.ui.timezone); + const formatDate = (timestamp) => { - const date = new Date(timestamp); - return date.toLocaleTimeString("en-US", { - hour: "numeric", - minute: "2-digit", - hour12: true, - }); + return formatDateWithTz(timestamp, "HH:mm:ss", uiTimezone); }; const memoizedChecks = useMemo(() => checks, [checks[0]]); diff --git a/Client/src/Pages/Incidents/IncidentTable/index.jsx b/Client/src/Pages/Incidents/IncidentTable/index.jsx index 2f79c5983..b80fdee67 100644 --- a/Client/src/Pages/Incidents/IncidentTable/index.jsx +++ b/Client/src/Pages/Incidents/IncidentTable/index.jsx @@ -21,13 +21,9 @@ import { networkService } from "../../../main"; import { StatusLabel } from "../../../Components/Label"; import { logger } from "../../../Utils/Logger"; import { useTheme } from "@emotion/react"; -import dayjs from "dayjs"; -import utc from "dayjs/plugin/utc"; -import timezone from "dayjs/plugin/timezone"; +import { formatDateWithTz } from "../../../Utils/timeUtils"; const IncidentTable = ({ monitors, selectedMonitor, filter }) => { - dayjs.extend(utc); - dayjs.extend(timezone); const uiTimezone = useSelector((state) => state.ui.timezone); const theme = useTheme(); @@ -159,9 +155,11 @@ const IncidentTable = ({ monitors, selectedMonitor, filter }) => { {checks.map((check) => { const status = check.status === true ? "up" : "down"; - const formattedDate = dayjs(check.createdAt) - .tz(uiTimezone) - .format("YYYY-MM-DD HH:mm:ss"); + const formattedDate = formatDateWithTz( + check.createdAt, + "YYYY-MM-DD HH:mm:ss A", + uiTimezone + ); return ( diff --git a/Client/src/Pages/Monitors/Details/Charts/index.jsx b/Client/src/Pages/Monitors/Details/Charts/index.jsx index cb0afb55b..b70712340 100644 --- a/Client/src/Pages/Monitors/Details/Charts/index.jsx +++ b/Client/src/Pages/Monitors/Details/Charts/index.jsx @@ -1,4 +1,5 @@ import { useTheme } from "@emotion/react"; +import PropTypes from "prop-types"; import { BarChart, Bar, @@ -8,8 +9,9 @@ import { RadialBarChart, RadialBar, } from "recharts"; -import { formatDate } from "../../../../Utils/timeUtils"; import { memo, useMemo, useState } from "react"; +import { useSelector } from "react-redux"; +import { formatDateWithTz } from "../../../../Utils/timeUtils"; const CustomLabels = ({ x, @@ -19,27 +21,35 @@ const CustomLabels = ({ lastDataPoint, type, }) => { - let options = { - month: "short", - year: undefined, - hour: undefined, - minute: undefined, - }; - if (type === "day") delete options.hour; + const uiTimezone = useSelector((state) => state.ui.timezone); + const dateFormat = type === "day" ? "MMM D, h:mm A" : "MMM D"; return ( <> - {formatDate(new Date(firstDataPoint.time), options)} + {formatDateWithTz( + new Date(firstDataPoint.time), + dateFormat, + uiTimezone + )} - {formatDate(new Date(lastDataPoint.time), options)} + {formatDateWithTz(new Date(lastDataPoint.time), dateFormat, uiTimezone)} ); }; -export const UpBarChart = memo(({ data, type, onBarHover }) => { +CustomLabels.propTypes = { + x: PropTypes.number.isRequired, + width: PropTypes.number.isRequired, + height: PropTypes.number.isRequired, + firstDataPoint: PropTypes.object.isRequired, + lastDataPoint: PropTypes.object.isRequired, + type: PropTypes.string.isRequired, +}; + +const UpBarChart = memo(({ data, type, onBarHover }) => { const theme = useTheme(); const [chartHovered, setChartHovered] = useState(false); @@ -122,7 +132,18 @@ export const UpBarChart = memo(({ data, type, onBarHover }) => { ); }); -export const DownBarChart = memo(({ data, type, onBarHover }) => { +// Add display name for the component +UpBarChart.displayName = "UpBarChart"; + +// Validate props using PropTypes +UpBarChart.propTypes = { + data: PropTypes.arrayOf(PropTypes.object), + type: PropTypes.string, + onBarHover: PropTypes.func, +}; +export { UpBarChart }; + +const DownBarChart = memo(({ data, type, onBarHover }) => { const theme = useTheme(); const [chartHovered, setChartHovered] = useState(false); @@ -194,7 +215,15 @@ export const DownBarChart = memo(({ data, type, onBarHover }) => { ); }); -export const ResponseGaugeChart = ({ data }) => { +DownBarChart.displayName = "DownBarChart"; +DownBarChart.propTypes = { + data: PropTypes.arrayOf(PropTypes.object), + type: PropTypes.string, + onBarHover: PropTypes.func, +}; +export { DownBarChart }; + +const ResponseGaugeChart = ({ data }) => { const theme = useTheme(); let max = 1000; // max ms @@ -281,3 +310,9 @@ export const ResponseGaugeChart = ({ data }) => { ); }; + +ResponseGaugeChart.propTypes = { + data: PropTypes.arrayOf(PropTypes.object).isRequired, +}; + +export { ResponseGaugeChart }; diff --git a/Client/src/Pages/Monitors/Details/PaginationTable/index.jsx b/Client/src/Pages/Monitors/Details/PaginationTable/index.jsx index 40b9e93e8..b438f104b 100644 --- a/Client/src/Pages/Monitors/Details/PaginationTable/index.jsx +++ b/Client/src/Pages/Monitors/Details/PaginationTable/index.jsx @@ -18,11 +18,7 @@ import { StatusLabel } from "../../../../Components/Label"; import ArrowBackRoundedIcon from "@mui/icons-material/ArrowBackRounded"; import ArrowForwardRoundedIcon from "@mui/icons-material/ArrowForwardRounded"; import { logger } from "../../../../Utils/Logger"; -import dayjs from "dayjs"; -import utc from "dayjs/plugin/utc"; -import timezone from "dayjs/plugin/timezone"; -dayjs.extend(utc); -dayjs.extend(timezone); +import { formatDateWithTz } from "../../../../Utils/timeUtils"; const PaginationTable = ({ monitorId, dateRange }) => { const { authToken } = useSelector((state) => state.auth); @@ -123,9 +119,11 @@ const PaginationTable = ({ monitorId, dateRange }) => { /> - {dayjs(check.createdAt) - .tz(uiTimezone) - .format("ddd, MMMM D, YYYY, HH:mm A")} + {formatDateWithTz( + check.createdAt, + "ddd, MMMM D, YYYY, HH:mm A", + uiTimezone + )} {check.statusCode ? check.statusCode : "N/A"} diff --git a/Client/src/Pages/Monitors/Details/index.jsx b/Client/src/Pages/Monitors/Details/index.jsx index 41e529eb9..eb18e36fc 100644 --- a/Client/src/Pages/Monitors/Details/index.jsx +++ b/Client/src/Pages/Monitors/Details/index.jsx @@ -14,7 +14,6 @@ import { useNavigate, useParams } from "react-router-dom"; import { networkService } from "../../../main"; import { logger } from "../../../Utils/Logger"; import { - formatDate, formatDurationRounded, formatDurationSplit, } from "../../../Utils/timeUtils"; @@ -35,6 +34,8 @@ import { DownBarChart, ResponseGaugeChart, UpBarChart } from "./Charts"; import SkeletonLayout from "./skeleton"; import "./index.css"; import useUtils from "../utils"; +import { formatDateWithTz } from "../../../Utils/timeUtils"; + /** * Details page component displaying monitor details and related information. * @component @@ -57,6 +58,9 @@ const DetailsPage = ({ isAdmin }) => { setAnchorEl(null); }; + const dateFormat = dateRange === "day" ? "MMM D, h A" : "MMM D"; + const uiTimezone = useSelector((state) => state.ui.timezone); + const fetchMonitor = useCallback(async () => { try { const res = await networkService.getStatsByMonitorId( @@ -95,10 +99,7 @@ const DetailsPage = ({ isAdmin }) => { const date = new Date(year, month - 1, day); setCertificateExpiry( - formatDate(date, { - hour: undefined, - minute: undefined, - }) ?? "N/A" + formatDateWithTz(date, dateFormat, uiTimezone) ?? "N/A" ); } } catch (error) { @@ -367,12 +368,11 @@ const DetailsPage = ({ isAdmin }) => { fontSize={11} color={theme.palette.text.tertiary} > - {formatDate(new Date(hoveredUptimeData.time), { - month: "short", - year: undefined, - minute: undefined, - hour: dateRange === "day" ? "numeric" : undefined, - })} + {formatDateWithTz( + hoveredUptimeData.time, + dateFormat, + uiTimezone + )} )} @@ -417,12 +417,11 @@ const DetailsPage = ({ isAdmin }) => { fontSize={11} color={theme.palette.text.tertiary} > - {formatDate(new Date(hoveredIncidentsData.time), { - month: "short", - year: undefined, - minute: undefined, - hour: dateRange === "day" ? "numeric" : undefined, - })} + {formatDateWithTz( + hoveredIncidentsData.time, + dateFormat, + uiTimezone + )} )} diff --git a/Client/src/Utils/timeUtils.js b/Client/src/Utils/timeUtils.js index f9f916d04..da2f7f9bb 100644 --- a/Client/src/Utils/timeUtils.js +++ b/Client/src/Utils/timeUtils.js @@ -1,3 +1,9 @@ +import dayjs from "dayjs"; +import utc from "dayjs/plugin/utc"; +import timezone from "dayjs/plugin/timezone"; +dayjs.extend(utc); +dayjs.extend(timezone); + export const formatDuration = (ms) => { const seconds = Math.floor(ms / 1000); const minutes = Math.floor(seconds / 60); @@ -76,3 +82,8 @@ export const formatDate = (date, customOptions) => { .toLocaleString("en-US", options) .replace(/\b(AM|PM)\b/g, (match) => match.toLowerCase()); }; + +export const formatDateWithTz = (timestamp, format, timezone) => { + const formattedDate = dayjs(timestamp, timezone).tz(timezone).format(format); + return formattedDate; +};