mirror of
https://github.com/bluewave-labs/Checkmate.git
synced 2026-01-31 14:18:28 -06:00
326 lines
8.7 KiB
JavaScript
326 lines
8.7 KiB
JavaScript
//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 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";
|
|
//Utils
|
|
import { networkService } from "../../../main";
|
|
import { useSelector } from "react-redux";
|
|
import { useTheme } from "@mui/material/styles";
|
|
import { useEffect, useState, useCallback, useRef } 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 (
|
|
// <Stack
|
|
// direction="row"
|
|
// width={"25%"}
|
|
// justifyContent="center"
|
|
// sx={{
|
|
// padding: `${theme.spacing(BASE_BOX_PADDING_VERTICAL)} ${theme.spacing(BASE_BOX_PADDING_HORIZONTAL)}`,
|
|
// backgroundColor: theme.palette.background.main,
|
|
// border: 1,
|
|
// borderStyle: "solid",
|
|
// borderColor: theme.palette.primary.lowContrast,
|
|
// }}
|
|
// >
|
|
// {img && (
|
|
// <img
|
|
// style={{ marginRight: theme.spacing(8) }}
|
|
// height={30}
|
|
// width={30}
|
|
// src={img}
|
|
// alt={altTxt}
|
|
// />
|
|
// )}
|
|
// <Stack direction="column">
|
|
// <Typography variant="h2">{heading}</Typography>
|
|
// <Typography>{value}</Typography>
|
|
// </Stack>
|
|
// </Stack>
|
|
// );
|
|
// };
|
|
|
|
const DistributedUptimeDetails = () => {
|
|
// Redux State
|
|
const { authToken } = useSelector((state) => state.auth);
|
|
const { mode } = useSelector((state) => state.ui);
|
|
|
|
// 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();
|
|
|
|
// 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 (!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]);
|
|
|
|
return (
|
|
monitor && (
|
|
<Stack
|
|
direction="column"
|
|
gap={theme.spacing(8)}
|
|
>
|
|
<Breadcrumbs list={BREADCRUMBS} />
|
|
{monitor?.url !== "https://jup.ag/" &&
|
|
monitor?.url !== "https://explorer.solana.com/" && (
|
|
<Box>
|
|
<Typography
|
|
component="h1"
|
|
variant="h1"
|
|
>
|
|
{monitor.name}
|
|
</Typography>
|
|
</Box>
|
|
)}
|
|
<Stack
|
|
direction="row"
|
|
alignItems="center"
|
|
gap={theme.spacing(8)}
|
|
>
|
|
<Typography variant="h2">
|
|
Distributed Uptime Monitoring powered by DePIN
|
|
</Typography>
|
|
</Stack>
|
|
<Stack
|
|
direction="row"
|
|
gap={theme.spacing(8)}
|
|
>
|
|
<StatBox
|
|
heading="Avg Response Time"
|
|
subHeading={`${Math.floor(monitor?.avgResponseTime ?? 0)} ms`}
|
|
/>
|
|
<StatBox
|
|
heading="Checking every"
|
|
subHeading={`${(monitor?.interval ?? 0) / 1000} seconds`}
|
|
/>
|
|
<StatBox
|
|
heading={"Last check"}
|
|
subHeading={
|
|
<LastUpdate
|
|
lastUpdateTime={monitor?.timeSinceLastCheck ?? 0}
|
|
suffix={"seconds ago"}
|
|
/>
|
|
}
|
|
/>
|
|
<StatBox
|
|
heading="Last server push"
|
|
subHeading={
|
|
<LastUpdate
|
|
suffix={"seconds ago"}
|
|
lastUpdateTime={0}
|
|
trigger={lastUpdateTrigger}
|
|
/>
|
|
}
|
|
/>
|
|
|
|
<StatBox
|
|
heading="UPT Burned"
|
|
subHeading={monitor?.totalUptBurnt ?? 0}
|
|
img={UptLogo}
|
|
alt="Upt Logo"
|
|
/>
|
|
</Stack>
|
|
<Box sx={{ width: "100%" }}>
|
|
<NextExpectedCheck
|
|
lastUpdateTime={monitor?.timeSinceLastCheck ?? 0}
|
|
interval={monitor?.interval ?? 0}
|
|
trigger={lastUpdateTrigger}
|
|
/>
|
|
</Box>
|
|
<Stack
|
|
direction="row"
|
|
justifyContent="space-between"
|
|
alignItems="flex-end"
|
|
gap={theme.spacing(4)}
|
|
mb={theme.spacing(8)}
|
|
>
|
|
<Typography variant="body2">
|
|
Showing statistics for past{" "}
|
|
{dateRange === "day"
|
|
? "24 hours"
|
|
: dateRange === "week"
|
|
? "7 days"
|
|
: "30 days"}
|
|
.
|
|
</Typography>
|
|
<ButtonGroup sx={{ height: 32 }}>
|
|
<Button
|
|
variant="group"
|
|
filled={(dateRange === "day").toString()}
|
|
onClick={() => setDateRange("day")}
|
|
>
|
|
Day
|
|
</Button>
|
|
<Button
|
|
variant="group"
|
|
filled={(dateRange === "week").toString()}
|
|
onClick={() => setDateRange("week")}
|
|
>
|
|
Week
|
|
</Button>
|
|
<Button
|
|
variant="group"
|
|
filled={(dateRange === "month").toString()}
|
|
onClick={() => setDateRange("month")}
|
|
>
|
|
Month
|
|
</Button>
|
|
</ButtonGroup>
|
|
</Stack>
|
|
<ChartBox
|
|
icon={<ResponseTimeIcon />}
|
|
header="Response Times"
|
|
sx={{ padding: 0 }}
|
|
>
|
|
<DistributedUptimeResponseChart checks={monitor?.groupedChecks ?? []} />
|
|
</ChartBox>
|
|
<Stack
|
|
direction="row"
|
|
gap={theme.spacing(8)}
|
|
>
|
|
<DistributedUptimeMap
|
|
checks={monitor?.groupedMapChecks ?? []}
|
|
height={"100%"}
|
|
width={"100%"}
|
|
/>
|
|
<DeviceTicker
|
|
width={"25vw"}
|
|
data={monitor?.latestChecks ?? []}
|
|
connectionStatus={connectionStatus}
|
|
/>
|
|
</Stack>
|
|
<Footer />
|
|
</Stack>
|
|
)
|
|
);
|
|
};
|
|
|
|
export default DistributedUptimeDetails;
|