diff --git a/Client/src/Pages/Uptime/Details/Charts/CustomLabels.jsx b/Client/src/Pages/Uptime/Details/Charts/CustomLabels.jsx
deleted file mode 100644
index 10494830f..000000000
--- a/Client/src/Pages/Uptime/Details/Charts/CustomLabels.jsx
+++ /dev/null
@@ -1,42 +0,0 @@
-import PropTypes from "prop-types";
-import { useSelector } from "react-redux";
-import { formatDateWithTz } from "../../../../Utils/timeUtils";
-
-const CustomLabels = ({ x, width, height, firstDataPoint, lastDataPoint, type }) => {
- const uiTimezone = useSelector((state) => state.ui.timezone);
- const dateFormat = type === "day" ? "MMM D, h:mm A" : "MMM D";
-
- return (
- <>
-
- {formatDateWithTz(firstDataPoint._id, dateFormat, uiTimezone)}
-
-
- {formatDateWithTz(lastDataPoint._id, dateFormat, uiTimezone)}
-
- >
- );
-};
-
-CustomLabels.propTypes = {
- x: PropTypes.number.isRequired,
- width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
- height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
- firstDataPoint: PropTypes.object.isRequired,
- lastDataPoint: PropTypes.object.isRequired,
- type: PropTypes.string.isRequired,
-};
-
-export default CustomLabels;
diff --git a/Client/src/Pages/Uptime/Details/Charts/DownBarChart.jsx b/Client/src/Pages/Uptime/Details/Charts/DownBarChart.jsx
deleted file mode 100644
index ae2adda0f..000000000
--- a/Client/src/Pages/Uptime/Details/Charts/DownBarChart.jsx
+++ /dev/null
@@ -1,92 +0,0 @@
-import { memo, useState } from "react";
-import { useTheme } from "@mui/material";
-import { ResponsiveContainer, BarChart, XAxis, Bar, Cell } from "recharts";
-import PropTypes from "prop-types";
-import CustomLabels from "./CustomLabels";
-
-const DownBarChart = memo(({ monitor, type, onBarHover }) => {
- const theme = useTheme();
-
- const [chartHovered, setChartHovered] = useState(false);
- const [hoveredBarIndex, setHoveredBarIndex] = useState(null);
-
- return (
-
- {
- setChartHovered(true);
- onBarHover({ time: null, totalChecks: 0 });
- }}
- onMouseLeave={() => {
- setChartHovered(false);
- setHoveredBarIndex(null);
- onBarHover(null);
- }}
- >
-
- }
- />
-
- {monitor.groupedDownChecks.map((entry, index) => {
- return (
- | {
- setHoveredBarIndex(index);
- onBarHover(entry);
- }}
- onMouseLeave={() => {
- setHoveredBarIndex(null);
- onBarHover({ time: null, totalChecks: 0 });
- }}
- />
- );
- })}
- |
-
-
- );
-});
-
-DownBarChart.displayName = "DownBarChart";
-DownBarChart.propTypes = {
- monitor: PropTypes.shape({
- groupedDownChecks: PropTypes.arrayOf(PropTypes.object),
- }),
- type: PropTypes.string,
- onBarHover: PropTypes.func,
-};
-export default DownBarChart;
diff --git a/Client/src/Pages/Uptime/Details/Charts/UpBarChart.jsx b/Client/src/Pages/Uptime/Details/Charts/UpBarChart.jsx
deleted file mode 100644
index 223dc8eef..000000000
--- a/Client/src/Pages/Uptime/Details/Charts/UpBarChart.jsx
+++ /dev/null
@@ -1,107 +0,0 @@
-import { memo, useState } from "react";
-import { useTheme } from "@mui/material";
-import { ResponsiveContainer, BarChart, XAxis, Bar, Cell } from "recharts";
-import PropTypes from "prop-types";
-import CustomLabels from "./CustomLabels";
-
-const getThemeColor = (responseTime) => {
- if (responseTime < 200) {
- return "success";
- } else if (responseTime < 300) {
- return "warning";
- } else {
- return "error";
- }
-};
-
-const UpBarChart = memo(({ monitor, type, onBarHover }) => {
- const theme = useTheme();
- const [chartHovered, setChartHovered] = useState(false);
- const [hoveredBarIndex, setHoveredBarIndex] = useState(null);
-
- return (
-
- {
- setChartHovered(true);
- onBarHover({ time: null, totalChecks: 0, avgResponseTime: 0 });
- }}
- onMouseLeave={() => {
- setChartHovered(false);
- setHoveredBarIndex(null);
- onBarHover(null);
- }}
- >
-
- }
- />
-
- {monitor.groupedUpChecks.map((entry, index) => {
- const themeColor = getThemeColor(entry.avgResponseTime);
- return (
- {
- setHoveredBarIndex(index);
- onBarHover(entry);
- }}
- onMouseLeave={() => {
- setHoveredBarIndex(null);
- onBarHover({
- time: null,
- totalChecks: 0,
- groupUptimePercentage: 0,
- });
- }}
- />
- );
- })}
- |
-
-
- );
-});
-
-// Add display name for the component
-UpBarChart.displayName = "UpBarChart";
-
-// Validate props using PropTypes
-UpBarChart.propTypes = {
- monitor: PropTypes.shape({
- groupedUpChecks: PropTypes.array,
- }),
- type: PropTypes.string,
- onBarHover: PropTypes.func,
-};
-export default UpBarChart;
diff --git a/Client/src/Pages/Uptime/NewDetails/Components/ChartBoxes/index.jsx b/Client/src/Pages/Uptime/Details/Components/ChartBoxes/index.jsx
similarity index 97%
rename from Client/src/Pages/Uptime/NewDetails/Components/ChartBoxes/index.jsx
rename to Client/src/Pages/Uptime/Details/Components/ChartBoxes/index.jsx
index afe93d028..d9e581267 100644
--- a/Client/src/Pages/Uptime/NewDetails/Components/ChartBoxes/index.jsx
+++ b/Client/src/Pages/Uptime/Details/Components/ChartBoxes/index.jsx
@@ -7,13 +7,14 @@ import AverageResponseIcon from "../../../../../assets/icons/average-response-ic
import UpBarChart from "../Charts/UpBarChart";
import DownBarChart from "../Charts/DownBarChart";
import ResponseGaugeChart from "../Charts/ResponseGaugeChart";
-
+import SkeletonLayout from "./skeleton";
// Utils
import { formatDateWithTz } from "../../../../../Utils/timeUtils";
import PropTypes from "prop-types";
import { useTheme } from "@emotion/react";
const ChartBoxes = ({
+ shouldRender = true,
monitor,
dateRange,
uiTimezone,
@@ -24,6 +25,11 @@ const ChartBoxes = ({
setHoveredIncidentsData,
}) => {
const theme = useTheme();
+
+ if (!shouldRender) {
+ return ;
+ }
+
return (
{
+ const theme = useTheme();
+ return (
+
+
+
+
+
+ );
+};
+
+export default SkeletonLayout;
diff --git a/Client/src/Pages/Uptime/NewDetails/Components/Charts/ChartBox.jsx b/Client/src/Pages/Uptime/Details/Components/Charts/ChartBox.jsx
similarity index 95%
rename from Client/src/Pages/Uptime/NewDetails/Components/Charts/ChartBox.jsx
rename to Client/src/Pages/Uptime/Details/Components/Charts/ChartBox.jsx
index e62949004..672134781 100644
--- a/Client/src/Pages/Uptime/NewDetails/Components/Charts/ChartBox.jsx
+++ b/Client/src/Pages/Uptime/Details/Components/Charts/ChartBox.jsx
@@ -2,7 +2,7 @@ import { Stack, Typography } from "@mui/material";
import { useTheme } from "@emotion/react";
import IconBox from "../../../../../Components/IconBox";
import PropTypes from "prop-types";
-const ChartBox = ({ children, icon, header }) => {
+const ChartBox = ({ children, icon, header, height = "300px" }) => {
const theme = useTheme();
return (
{
justifyContent: "space-between",
flex: "1 30%",
gap: theme.spacing(8),
- height: 300,
+ height,
minWidth: 250,
padding: theme.spacing(8),
border: 1,
diff --git a/Client/src/Pages/Uptime/NewDetails/Components/Charts/CustomLabels.jsx b/Client/src/Pages/Uptime/Details/Components/Charts/CustomLabels.jsx
similarity index 100%
rename from Client/src/Pages/Uptime/NewDetails/Components/Charts/CustomLabels.jsx
rename to Client/src/Pages/Uptime/Details/Components/Charts/CustomLabels.jsx
diff --git a/Client/src/Pages/Uptime/NewDetails/Components/Charts/DownBarChart.jsx b/Client/src/Pages/Uptime/Details/Components/Charts/DownBarChart.jsx
similarity index 100%
rename from Client/src/Pages/Uptime/NewDetails/Components/Charts/DownBarChart.jsx
rename to Client/src/Pages/Uptime/Details/Components/Charts/DownBarChart.jsx
diff --git a/Client/src/Pages/Uptime/Details/Charts/ResponseGaugeChart.jsx b/Client/src/Pages/Uptime/Details/Components/Charts/ResponseGaugeChart.jsx
similarity index 100%
rename from Client/src/Pages/Uptime/Details/Charts/ResponseGaugeChart.jsx
rename to Client/src/Pages/Uptime/Details/Components/Charts/ResponseGaugeChart.jsx
diff --git a/Client/src/Pages/Uptime/NewDetails/Components/Charts/ResponseTimeChart.jsx b/Client/src/Pages/Uptime/Details/Components/Charts/ResponseTimeChart.jsx
similarity index 70%
rename from Client/src/Pages/Uptime/NewDetails/Components/Charts/ResponseTimeChart.jsx
rename to Client/src/Pages/Uptime/Details/Components/Charts/ResponseTimeChart.jsx
index c28163394..73ffc035e 100644
--- a/Client/src/Pages/Uptime/NewDetails/Components/Charts/ResponseTimeChart.jsx
+++ b/Client/src/Pages/Uptime/Details/Components/Charts/ResponseTimeChart.jsx
@@ -1,7 +1,12 @@
import ChartBox from "./ChartBox";
import MonitorDetailsAreaChart from "../../../../../Components/Charts/MonitorDetailsAreaChart";
import ResponseTimeIcon from "../../../../../assets/icons/response-time-icon.svg?react";
-const ResponseTImeChart = ({ monitor, dateRange }) => {
+import SkeletonLayout from "./ResponseTimeChartSkeleton";
+const ResponseTImeChart = ({ shouldRender = true, monitor, dateRange }) => {
+ if (!shouldRender) {
+ return ;
+ }
+
return (
}
diff --git a/Client/src/Pages/Uptime/Details/Components/Charts/ResponseTimeChartSkeleton.jsx b/Client/src/Pages/Uptime/Details/Components/Charts/ResponseTimeChartSkeleton.jsx
new file mode 100644
index 000000000..a70757e36
--- /dev/null
+++ b/Client/src/Pages/Uptime/Details/Components/Charts/ResponseTimeChartSkeleton.jsx
@@ -0,0 +1,12 @@
+import { Skeleton } from "@mui/material";
+const ResponseTimeChartSkeleton = () => {
+ return (
+
+ );
+};
+
+export default ResponseTimeChartSkeleton;
diff --git a/Client/src/Pages/Uptime/NewDetails/Components/Charts/UpBarChart.jsx b/Client/src/Pages/Uptime/Details/Components/Charts/UpBarChart.jsx
similarity index 100%
rename from Client/src/Pages/Uptime/NewDetails/Components/Charts/UpBarChart.jsx
rename to Client/src/Pages/Uptime/Details/Components/Charts/UpBarChart.jsx
diff --git a/Client/src/Pages/Uptime/NewDetails/Components/ConfigButton/index.jsx b/Client/src/Pages/Uptime/Details/Components/ConfigButton/index.jsx
similarity index 100%
rename from Client/src/Pages/Uptime/NewDetails/Components/ConfigButton/index.jsx
rename to Client/src/Pages/Uptime/Details/Components/ConfigButton/index.jsx
diff --git a/Client/src/Pages/Uptime/NewDetails/Components/MonitorHeader/index.jsx b/Client/src/Pages/Uptime/Details/Components/MonitorHeader/index.jsx
similarity index 75%
rename from Client/src/Pages/Uptime/NewDetails/Components/MonitorHeader/index.jsx
rename to Client/src/Pages/Uptime/Details/Components/MonitorHeader/index.jsx
index 5802fd82d..fddf9c3e5 100644
--- a/Client/src/Pages/Uptime/NewDetails/Components/MonitorHeader/index.jsx
+++ b/Client/src/Pages/Uptime/Details/Components/MonitorHeader/index.jsx
@@ -5,10 +5,16 @@ import { useTheme } from "@emotion/react";
import useUtils from "../../../Home/Hooks/useUtils";
import { formatDurationRounded } from "../../../../../Utils/timeUtils";
import ConfigButton from "../ConfigButton";
+import SkeletonLayout from "./skeleton";
+import PropTypes from "prop-types";
-const MonitorHeader = ({ monitor }) => {
+const MonitorHeader = ({ shouldRender = true, isAdmin, monitor }) => {
const theme = useTheme();
const { statusColor, statusMsg, determineState } = useUtils();
+ console.log(shouldRender);
+ if (!shouldRender) {
+ return ;
+ }
return (
{
);
};
+MonitorHeader.propTypes = {
+ shouldRender: PropTypes.bool,
+ isAdmin: PropTypes.bool,
+ monitor: PropTypes.object,
+};
+
export default MonitorHeader;
diff --git a/Client/src/Pages/Uptime/Details/Components/MonitorHeader/skeleton.jsx b/Client/src/Pages/Uptime/Details/Components/MonitorHeader/skeleton.jsx
new file mode 100644
index 000000000..64dc0547f
--- /dev/null
+++ b/Client/src/Pages/Uptime/Details/Components/MonitorHeader/skeleton.jsx
@@ -0,0 +1,23 @@
+import { Stack, Skeleton } from "@mui/material";
+
+const SkeletonLayout = () => {
+ return (
+
+
+
+
+ );
+};
+
+export default SkeletonLayout;
diff --git a/Client/src/Pages/Uptime/Details/Components/ResponseTable/index.jsx b/Client/src/Pages/Uptime/Details/Components/ResponseTable/index.jsx
new file mode 100644
index 000000000..a510b9bf1
--- /dev/null
+++ b/Client/src/Pages/Uptime/Details/Components/ResponseTable/index.jsx
@@ -0,0 +1,88 @@
+import ChartBox from "../Charts/ChartBox";
+import PropTypes from "prop-types";
+import HistoryIcon from "../../../../../assets/icons/history-icon.svg?react";
+import Table from "../../../../../Components/Table";
+import TablePagination from "../../../../../Components/Table/TablePagination";
+import { StatusLabel } from "../../../../../Components/Label";
+import { formatDateWithTz } from "../../../../../Utils/timeUtils";
+import SkeletonLayout from "./skeleton";
+const ResponseTable = ({
+ shouldRender = true,
+ checks,
+ checksCount,
+ uiTimezone,
+ page,
+ setPage,
+ rowsPerPage,
+ setRowsPerPage,
+}) => {
+ if (!shouldRender) {
+ return ;
+ }
+
+ const headers = [
+ {
+ id: "status",
+ content: "Status",
+ render: (row) => {
+ const status = row.status === true ? "up" : "down";
+
+ return (
+
+ );
+ },
+ },
+ {
+ id: "date",
+ content: "Date & Time",
+ render: (row) =>
+ formatDateWithTz(row.createdAt, "ddd, MMMM D, YYYY, HH:mm A", uiTimezone),
+ },
+ {
+ id: "statusCode",
+ content: "Status code",
+ render: (row) => (row.statusCode ? row.statusCode : "N/A"),
+ },
+ {
+ id: "message",
+ content: "Message",
+ render: (row) => row.message,
+ },
+ ];
+
+ return (
+ }
+ header="Response Times"
+ height="100%"
+ >
+
+
+
+ );
+};
+
+ResponseTable.propTypes = {
+ checks: PropTypes.array.isRequired,
+ checksCount: PropTypes.number.isRequired,
+ uiTimezone: PropTypes.string.isRequired,
+ page: PropTypes.number.isRequired,
+ setPage: PropTypes.func.isRequired,
+ rowsPerPage: PropTypes.number.isRequired,
+ setRowsPerPage: PropTypes.func.isRequired,
+};
+
+export default ResponseTable;
diff --git a/Client/src/Pages/Uptime/Details/Components/ResponseTable/skeleton.jsx b/Client/src/Pages/Uptime/Details/Components/ResponseTable/skeleton.jsx
new file mode 100644
index 000000000..2665ffaf1
--- /dev/null
+++ b/Client/src/Pages/Uptime/Details/Components/ResponseTable/skeleton.jsx
@@ -0,0 +1,13 @@
+import { Skeleton } from "@mui/material";
+
+const SkeletonLayout = () => {
+ return (
+
+ );
+};
+
+export default SkeletonLayout;
diff --git a/Client/src/Pages/Uptime/NewDetails/Components/StatusBoxes/index.jsx b/Client/src/Pages/Uptime/Details/Components/StatusBoxes/index.jsx
similarity index 90%
rename from Client/src/Pages/Uptime/NewDetails/Components/StatusBoxes/index.jsx
rename to Client/src/Pages/Uptime/Details/Components/StatusBoxes/index.jsx
index e994dd63b..55bcf34da 100644
--- a/Client/src/Pages/Uptime/NewDetails/Components/StatusBoxes/index.jsx
+++ b/Client/src/Pages/Uptime/Details/Components/StatusBoxes/index.jsx
@@ -1,13 +1,16 @@
// Components
import { Stack, Typography } from "@mui/material";
import StatBox from "../../../../../Components/StatBox";
-
+import SkeletonLayout from "./skeleton";
// Utils
import { useTheme } from "@mui/material/styles";
import useUtils from "../../../Home/Hooks/useUtils";
import { getHumanReadableDuration } from "../../../../../Utils/timeUtils";
-const StatusBoxes = ({ monitor, certificateExpiry }) => {
+const StatusBoxes = ({ shouldRender, monitor, certificateExpiry }) => {
+ if (!shouldRender) {
+ return ;
+ }
const theme = useTheme();
const { time: streakTime, units: streakUnits } = getHumanReadableDuration(
monitor?.uptimeStreak
@@ -18,6 +21,7 @@ const StatusBoxes = ({ monitor, certificateExpiry }) => {
);
const { determineState } = useUtils();
+
return (
{
+ const theme = useTheme();
+ return (
+
+
+
+
+
+ );
+};
+
+export default SkeletonLayout;
diff --git a/Client/src/Pages/Uptime/NewDetails/Components/TimeFramePicker/index.jsx b/Client/src/Pages/Uptime/Details/Components/TimeFramePicker/index.jsx
similarity index 85%
rename from Client/src/Pages/Uptime/NewDetails/Components/TimeFramePicker/index.jsx
rename to Client/src/Pages/Uptime/Details/Components/TimeFramePicker/index.jsx
index ffb581e23..ade677604 100644
--- a/Client/src/Pages/Uptime/NewDetails/Components/TimeFramePicker/index.jsx
+++ b/Client/src/Pages/Uptime/Details/Components/TimeFramePicker/index.jsx
@@ -1,7 +1,14 @@
import { Stack, Typography, Button, ButtonGroup } from "@mui/material";
import { useTheme } from "@emotion/react";
-const TimeFramePicker = ({ dateRange, setDateRange }) => {
+import SkeletonLayout from "./skeleton";
+
+const TimeFramePicker = ({ shouldRender = true, dateRange, setDateRange }) => {
const theme = useTheme();
+
+ if (!shouldRender) {
+ return ;
+ }
+
return (
{
+ return (
+
+
+
+
+ );
+};
+
+export default SkeletonLayout;
diff --git a/Client/src/Pages/Uptime/NewDetails/Hooks/useCertificateFetch.jsx b/Client/src/Pages/Uptime/Details/Hooks/useCertificateFetch.jsx
similarity index 100%
rename from Client/src/Pages/Uptime/NewDetails/Hooks/useCertificateFetch.jsx
rename to Client/src/Pages/Uptime/Details/Hooks/useCertificateFetch.jsx
diff --git a/Client/src/Pages/Uptime/Details/Hooks/useChecksFetch.jsx b/Client/src/Pages/Uptime/Details/Hooks/useChecksFetch.jsx
new file mode 100644
index 000000000..2a50c2172
--- /dev/null
+++ b/Client/src/Pages/Uptime/Details/Hooks/useChecksFetch.jsx
@@ -0,0 +1,45 @@
+import { useState } from "react";
+import { useEffect } from "react";
+import { logger } from "../../../../Utils/Logger";
+import { networkService } from "../../../../main";
+
+export const useChecksFetch = ({
+ authToken,
+ monitorId,
+ dateRange,
+ page,
+ rowsPerPage,
+}) => {
+ const [checks, setChecks] = useState([]);
+ const [checksCount, setChecksCount] = useState(0);
+ const [checksAreLoading, setChecksAreLoading] = useState(false);
+
+ useEffect(() => {
+ const fetchChecks = async () => {
+ try {
+ setChecksAreLoading(true);
+ const res = await networkService.getChecksByMonitor({
+ authToken: authToken,
+ monitorId: monitorId,
+ sortOrder: "desc",
+ limit: null,
+ dateRange: dateRange,
+ filter: null,
+ page: page,
+ rowsPerPage: rowsPerPage,
+ });
+ setChecks(res.data.data.checks);
+ setChecksCount(res.data.data.checksCount);
+ } catch (error) {
+ logger.error(error);
+ } finally {
+ setChecksAreLoading(false);
+ }
+ };
+ fetchChecks();
+ }, [authToken, monitorId, dateRange, page, rowsPerPage]);
+
+ return { checks, checksCount, checksAreLoading };
+};
+
+export default useChecksFetch;
diff --git a/Client/src/Pages/Uptime/NewDetails/Hooks/useMonitorFetch.jsx b/Client/src/Pages/Uptime/Details/Hooks/useMonitorFetch.jsx
similarity index 100%
rename from Client/src/Pages/Uptime/NewDetails/Hooks/useMonitorFetch.jsx
rename to Client/src/Pages/Uptime/Details/Hooks/useMonitorFetch.jsx
diff --git a/Client/src/Pages/Uptime/Details/PaginationTable/index.jsx b/Client/src/Pages/Uptime/Details/PaginationTable/index.jsx
deleted file mode 100644
index 93e9532c5..000000000
--- a/Client/src/Pages/Uptime/Details/PaginationTable/index.jsx
+++ /dev/null
@@ -1,163 +0,0 @@
-import PropTypes from "prop-types";
-import {
- TableContainer,
- Table,
- TableHead,
- TableRow,
- TableCell,
- TableBody,
- PaginationItem,
- Pagination,
- Paper,
-} from "@mui/material";
-
-import { useState, useEffect } from "react";
-import { useSelector } from "react-redux";
-import { networkService } from "../../../../main";
-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 { formatDateWithTz } from "../../../../Utils/timeUtils";
-import { useTheme } from "@emotion/react";
-const PaginationTable = ({ monitorId, dateRange }) => {
- const theme = useTheme();
- const { authToken } = useSelector((state) => state.auth);
- const [checks, setChecks] = useState([]);
- const [checksCount, setChecksCount] = useState(0);
- const [paginationController, setPaginationController] = useState({
- page: 0,
- rowsPerPage: 5,
- });
- const uiTimezone = useSelector((state) => state.ui.timezone);
-
- useEffect(() => {
- setPaginationController((prevPaginationController) => ({
- ...prevPaginationController,
- page: 0,
- }));
- }, [dateRange]);
-
- useEffect(() => {
- const fetchPage = async () => {
- try {
- const res = await networkService.getChecksByMonitor({
- authToken: authToken,
- monitorId: monitorId,
- sortOrder: "desc",
- limit: null,
- dateRange: dateRange,
- filter: null,
- page: paginationController.page,
- rowsPerPage: paginationController.rowsPerPage,
- });
- setChecks(res.data.data.checks);
- setChecksCount(res.data.data.checksCount);
- } catch (error) {
- logger.error(error);
- }
- };
- fetchPage();
- }, [
- authToken,
- monitorId,
- dateRange,
- paginationController.page,
- paginationController.rowsPerPage,
- ]);
-
- const handlePageChange = (_, newPage) => {
- setPaginationController({
- ...paginationController,
- page: newPage - 1, // 0-indexed
- });
- };
-
- let paginationComponent = <>>;
- if (checksCount > paginationController.rowsPerPage) {
- paginationComponent = (
- (
-
- )}
- />
- );
- }
-
- return (
- <>
-
-
-
-
- Status
- Date & Time
- Status Code
- Message
-
-
-
- {checks.map((check) => {
- const status = check.status === true ? "up" : "down";
-
- return (
-
-
-
-
-
- {formatDateWithTz(
- check.createdAt,
- "ddd, MMMM D, YYYY, HH:mm A",
- uiTimezone
- )}
-
- {check.statusCode ? check.statusCode : "N/A"}
- {check.message}
-
- );
- })}
-
-
-
- {paginationComponent}
- >
- );
-};
-
-PaginationTable.propTypes = {
- monitorId: PropTypes.string.isRequired,
- dateRange: PropTypes.string.isRequired,
-};
-
-export default PaginationTable;
diff --git a/Client/src/Pages/Uptime/Details/index.css b/Client/src/Pages/Uptime/Details/index.css
deleted file mode 100644
index e69de29bb..000000000
diff --git a/Client/src/Pages/Uptime/Details/index.jsx b/Client/src/Pages/Uptime/Details/index.jsx
index be589c1ba..81265eb56 100644
--- a/Client/src/Pages/Uptime/Details/index.jsx
+++ b/Client/src/Pages/Uptime/Details/index.jsx
@@ -1,476 +1,128 @@
-import PropTypes from "prop-types";
-import { useEffect, useState, useCallback } from "react";
-import { Box, Button, Stack, Tooltip, Typography, useTheme } from "@mui/material";
-import { useSelector } from "react-redux";
-import { useNavigate, useParams } from "react-router-dom";
-import { networkService } from "../../../main";
-import { logger } from "../../../Utils/Logger";
-import MonitorDetailsAreaChart from "../../../Components/Charts/MonitorDetailsAreaChart";
-import ButtonGroup from "@mui/material/ButtonGroup";
-import SettingsIcon from "../../../assets/icons/settings-bold.svg?react";
-import UptimeIcon from "../../../assets/icons/uptime-icon.svg?react";
-import ResponseTimeIcon from "../../../assets/icons/response-time-icon.svg?react";
-import AverageResponseIcon from "../../../assets/icons/average-response-icon.svg?react";
-import IncidentsIcon from "../../../assets/icons/incidents.svg?react";
-import HistoryIcon from "../../../assets/icons/history-icon.svg?react";
-import PaginationTable from "./PaginationTable";
+// Components
import Breadcrumbs from "../../../Components/Breadcrumbs";
-import PulseDot from "../../../Components/Animated/PulseDot";
-import { ChartBox } from "./styled";
-import SkeletonLayout from "./skeleton";
-import "./index.css";
-import useUtils from "../Home/Hooks/useUtils";
-import { formatDateWithTz, formatDurationSplit } from "../../../Utils/timeUtils";
-import { useIsAdmin } from "../../../Hooks/useIsAdmin";
-import IconBox from "../../../Components/IconBox";
-import StatBox from "../../../Components/StatBox";
-import UpBarChart from "./Charts/UpBarChart";
-import DownBarChart from "./Charts/DownBarChart";
-import ResponseGaugeChart from "./Charts/ResponseGaugeChart";
-/**
- * Details page component displaying monitor details and related information.
- * @component
- */
-const DetailsPage = () => {
- const theme = useTheme();
- const { statusColor, statusMsg, determineState } = useUtils();
- const isAdmin = useIsAdmin();
- const [monitor, setMonitor] = useState({});
- const { monitorId } = useParams();
- const { authToken } = useSelector((state) => state.auth);
- const [dateRange, setDateRange] = useState("day");
- const [certificateExpiry, setCertificateExpiry] = useState("N/A");
- const navigate = useNavigate();
+import MonitorHeader from "./Components/MonitorHeader";
+import StatusBoxes from "./Components/StatusBoxes";
+import TimeFramePicker from "./Components/TimeFramePicker";
+import ChartBoxes from "./Components/ChartBoxes";
+import ResponseTimeChart from "./Components/Charts/ResponseTimeChart";
+import ResponseTable from "./Components/ResponseTable";
+// MUI Components
+import { Stack } from "@mui/material";
- const certificateDateFormat = "MMM D, YYYY h A";
- const dateFormat = dateRange === "day" ? "MMM D, h A" : "MMM D";
+// 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";
+import useMonitorFetch from "./Hooks/useMonitorFetch";
+import useCertificateFetch from "./Hooks/useCertificateFetch";
+import useChecksFetch from "./Hooks/useChecksFetch";
+
+// 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 { authToken } = useSelector((state) => state.auth);
const uiTimezone = useSelector((state) => state.ui.timezone);
- const fetchMonitor = useCallback(async () => {
- try {
- const res = await networkService.getUptimeDetailsById({
- authToken: authToken,
- monitorId: monitorId,
- dateRange: dateRange,
- normalize: true,
- });
- setMonitor(res?.data?.data ?? {});
- } catch (error) {
- logger.error(error);
- navigate("/not-found", { replace: true });
- }
- }, [authToken, monitorId, navigate, dateRange]);
-
- useEffect(() => {
- fetchMonitor();
- }, [fetchMonitor]);
-
- useEffect(() => {
- const fetchCertificate = async () => {
- if (monitor?.type !== "http") {
- return;
- }
- try {
- const res = await networkService.getCertificateExpiry({
- authToken: authToken,
- 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");
- console.error(error);
- }
- };
- fetchCertificate();
- }, [authToken, monitorId, monitor, uiTimezone, dateFormat]);
-
- const splitDuration = (duration) => {
- const { time, format } = formatDurationSplit(duration);
- return (
- <>
- {time}
- {format}
- >
- );
- };
-
- let loading = Object.keys(monitor).length === 0;
-
+ // Local state
+ const [dateRange, setDateRange] = useState("day");
const [hoveredUptimeData, setHoveredUptimeData] = useState(null);
const [hoveredIncidentsData, setHoveredIncidentsData] = useState(null);
+ const [page, setPage] = useState(0);
+ const [rowsPerPage, setRowsPerPage] = useState(5);
+
+ // Utils
+ const dateFormat = dateRange === "day" ? "MMM D, h A" : "MMM D";
+ const { monitorId } = useParams();
+ const theme = useTheme();
+ const isAdmin = useIsAdmin();
+
+ const { monitor, monitorIsLoading } = useMonitorFetch({
+ authToken,
+ monitorId,
+ dateRange,
+ });
+
+ const { certificateExpiry, certificateIsLoading } = useCertificateFetch({
+ monitor,
+ authToken,
+ monitorId,
+ certificateDateFormat,
+ uiTimezone,
+ });
+
+ const { checks, checksCount, checksAreLoading } = useChecksFetch({
+ authToken,
+ monitorId,
+ dateRange,
+ page,
+ rowsPerPage,
+ });
+
+ // Handlers
+ const handlePageChange = (_, newPage) => {
+ setPage(newPage);
+ };
+
+ const handleChangeRowsPerPage = (event) => {
+ setRowsPerPage(event.target.value);
+ };
- const BREADCRUMBS = [
- { name: "uptime", path: "/uptime" },
- { name: "details", path: `/uptime/${monitorId}` },
- ];
return (
-
- {loading ? (
-
- ) : (
- <>
-
-
-
-
-
- {monitor.name}
-
-
- {/* TODO there is a tooltip at BarChart component. Wrap the Tooltip on our own component */}
-
-
-
-
-
-
- {monitor.url?.replace(/^https?:\/\//, "") || "..."}
-
-
- {/* Checking every {formatDurationRounded(monitor?.interval)}. */}
-
-
-
-
- {isAdmin && (
-
- )}
-
-
-
-
-
-
- {monitor?.latestResponseTime}
- {"ms"}
- >
- }
- />
-
- {certificateExpiry}
-
- }
- />
-
-
-
-
- Showing statistics for past{" "}
- {dateRange === "day"
- ? "24 hours"
- : dateRange === "week"
- ? "7 days"
- : "30 days"}
- .
-
-
-
-
-
-
-
-
-
-
-
-
-
- Uptime
-
-
-
- Total Checks
-
- {hoveredUptimeData !== null
- ? hoveredUptimeData.totalChecks
- : (monitor?.groupedUpChecks?.reduce((count, checkGroup) => {
- return count + checkGroup.totalChecks;
- }, 0) ?? 0)}
-
- {hoveredUptimeData !== null && hoveredUptimeData.time !== null && (
-
- {formatDateWithTz(
- hoveredUptimeData._id,
- dateFormat,
- uiTimezone
- )}
-
- )}
-
-
-
- {hoveredUptimeData !== null
- ? "Avg Response Time"
- : "Uptime Percentage"}
-
-
- {hoveredUptimeData !== null
- ? Math.floor(hoveredUptimeData?.avgResponseTime ?? 0)
- : Math.floor(
- ((monitor?.upChecks?.totalChecks ?? 0) /
- (monitor?.totalChecks ?? 1)) *
- 100
- )}
-
- {hoveredUptimeData !== null ? " ms" : " %"}
-
-
-
-
-
-
-
-
-
-
-
- Incidents
-
-
- Total Incidents
-
- {hoveredIncidentsData !== null
- ? hoveredIncidentsData.totalChecks
- : (monitor?.groupedDownChecks?.reduce((count, checkGroup) => {
- return count + checkGroup.totalChecks;
- }, 0) ?? 0)}
-
- {hoveredIncidentsData !== null &&
- hoveredIncidentsData.time !== null && (
-
- {formatDateWithTz(
- hoveredIncidentsData._id,
- dateFormat,
- uiTimezone
- )}
-
- )}
-
-
-
-
-
-
-
-
- Average Response Time
-
-
-
-
-
-
-
-
- Response Times
-
-
-
-
-
-
-
-
-
- History
-
-
-
-
-
-
-
- >
- )}
-
+
+
+
+
+
+
+
+
+
);
};
-DetailsPage.propTypes = {
- isAdmin: PropTypes.bool,
-};
-export default DetailsPage;
+export default UptimeDetails;
diff --git a/Client/src/Pages/Uptime/Details/skeleton.jsx b/Client/src/Pages/Uptime/Details/skeleton.jsx
deleted file mode 100644
index 0bdc03ca8..000000000
--- a/Client/src/Pages/Uptime/Details/skeleton.jsx
+++ /dev/null
@@ -1,120 +0,0 @@
-import { Box, Skeleton, Stack, useTheme } from "@mui/material";
-
-/**
- * Renders a skeleton layout.
- *
- * @returns {JSX.Element}
- */
-const SkeletonLayout = () => {
- const theme = useTheme();
-
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
-};
-
-export default SkeletonLayout;
diff --git a/Client/src/Pages/Uptime/Details/styled.jsx b/Client/src/Pages/Uptime/Details/styled.jsx
deleted file mode 100644
index 164fee457..000000000
--- a/Client/src/Pages/Uptime/Details/styled.jsx
+++ /dev/null
@@ -1,45 +0,0 @@
-import { Stack, styled } from "@mui/material";
-
-export const ChartBox = styled(Stack)(({ theme }) => ({
- flex: "1 30%",
- gap: theme.spacing(8),
- height: 300,
- minWidth: 250,
- padding: theme.spacing(8),
- border: 1,
- borderStyle: "solid",
- borderColor: theme.palette.primary.lowContrast,
- borderRadius: 4,
- backgroundColor: theme.palette.primary.main,
- "& h2": {
- color: theme.palette.primary.contrastTextSecondary,
- fontSize: 15,
- fontWeight: 500,
- },
- "& .MuiBox-root:not(.area-tooltip) p": {
- color: theme.palette.primary.contrastTextTertiary,
- fontSize: 13,
- },
- "& .MuiBox-root > span": {
- color: theme.palette.primary.contrastText,
- fontSize: 20,
- "& span": {
- opacity: 0.8,
- marginLeft: 2,
- fontSize: 15,
- },
- },
- "& .MuiStack-root": {
- flexDirection: "row",
- gap: theme.spacing(6),
- },
- "& .MuiStack-root:first-of-type": {
- alignItems: "center",
- },
- "& tspan, & text": {
- fill: theme.palette.primary.contrastTextTertiary,
- },
- "& path": {
- transition: "fill 300ms ease, stroke-width 400ms ease",
- },
-}));
diff --git a/Client/src/Pages/Uptime/NewDetails/Components/Charts/ResponseGaugeChart.jsx b/Client/src/Pages/Uptime/NewDetails/Components/Charts/ResponseGaugeChart.jsx
deleted file mode 100644
index e94af8441..000000000
--- a/Client/src/Pages/Uptime/NewDetails/Components/Charts/ResponseGaugeChart.jsx
+++ /dev/null
@@ -1,117 +0,0 @@
-import PropTypes from "prop-types";
-import { useTheme } from "@mui/material";
-import { ResponsiveContainer, RadialBarChart, RadialBar, Cell } from "recharts";
-
-const ResponseGaugeChart = ({ avgResponseTime }) => {
- const theme = useTheme();
-
- let max = 1000; // max ms
-
- const data = [
- { response: max, fill: "transparent", background: false },
- { response: avgResponseTime, background: true },
- ];
- let responseTime = Math.floor(avgResponseTime);
- let responseProps =
- responseTime <= 200
- ? {
- category: "Excellent",
- main: theme.palette.success.main,
- bg: theme.palette.success.contrastText,
- }
- : responseTime <= 500
- ? {
- category: "Fair",
- main: theme.palette.success.main,
- bg: theme.palette.success.contrastText,
- }
- : responseTime <= 600
- ? {
- category: "Acceptable",
- main: theme.palette.warning.main,
- bg: theme.palette.warning.lowContrast,
- }
- : {
- category: "Poor",
- main: theme.palette.error.main,
- bg: theme.palette.error.contrastText,
- };
-
- return (
-
-
-
- low
-
-
- high
-
-
- {responseProps.category}
-
-
- {responseTime} ms
-
-
- |
- |
-
-
-
- );
-};
-
-ResponseGaugeChart.propTypes = {
- avgResponseTime: PropTypes.number.isRequired,
-};
-
-export default ResponseGaugeChart;
diff --git a/Client/src/Pages/Uptime/NewDetails/Components/ResponseTable/index.jsx b/Client/src/Pages/Uptime/NewDetails/Components/ResponseTable/index.jsx
deleted file mode 100644
index e69de29bb..000000000
diff --git a/Client/src/Pages/Uptime/NewDetails/index.jsx b/Client/src/Pages/Uptime/NewDetails/index.jsx
deleted file mode 100644
index eca12ec57..000000000
--- a/Client/src/Pages/Uptime/NewDetails/index.jsx
+++ /dev/null
@@ -1,86 +0,0 @@
-// Components
-import Breadcrumbs from "../../../Components/Breadcrumbs";
-import MonitorHeader from "./Components/MonitorHeader";
-import StatusBoxes from "./Components/StatusBoxes";
-import TimeFramePicker from "./Components/TimeFramePicker";
-import ChartBoxes from "./Components/ChartBoxes";
-import ResponseTimeChart from "./Components/Charts/ResponseTimeChart";
-// MUI Components
-import { Stack } from "@mui/material";
-
-// Utils
-import { useState } from "react";
-import { useParams } from "react-router-dom";
-import { useSelector } from "react-redux";
-import { useTheme } from "@emotion/react";
-import useMonitorFetch from "./Hooks/useMonitorFetch";
-import useCertificateFetch from "./Hooks/useCertificateFetch";
-// 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 { authToken } = useSelector((state) => state.auth);
- const uiTimezone = useSelector((state) => state.ui.timezone);
-
- // Local state
- const [dateRange, setDateRange] = useState("day");
- const [hoveredUptimeData, setHoveredUptimeData] = useState(null);
- const [hoveredIncidentsData, setHoveredIncidentsData] = useState(null);
-
- // Utils
- const dateFormat = dateRange === "day" ? "MMM D, h A" : "MMM D";
- const { monitorId } = useParams();
- const theme = useTheme();
-
- const { monitor, monitorIsLoading } = useMonitorFetch({
- authToken,
- monitorId,
- dateRange,
- });
-
- const { certificateExpiry, certificateIsLoading } = useCertificateFetch({
- monitor,
- authToken,
- monitorId,
- certificateDateFormat,
- uiTimezone,
- });
-
- return (
-
-
-
-
-
-
-
-
- );
-};
-
-export default UptimeDetails;
diff --git a/Client/src/Routes/index.jsx b/Client/src/Routes/index.jsx
index 6ac5624a9..575c108cf 100644
--- a/Client/src/Routes/index.jsx
+++ b/Client/src/Routes/index.jsx
@@ -6,7 +6,9 @@ import NotFound from "../Pages/NotFound";
import Login from "../Pages/Auth/Login/Login";
import Register from "../Pages/Auth/Register/Register";
import Account from "../Pages/Account";
-import Monitors from "../Pages/Uptime/Home";
+import Uptime from "../Pages/Uptime/Home";
+import UptimeDetails from "../Pages/Uptime/Details";
+
import CreateMonitor from "../Pages/Uptime/CreateUptime";
import CreateInfrastructureMonitor from "../Pages/Infrastructure/CreateMonitor";
import Incidents from "../Pages/Incidents";
@@ -18,9 +20,6 @@ import CheckEmail from "../Pages/Auth/CheckEmail";
import SetNewPassword from "../Pages/Auth/SetNewPassword";
import NewPasswordConfirmed from "../Pages/Auth/NewPasswordConfirmed";
import ProtectedRoute from "../Components/ProtectedRoute";
-import Details from "../Pages/Uptime/Details";
-
-import UptimeDetails from "../Pages/Uptime/NewDetails";
import Maintenance from "../Pages/Maintenance";
import Configure from "../Pages/Uptime/Configure";
import PageSpeed from "../Pages/PageSpeed";
@@ -48,7 +47,7 @@ const Routes = () => {
/>
}
+ element={}
/>