Files
Checkmate/src/Pages/DistributedUptimeStatus/Status/index.jsx
T

316 lines
9.1 KiB
React

//Components
import DistributedUptimeMap from "../../DistributedUptime/Details/Components/DistributedUptimeMap";
import Breadcrumbs from "../../../Components/Breadcrumbs";
import { Stack, Typography } from "@mui/material";
import DeviceTicker from "../../DistributedUptime/Details/Components/DeviceTicker";
import DistributedUptimeResponseChart from "../../DistributedUptime/Details/Components/DistributedUptimeResponseChart";
import NextExpectedCheck from "../../DistributedUptime/Details/Components/NextExpectedCheck";
import Footer from "../../DistributedUptime/Details/Components/Footer";
import StatBoxes from "../../DistributedUptime/Details/Components/StatBoxes";
import ControlsHeader from "../../StatusPage/Status/Components/ControlsHeader";
import MonitorTimeFrameHeader from "../../../Components/MonitorTimeFrameHeader";
import GenericFallback from "../../../Components/GenericFallback";
import Dialog from "../../../Components/Dialog";
import SkeletonLayout from "./Components/Skeleton";
import UptLogo from "../../../assets/icons/upt_logo.png";
import PeopleAltOutlinedIcon from "@mui/icons-material/PeopleAltOutlined";
import InfoBox from "../../../Components/InfoBox";
import StatusHeader from "../../DistributedUptime/Details/Components/StatusHeader";
import MonitorsList from "./Components/MonitorsList";
import { RowContainer } from "../../../Components/StandardContainer";
//Utils
import { useTheme } from "@mui/material/styles";
import { useState, useEffect, useRef } from "react";
import { useParams } from "react-router-dom";
import { useSubscribeToDetails } from "../../DistributedUptime/Details/Hooks/useSubscribeToDetails";
import { useDUStatusPageFetchByUrl } from "./Hooks/useDUStatusPageFetchByUrl";
import { useStatusPageDelete } from "../../StatusPage/Status/Hooks/useStatusPageDelete";
import TimeFrameHeader from "./Components/TimeframeHeader";
import SubHeader from "../../../Components/Subheader";
import { safelyParseFloat } from "../../../Utils/utils";
import { useNavigate, useLocation } from "react-router-dom";
import { useTranslation } from "react-i18next";
import { useSelector, useDispatch } from "react-redux";
import { setMode } from "../../../Features/UI/uiSlice";
// Responsive
import { useMediaQuery } from "@mui/material";
const DistributedUptimeStatus = () => {
const { url } = useParams();
const location = useLocation();
const { t } = useTranslation();
const isPublic = location.pathname.startsWith("/status/distributed/public");
const elementToCapture = useRef(null);
// Redux state
const mode = useSelector((state) => state.ui.mode);
const originalModeRef = useRef(null);
// Local State
const [dateRange, setDateRange] = useState("recent");
const [isDeleteOpen, setIsDeleteOpen] = useState(false);
const [timeFrame, setTimeFrame] = useState(30);
// Utils
const theme = useTheme();
const isSmallScreen = useMediaQuery(theme.breakpoints.down("sm"));
const navigate = useNavigate();
const dispatch = useDispatch();
const [
statusPageIsLoading,
statusPageNetworkError,
statusPage,
monitorId,
isPublished,
] = useDUStatusPageFetchByUrl({
url,
timeFrame,
});
const [isLoading, networkError, connectionStatus, monitor, lastUpdateTrigger] =
useSubscribeToDetails({ monitorId, dateRange, isPublic, isPublished });
const [deleteStatusPage, isDeleting] = useStatusPageDelete(() => {
navigate("/distributed-uptime");
}, url);
// Constants
const BREADCRUMBS = [
{ name: "Distributed Uptime", path: "/distributed-uptime" },
{ name: "details", path: `/distributed-uptime/${monitorId}` },
{ name: "status", path: `` },
];
let sx = {};
if (isPublic) {
sx = {
paddingTop: "10vh",
paddingRight: "10vw",
paddingBottom: "10vh",
paddingLeft: "10vw",
};
}
// Default to dark mode
useEffect(() => {
const cleanup = () => {
if (originalModeRef.current === null) {
originalModeRef.current = mode;
}
if (isPublic) {
dispatch(setMode(originalModeRef.current));
}
};
if (isPublic) {
dispatch(setMode("dark"));
}
window.addEventListener("beforeunload", cleanup);
return () => {
window.removeEventListener("beforeunload", cleanup);
};
}, [dispatch, isPublic]);
// Done loading, a status page doesn't exist
if (!statusPageIsLoading && typeof statusPage === "undefined") {
return (
<Stack sx={sx}>
<GenericFallback>
<Typography
variant="h1"
marginY={theme.spacing(4)}
color={theme.palette.primary.contrastTextTertiary}
>
{t("distributedUptimeStatusPageNotSetUp")}
</Typography>
<Typography>{t("distributedUptimeStatusContactAdmin")}</Typography>
</GenericFallback>
</Stack>
);
}
// Done loading, a status page exists but is not public
if (!statusPageIsLoading && isPublic && statusPage.isPublished === false) {
return (
<Stack sx={sx}>
<GenericFallback>
<Typography>{t("distributedUptimeStatusPageNotPublic")}</Typography>
</GenericFallback>
</Stack>
);
}
if (isLoading || statusPageIsLoading) {
return <SkeletonLayout />;
}
if (networkError || statusPageNetworkError) {
return (
<GenericFallback>
<Typography
variant="h1"
marginY={theme.spacing(4)}
color={theme.palette.primary.contrastTextTertiary}
>
{t("networkError")}
</Typography>
<Typography>{t("checkConnection")}</Typography>
</GenericFallback>
);
}
if (
typeof statusPage === "undefined" ||
typeof monitor === "undefined" ||
monitor.totalChecks === 0
) {
return (
<Stack gap={theme.spacing(10)}>
<Breadcrumbs list={BREADCRUMBS} />
<GenericFallback>
<Typography>{t("distributedUptimeDetailsNoMonitorHistory")}</Typography>
</GenericFallback>
</Stack>
);
}
return (
<Stack
ref={elementToCapture}
direction="column"
gap={theme.spacing(10)}
sx={{
...sx,
}}
>
{!isPublic && <Breadcrumbs list={BREADCRUMBS} />}
<ControlsHeader
statusPage={statusPage}
isPublic={isPublic}
isDeleting={isDeleting}
isDeleteOpen={isDeleteOpen}
setIsDeleteOpen={setIsDeleteOpen}
url={url}
type="distributed"
/>
<StatusHeader
monitor={monitor}
connectionStatus={connectionStatus}
elementToCapture={elementToCapture}
/>
<SubHeader
direction={{ s: "column", md: "row" }}
headerText={t("distributedStatusHeaderText")}
subHeaderText={t("distributedStatusSubHeaderText")}
gap={isSmallScreen ? theme.spacing(10) : 0}
alignItems={{ s: "flex-start", md: "flex-end" }}
>
<RowContainer>
<Stack>
<Typography variant={`body2`}>
{t("distributedRightCategoryTitle")}
</Typography>
<Typography variant={`h2`}>{statusPage.companyName}</Typography>
</Stack>
</RowContainer>
</SubHeader>
<NextExpectedCheck
lastUpdateTime={monitor?.timeSinceLastCheck ?? 0}
interval={monitor?.interval ?? 0}
trigger={lastUpdateTrigger}
/>
<MonitorTimeFrameHeader
dateRange={dateRange}
setDateRange={setDateRange}
/>
<Stack
gap={theme.spacing(8)}
direction={{ s: "column", md: "row" }}
>
<DistributedUptimeMap
checks={monitor?.groupedMapChecks ?? []}
width={isSmallScreen ? "100%" : "50%"}
/>
<Stack
width={{ s: "100%", md: "50%" }}
gap={theme.spacing(8)}
>
<Stack
direction="row"
gap={theme.spacing(8)}
>
<InfoBox
heading={t("distributedUptimeStatusDevices")}
subHeading={monitor?.totalChecks ?? 0}
icon={PeopleAltOutlinedIcon}
alt="Upt Logo"
sx={{ width: "50%" }}
/>
<InfoBox
heading={isSmallScreen ? t("distributedUptimeStatusUpt") : t("distributedUptimeStatusUptBurned")}
subHeading={safelyParseFloat(monitor?.uptBurnt).toFixed(4)}
img={UptLogo}
alt={t("distributedUptimeStatusUptLogo")}
sx={{ width: "50%" }}
/>
</Stack>
<DeviceTicker
data={monitor?.latestChecks ?? []}
connectionStatus={connectionStatus}
/>
</Stack>
</Stack>
<DistributedUptimeResponseChart checks={monitor?.groupedChecks ?? []} />
<StatBoxes
monitor={monitor}
lastUpdateTrigger={lastUpdateTrigger}
/>
<SubHeader
shouldRender={statusPage?.subMonitors?.length > 0}
direction={{ s: "column", md: "row" }}
headerText={t("distributedStatusServerMonitors")}
subHeaderText={t("distributedStatusServerMonitorsDescription")}
gap={isSmallScreen ? theme.spacing(10) : 0}
alignItems={{ s: "flex-start", md: "flex-end" }}
>
<TimeFrameHeader
timeFrame={timeFrame}
setTimeFrame={setTimeFrame}
alignSelf="flex-start"
/>
</SubHeader>
<MonitorsList
monitors={statusPage?.subMonitors}
timeFrame={timeFrame}
/>
<Footer />
<Dialog
// open={isOpen.deleteStats}
title={t("distributedUptimeStatusPageDeleteDialog")}
onConfirm={() => {
deleteStatusPage();
setIsDeleteOpen(false);
}}
onCancel={() => {
setIsDeleteOpen(false);
}}
open={isDeleteOpen}
confirmationButtonLabel={t("distributedUptimeStatusPageDeleteConfirm")}
description={t("distributedUptimeStatusPageDeleteDescription")}
isLoading={isDeleting || isLoading}
/>
</Stack>
);
};
export default DistributedUptimeStatus;