diff --git a/Client/src/Components/GenericFallback/NetworkError.jsx b/Client/src/Components/GenericFallback/NetworkError.jsx
new file mode 100644
index 000000000..b26037a57
--- /dev/null
+++ b/Client/src/Components/GenericFallback/NetworkError.jsx
@@ -0,0 +1,20 @@
+import { Typography } from "@mui/material";
+import { useTheme } from "@emotion/react";
+
+const NetworkError = () => {
+ const theme = useTheme();
+ return (
+ <>
+
+ Network error
+
+ Please check your connection
+ >
+ );
+};
+
+export default NetworkError;
diff --git a/Client/src/Components/NetworkErrorFallback/index.jsx b/Client/src/Components/GenericFallback/index.jsx
similarity index 81%
rename from Client/src/Components/NetworkErrorFallback/index.jsx
rename to Client/src/Components/GenericFallback/index.jsx
index 1039b256b..af9ed2ea4 100644
--- a/Client/src/Components/NetworkErrorFallback/index.jsx
+++ b/Client/src/Components/GenericFallback/index.jsx
@@ -1,5 +1,5 @@
import { useTheme } from "@emotion/react";
-import { Box, Stack, Typography } from "@mui/material";
+import { Box, Stack } from "@mui/material";
import Skeleton from "../../assets/Images/create-placeholder.svg?react";
import SkeletonDark from "../../assets/Images/create-placeholder-dark.svg?react";
import Background from "../../assets/Images/background-grid.svg?react";
@@ -11,13 +11,13 @@ import { useSelector } from "react-redux";
* @returns {JSX.Element} The rendered fallback UI.
*/
-const NetworkErrorFallback = () => {
+const GenericFallback = ({ children }) => {
const theme = useTheme();
const mode = useSelector((state) => state.ui.mode);
return (
{
maxWidth={"300px"}
zIndex={1}
>
-
- Network error
-
- Please check your connection
+ {children}
);
};
-export default NetworkErrorFallback;
+export default GenericFallback;
diff --git a/Client/src/Components/Table/TablePagination/index.jsx b/Client/src/Components/Table/TablePagination/index.jsx
index 014e2405f..8427f4270 100644
--- a/Client/src/Components/Table/TablePagination/index.jsx
+++ b/Client/src/Components/Table/TablePagination/index.jsx
@@ -8,7 +8,7 @@ Pagination.propTypes = {
paginationLabel: PropTypes.string, // Label for the pagination.
itemCount: PropTypes.number, // Total number of items for pagination.
page: PropTypes.number, // Current page index.
- rowsPerPage: PropTypes.number.isRequired, // Number of rows displayed per page.
+ rowsPerPage: PropTypes.number, // Number of rows displayed per page.
handleChangePage: PropTypes.func.isRequired, // Function to handle page changes.
handleChangeRowsPerPage: PropTypes.func, // Function to handle changes in rows per page.
};
diff --git a/Client/src/Pages/Uptime/Monitors/Components/UptimeDataTable/skeleton.jsx b/Client/src/Components/Table/skeleton.jsx
similarity index 56%
rename from Client/src/Pages/Uptime/Monitors/Components/UptimeDataTable/skeleton.jsx
rename to Client/src/Components/Table/skeleton.jsx
index e3c4fa2e2..062d39156 100644
--- a/Client/src/Pages/Uptime/Monitors/Components/UptimeDataTable/skeleton.jsx
+++ b/Client/src/Components/Table/skeleton.jsx
@@ -1,14 +1,14 @@
import { Skeleton } from "@mui/material";
-const UptimeDataTableSkeleton = () => {
+const TableSkeleton = () => {
return (
);
};
-export default UptimeDataTableSkeleton;
+export default TableSkeleton;
diff --git a/Client/src/Pages/Incidents/Components/IncidentTable/index.jsx b/Client/src/Pages/Incidents/Components/IncidentTable/index.jsx
new file mode 100644
index 000000000..ba7a03e05
--- /dev/null
+++ b/Client/src/Pages/Incidents/Components/IncidentTable/index.jsx
@@ -0,0 +1,126 @@
+//Components
+import Table from "../../../../Components/Table";
+import TableSkeleton from "../../../../Components/Table/skeleton";
+import Pagination from "../../../../Components/Table/TablePagination";
+import { StatusLabel } from "../../../../Components/Label";
+import { HttpStatusLabel } from "../../../../Components/HttpStatusLabel";
+import GenericFallback from "../../../../Components/GenericFallback";
+import NetworkError from "../../../../Components/GenericFallback/NetworkError";
+
+//Utils
+import { formatDateWithTz } from "../../../../Utils/timeUtils";
+import { useSelector } from "react-redux";
+import { useState } from "react";
+import useChecksFetch from "../../Hooks/useChecksFetch";
+import PropTypes from "prop-types";
+
+const IncidentTable = ({
+ shouldRender,
+ monitors,
+ selectedMonitor,
+ filter,
+ dateRange,
+}) => {
+ //Redux state
+ const uiTimezone = useSelector((state) => state.ui.timezone);
+
+ //Local state
+ const [page, setPage] = useState(0);
+ const [rowsPerPage, setRowsPerPage] = useState(10);
+ const { isLoading, networkError, checks, checksCount } = useChecksFetch({
+ selectedMonitor,
+ filter,
+ dateRange,
+ page,
+ rowsPerPage,
+ });
+
+ //Handlers
+ const handleChangePage = (_, newPage) => {
+ setPage(newPage);
+ };
+
+ const handleChangeRowsPerPage = (event) => {
+ setRowsPerPage(event.target.value);
+ };
+
+ const headers = [
+ {
+ id: "monitorName",
+ content: "Monitor Name",
+ render: (row) => monitors[row.monitorId]?.name ?? "N/A",
+ },
+ {
+ id: "status",
+ content: "Status",
+ render: (row) => {
+ const status = row.status === true ? "up" : "down";
+ return (
+
+ );
+ },
+ },
+ {
+ id: "dateTime",
+ content: "Date & Time",
+ render: (row) => {
+ const formattedDate = formatDateWithTz(
+ row.createdAt,
+ "YYYY-MM-DD HH:mm:ss A",
+ uiTimezone
+ );
+ return formattedDate;
+ },
+ },
+ {
+ id: "statusCode",
+ content: "Status Code",
+ render: (row) => ,
+ },
+ { id: "message", content: "Message", render: (row) => row.message },
+ ];
+
+ if (!shouldRender || isLoading) return ;
+
+ if (networkError) {
+ return (
+
+
+
+ );
+ }
+
+ if (!isLoading && typeof checksCount === "undefined") {
+ return No incidents recorded;
+ }
+
+ return (
+ <>
+
+
+ >
+ );
+};
+
+IncidentTable.propTypes = {
+ shouldRender: PropTypes.bool,
+ monitors: PropTypes.object,
+ selectedMonitor: PropTypes.string,
+ filter: PropTypes.string,
+ dateRange: PropTypes.string,
+};
+export default IncidentTable;
diff --git a/Client/src/Pages/Incidents/Components/OptionsHeader/index.jsx b/Client/src/Pages/Incidents/Components/OptionsHeader/index.jsx
new file mode 100644
index 000000000..967acfed5
--- /dev/null
+++ b/Client/src/Pages/Incidents/Components/OptionsHeader/index.jsx
@@ -0,0 +1,162 @@
+// Components
+import { Stack, Typography, Button, ButtonGroup } from "@mui/material";
+import Select from "../../../../Components/Inputs/Select";
+import PropTypes from "prop-types";
+
+//Utils
+import { useTheme } from "@emotion/react";
+import SkeletonLayout from "./skeleton";
+
+const OptionsHeader = ({
+ shouldRender,
+ selectedMonitor = 0,
+ setSelectedMonitor,
+ monitors,
+ filter = "all",
+ setFilter,
+ dateRange = "hour",
+ setDateRange,
+}) => {
+ const theme = useTheme();
+ const monitorNames = typeof monitors !== "undefined" ? Object.values(monitors) : [];
+
+ if (!shouldRender) return ;
+
+ return (
+
+
+
+ Incidents for
+
+
+
+
+ Filter by:
+
+
+
+
+
+
+
+
+
+ Show:
+
+
+
+
+
+
+
+
+
+ );
+};
+
+OptionsHeader.propTypes = {
+ shouldRender: PropTypes.bool,
+ selectedMonitor: PropTypes.string,
+ setSelectedMonitor: PropTypes.func,
+ monitors: PropTypes.object,
+ filter: PropTypes.string,
+ setFilter: PropTypes.func,
+ dateRange: PropTypes.string,
+ setDateRange: PropTypes.func,
+};
+
+export default OptionsHeader;
diff --git a/Client/src/Pages/Incidents/Components/OptionsHeader/skeleton.jsx b/Client/src/Pages/Incidents/Components/OptionsHeader/skeleton.jsx
new file mode 100644
index 000000000..8a8990dc4
--- /dev/null
+++ b/Client/src/Pages/Incidents/Components/OptionsHeader/skeleton.jsx
@@ -0,0 +1,11 @@
+import { Stack, Skeleton } from "@mui/material";
+
+const SkeletonLayout = () => {
+ return (
+
+
+
+ );
+};
+
+export default SkeletonLayout;
diff --git a/Client/src/Pages/Incidents/Hooks/useChecksFetch.jsx b/Client/src/Pages/Incidents/Hooks/useChecksFetch.jsx
new file mode 100644
index 000000000..57444ad05
--- /dev/null
+++ b/Client/src/Pages/Incidents/Hooks/useChecksFetch.jsx
@@ -0,0 +1,60 @@
+import { useState, useEffect } from "react";
+import { networkService } from "../../../main";
+import { createToast } from "../../../Utils/toastUtils";
+import { useSelector } from "react-redux";
+const useChecksFetch = ({ selectedMonitor, filter, dateRange, page, rowsPerPage }) => {
+ //Redux
+ const { authToken, user } = useSelector((state) => state.auth);
+
+ //Local
+ const [isLoading, setIsLoading] = useState(false);
+ const [networkError, setNetworkError] = useState(false);
+ const [checks, setChecks] = useState(undefined);
+ const [checksCount, setChecksCount] = useState(undefined);
+
+ useEffect(() => {
+ const fetchChecks = async () => {
+ try {
+ setIsLoading(true);
+ let res;
+
+ if (selectedMonitor === "0") {
+ res = await networkService.getChecksByTeam({
+ authToken: authToken,
+ status: false,
+ teamId: user.teamId,
+ sortOrder: "desc",
+ limit: null,
+ dateRange,
+ filter: filter,
+ page: page,
+ rowsPerPage: rowsPerPage,
+ });
+ } else {
+ res = await networkService.getChecksByMonitor({
+ authToken: authToken,
+ status: false,
+ monitorId: selectedMonitor,
+ sortOrder: "desc",
+ limit: null,
+ dateRange,
+ filter: filter,
+ page,
+ rowsPerPage,
+ });
+ }
+ setChecks(res.data.data.checks);
+ setChecksCount(res.data.data.checksCount);
+ } catch (error) {
+ setNetworkError(true);
+ createToast({ body: error.message });
+ } finally {
+ setIsLoading(false);
+ }
+ };
+ fetchChecks();
+ }, [authToken, user, dateRange, page, rowsPerPage, filter, selectedMonitor]);
+ return { isLoading, networkError, checks, checksCount };
+};
+
+export default useChecksFetch;
diff --git a/Client/src/Pages/Incidents/Hooks/useMonitorsFetch.jsx b/Client/src/Pages/Incidents/Hooks/useMonitorsFetch.jsx
new file mode 100644
index 000000000..0ffd18571
--- /dev/null
+++ b/Client/src/Pages/Incidents/Hooks/useMonitorsFetch.jsx
@@ -0,0 +1,51 @@
+import { useState, useEffect } from "react";
+import { networkService } from "../../../main";
+import { createToast } from "../../../Utils/toastUtils";
+const useMonitorsFetch = ({ authToken, teamId }) => {
+ //Local state
+ const [isLoading, setIsLoading] = useState(false);
+ const [networkError, setNetworkError] = useState(false);
+
+ const [monitors, setMonitors] = useState(undefined);
+
+ useEffect(() => {
+ const fetchMonitors = async () => {
+ try {
+ setIsLoading(true);
+ const res = await networkService.getMonitorsByTeamId({
+ authToken,
+ teamId,
+ limit: null,
+ types: null,
+ status: null,
+ checkOrder: null,
+ normalize: null,
+ page: null,
+ rowsPerPage: null,
+ filter: null,
+ field: null,
+ order: null,
+ });
+ if (res?.data?.data?.monitors?.length > 0) {
+ const monitorLookup = res.data.data.monitors.reduce((acc, monitor) => {
+ acc[monitor._id] = monitor;
+ return acc;
+ }, {});
+ setMonitors(monitorLookup);
+ }
+ } catch (error) {
+ setNetworkError(true);
+ createToast({
+ body: error.message,
+ });
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ fetchMonitors();
+ }, [authToken, teamId]);
+ return { isLoading, monitors, networkError };
+};
+
+export { useMonitorsFetch };
diff --git a/Client/src/Pages/Incidents/IncidentTable/Empty/Empty.jsx b/Client/src/Pages/Incidents/IncidentTable/Empty/Empty.jsx
deleted file mode 100644
index 78b7e8d6d..000000000
--- a/Client/src/Pages/Incidents/IncidentTable/Empty/Empty.jsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import { useTheme } from "@emotion/react";
-import PlaceholderLight from "../../../../assets/Images/data_placeholder.svg?react";
-import PlaceholderDark from "../../../../assets/Images/data_placeholder_dark.svg?react";
-import { Box, Typography } from "@mui/material";
-import PropTypes from "prop-types";
-
-const Empty = ({ styles, mode }) => {
- const theme = useTheme();
- return (
-
-
- {mode === "light" ? : }
-
-
- No incidents recorded yet.
-
-
- );
-};
-
-Empty.propTypes = {
- styles: PropTypes.object,
- mode: PropTypes.string,
-};
-
-export { Empty };
diff --git a/Client/src/Pages/Incidents/IncidentTable/Skeleton/Skeleton.jsx b/Client/src/Pages/Incidents/IncidentTable/Skeleton/Skeleton.jsx
deleted file mode 100644
index a3a23c14c..000000000
--- a/Client/src/Pages/Incidents/IncidentTable/Skeleton/Skeleton.jsx
+++ /dev/null
@@ -1,21 +0,0 @@
-import { Skeleton /* , Stack */ } from "@mui/material";
-const IncidentSkeleton = () => {
- return (
- <>
-
-
- >
- );
-};
-
-export { IncidentSkeleton };
diff --git a/Client/src/Pages/Incidents/IncidentTable/index.jsx b/Client/src/Pages/Incidents/IncidentTable/index.jsx
deleted file mode 100644
index 15d65cadd..000000000
--- a/Client/src/Pages/Incidents/IncidentTable/index.jsx
+++ /dev/null
@@ -1,187 +0,0 @@
-import PropTypes from "prop-types";
-import { Typography, Box } from "@mui/material";
-
-import { useState, useEffect } from "react";
-import { useSelector } from "react-redux";
-import { networkService } from "../../../main";
-import { StatusLabel } from "../../../Components/Label";
-import { logger } from "../../../Utils/Logger";
-import { useTheme } from "@emotion/react";
-import { formatDateWithTz } from "../../../Utils/timeUtils";
-import PlaceholderLight from "../../../assets/Images/data_placeholder.svg?react";
-import PlaceholderDark from "../../../assets/Images/data_placeholder_dark.svg?react";
-import { HttpStatusLabel } from "../../../Components/HttpStatusLabel";
-import { Empty } from "./Empty/Empty";
-import { IncidentSkeleton } from "./Skeleton/Skeleton";
-import DataTable from "../../../Components/Table";
-import Pagination from "../../../Components/Table/TablePagination";
-
-const IncidentTable = ({ monitors, selectedMonitor, filter, dateRange }) => {
- const uiTimezone = useSelector((state) => state.ui.timezone);
-
- const theme = useTheme();
- const { authToken, user } = useSelector((state) => state.auth);
- const mode = useSelector((state) => state.ui.mode);
- const [checks, setChecks] = useState([]);
- const [checksCount, setChecksCount] = useState(0);
- const [page, setPage] = useState(0);
- const [rowsPerPage, setRowsPerPage] = useState(10);
- const [isLoading, setIsLoading] = useState(false);
-
- useEffect(() => {
- const fetchPage = async () => {
- if (!monitors || Object.keys(monitors).length === 0) {
- return;
- }
- try {
- setIsLoading(true);
- let res;
- if (selectedMonitor === "0") {
- res = await networkService.getChecksByTeam({
- authToken: authToken,
- status: false,
- teamId: user.teamId,
- sortOrder: "desc",
- limit: null,
- dateRange,
- filter: filter,
- page: page,
- rowsPerPage: rowsPerPage,
- });
- } else {
- res = await networkService.getChecksByMonitor({
- authToken: authToken,
- status: false,
- monitorId: selectedMonitor,
- sortOrder: "desc",
- limit: null,
- dateRange,
- filter: filter,
- page,
- rowsPerPage,
- });
- }
-
- setChecks(res.data.data.checks);
- setChecksCount(res.data.data.checksCount);
- } catch (error) {
- logger.error(error);
- } finally {
- setIsLoading(false);
- }
- };
- fetchPage();
- }, [authToken, user, monitors, selectedMonitor, filter, page, rowsPerPage, dateRange]);
-
- const handlePageChange = (_, newPage) => {
- setPage(newPage);
- };
-
- const handleChangeRowsPerPage = (event) => {
- setRowsPerPage(event.target.value);
- };
-
- const headers = [
- {
- id: "monitorName",
- content: "Monitor Name",
- render: (row) => monitors[row.monitorId]?.name ?? "N/A",
- },
- {
- id: "status",
- content: "Status",
- render: (row) => {
- const status = row.status === true ? "up" : "down";
- return (
-
- );
- },
- },
- {
- id: "dateTime",
- content: "Date & Time",
- render: (row) => {
- const formattedDate = formatDateWithTz(
- row.createdAt,
- "YYYY-MM-DD HH:mm:ss A",
- uiTimezone
- );
- return formattedDate;
- },
- },
- {
- id: "statusCode",
- content: "Status Code",
- render: (row) => ,
- },
- { id: "message", content: "Message", render: (row) => row.message },
- ];
-
- let sharedStyles = {
- border: 1,
- borderColor: theme.palette.primary.lowContrast,
- borderRadius: theme.shape.borderRadius,
- backgroundColor: theme.palette.primary.main,
- p: theme.spacing(30),
- };
-
- const hasChecks = checks?.length === 0;
- const noIncidentsRecordedYet = hasChecks && selectedMonitor === "0";
- const noIncidentsForThatMonitor = hasChecks && selectedMonitor !== "0";
-
- return (
- <>
- {isLoading ? (
-
- ) : noIncidentsRecordedYet ? (
-
- ) : noIncidentsForThatMonitor ? (
-
-
- {mode === "light" ? : }
-
-
- The monitor you have selected has no recorded incidents yet.
-
-
- ) : (
- <>
-
-
- >
- )}
- >
- );
-};
-
-IncidentTable.propTypes = {
- monitors: PropTypes.object.isRequired,
- selectedMonitor: PropTypes.string.isRequired,
- filter: PropTypes.string.isRequired,
- dateRange: PropTypes.string.isRequired,
-};
-
-export default IncidentTable;
diff --git a/Client/src/Pages/Incidents/index.jsx b/Client/src/Pages/Incidents/index.jsx
index 8305ec672..a5b534ccc 100644
--- a/Client/src/Pages/Incidents/index.jsx
+++ b/Client/src/Pages/Incidents/index.jsx
@@ -1,211 +1,63 @@
-import { useState, useEffect } from "react";
-import { useSelector } from "react-redux";
-import { ButtonGroup, Stack, Typography, Button } from "@mui/material";
-import { useParams } from "react-router-dom";
+// Components
+import { Stack } from "@mui/material";
+import Breadcrumbs from "../../Components/Breadcrumbs";
-import { networkService } from "../../main";
+//Utils
import { useTheme } from "@emotion/react";
-import Select from "../../Components/Inputs/Select";
-import IncidentTable from "./IncidentTable";
-import SkeletonLayout from "./skeleton";
+import { useMonitorsFetch } from "./Hooks/useMonitorsFetch";
+import { useSelector } from "react-redux";
+import OptionsHeader from "./Components/OptionsHeader";
+import { useState } from "react";
+import IncidentTable from "./Components/IncidentTable";
+import GenericFallback from "../../Components/GenericFallback";
+import NetworkError from "../../Components/GenericFallback/NetworkError";
+//Constants
+const BREADCRUMBS = [{ name: `Incidents`, path: "/incidents" }];
const Incidents = () => {
- const theme = useTheme();
- const authState = useSelector((state) => state.auth);
- const { monitorId } = useParams();
+ // Redux state
+ const { authToken, user } = useSelector((state) => state.auth);
- const [monitors, setMonitors] = useState({});
+ // Local state
const [selectedMonitor, setSelectedMonitor] = useState("0");
- const [isLoading, setIsLoading] = useState(true);
+ const [filter, setFilter] = useState(undefined);
+ const [dateRange, setDateRange] = useState(undefined);
+ //Utils
+ const theme = useTheme();
- // TODO do something with these filters
- const [filter, setFilter] = useState("all");
- const [dateRange, setDateRange] = useState("hour");
+ const { monitors, isLoading, networkError } = useMonitorsFetch({
+ authToken,
+ teamId: user.teamId,
+ });
- useEffect(() => {
- const fetchMonitors = async () => {
- try {
- setIsLoading(true);
- const res = await networkService.getMonitorsByTeamId({
- authToken: authState.authToken,
- teamId: authState.user.teamId,
- limit: null,
- types: null,
- status: null,
- checkOrder: null,
- normalize: null,
- page: null,
- rowsPerPage: null,
- filter: null,
- field: null,
- order: null,
- });
- if (res?.data?.data?.monitors?.length > 0) {
- const monitorLookup = res.data.data.monitors.reduce((acc, monitor) => {
- acc[monitor._id] = monitor;
- return acc;
- }, {});
- setMonitors(monitorLookup);
- monitorId !== undefined && setSelectedMonitor(monitorId);
- }
- } catch (error) {
- console.info(error);
- } finally {
- setIsLoading(false);
- }
- };
- fetchMonitors();
- }, [authState, monitorId]);
-
- useEffect(() => {}, [monitors]);
-
- const handleSelect = (event) => {
- setSelectedMonitor(event.target.value);
- };
-
- const isActuallyLoading = isLoading && Object.keys(monitors)?.length === 0;
+ if (networkError) {
+ return (
+
+
+
+ );
+ }
return (
-
- {isActuallyLoading ? (
-
- ) : (
- <>
-
-
-
- Incidents for
-
-
-
-
-
- Filter by:
-
-
-
-
-
-
-
-
-
- Show:
-
-
-
-
-
-
-
-
-
-
- >
- )}
+
+
+
+
);
};
diff --git a/Client/src/Pages/Incidents/skeleton.jsx b/Client/src/Pages/Incidents/skeleton.jsx
deleted file mode 100644
index 51848a108..000000000
--- a/Client/src/Pages/Incidents/skeleton.jsx
+++ /dev/null
@@ -1,50 +0,0 @@
-import { Stack, Skeleton } 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/PageSpeed/Monitors/index.jsx b/Client/src/Pages/PageSpeed/Monitors/index.jsx
index a0c24d48e..470a33f18 100644
--- a/Client/src/Pages/PageSpeed/Monitors/index.jsx
+++ b/Client/src/Pages/PageSpeed/Monitors/index.jsx
@@ -1,6 +1,6 @@
// Components
import Breadcrumbs from "../../../Components/Breadcrumbs";
-import { Stack } from "@mui/material";
+import { Stack, Typography } from "@mui/material";
import CreateMonitorHeader from "../../../Components/CreateMonitorHeader";
import MonitorCountHeader from "../../../Components/MonitorCountHeader";
import MonitorGrid from "./Components/MonitorGrid";
@@ -11,7 +11,7 @@ import { useTheme } from "@emotion/react";
import { useSelector } from "react-redux";
import { useIsAdmin } from "../../../Hooks/useIsAdmin";
import useMonitorsFetch from "./Hooks/useMonitorsFetch";
-import NetworkErrorFallback from "../../../Components/NetworkErrorFallback";
+import GenericFallback from "../../../Components/GenericFallback";
// Constants
const BREADCRUMBS = [{ name: `pagespeed`, path: "/pagespeed" }];
@@ -27,7 +27,18 @@ const PageSpeed = () => {
});
if (networkError === true) {
- return ;
+ return (
+
+
+ Network error
+
+ Please check your connection
+
+ );
}
if (!isLoading && monitors?.length === 0) {
diff --git a/Client/src/Pages/Uptime/Monitors/Components/UptimeDataTable/index.jsx b/Client/src/Pages/Uptime/Monitors/Components/UptimeDataTable/index.jsx
index 8a9fdcbe9..2824f80d6 100644
--- a/Client/src/Pages/Uptime/Monitors/Components/UptimeDataTable/index.jsx
+++ b/Client/src/Pages/Uptime/Monitors/Components/UptimeDataTable/index.jsx
@@ -9,7 +9,7 @@ import BarChart from "../../../../../Components/Charts/BarChart";
import ActionsMenu from "../ActionsMenu";
import LoadingSpinner from "../LoadingSpinner";
-import UptimeDataTableSkeleton from "./skeleton";
+import TableSkeleton from "../../../../../Components/Table/skeleton";
// Utils
import { useTheme } from "@emotion/react";
@@ -175,7 +175,7 @@ const UptimeDataTable = ({
];
if (monitorsAreLoading) {
- return ;
+ return ;
}
return (
diff --git a/Client/src/Pages/Uptime/Monitors/index.jsx b/Client/src/Pages/Uptime/Monitors/index.jsx
index 1356d9e7c..31dcc93be 100644
--- a/Client/src/Pages/Uptime/Monitors/index.jsx
+++ b/Client/src/Pages/Uptime/Monitors/index.jsx
@@ -6,13 +6,13 @@ import UptimeDataTable from "./Components/UptimeDataTable";
import Pagination from "../../../Components/Table/TablePagination";
import CreateMonitorHeader from "../../../Components/CreateMonitorHeader";
import Fallback from "../../../Components/Fallback";
-import NetworkErrorFallback from "../../../Components/NetworkErrorFallback";
+import GenericFallback from "../../../Components/GenericFallback";
import SearchComponent from "./Components/SearchComponent";
import MonitorCountHeader from "../../../Components/MonitorCountHeader";
// MUI Components
-import { Stack, Box, Button } from "@mui/material";
+import { Stack, Box, Button, Typography } from "@mui/material";
// Utils
import { useState, useCallback } from "react";
@@ -109,8 +109,21 @@ const UptimeMonitors = () => {
});
const totalMonitors = monitorsSummary?.totalMonitors ?? 0;
- if (networkError) return ;
-
+ if (networkError) {
+ return (
+
+ {" "}
+
+ Network error
+
+ Please check your connection
+
+ );
+ }
if (!isLoading && !monitorsAreLoading && totalMonitors === 0) {
return (