diff --git a/Client/src/Components/BasicTable/index.jsx b/Client/src/Components/BasicTable/index.jsx
deleted file mode 100644
index b93c584da..000000000
--- a/Client/src/Components/BasicTable/index.jsx
+++ /dev/null
@@ -1,360 +0,0 @@
-/* TODO
-
-Should we delete this?
-*/
-
-import PropTypes from "prop-types";
-import { useState, useEffect } from "react";
-import { useTheme } from "@emotion/react";
-import {
- TableContainer,
- Paper,
- Table,
- TableHead,
- TableRow,
- TableCell,
- TableBody,
- TablePagination,
- Box,
- Typography,
- Stack,
- Button,
-} from "@mui/material";
-import { useDispatch, useSelector } from "react-redux";
-import { setRowsPerPage } from "../../Features/UI/uiSlice";
-import LeftArrowDouble from "../../assets/icons/left-arrow-double.svg?react";
-import RightArrowDouble from "../../assets/icons/right-arrow-double.svg?react";
-import LeftArrow from "../../assets/icons/left-arrow.svg?react";
-import RightArrow from "../../assets/icons/right-arrow.svg?react";
-import SelectorVertical from "../../assets/icons/selector-vertical.svg?react";
-import "./index.css";
-/**
- * Component for pagination actions (first, previous, next, last).
- *
- * @component
- * @param {Object} props
- * @param {number} props.count - Total number of items.
- * @param {number} props.page - Current page number.
- * @param {number} props.rowsPerPage - Number of rows per page.
- * @param {function} props.onPageChange - Callback function to handle page change.
- *
- * @returns {JSX.Element} Pagination actions component.
- */
-const TablePaginationActions = (props) => {
- const { count, page, rowsPerPage, onPageChange } = props;
-
- const handleFirstPageButtonClick = (event) => {
- onPageChange(event, 0);
- };
- const handleBackButtonClick = (event) => {
- onPageChange(event, page - 1);
- };
- const handleNextButtonClick = (event) => {
- onPageChange(event, page + 1);
- };
- const handleLastPageButtonClick = (event) => {
- onPageChange(event, Math.max(0, Math.ceil(count / rowsPerPage) - 1));
- };
-
- return (
-
-
-
-
-
-
- );
-};
-
-TablePaginationActions.propTypes = {
- count: PropTypes.number.isRequired,
- page: PropTypes.number.isRequired,
- rowsPerPage: PropTypes.number.isRequired,
- onPageChange: PropTypes.func.isRequired,
-};
-
-/**
- * BasicTable Component
- * Renders a table with optional pagination.
- *
- * @component
- * @param {Object} props - Component props.
- * @param {Object} props.data - Data for the table including columns and rows.
- * @param {Array} props.data.cols - Array of objects for column headers.
- * @param {number} props.data.cols[].id - Unique identifier for the column.
- * @param {string} props.data.cols[].name - Name of the column to display as header.
- * @param {Array} props.data.rows - Array of row objects.
- * @param {number} props.data.rows[].id - Unique identifier for the row.
- * @param {Array} props.data.rows[].data - Array of cell data objects for the row.
- * @param {number} props.data.rows[].data[].id - Unique identifier for the cell.
- * @param {JSX.Element} props.data.rows[].data[].data - The content to display in the cell.
- * @param {function} props.data.rows.data.handleClick - Function to call when the row is clicked.
- * @param {boolean} [props.paginated=false] - Flag to enable pagination.
- * @param {boolean} [props.reversed=false] - Flag to enable reverse order.
- * @param {number} props.rowsPerPage- Number of rows per page (table).
- * @param {string} props.emptyMessage - Message to display when there is no data.
- * @example
- * const data = {
- * cols: [
- * { id: 1, name: "First Col" },
- * { id: 2, name: "Second Col" },
- * { id: 3, name: "Third Col" },
- * { id: 4, name: "Fourth Col" },
- * ],
- * rows: [
- * {
- * id: 1,
- * data: [
- * { id: 1, data:
Data for Row 1 Col 1
},
- * { id: 2, data: Data for Row 1 Col 2
},
- * { id: 3, data: Data for Row 1 Col 3
},
- * { id: 4, data: Data for Row 1 Col 4
},
- * ],
- * },
- * {
- * id: 2,
- * data: [
- * { id: 5, data: Data for Row 2 Col 1
},
- * { id: 6, data: Data for Row 2 Col 2
},
- * { id: 7, data: Data for Row 2 Col 3
},
- * { id: 8, data: Data for Row 2 Col 4
},
- * ],
- * },
- * ],
- * };
- *
- *
- */
-
-const BasicTable = ({ data, paginated, reversed, table, emptyMessage = "No data" }) => {
- const DEFAULT_ROWS_PER_PAGE = 5;
- const theme = useTheme();
- const dispatch = useDispatch();
- const uiState = useSelector((state) => state.ui);
- let rowsPerPage = uiState?.[table]?.rowsPerPage ?? DEFAULT_ROWS_PER_PAGE;
- const [page, setPage] = useState(0);
-
- useEffect(() => {
- setPage(0);
- }, [data]);
-
- const handleChangePage = (event, newPage) => {
- setPage(newPage);
- };
-
- const handleChangeRowsPerPage = (event) => {
- dispatch(
- setRowsPerPage({
- value: parseInt(event.target.value, 10),
- table: table,
- })
- );
- setPage(0);
- };
-
- let displayData = [];
-
- if (data && data.rows) {
- let rows = reversed ? [...data.rows].reverse() : data.rows;
- displayData = paginated
- ? rows.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
- : rows;
- }
-
- if (!data || !data.cols || !data.rows) {
- return No data
;
- }
-
- /**
- * Helper function to calculate the range of displayed rows.
- * @returns {string}
- */
- const getRange = () => {
- let start = page * rowsPerPage + 1;
- let end = Math.min(page * rowsPerPage + rowsPerPage, data.rows.length);
- return `${start} - ${end}`;
- };
-
- return (
- <>
-
-
-
-
- {data.cols.map((col) => (
- {col.name}
- ))}
-
-
-
- {displayData.map((row) => {
- return (
-
- {row.data.map((cell) => {
- return {cell.data};
- })}
-
- );
- })}
- {displayData.length === 0 && (
-
-
- {emptyMessage}
-
-
- )}
-
-
-
- {paginated && (
-
-
- Showing {getRange()} of {data.rows.length} monitor(s)
-
-
- `Page ${page + 1} of ${Math.max(0, Math.ceil(count / rowsPerPage))}`
- }
- slotProps={{
- select: {
- MenuProps: {
- keepMounted: true,
- PaperProps: {
- className: "pagination-dropdown",
- sx: {
- mt: 0,
- mb: theme.spacing(2),
- },
- },
- transformOrigin: { vertical: "bottom", horizontal: "left" },
- anchorOrigin: { vertical: "top", horizontal: "left" },
- sx: { mt: theme.spacing(-2) },
- },
- inputProps: { id: "pagination-dropdown" },
- IconComponent: SelectorVertical,
- sx: {
- ml: theme.spacing(4),
- mr: theme.spacing(12),
- minWidth: theme.spacing(20),
- textAlign: "left",
- "&.Mui-focused > div": {
- backgroundColor: theme.palette.primary.main,
- },
- },
- },
- }}
- sx={{
- mt: theme.spacing(6),
- color: theme.palette.primary.contrastTextSecondary,
- "& svg path": {
- stroke: theme.palette.primary.contrastTextTertiary,
- strokeWidth: 1.3,
- },
- "& .MuiSelect-select": {
- border: 1,
- borderColor: theme.palette.primary.lowContrast,
- borderRadius: theme.shape.borderRadius,
- },
- }}
- />
-
- )}
- >
- );
-};
-
-BasicTable.propTypes = {
- data: PropTypes.object.isRequired,
- paginated: PropTypes.bool,
- reversed: PropTypes.bool,
- rowPerPage: PropTypes.number,
- table: PropTypes.string,
- emptyMessage: PropTypes.string,
-};
-
-export default BasicTable;
diff --git a/Client/src/Components/CreateMonitorHeader/index.jsx b/Client/src/Components/CreateMonitorHeader/index.jsx
new file mode 100644
index 000000000..b8fcbc39a
--- /dev/null
+++ b/Client/src/Components/CreateMonitorHeader/index.jsx
@@ -0,0 +1,33 @@
+import { Stack, Button } from "@mui/material";
+import { useNavigate } from "react-router-dom";
+import PropTypes from "prop-types";
+import SkeletonLayout from "./skeleton";
+
+const CreateMonitorHeader = ({ isAdmin, shouldRender, path }) => {
+ const navigate = useNavigate();
+ if (!isAdmin) return null;
+ if (!shouldRender) return ;
+ return (
+
+
+
+ );
+};
+
+export default CreateMonitorHeader;
+
+CreateMonitorHeader.propTypes = {
+ isAdmin: PropTypes.bool.isRequired,
+ shouldRender: PropTypes.bool.isRequired,
+ path: PropTypes.string.isRequired,
+};
diff --git a/Client/src/Components/CreateMonitorHeader/skeleton.jsx b/Client/src/Components/CreateMonitorHeader/skeleton.jsx
new file mode 100644
index 000000000..7583f7849
--- /dev/null
+++ b/Client/src/Components/CreateMonitorHeader/skeleton.jsx
@@ -0,0 +1,19 @@
+import { Stack, Skeleton } from "@mui/material";
+
+const SkeletonLayout = () => {
+ return (
+
+
+
+ );
+};
+
+export default SkeletonLayout;
diff --git a/Client/src/Components/Fallback/index.jsx b/Client/src/Components/Fallback/index.jsx
index 61840452f..48d9e2198 100644
--- a/Client/src/Components/Fallback/index.jsx
+++ b/Client/src/Components/Fallback/index.jsx
@@ -26,58 +26,69 @@ const Fallback = ({ title, checks, link = "/", isAdmin, vowelStart = false }) =>
const mode = useSelector((state) => state.ui.mode);
return (
-
- {mode === "light" ? (
-
- ) : (
-
- )}
-
-
-
-
+ ) : (
+
+ )}
+
- {vowelStart ? "An" : "A"} {title} is used to:
-
- {checks.map((check, index) => (
-
- ))}
+
+
+
+
+ {vowelStart ? "An" : "A"} {title} is used to:
+
+ {checks.map((check, index) => (
+
+ ))}
+
+ {/* TODO - display a different fallback if user is not an admin*/}
+ {isAdmin && (
+
+ )}
- {/* TODO - display a different fallback if user is not an admin*/}
- {isAdmin && (
-
- )}
-
+
);
};
diff --git a/Client/src/Components/MonitorCountHeader/index.jsx b/Client/src/Components/MonitorCountHeader/index.jsx
new file mode 100644
index 000000000..f7c31a5a0
--- /dev/null
+++ b/Client/src/Components/MonitorCountHeader/index.jsx
@@ -0,0 +1,40 @@
+import { Stack } from "@mui/material";
+import { Heading } from "../Heading";
+import CircularCount from "../CircularCount";
+import PropTypes from "prop-types";
+import { useTheme } from "@emotion/react";
+import SkeletonLayout from "./skeleton";
+
+const MonitorCountHeader = ({
+ shouldRender = true,
+ monitorCount,
+ heading,
+ sx,
+ children,
+}) => {
+ const theme = useTheme();
+ if (!shouldRender) return ;
+
+ return (
+
+ {heading}
+
+ {children}
+
+ );
+};
+
+MonitorCountHeader.propTypes = {
+ shouldRender: PropTypes.bool,
+ monitorCount: PropTypes.number,
+ heading: PropTypes.string,
+ children: PropTypes.node,
+ sx: PropTypes.object,
+};
+
+export default MonitorCountHeader;
diff --git a/Client/src/Components/MonitorCountHeader/skeleton.jsx b/Client/src/Components/MonitorCountHeader/skeleton.jsx
new file mode 100644
index 000000000..9b4971c32
--- /dev/null
+++ b/Client/src/Components/MonitorCountHeader/skeleton.jsx
@@ -0,0 +1,26 @@
+import { Stack, Skeleton } from "@mui/material";
+import { useTheme } from "@emotion/react";
+
+const SkeletonLayout = () => {
+ const theme = useTheme();
+ return (
+
+
+
+
+ );
+};
+
+export default SkeletonLayout;
diff --git a/Client/src/Components/StatBox/index.jsx b/Client/src/Components/StatBox/index.jsx
index b476a1c33..4b1fd2454 100644
--- a/Client/src/Components/StatBox/index.jsx
+++ b/Client/src/Components/StatBox/index.jsx
@@ -1,7 +1,7 @@
import { Box, Typography } from "@mui/material";
import { useTheme } from "@mui/material/styles";
import PropTypes from "prop-types";
-import useUtils from "../../Pages/Uptime/Home/Hooks/useUtils";
+import useUtils from "../../Pages/Uptime/Monitors/Hooks/useUtils";
/**
* StatBox Component
diff --git a/Client/src/Pages/Infrastructure/CreateMonitor/CustomThreshold/index.jsx b/Client/src/Pages/Infrastructure/Create/Components/CustomThreshold/index.jsx
similarity index 96%
rename from Client/src/Pages/Infrastructure/CreateMonitor/CustomThreshold/index.jsx
rename to Client/src/Pages/Infrastructure/Create/Components/CustomThreshold/index.jsx
index 3220582a8..922cb46d8 100644
--- a/Client/src/Pages/Infrastructure/CreateMonitor/CustomThreshold/index.jsx
+++ b/Client/src/Pages/Infrastructure/Create/Components/CustomThreshold/index.jsx
@@ -1,6 +1,6 @@
import { Box, Stack, Typography } from "@mui/material";
-import TextInput from "../../../../Components/Inputs/TextInput";
-import Checkbox from "../../../../Components/Inputs/Checkbox";
+import TextInput from "../../../../../Components/Inputs/TextInput";
+import Checkbox from "../../../../../Components/Inputs/Checkbox";
import { useTheme } from "@emotion/react";
import PropTypes from "prop-types";
diff --git a/Client/src/Pages/Infrastructure/CreateMonitor/index.jsx b/Client/src/Pages/Infrastructure/Create/index.jsx
similarity index 99%
rename from Client/src/Pages/Infrastructure/CreateMonitor/index.jsx
rename to Client/src/Pages/Infrastructure/Create/index.jsx
index c51b56360..464bdeceb 100644
--- a/Client/src/Pages/Infrastructure/CreateMonitor/index.jsx
+++ b/Client/src/Pages/Infrastructure/Create/index.jsx
@@ -22,7 +22,7 @@ import { HttpAdornment } from "../../../Components/Inputs/TextInput/Adornments";
import { createToast } from "../../../Utils/toastUtils";
import Checkbox from "../../../Components/Inputs/Checkbox";
import Select from "../../../Components/Inputs/Select";
-import { CustomThreshold } from "./CustomThreshold";
+import { CustomThreshold } from "./Components/CustomThreshold";
const SELECT_VALUES = [
{ _id: 0.25, name: "15 seconds" },
diff --git a/Client/src/Pages/Infrastructure/Details/index.jsx b/Client/src/Pages/Infrastructure/Details/index.jsx
index 07fbd7c06..9d6b09330 100644
--- a/Client/src/Pages/Infrastructure/Details/index.jsx
+++ b/Client/src/Pages/Infrastructure/Details/index.jsx
@@ -8,7 +8,7 @@ import AreaChart from "../../../Components/Charts/AreaChart";
import { useSelector } from "react-redux";
import { networkService } from "../../../main";
import PulseDot from "../../../Components/Animated/PulseDot";
-import useUtils from "../../Uptime/Home/Hooks/useUtils";
+import useUtils from "../../Uptime/Monitors/Hooks/useUtils";
import { useNavigate } from "react-router-dom";
import Empty from "./empty";
import { logger } from "../../../Utils/Logger";
diff --git a/Client/src/Pages/Infrastructure/index.jsx b/Client/src/Pages/Infrastructure/index.jsx
index 3f295d434..91367ce22 100644
--- a/Client/src/Pages/Infrastructure/index.jsx
+++ b/Client/src/Pages/Infrastructure/index.jsx
@@ -2,7 +2,7 @@ import { useEffect, useState, useCallback } from "react";
import { useNavigate } from "react-router-dom";
import { /* useDispatch, */ useSelector } from "react-redux";
import { useTheme } from "@emotion/react";
-import useUtils from "../Uptime/Home/Hooks/useUtils.jsx";
+import useUtils from "../Uptime/Monitors/Hooks/useUtils.jsx";
import { jwtDecode } from "jwt-decode";
import SkeletonLayout from "./skeleton";
import Fallback from "../../Components/Fallback";
@@ -17,7 +17,7 @@ import Pagination from "../../Components/Table/TablePagination/index.jsx";
// import { getInfrastructureMonitorsByTeamId } from "../../Features/InfrastructureMonitors/infrastructureMonitorsSlice";
import { networkService } from "../../Utils/NetworkService.js";
import CustomGauge from "../../Components/Charts/CustomGauge/index.jsx";
-import Host from "../Uptime/Home/Components/Host";
+import Host from "../Uptime/Monitors/Components/Host/index.jsx";
import { useIsAdmin } from "../../Hooks/useIsAdmin.js";
import { InfrastructureMenu } from "./components/Menu";
@@ -156,12 +156,13 @@ function Infrastructure() {
const uptimePercentage = ((monitor?.uptimePercentage ?? 0) * 100)
.toFixed(2)
.toString();
- const percentageColor = monitor.uptimePercentage < 0.25
- ? theme.palette.error.main
- : monitor.uptimePercentage < 0.5
- ? theme.palette.warning.main
- : theme.palette.success.main;
-
+ const percentageColor =
+ monitor.uptimePercentage < 0.25
+ ? theme.palette.error.main
+ : monitor.uptimePercentage < 0.5
+ ? theme.palette.warning.main
+ : theme.palette.success.main;
+
return {
id: monitor._id,
name: monitor.name,
diff --git a/Client/src/Pages/PageSpeed/Configure/index.jsx b/Client/src/Pages/PageSpeed/Configure/index.jsx
index eee6dfcc9..a76f496cb 100644
--- a/Client/src/Pages/PageSpeed/Configure/index.jsx
+++ b/Client/src/Pages/PageSpeed/Configure/index.jsx
@@ -23,7 +23,7 @@ import PulseDot from "../../../Components/Animated/PulseDot";
import LoadingButton from "@mui/lab/LoadingButton";
import PlayCircleOutlineRoundedIcon from "@mui/icons-material/PlayCircleOutlineRounded";
import SkeletonLayout from "./skeleton";
-import useUtils from "../../Uptime/Home/Hooks/useUtils";
+import useUtils from "../../Uptime/Monitors/Hooks/useUtils";
import "./index.css";
import Dialog from "../../../Components/Dialog";
diff --git a/Client/src/Pages/PageSpeed/CreatePageSpeed/index.css b/Client/src/Pages/PageSpeed/Create/index.css
similarity index 100%
rename from Client/src/Pages/PageSpeed/CreatePageSpeed/index.css
rename to Client/src/Pages/PageSpeed/Create/index.css
diff --git a/Client/src/Pages/PageSpeed/CreatePageSpeed/index.jsx b/Client/src/Pages/PageSpeed/Create/index.jsx
similarity index 100%
rename from Client/src/Pages/PageSpeed/CreatePageSpeed/index.jsx
rename to Client/src/Pages/PageSpeed/Create/index.jsx
diff --git a/Client/src/Pages/PageSpeed/Details/index.jsx b/Client/src/Pages/PageSpeed/Details/index.jsx
index 9192faaa9..4c4bceb1b 100644
--- a/Client/src/Pages/PageSpeed/Details/index.jsx
+++ b/Client/src/Pages/PageSpeed/Details/index.jsx
@@ -19,7 +19,7 @@ import PulseDot from "../../../Components/Animated/PulseDot";
import PagespeedDetailsAreaChart from "./Charts/AreaChart";
import Checkbox from "../../../Components/Inputs/Checkbox";
import PieChart from "./Charts/PieChart";
-import useUtils from "../../Uptime/Home/Hooks/useUtils";
+import useUtils from "../../Uptime/Monitors/Hooks/useUtils";
import "./index.css";
import { useIsAdmin } from "../../../Hooks/useIsAdmin";
import StatBox from "../../../Components/StatBox";
diff --git a/Client/src/Pages/PageSpeed/card.jsx b/Client/src/Pages/PageSpeed/Monitors/Components/Card/index.jsx
similarity index 94%
rename from Client/src/Pages/PageSpeed/card.jsx
rename to Client/src/Pages/PageSpeed/Monitors/Components/Card/index.jsx
index f7f6c4249..42abca268 100644
--- a/Client/src/Pages/PageSpeed/card.jsx
+++ b/Client/src/Pages/PageSpeed/Monitors/Components/Card/index.jsx
@@ -1,15 +1,16 @@
import PropTypes from "prop-types";
-import PageSpeedIcon from "../../assets/icons/page-speed.svg?react";
-import { StatusLabel } from "../../Components/Label";
+// import PageSpeedIcon from "../../../../assets/icons/page-speed.svg?react";
+import PageSpeedIcon from "../../../../../assets/icons/page-speed.svg?react";
+import { StatusLabel } from "../../../../../Components/Label";
import { Box, Grid, Stack, Typography } from "@mui/material";
import { useNavigate } from "react-router";
import { useTheme } from "@emotion/react";
import { Area, AreaChart, CartesianGrid, ResponsiveContainer, Tooltip } from "recharts";
import { useSelector } from "react-redux";
-import { formatDateWithTz, formatDurationSplit } from "../../Utils/timeUtils";
-import useUtils from "../Uptime/Home/Hooks/useUtils";
+import { formatDateWithTz, formatDurationSplit } from "../../../../../Utils/timeUtils";
+import useUtils from "../../../../Uptime/Monitors/Hooks/useUtils";
import { useState } from "react";
-import IconBox from "../../Components/IconBox";
+import IconBox from "../../../../../Components/IconBox";
/**
* CustomToolTip displays a tooltip with formatted date and score information.
* @param {Object} props
diff --git a/Client/src/Pages/PageSpeed/Monitors/Components/MonitorGrid/index.jsx b/Client/src/Pages/PageSpeed/Monitors/Components/MonitorGrid/index.jsx
new file mode 100644
index 000000000..0e61c9c15
--- /dev/null
+++ b/Client/src/Pages/PageSpeed/Monitors/Components/MonitorGrid/index.jsx
@@ -0,0 +1,22 @@
+import { Grid, Grid2 } from "@mui/material";
+import Card from "../Card";
+
+const MonitorGrid = ({ shouldRender, monitors }) => {
+ if (!shouldRender) return null;
+
+ return (
+
+ {monitors?.map((monitor) => (
+
+ ))}
+
+ );
+};
+
+export default MonitorGrid;
diff --git a/Client/src/Pages/PageSpeed/Monitors/Hooks/useMonitorsFetch.jsx b/Client/src/Pages/PageSpeed/Monitors/Hooks/useMonitorsFetch.jsx
new file mode 100644
index 000000000..06d423acc
--- /dev/null
+++ b/Client/src/Pages/PageSpeed/Monitors/Hooks/useMonitorsFetch.jsx
@@ -0,0 +1,43 @@
+import { useEffect, useState } from "react";
+import { networkService } from "../../../../main";
+import { createToast } from "../../../../Utils/toastUtils";
+
+const useMonitorsFetch = ({ authToken, teamId }) => {
+ const [isLoading, setIsLoading] = useState(true);
+ const [monitors, setMonitors] = useState([]);
+ const [summary, setSummary] = useState({});
+
+ useEffect(() => {
+ const fetchMonitors = async () => {
+ try {
+ setIsLoading(true);
+ const res = await networkService.getMonitorsByTeamId({
+ authToken: authToken,
+ teamId: teamId,
+ limit: 10,
+ types: ["pagespeed"],
+ page: null,
+ rowsPerPage: null,
+ filter: null,
+ field: null,
+ order: null,
+ });
+ if (res?.data?.data?.filteredMonitors) {
+ setMonitors(res.data.data.filteredMonitors);
+ setSummary(res.data.data.summary);
+ }
+ } catch (error) {
+ createToast({
+ body: error.message,
+ });
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ fetchMonitors();
+ }, [authToken, teamId]);
+ return { isLoading, monitors, summary };
+};
+
+export default useMonitorsFetch;
diff --git a/Client/src/Pages/PageSpeed/Monitors/index.jsx b/Client/src/Pages/PageSpeed/Monitors/index.jsx
new file mode 100644
index 000000000..228e522ff
--- /dev/null
+++ b/Client/src/Pages/PageSpeed/Monitors/index.jsx
@@ -0,0 +1,66 @@
+// Components
+import Breadcrumbs from "../../../Components/Breadcrumbs";
+import { Stack, Box } from "@mui/material";
+import CreateMonitorHeader from "../../../Components/CreateMonitorHeader";
+import MonitorCountHeader from "../../../Components/MonitorCountHeader";
+import MonitorGrid from "./Components/MonitorGrid";
+import Fallback from "../../../Components/Fallback";
+
+// Utils
+import { useTheme } from "@emotion/react";
+import { useSelector } from "react-redux";
+import { useIsAdmin } from "../../../Hooks/useIsAdmin";
+import useMonitorsFetch from "./Hooks/useMonitorsFetch";
+
+// Constants
+const BREADCRUMBS = [{ name: `pagespeed`, path: "/pagespeed" }];
+
+const PageSpeed = () => {
+ const theme = useTheme();
+ const isAdmin = useIsAdmin();
+ const { user, authToken } = useSelector((state) => state.auth);
+
+ const { isLoading, monitors, summary } = useMonitorsFetch({
+ authToken: authToken,
+ teamId: user.teamId,
+ });
+
+ if (!isLoading && monitors?.length === 0) {
+ return (
+
+ );
+ }
+
+ return (
+
+
+
+
+
+
+ );
+};
+
+export default PageSpeed;
diff --git a/Client/src/Pages/PageSpeed/index.css b/Client/src/Pages/PageSpeed/index.css
deleted file mode 100644
index 3741a6f0f..000000000
--- a/Client/src/Pages/PageSpeed/index.css
+++ /dev/null
@@ -1,8 +0,0 @@
-.page-speed .label {
- padding: 7px;
- height: 24px;
- font-size: var(--env-var-font-size-small);
-}
-.page-speed:not(:has([class*="fallback__"])) button {
- min-height: 34px;
-}
diff --git a/Client/src/Pages/PageSpeed/index.jsx b/Client/src/Pages/PageSpeed/index.jsx
deleted file mode 100644
index c3d37e2c0..000000000
--- a/Client/src/Pages/PageSpeed/index.jsx
+++ /dev/null
@@ -1,153 +0,0 @@
-import { Box, Button, Grid, Stack } from "@mui/material";
-import { useEffect, useState } from "react";
-import { useTheme } from "@emotion/react";
-import { useSelector } from "react-redux";
-import Fallback from "../../Components/Fallback";
-import "./index.css";
-import { useNavigate } from "react-router";
-import PropTypes from "prop-types";
-import Breadcrumbs from "../../Components/Breadcrumbs";
-import SkeletonLayout from "./skeleton";
-import Card from "./card";
-import { networkService } from "../../main";
-import { Heading } from "../../Components/Heading";
-import { useIsAdmin } from "../../Hooks/useIsAdmin";
-const PageSpeed = () => {
- const theme = useTheme();
- const navigate = useNavigate();
- const isAdmin = useIsAdmin();
- const { user, authToken } = useSelector((state) => state.auth);
- const [isLoading, setIsLoading] = useState(true);
- const [monitors, setMonitors] = useState([]);
- const [summary, setSummary] = useState({});
-
- useEffect(() => {
- const fetchMonitors = async () => {
- try {
- setIsLoading(true);
- const res = await networkService.getMonitorsByTeamId({
- authToken: authToken,
- teamId: user.teamId,
- limit: 10,
- types: ["pagespeed"],
- page: null,
- rowsPerPage: null,
- filter: null,
- field: null,
- order: null,
- });
- if (res?.data?.data?.filteredMonitors) {
- setMonitors(res.data.data.filteredMonitors);
- setSummary(res.data.data.summary);
- }
- } catch (error) {
- console.log(error);
- } finally {
- setIsLoading(false);
- }
- };
-
- fetchMonitors();
- }, [authToken, user.teamId]);
-
- // will show skeletons only on initial load
- // since monitor state is being added to redux persist, there's no reason to display skeletons on every render
- let isActuallyLoading = isLoading && monitors?.length === 0;
- return (
- [class*="fallback__"])': {
- position: "relative",
- border: 1,
- borderColor: theme.palette.primary.lowContrast,
- borderRadius: theme.shape.borderRadius,
- borderStyle: "dashed",
- backgroundColor: theme.palette.primary.main,
- overflow: "hidden",
- },
- }}
- >
- {isActuallyLoading ? (
-
- ) : monitors?.length !== 0 ? (
-
-
-
-
- {isAdmin && (
-
- )}
-
-
-
- PageSpeed monitors
- {/* TODO Correct the class current-monitors-counter, there are some unnecessary things there */}
-
- {summary?.totalMonitors ?? 0}
-
-
-
- {monitors?.map((monitor) => (
-
- ))}
-
-
- ) : (
-
- )}
-
- );
-};
-PageSpeed.propTypes = {
- isAdmin: PropTypes.bool,
-};
-
-export default PageSpeed;
diff --git a/Client/src/Pages/PageSpeed/skeleton.jsx b/Client/src/Pages/PageSpeed/skeleton.jsx
deleted file mode 100644
index b6d29dc38..000000000
--- a/Client/src/Pages/PageSpeed/skeleton.jsx
+++ /dev/null
@@ -1,73 +0,0 @@
-import { Box, 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/CreateUptime/index.css b/Client/src/Pages/Uptime/Create/index.css
similarity index 100%
rename from Client/src/Pages/Uptime/CreateUptime/index.css
rename to Client/src/Pages/Uptime/Create/index.css
diff --git a/Client/src/Pages/Uptime/CreateUptime/index.jsx b/Client/src/Pages/Uptime/Create/index.jsx
similarity index 100%
rename from Client/src/Pages/Uptime/CreateUptime/index.jsx
rename to Client/src/Pages/Uptime/Create/index.jsx
diff --git a/Client/src/Pages/Uptime/Details/Components/MonitorHeader/index.jsx b/Client/src/Pages/Uptime/Details/Components/MonitorHeader/index.jsx
index fddf9c3e5..53d4c4dfa 100644
--- a/Client/src/Pages/Uptime/Details/Components/MonitorHeader/index.jsx
+++ b/Client/src/Pages/Uptime/Details/Components/MonitorHeader/index.jsx
@@ -2,7 +2,7 @@ import { Stack, Typography } from "@mui/material";
import PulseDot from "../../../../../Components/Animated/PulseDot";
import Dot from "../../../../../Components/Dot";
import { useTheme } from "@emotion/react";
-import useUtils from "../../../Home/Hooks/useUtils";
+import useUtils from "../../../Monitors/Hooks/useUtils";
import { formatDurationRounded } from "../../../../../Utils/timeUtils";
import ConfigButton from "../ConfigButton";
import SkeletonLayout from "./skeleton";
diff --git a/Client/src/Pages/Uptime/Details/Components/StatusBoxes/index.jsx b/Client/src/Pages/Uptime/Details/Components/StatusBoxes/index.jsx
index 21922537f..3f483889b 100644
--- a/Client/src/Pages/Uptime/Details/Components/StatusBoxes/index.jsx
+++ b/Client/src/Pages/Uptime/Details/Components/StatusBoxes/index.jsx
@@ -4,7 +4,7 @@ import StatBox from "../../../../../Components/StatBox";
import SkeletonLayout from "./skeleton";
// Utils
import { useTheme } from "@mui/material/styles";
-import useUtils from "../../../Home/Hooks/useUtils";
+import useUtils from "../../../Monitors/Hooks/useUtils";
import { getHumanReadableDuration } from "../../../../../Utils/timeUtils";
import PropTypes from "prop-types";
const StatusBoxes = ({ shouldRender, monitor, certificateExpiry }) => {
diff --git a/Client/src/Pages/Uptime/Home/Components/ActionsMenu/index.jsx b/Client/src/Pages/Uptime/Monitors/Components/ActionsMenu/index.jsx
similarity index 100%
rename from Client/src/Pages/Uptime/Home/Components/ActionsMenu/index.jsx
rename to Client/src/Pages/Uptime/Monitors/Components/ActionsMenu/index.jsx
diff --git a/Client/src/Pages/Uptime/Home/Components/Host/index.jsx b/Client/src/Pages/Uptime/Monitors/Components/Host/index.jsx
similarity index 100%
rename from Client/src/Pages/Uptime/Home/Components/Host/index.jsx
rename to Client/src/Pages/Uptime/Monitors/Components/Host/index.jsx
diff --git a/Client/src/Pages/Uptime/Home/Components/LoadingSpinner/index.jsx b/Client/src/Pages/Uptime/Monitors/Components/LoadingSpinner/index.jsx
similarity index 100%
rename from Client/src/Pages/Uptime/Home/Components/LoadingSpinner/index.jsx
rename to Client/src/Pages/Uptime/Monitors/Components/LoadingSpinner/index.jsx
diff --git a/Client/src/Pages/Uptime/Home/Components/SearchComponent/index.jsx b/Client/src/Pages/Uptime/Monitors/Components/SearchComponent/index.jsx
similarity index 100%
rename from Client/src/Pages/Uptime/Home/Components/SearchComponent/index.jsx
rename to Client/src/Pages/Uptime/Monitors/Components/SearchComponent/index.jsx
diff --git a/Client/src/Pages/Uptime/Home/Components/Skeleton/index.jsx b/Client/src/Pages/Uptime/Monitors/Components/Skeleton/index.jsx
similarity index 100%
rename from Client/src/Pages/Uptime/Home/Components/Skeleton/index.jsx
rename to Client/src/Pages/Uptime/Monitors/Components/Skeleton/index.jsx
diff --git a/Client/src/Pages/Uptime/Home/Components/StatusBoxes/index.jsx b/Client/src/Pages/Uptime/Monitors/Components/StatusBoxes/index.jsx
similarity index 94%
rename from Client/src/Pages/Uptime/Home/Components/StatusBoxes/index.jsx
rename to Client/src/Pages/Uptime/Monitors/Components/StatusBoxes/index.jsx
index ac9eca47f..aa7b7ee0d 100644
--- a/Client/src/Pages/Uptime/Home/Components/StatusBoxes/index.jsx
+++ b/Client/src/Pages/Uptime/Monitors/Components/StatusBoxes/index.jsx
@@ -30,7 +30,7 @@ const StatusBoxes = ({ shouldRender, monitorsSummary }) => {
};
StatusBoxes.propTypes = {
- monitorsSummary: PropTypes.object.isRequired,
+ monitorsSummary: PropTypes.object,
};
export default StatusBoxes;
diff --git a/Client/src/Pages/Uptime/Home/Components/StatusBoxes/skeleton.jsx b/Client/src/Pages/Uptime/Monitors/Components/StatusBoxes/skeleton.jsx
similarity index 100%
rename from Client/src/Pages/Uptime/Home/Components/StatusBoxes/skeleton.jsx
rename to Client/src/Pages/Uptime/Monitors/Components/StatusBoxes/skeleton.jsx
diff --git a/Client/src/Pages/Uptime/Home/Components/StatusBoxes/statusBox.jsx b/Client/src/Pages/Uptime/Monitors/Components/StatusBoxes/statusBox.jsx
similarity index 100%
rename from Client/src/Pages/Uptime/Home/Components/StatusBoxes/statusBox.jsx
rename to Client/src/Pages/Uptime/Monitors/Components/StatusBoxes/statusBox.jsx
diff --git a/Client/src/Pages/Uptime/Home/Components/UptimeDataTable/index.jsx b/Client/src/Pages/Uptime/Monitors/Components/UptimeDataTable/index.jsx
similarity index 96%
rename from Client/src/Pages/Uptime/Home/Components/UptimeDataTable/index.jsx
rename to Client/src/Pages/Uptime/Monitors/Components/UptimeDataTable/index.jsx
index 936a6ebed..e96705cc1 100644
--- a/Client/src/Pages/Uptime/Home/Components/UptimeDataTable/index.jsx
+++ b/Client/src/Pages/Uptime/Monitors/Components/UptimeDataTable/index.jsx
@@ -12,7 +12,9 @@ import { useState } from "react";
import SearchComponent from "../SearchComponent";
import CircularCount from "../../../../../Components/CircularCount";
import LoadingSpinner from "../LoadingSpinner";
+import MonitorCountHeader from "../../../../../Components/MonitorCountHeader";
import UptimeDataTableSkeleton from "./skeleton";
+
// Utils
import { useTheme } from "@emotion/react";
import useUtils from "../../Hooks/useUtils";
@@ -214,21 +216,19 @@ const UptimeDataTable = (props) => {
flex={1}
py={theme.spacing(8)}
>
-
- Uptime monitors
-
-
+
{
});
const totalMonitors = monitorsSummary?.totalMonitors ?? 0;
+ if (!isLoading && monitors?.length === 0) {
+ return (
+
+ );
+ }
+
return (
-
+
{
- const AdminCheckedRegister = withAdminCheck(Register);
+ const AdminCheckedRegister = withAdminCheck(AuthRegister);
return (
{
}
+ element={}
/>
{
/>
}
+ element={}
/>
{
/>
}
+ element={}
/>
{
/>
}
+ element={}
/>
{
}
+ element={}
/>
{
}
+ element={}
/>
}
+ element={}
/>
}
+ element={}
/>
}
+ element={}
/>
}
+ element={}
/>