diff --git a/Client/src/Pages/Uptime/Monitors/Components/ActionsMenu/index.jsx b/Client/src/Components/ActionsMenu/index.jsx
similarity index 94%
rename from Client/src/Pages/Uptime/Monitors/Components/ActionsMenu/index.jsx
rename to Client/src/Components/ActionsMenu/index.jsx
index f0561d6e6..a14e347fe 100644
--- a/Client/src/Pages/Uptime/Monitors/Components/ActionsMenu/index.jsx
+++ b/Client/src/Components/ActionsMenu/index.jsx
@@ -2,16 +2,16 @@ import { useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { useTheme } from "@emotion/react";
import { useNavigate } from "react-router-dom";
-import { createToast } from "../../../../../Utils/toastUtils";
-import { logger } from "../../../../../Utils/Logger";
+import { createToast } from "../../Utils/toastUtils";
+import { logger } from "../../Utils/Logger";
import { IconButton, Menu, MenuItem } from "@mui/material";
import {
deleteUptimeMonitor,
pauseUptimeMonitor,
-} from "../../../../../Features/UptimeMonitors/uptimeMonitorsSlice";
-import Settings from "../../../../../assets/icons/settings-bold.svg?react";
+} from "../../Features/UptimeMonitors/uptimeMonitorsSlice";
+import Settings from "../../assets/icons/settings-bold.svg?react";
import PropTypes from "prop-types";
-import Dialog from "../../../../../Components/Dialog";
+import Dialog from "../../Components/Dialog";
const ActionsMenu = ({
monitor,
diff --git a/Client/src/Pages/Uptime/Monitors/Components/Host/index.jsx b/Client/src/Components/Host/index.jsx
similarity index 96%
rename from Client/src/Pages/Uptime/Monitors/Components/Host/index.jsx
rename to Client/src/Components/Host/index.jsx
index c2f082f3a..051e60331 100644
--- a/Client/src/Pages/Uptime/Monitors/Components/Host/index.jsx
+++ b/Client/src/Components/Host/index.jsx
@@ -1,7 +1,7 @@
import { Stack, Typography } from "@mui/material";
import PropTypes from "prop-types";
import { useTheme } from "@emotion/react";
-import Dot from "../../../../../Components/Dot";
+import Dot from "../Dot";
/**
* Host component.
* This subcomponent receives a params object and displays the host details.
diff --git a/Client/src/Hooks/useMonitorUtils.js b/Client/src/Hooks/useMonitorUtils.js
new file mode 100644
index 000000000..1e235af68
--- /dev/null
+++ b/Client/src/Hooks/useMonitorUtils.js
@@ -0,0 +1,45 @@
+import { useCallback } from "react";
+
+const useMonitorUtils = () => {
+ const getMonitorWithPercentage = useCallback((monitor, theme) => {
+ let uptimePercentage = "";
+ let percentageColor = "";
+
+ if (monitor.uptimePercentage !== undefined) {
+ uptimePercentage =
+ monitor.uptimePercentage === 0
+ ? "0"
+ : (monitor.uptimePercentage * 100).toFixed(2);
+
+ percentageColor =
+ monitor.uptimePercentage < 0.25
+ ? theme.palette.error.main
+ : monitor.uptimePercentage < 0.5
+ ? theme.palette.warning.main
+ : monitor.uptimePercentage < 0.75
+ ? theme.palette.success.main
+ : theme.palette.success.main;
+ }
+
+ return {
+ id: monitor._id,
+ name: monitor.name,
+ url: monitor.url,
+ title: monitor.name,
+ percentage: uptimePercentage,
+ percentageColor,
+ monitor: monitor,
+ };
+ }, []);
+
+ const determineState = useCallback((monitor) => {
+ if (typeof monitor === "undefined") return "pending";
+ if (monitor.isActive === false) return "paused";
+ if (monitor?.status === undefined) return "pending";
+ return monitor?.status == true ? "up" : "down";
+ }, []);
+
+ return { getMonitorWithPercentage, determineState };
+};
+
+export { useMonitorUtils };
diff --git a/Client/src/Pages/DistributedUptime/Details/Components/DistributedUptimeResponseChart/index.jsx b/Client/src/Pages/DistributedUptime/Details/Components/DistributedUptimeResponseChart/index.jsx
index 56d2f9618..7a4c4b210 100644
--- a/Client/src/Pages/DistributedUptime/Details/Components/DistributedUptimeResponseChart/index.jsx
+++ b/Client/src/Pages/DistributedUptime/Details/Components/DistributedUptimeResponseChart/index.jsx
@@ -8,6 +8,8 @@ import {
ResponsiveContainer,
Text,
} from "recharts";
+import ChartBox from "../../../../../Components/Charts/ChartBox";
+import ResponseTimeIcon from "../../../../../assets/icons/response-time-icon.svg?react";
import { Box, Stack, Typography } from "@mui/material";
import { useTheme } from "@emotion/react";
import { useState } from "react";
@@ -22,67 +24,73 @@ const CustomToolTip = ({ active, payload, label }) => {
? payload[0]?.payload?.originalAvgResponseTime
: (payload[0]?.payload?.avgResponseTime ?? 0);
return (
- }
+ header="Response Times"
+ sx={{ padding: 0 }}
>
-
- {formatDateWithTz(label, "ddd, MMMM D, YYYY, h:mm A", uiTimezone)}
-
-
-
-
-
+
+
+
- Response Time
- {" "}
-
- {Math.floor(responseTime)}
- {" "}
- ms
+ Response Time
+ {" "}
+
+ {Math.floor(responseTime)}
+
+ {" "}
+ ms
+
-
-
+
+
+ {/* Display original value */}
- {/* Display original value */}
-
+
);
}
return null;
diff --git a/Client/src/Pages/DistributedUptime/Details/Components/MonitorHeader/index.jsx b/Client/src/Pages/DistributedUptime/Details/Components/MonitorHeader/index.jsx
new file mode 100644
index 000000000..53f36542f
--- /dev/null
+++ b/Client/src/Pages/DistributedUptime/Details/Components/MonitorHeader/index.jsx
@@ -0,0 +1,23 @@
+import { Stack, Typography } from "@mui/material";
+import { useTheme } from "@mui/material/styles";
+import PropTypes from "prop-types";
+
+const MonitorHeader = ({ monitor }) => {
+ const theme = useTheme();
+ return (
+
+
+ {monitor.name}
+
+ Distributed Uptime Monitoring powered by DePIN
+
+
+
+ );
+};
+
+MonitorHeader.propTypes = {
+ monitor: PropTypes.object,
+};
+
+export default MonitorHeader;
diff --git a/Client/src/Pages/DistributedUptime/Details/Components/StatBoxes/index.jsx b/Client/src/Pages/DistributedUptime/Details/Components/StatBoxes/index.jsx
new file mode 100644
index 000000000..a4fd3b03d
--- /dev/null
+++ b/Client/src/Pages/DistributedUptime/Details/Components/StatBoxes/index.jsx
@@ -0,0 +1,62 @@
+// Components
+import { Stack } from "@mui/material";
+import StatBox from "../../../../../Components/StatBox";
+import LastUpdate from "../LastUpdate";
+import UptLogo from "../../../../../assets/icons/upt_logo.png";
+
+// Utils
+import { useTheme } from "@mui/material/styles";
+import PropTypes from "prop-types";
+
+const StatBoxes = ({ monitor, lastUpdateTrigger }) => {
+ const theme = useTheme();
+
+ return (
+
+
+
+
+ }
+ />
+
+ }
+ />
+
+
+
+ );
+};
+
+StatBoxes.propTypes = {
+ monitor: PropTypes.object,
+ lastUpdateTrigger: PropTypes.number,
+};
+
+export default StatBoxes;
diff --git a/Client/src/Pages/DistributedUptime/Details/Hooks/useSubscribeToDetails.jsx b/Client/src/Pages/DistributedUptime/Details/Hooks/useSubscribeToDetails.jsx
new file mode 100644
index 000000000..409e9cf89
--- /dev/null
+++ b/Client/src/Pages/DistributedUptime/Details/Hooks/useSubscribeToDetails.jsx
@@ -0,0 +1,119 @@
+import { useState, useEffect, useRef } from "react";
+import { networkService } from "../../../../main";
+import { useSelector } from "react-redux";
+
+const getRandomDevice = () => {
+ const manufacturers = {
+ Apple: ["iPhone 15 Pro Max", "iPhone 15", "iPhone 14 Pro", "iPhone 14", "iPhone 13"],
+ Samsung: [
+ "Galaxy S23 Ultra",
+ "Galaxy S23+",
+ "Galaxy S23",
+ "Galaxy Z Fold5",
+ "Galaxy Z Flip5",
+ ],
+ Google: ["Pixel 8 Pro", "Pixel 8", "Pixel 7a", "Pixel 7", "Pixel 6a"],
+ OnePlus: [
+ "OnePlus 11",
+ "OnePlus 10T",
+ "OnePlus Nord 3",
+ "OnePlus 10 Pro",
+ "OnePlus Nord 2T",
+ ],
+ Xiaomi: ["13 Pro", "13", "Redmi Note 12", "POCO F5", "Redmi 12"],
+ Huawei: ["P60 Pro", "Mate X3", "Nova 11", "P50 Pro", "Mate 50"],
+ Sony: ["Xperia 1 V", "Xperia 5 V", "Xperia 10 V", "Xperia Pro-I", "Xperia 1 IV"],
+ Motorola: ["Edge 40 Pro", "Edge 40", "G84", "G54", "Razr 40 Ultra"],
+ ASUS: [
+ "ROG Phone 7",
+ "Zenfone 10",
+ "ROG Phone 6",
+ "Zenfone 9",
+ "ROG Phone 7 Ultimate",
+ ],
+ };
+
+ const manufacturerNames = Object.keys(manufacturers);
+ const randomManufacturer =
+ manufacturerNames[Math.floor(Math.random() * manufacturerNames.length)];
+
+ const models = manufacturers[randomManufacturer];
+ const randomModel = models[Math.floor(Math.random() * models.length)];
+
+ return {
+ manufacturer: randomManufacturer,
+ model: randomModel,
+ };
+};
+const useSubscribeToDetails = ({ monitorId, dateRange }) => {
+ const [isLoading, setIsLoading] = useState(true);
+ const [connectionStatus, setConnectionStatus] = useState(undefined);
+ const [retryCount, setRetryCount] = useState(0);
+ const [networkError, setNetworkError] = useState(false);
+ const [monitor, setMonitor] = useState(undefined);
+ const [lastUpdateTrigger, setLastUpdateTrigger] = useState(0);
+ const [devices, setDevices] = useState(Array.from({ length: 5 }, getRandomDevice));
+ const authToken = useSelector((state) => state.auth.token);
+
+ const prevDateRangeRef = useRef(dateRange);
+
+ useEffect(() => {
+ try {
+ const cleanup = networkService.subscribeToDistributedUptimeDetails({
+ authToken,
+ monitorId,
+ dateRange: dateRange,
+ normalize: true,
+ onUpdate: (data) => {
+ if (networkError === true) {
+ setNetworkError(false);
+ }
+ setLastUpdateTrigger(Date.now());
+ const latestChecksWithDevice = data?.monitor?.latestChecks.map((check, idx) => {
+ check.device = devices[idx];
+ return check;
+ });
+ const monitorWithDevice = {
+ ...data.monitor,
+ latestChecks: latestChecksWithDevice,
+ };
+ setMonitor(monitorWithDevice);
+ },
+ onOpen: () => {
+ setConnectionStatus("up");
+ setRetryCount(0); // Reset retry count on successful connection
+ },
+ onError: () => {
+ setNetworkError(true);
+ setConnectionStatus("down");
+ },
+ });
+ return cleanup;
+ } catch (error) {
+ setNetworkError(true);
+ } finally {
+ setIsLoading(false);
+ }
+ }, [
+ authToken,
+ dateRange,
+ monitorId,
+ retryCount,
+ setConnectionStatus,
+ networkError,
+ devices,
+ ]);
+
+ useEffect(() => {
+ const hasDateRangeChanged = prevDateRangeRef.current !== dateRange;
+ prevDateRangeRef.current = dateRange; // Update the ref to the current dateRange
+
+ if (!hasDateRangeChanged) {
+ setDevices(Array.from({ length: 5 }, getRandomDevice));
+ }
+ }, [dateRange]);
+
+ return [isLoading, networkError, connectionStatus, monitor, lastUpdateTrigger];
+};
+
+export default useSubscribeToDetails;
diff --git a/Client/src/Pages/DistributedUptime/Details/index.jsx b/Client/src/Pages/DistributedUptime/Details/index.jsx
index 6c921063f..ab39ec2ec 100644
--- a/Client/src/Pages/DistributedUptime/Details/index.jsx
+++ b/Client/src/Pages/DistributedUptime/Details/index.jsx
@@ -1,324 +1,102 @@
//Components
import DistributedUptimeMap from "./Components/DistributedUptimeMap";
import Breadcrumbs from "../../../Components/Breadcrumbs";
-import { Stack, Typography, Box, Button, ButtonGroup } from "@mui/material";
-import ChartBox from "../../../Components/Charts/ChartBox";
-import StatBox from "../../../Components/StatBox";
-import ResponseTimeIcon from "../../../assets/icons/response-time-icon.svg?react";
+import { Stack, Typography } from "@mui/material";
import DeviceTicker from "./Components/DeviceTicker";
import DistributedUptimeResponseChart from "./Components/DistributedUptimeResponseChart";
-import UptLogo from "../../../assets/icons/upt_logo.png";
-import LastUpdate from "./Components/LastUpdate";
import NextExpectedCheck from "./Components/NextExpectedCheck";
import Footer from "./Components/Footer";
+import StatBoxes from "./Components/StatBoxes";
+import MonitorHeader from "./Components/MonitorHeader";
+import MonitorTimeFrameHeader from "../../../Components/MonitorTimeFrameHeader";
+import GenericFallback from "../../../Components/GenericFallback";
+
//Utils
-import { networkService } from "../../../main";
-import { useSelector } from "react-redux";
import { useTheme } from "@mui/material/styles";
-import { useEffect, useState, useCallback, useRef } from "react";
+import { useState } from "react";
import { useParams } from "react-router-dom";
-
-//Constants
-const BASE_BOX_PADDING_VERTICAL = 8;
-const BASE_BOX_PADDING_HORIZONTAL = 8;
-const MAX_RETRIES = 10;
-const RETRY_DELAY = 5000;
-
-function getRandomDevice() {
- const manufacturers = {
- Apple: ["iPhone 15 Pro Max", "iPhone 15", "iPhone 14 Pro", "iPhone 14", "iPhone 13"],
- Samsung: [
- "Galaxy S23 Ultra",
- "Galaxy S23+",
- "Galaxy S23",
- "Galaxy Z Fold5",
- "Galaxy Z Flip5",
- ],
- Google: ["Pixel 8 Pro", "Pixel 8", "Pixel 7a", "Pixel 7", "Pixel 6a"],
- OnePlus: [
- "OnePlus 11",
- "OnePlus 10T",
- "OnePlus Nord 3",
- "OnePlus 10 Pro",
- "OnePlus Nord 2T",
- ],
- Xiaomi: ["13 Pro", "13", "Redmi Note 12", "POCO F5", "Redmi 12"],
- Huawei: ["P60 Pro", "Mate X3", "Nova 11", "P50 Pro", "Mate 50"],
- Sony: ["Xperia 1 V", "Xperia 5 V", "Xperia 10 V", "Xperia Pro-I", "Xperia 1 IV"],
- Motorola: ["Edge 40 Pro", "Edge 40", "G84", "G54", "Razr 40 Ultra"],
- ASUS: [
- "ROG Phone 7",
- "Zenfone 10",
- "ROG Phone 6",
- "Zenfone 9",
- "ROG Phone 7 Ultimate",
- ],
- };
-
- const manufacturerNames = Object.keys(manufacturers);
- const randomManufacturer =
- manufacturerNames[Math.floor(Math.random() * manufacturerNames.length)];
-
- const models = manufacturers[randomManufacturer];
- const randomModel = models[Math.floor(Math.random() * models.length)];
-
- return {
- manufacturer: randomManufacturer,
- model: randomModel,
- };
-}
-
-// export const StatBox = ({ heading, value, img, altTxt }) => {
-// const theme = useTheme();
-// return (
-//
-// {img && (
-//
-// )}
-//
-// {heading}
-// {value}
-//
-//
-// );
-// };
+import useSubscribeToDetails from "./Hooks/useSubscribeToDetails";
const DistributedUptimeDetails = () => {
- // Redux State
- const { authToken } = useSelector((state) => state.auth);
- const { mode } = useSelector((state) => state.ui);
+ const { monitorId } = useParams();
// Local State
- // const [hoveredUptimeData, setHoveredUptimeData] = useState(null);
- // const [hoveredIncidentsData, setHoveredIncidentsData] = useState(null);
- const [retryCount, setRetryCount] = useState(0);
- const [connectionStatus, setConnectionStatus] = useState("down");
- const [lastUpdateTrigger, setLastUpdateTrigger] = useState(Date.now());
const [dateRange, setDateRange] = useState("day");
- const [monitor, setMonitor] = useState(null);
- const [devices, setDevices] = useState([]);
-
- // Refs
- const prevDateRangeRef = useRef(dateRange);
// Utils
const theme = useTheme();
- const { monitorId } = useParams();
-
+ const [isLoading, networkError, connectionStatus, monitor, lastUpdateTrigger] =
+ useSubscribeToDetails({ monitorId, dateRange });
// Constants
const BREADCRUMBS = [
{ name: "Distributed Uptime", path: "/distributed-uptime" },
{ name: "Details", path: `/distributed-uptime/${monitorId}` },
];
- useEffect(() => {
- const hasDateRangeChanged = prevDateRangeRef.current !== dateRange;
- prevDateRangeRef.current = dateRange; // Update the ref to the current dateRange
+ if (networkError) {
+ return (
+
+
+ Network error
+
+ Please check your connection
+
+ );
+ }
- if (!hasDateRangeChanged) {
- setDevices(Array.from({ length: 5 }, getRandomDevice));
- }
- }, [dateRange]);
-
- const connectToService = useCallback(() => {
- return networkService.subscribeToDistributedUptimeDetails({
- authToken,
- monitorId,
- dateRange: dateRange,
- normalize: true,
- onUpdate: (data) => {
- setLastUpdateTrigger(Date.now());
- const latestChecksWithDevice = data?.monitor?.latestChecks.map((check, idx) => {
- check.device = devices[idx];
- return check;
- });
- const monitorWithDevice = {
- ...data.monitor,
- latestChecks: latestChecksWithDevice,
- };
- setMonitor(monitorWithDevice);
- },
- onOpen: () => {
- setConnectionStatus("up");
- setRetryCount(0); // Reset retry count on successful connection
- },
- onError: () => {
- setConnectionStatus("down");
- console.log("Error, attempting reconnect...");
-
- if (retryCount < MAX_RETRIES) {
- setTimeout(() => {
- setRetryCount((prev) => prev + 1);
- connectToService();
- }, RETRY_DELAY);
- } else {
- console.log("Max retries reached");
- }
- },
- });
- }, [authToken, monitorId, dateRange, retryCount, devices]);
-
- useEffect(() => {
- const devices = Array.from({ length: 5 }, getRandomDevice);
- const cleanup = connectToService(devices);
- return cleanup;
- }, [connectToService]);
+ if (typeof monitor === "undefined" || monitor.totalChecks === 0) {
+ return (
+
+
+
+ There is no check history for this monitor yet.
+
+
+ );
+ }
return (
- monitor && (
+
+
+
+
+
+
+
-
- {monitor?.url !== "https://jup.ag/" &&
- monitor?.url !== "https://explorer.solana.com/" && (
-
-
- {monitor.name}
-
-
- )}
-
-
- Distributed Uptime Monitoring powered by DePIN
-
-
-
-
-
-
- }
- />
-
- }
- />
-
-
-
-
-
-
-
-
- Showing statistics for past{" "}
- {dateRange === "day"
- ? "24 hours"
- : dateRange === "week"
- ? "7 days"
- : "30 days"}
- .
-
-
-
-
-
-
-
- }
- header="Response Times"
- sx={{ padding: 0 }}
- >
-
-
-
-
-
-
-
+
+
- )
+
+
);
};
diff --git a/Client/src/Pages/DistributedUptime/Monitors/Components/MonitorTable/index.jsx b/Client/src/Pages/DistributedUptime/Monitors/Components/MonitorTable/index.jsx
new file mode 100644
index 000000000..c0aa5b57c
--- /dev/null
+++ b/Client/src/Pages/DistributedUptime/Monitors/Components/MonitorTable/index.jsx
@@ -0,0 +1,94 @@
+// Components
+import DataTable from "../../../../../Components/Table";
+import BarChart from "../../../../../Components/Charts/BarChart";
+import { Box } from "@mui/material";
+import { StatusLabel } from "../../../../../Components/Label";
+import Host from "../../../../../Components/Host";
+
+// Utils
+import { useTheme } from "@mui/material/styles";
+import { useNavigate } from "react-router-dom";
+import { useMonitorUtils } from "../../../../../Hooks/useMonitorUtils";
+import PropTypes from "prop-types";
+
+// Constants
+const TYPE_MAP = {
+ distributed_http: "Distributed HTTP",
+};
+
+const MonitorTable = ({ isLoading, monitors }) => {
+ const theme = useTheme();
+ const navigate = useNavigate();
+ const { determineState } = useMonitorUtils();
+
+ const headers = [
+ {
+ id: "name",
+ content: Host,
+ render: (row) => (
+
+ ),
+ },
+ {
+ id: "status",
+ content: Status,
+ render: (row) => {
+ const status = determineState(row?.monitor);
+ return (
+
+ );
+ },
+ },
+ {
+ id: "responseTime",
+ content: "Response Time",
+ render: (row) => ,
+ },
+ {
+ id: "type",
+ content: "Type",
+ render: (row) => {TYPE_MAP[row.monitor.type]},
+ },
+ {
+ id: "actions",
+ content: "Actions",
+ render: (row) => {"TODO"},
+ },
+ ];
+
+ return (
+ {
+ navigate(`/distributed-uptime/${row.id}`);
+ },
+ }}
+ />
+ );
+};
+
+MonitorTable.propTypes = {
+ isLoading: PropTypes.bool,
+ monitors: PropTypes.array,
+};
+
+export default MonitorTable;
diff --git a/Client/src/Pages/DistributedUptime/Monitors/Hooks/useSubscribeToMonitors.jsx b/Client/src/Pages/DistributedUptime/Monitors/Hooks/useSubscribeToMonitors.jsx
new file mode 100644
index 000000000..1a1db1453
--- /dev/null
+++ b/Client/src/Pages/DistributedUptime/Monitors/Hooks/useSubscribeToMonitors.jsx
@@ -0,0 +1,58 @@
+import { useEffect, useState } from "react";
+import { networkService } from "../../../../main";
+import { useSelector } from "react-redux";
+import { useTheme } from "@emotion/react";
+import { useMonitorUtils } from "../../../../Hooks/useMonitorUtils";
+import { createToast } from "../../../../Utils/toastUtils";
+
+const useSubscribeToMonitors = () => {
+ // Redux
+ const { authToken, user } = useSelector((state) => state.auth);
+
+ // Local state
+ const [isLoading, setIsLoading] = useState(true);
+ const [networkError, setNetworkError] = useState(false);
+ const [monitors, setMonitors] = useState(undefined);
+ const [monitorsSummary, setMonitorsSummary] = useState(undefined);
+ const [filteredMonitors, setFilteredMonitors] = useState(undefined);
+
+ const theme = useTheme();
+ const { getMonitorWithPercentage } = useMonitorUtils();
+
+ useEffect(() => {
+ try {
+ const cleanup = networkService.subscribeToDistributedUptimeMonitors({
+ authToken: authToken,
+ teamId: user.teamId,
+ limit: 25,
+ types: ["distributed_http"],
+ page: 0,
+ rowsPerPage: 10,
+ filter: null,
+ field: null,
+ order: null,
+ onUpdate: (data) => {
+ const res = data.monitors;
+ const { monitors, filteredMonitors, summary } = res;
+ const mappedMonitors = filteredMonitors.map((monitor) =>
+ getMonitorWithPercentage(monitor, theme)
+ );
+ setMonitors(monitors);
+ setMonitorsSummary(summary);
+ setFilteredMonitors(mappedMonitors);
+ },
+ });
+
+ return cleanup;
+ } catch (error) {
+ createToast({
+ body: error.message,
+ });
+ setNetworkError(true);
+ } finally {
+ setIsLoading(false);
+ }
+ }, [authToken, user, getMonitorWithPercentage, theme]);
+ return [isLoading, networkError, monitors, monitorsSummary, filteredMonitors];
+};
+export { useSubscribeToMonitors };
diff --git a/Client/src/Pages/DistributedUptime/Monitors/index.jsx b/Client/src/Pages/DistributedUptime/Monitors/index.jsx
index 0d1288aa9..a3466b845 100644
--- a/Client/src/Pages/DistributedUptime/Monitors/index.jsx
+++ b/Client/src/Pages/DistributedUptime/Monitors/index.jsx
@@ -1,185 +1,69 @@
// Components
-import { Stack, Box, Button } from "@mui/material";
-import DataTable from "../../../Components/Table";
+import { Stack, Typography } from "@mui/material";
import Breadcrumbs from "../../../Components/Breadcrumbs";
-import Host from "../../Uptime/Monitors/Components/Host";
-import BarChart from "../../../Components/Charts/BarChart";
-import ActionsMenu from "../../Uptime/Monitors/Components/ActionsMenu";
-import { StatusLabel } from "../../../Components/Label";
-// Utils
-import { networkService } from "../../../main";
-import { useTheme } from "@mui/material/styles";
-import { useNavigate } from "react-router-dom";
-import useUtils from "../../Uptime/Monitors/Hooks/useUtils";
-import { useEffect, useState } from "react";
-import { useSelector } from "react-redux";
+import CreateMonitorHeader from "../../../Components/MonitorCreateHeader";
+import MonitorTable from "./Components/MonitorTable";
+import Fallback from "../../../Components/Fallback";
+import GenericFallback from "../../../Components/GenericFallback";
+// Utils
+import { useTheme } from "@mui/material/styles";
+import { useIsAdmin } from "../../../Hooks/useIsAdmin";
+import { useSubscribeToMonitors } from "./Hooks/useSubscribeToMonitors";
// Constants
const BREADCRUMBS = [{ name: `Distributed Uptime`, path: "/distributed-uptime" }];
-const TYPE_MAP = {
- distributed_http: "Distributed HTTP",
-};
const DistributedUptimeMonitors = () => {
- // Redux state
- const { authToken, user } = useSelector((state) => state.auth);
// Local state
- const [monitors, setMonitors] = useState([]);
- const [filteredMonitors, setFilteredMonitors] = useState([]);
- const [monitorsSummary, setMonitorsSummary] = useState({});
// Utils
-
- const { determineState } = useUtils();
const theme = useTheme();
- const navigate = useNavigate();
- const headers = [
- {
- id: "name",
- content: Host,
- render: (row) => (
-
- ),
- },
- {
- id: "status",
- content: Status,
- render: (row) => {
- const status = determineState(row?.monitor);
- return (
-
- );
- },
- },
- {
- id: "responseTime",
- content: "Response Time",
- render: (row) => ,
- },
- {
- id: "type",
- content: "Type",
- render: (row) => {TYPE_MAP[row.monitor.type]},
- },
- {
- id: "actions",
- content: "Actions",
- render: (row) => (
-
- ),
- },
- ];
+ const isAdmin = useIsAdmin();
+ const [isLoading, networkError, monitors, monitorsSummary, filteredMonitors] =
+ useSubscribeToMonitors();
- const getMonitorWithPercentage = (monitor, theme) => {
- let uptimePercentage = "";
- let percentageColor = "";
-
- if (monitor.uptimePercentage !== undefined) {
- uptimePercentage =
- monitor.uptimePercentage === 0
- ? "0"
- : (monitor.uptimePercentage * 100).toFixed(2);
-
- percentageColor =
- monitor.uptimePercentage < 0.25
- ? theme.palette.error.main
- : monitor.uptimePercentage < 0.5
- ? theme.palette.warning.main
- : monitor.uptimePercentage < 0.75
- ? theme.palette.success.main
- : theme.palette.success.main;
- }
-
- return {
- id: monitor._id,
- name: monitor.name,
- url: monitor.url,
- title: monitor.name,
- percentage: uptimePercentage,
- percentageColor,
- monitor: monitor,
- };
- };
-
- useEffect(() => {
- const cleanup = networkService.subscribeToDistributedUptimeMonitors({
- authToken: authToken,
- teamId: user.teamId,
- limit: 25,
- types: ["distributed_http"],
- page: 0,
- rowsPerPage: 10,
- filter: null,
- field: null,
- order: null,
- onUpdate: (data) => {
- const res = data.monitors;
- const { monitors, filteredMonitors, summary } = res;
- const mappedMonitors = filteredMonitors.map((monitor) =>
- getMonitorWithPercentage(monitor, theme)
- );
- setMonitors(monitors);
- setFilteredMonitors(mappedMonitors);
- setMonitorsSummary(summary);
- },
- });
-
- return cleanup;
- }, [user.teamId, authToken, theme]);
-
- return (
-
-
-
-
-
- {monitors.length > 0 && (
- {
- navigate(`/distributed-uptime/${row.id}`);
- },
- }}
- />
- )}
+ Network error
+
+ Please check your connection
+
+ );
+ }
+
+ if (typeof monitorsSummary !== "undefined" && monitorsSummary.totalMonitors === 0) {
+ return (
+
+ );
+ }
+ return (
+
+
+
+
);
};
diff --git a/Client/src/Pages/Infrastructure/Monitors/Components/MonitorsTable/index.jsx b/Client/src/Pages/Infrastructure/Monitors/Components/MonitorsTable/index.jsx
index f44b844a7..3f1832889 100644
--- a/Client/src/Pages/Infrastructure/Monitors/Components/MonitorsTable/index.jsx
+++ b/Client/src/Pages/Infrastructure/Monitors/Components/MonitorsTable/index.jsx
@@ -1,6 +1,6 @@
// Components
import DataTable from "../../../../../Components/Table";
-import Host from "../../../../Uptime/Monitors/Components/Host";
+import Host from "../../../../../Components/Host";
import { StatusLabel } from "../../../../../Components/Label";
import { Stack } from "@mui/material";
import { InfrastructureMenu } from "../MonitorsTableMenu";
@@ -12,6 +12,7 @@ import CustomGauge from "../../../../../Components/Charts/CustomGauge";
import { useTheme } from "@emotion/react";
import useUtils from "../../../../Uptime/Monitors/Hooks/useUtils";
import { useNavigate } from "react-router-dom";
+import PropTypes from "prop-types";
const MonitorsTable = ({ shouldRender, monitors, isAdmin, handleActionMenuDelete }) => {
// Utils
@@ -131,4 +132,11 @@ const MonitorsTable = ({ shouldRender, monitors, isAdmin, handleActionMenuDelete
);
};
+MonitorsTable.propTypes = {
+ shouldRender: PropTypes.bool,
+ monitors: PropTypes.array,
+ isAdmin: PropTypes.bool,
+ handleActionMenuDelete: PropTypes.func,
+};
+
export default MonitorsTable;
diff --git a/Client/src/Pages/StatusPage/Status/Components/MonitorsList/index.jsx b/Client/src/Pages/StatusPage/Status/Components/MonitorsList/index.jsx
index 65a4a182a..ff7a18f97 100644
--- a/Client/src/Pages/StatusPage/Status/Components/MonitorsList/index.jsx
+++ b/Client/src/Pages/StatusPage/Status/Components/MonitorsList/index.jsx
@@ -1,6 +1,6 @@
// Components
import { Stack, Box } from "@mui/material";
-import Host from "../../../../Uptime/Monitors/Components/Host";
+import Host from "../../../../../Components/Host";
import StatusPageBarChart from "../../../../../Components/Charts/StatusPageBarChart";
import { StatusLabel } from "../../../../../Components/Label";
diff --git a/Client/src/Pages/StatusPage/Status/Hooks/useStatusPageFetch.jsx b/Client/src/Pages/StatusPage/Status/Hooks/useStatusPageFetch.jsx
index 815b50a52..d2b2eae2a 100644
--- a/Client/src/Pages/StatusPage/Status/Hooks/useStatusPageFetch.jsx
+++ b/Client/src/Pages/StatusPage/Status/Hooks/useStatusPageFetch.jsx
@@ -3,30 +3,7 @@ import { networkService } from "../../../../main";
import { useSelector } from "react-redux";
import { createToast } from "../../../../Utils/toastUtils";
import { useTheme } from "@emotion/react";
-const getMonitorWithPercentage = (monitor, theme) => {
- let uptimePercentage = "";
- let percentageColor = "";
-
- if (monitor.uptimePercentage !== undefined) {
- uptimePercentage =
- monitor.uptimePercentage === 0 ? "0" : (monitor.uptimePercentage * 100).toFixed(2);
-
- percentageColor =
- monitor.uptimePercentage < 0.25
- ? theme.palette.error.main
- : monitor.uptimePercentage < 0.5
- ? theme.palette.warning.main
- : monitor.uptimePercentage < 0.75
- ? theme.palette.success.main
- : theme.palette.success.main;
- }
-
- return {
- ...monitor,
- percentage: uptimePercentage,
- percentageColor,
- };
-};
+import { useMonitorUtils } from "../../../../Hooks/useMonitorUtils";
const useStatusPageFetch = (isCreate = false) => {
const [isLoading, setIsLoading] = useState(true);
@@ -35,7 +12,7 @@ const useStatusPageFetch = (isCreate = false) => {
const [monitors, setMonitors] = useState(undefined);
const { authToken } = useSelector((state) => state.auth);
const theme = useTheme();
-
+ const { getMonitorWithPercentage } = useMonitorUtils();
const fetchStatusPage = useCallback(async () => {
try {
const response = await networkService.getStatusPage({ authToken });
diff --git a/Client/src/Pages/Uptime/Monitors/Components/UptimeDataTable/index.jsx b/Client/src/Pages/Uptime/Monitors/Components/UptimeDataTable/index.jsx
index 2824f80d6..323365031 100644
--- a/Client/src/Pages/Uptime/Monitors/Components/UptimeDataTable/index.jsx
+++ b/Client/src/Pages/Uptime/Monitors/Components/UptimeDataTable/index.jsx
@@ -3,10 +3,10 @@ import { Box, Stack } from "@mui/material";
import DataTable from "../../../../../Components/Table";
import ArrowDownwardRoundedIcon from "@mui/icons-material/ArrowDownwardRounded";
import ArrowUpwardRoundedIcon from "@mui/icons-material/ArrowUpwardRounded";
-import Host from "../Host";
+import Host from "../../../../../Components/Host";
import { StatusLabel } from "../../../../../Components/Label";
import BarChart from "../../../../../Components/Charts/BarChart";
-import ActionsMenu from "../ActionsMenu";
+import ActionsMenu from "../../../../../Components/ActionsMenu";
import LoadingSpinner from "../LoadingSpinner";
import TableSkeleton from "../../../../../Components/Table/skeleton";
diff --git a/Client/src/Pages/Uptime/Monitors/Hooks/useMonitorsFetch.jsx b/Client/src/Pages/Uptime/Monitors/Hooks/useMonitorsFetch.jsx
index ec768e9f8..b65de3525 100644
--- a/Client/src/Pages/Uptime/Monitors/Hooks/useMonitorsFetch.jsx
+++ b/Client/src/Pages/Uptime/Monitors/Hooks/useMonitorsFetch.jsx
@@ -2,34 +2,7 @@ import { useEffect, useState } from "react";
import { networkService } from "../../../../main";
import { createToast } from "../../../../Utils/toastUtils";
import { useTheme } from "@emotion/react";
-const getMonitorWithPercentage = (monitor, theme) => {
- let uptimePercentage = "";
- let percentageColor = "";
-
- if (monitor.uptimePercentage !== undefined) {
- uptimePercentage =
- monitor.uptimePercentage === 0 ? "0" : (monitor.uptimePercentage * 100).toFixed(2);
-
- percentageColor =
- monitor.uptimePercentage < 0.25
- ? theme.palette.error.main
- : monitor.uptimePercentage < 0.5
- ? theme.palette.warning.main
- : monitor.uptimePercentage < 0.75
- ? theme.palette.success.main
- : theme.palette.success.main;
- }
-
- return {
- id: monitor._id,
- name: monitor.name,
- url: monitor.url,
- title: monitor.name,
- percentage: uptimePercentage,
- percentageColor,
- monitor: monitor,
- };
-};
+import { useMonitorUtils } from "../../../../Hooks/useMonitorUtils";
export const useMonitorFetch = ({
authToken,
@@ -49,7 +22,7 @@ export const useMonitorFetch = ({
const [networkError, setNetworkError] = useState(false);
const theme = useTheme();
-
+ const { getMonitorWithPercentage } = useMonitorUtils();
useEffect(() => {
const fetchMonitors = async () => {
try {
diff --git a/Client/src/Utils/NetworkService.js b/Client/src/Utils/NetworkService.js
index 254138ff3..52edfa91f 100644
--- a/Client/src/Utils/NetworkService.js
+++ b/Client/src/Utils/NetworkService.js
@@ -905,9 +905,7 @@ class NetworkService {
onOpen?.();
};
- this.eventSource.addEventListener("open", (e) => {
- console.log("getDistributedUptimeMonitors connection opened:");
- });
+ this.eventSource.addEventListener("open", (e) => {});
this.eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);