Files
Checkmate/client/src/Pages/Uptime/Monitors/index.jsx
T

246 lines
6.7 KiB
React

// Required Data
// 1. Monitor summary
// 2. List of monitors filtered by search term with 25 checks each
// 2a.List of monitors must have the total number of monitors that match.
// Components
import Breadcrumbs from "../../../Components/Breadcrumbs";
import Greeting from "../../../Utils/greeting";
import StatusBoxes from "./Components/StatusBoxes";
import UptimeDataTable from "./Components/UptimeDataTable";
import Pagination from "../../../Components/Table/TablePagination";
import CreateMonitorHeader from "../../../Components/MonitorCreateHeader";
import Fallback from "../../../Components/Fallback";
import GenericFallback from "../../../Components/GenericFallback";
import SearchComponent from "./Components/SearchComponent";
import Filter from "./Components/Filter";
import MonitorCountHeader from "../../../Components/MonitorCountHeader";
// MUI Components
import { Stack, Box, Button, Typography } from "@mui/material";
// Utils
import { useState, useCallback } from "react";
import { useIsAdmin } from "../../../Hooks/useIsAdmin";
import { useTheme } from "@emotion/react";
import { useNavigate } from "react-router-dom";
import { useSelector, useDispatch } from "react-redux";
import { setRowsPerPage } from "../../../Features/UI/uiSlice";
import PropTypes from "prop-types";
import {
useFetchMonitorsWithSummary,
useFetchMonitorsWithChecks,
} from "../../../Hooks/monitorHooks";
import { useTranslation } from "react-i18next";
const TYPES = ["http", "ping", "docker", "port"];
const CreateMonitorButton = ({ shouldRender }) => {
// Utils
const navigate = useNavigate();
const { t } = useTranslation();
if (shouldRender === false) {
return;
}
return (
<Box alignSelf="flex-end">
<Button
variant="contained"
color="accent"
onClick={() => {
navigate("/uptime/create");
}}
>
{t("createNew")}
</Button>
</Box>
);
};
CreateMonitorButton.propTypes = {
shouldRender: PropTypes.bool,
};
const UptimeMonitors = () => {
// Redux state
const rowsPerPage = useSelector((state) => state.ui.monitors.rowsPerPage);
// Local state
const [search, setSearch] = useState(undefined);
const [page, setPage] = useState(undefined);
const [sort, setSort] = useState(undefined);
const [isSearching, setIsSearching] = useState(false);
const [monitorUpdateTrigger, setMonitorUpdateTrigger] = useState(false);
const [selectedTypes, setSelectedTypes] = useState(undefined);
const [selectedState, setSelectedState] = useState(undefined);
const [selectedStatus, setSelectedStatus] = useState(undefined);
const [toFilterStatus, setToFilterStatus] = useState(undefined);
const [toFilterActive, setToFilterActive] = useState(undefined);
// Utils
const theme = useTheme();
const isAdmin = useIsAdmin();
const dispatch = useDispatch();
const { t } = useTranslation();
const BREADCRUMBS = [{ name: t("menu.uptime"), path: "/uptime" }];
// Handlers
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (event) => {
dispatch(
setRowsPerPage({
value: parseInt(event.target.value, 10),
table: "monitors",
})
);
setPage(0);
};
const triggerUpdate = useCallback(() => {
setMonitorUpdateTrigger((prev) => !prev);
}, []);
const [monitors, monitorsSummary, monitorsWithSummaryIsLoading, networkError] =
useFetchMonitorsWithSummary({
types: TYPES,
monitorUpdateTrigger,
});
const handleReset = () => {
setSelectedState(undefined);
setSelectedTypes(undefined);
setSelectedStatus(undefined);
setToFilterStatus(undefined);
setToFilterActive(undefined);
};
const filterLookup = new Map([
[toFilterStatus, "status"],
[toFilterActive, "isActive"],
]);
const activeFilter = [...filterLookup].find(([key]) => key !== undefined);
const field = activeFilter?.[1] || sort?.field;
const filter = activeFilter?.[0] || search;
const effectiveTypes = selectedTypes?.length ? selectedTypes : TYPES;
const [
monitorsWithChecks,
monitorsWithChecksCount,
monitorsWithChecksIsLoading,
monitorsWithChecksNetworkError,
] = useFetchMonitorsWithChecks({
types: effectiveTypes,
limit: 25,
page: page,
rowsPerPage: rowsPerPage,
filter: filter,
field: field,
order: sort?.order,
monitorUpdateTrigger,
});
const isLoading = monitorsWithSummaryIsLoading || monitorsWithChecksIsLoading;
if (networkError) {
return (
<GenericFallback>
<Typography
variant="h1"
marginY={theme.spacing(4)}
color={theme.palette.primary.contrastTextTertiary}
>
{t("common.toasts.networkError")}
</Typography>
<Typography>{t("common.toasts.checkConnection")}</Typography>
</GenericFallback>
);
}
if (
!isLoading &&
(monitorsSummary?.totalMonitors === 0 ||
typeof monitorsSummary?.totalMonitors === "undefined")
) {
return (
<Fallback
vowelStart={true}
title="uptime monitor"
checks={[
"Check if websites or servers are online & responsive",
"Alert teams about downtime or performance issues",
"Monitor HTTP endpoints, pings, containers & ports",
"Track historical uptime and reliability trends",
]}
link="/uptime/create"
isAdmin={isAdmin}
/>
);
}
return (
<Stack
className="monitors"
gap={theme.spacing(10)}
>
<Breadcrumbs list={BREADCRUMBS} />
<CreateMonitorHeader
isAdmin={isAdmin}
isLoading={isLoading}
path="/uptime/create"
bulkPath="/uptime/bulk-import"
/>
<Greeting type="uptime" />
<StatusBoxes
monitorsSummary={monitorsSummary}
shouldRender={!monitorsWithSummaryIsLoading}
/>
<Stack direction={"row"}>
<MonitorCountHeader
shouldRender={monitors?.length > 0 && !monitorsWithSummaryIsLoading}
monitorCount={monitorsSummary?.totalMonitors}
></MonitorCountHeader>
<Filter
selectedTypes={selectedTypes}
setSelectedTypes={setSelectedTypes}
selectedStatus={selectedStatus}
setSelectedStatus={setSelectedStatus}
selectedState={selectedState}
setSelectedState={setSelectedState}
setToFilterStatus={setToFilterStatus}
setToFilterActive={setToFilterActive}
handleReset={handleReset}
/>
<SearchComponent
monitors={monitors}
onSearchChange={setSearch}
setIsSearching={setIsSearching}
/>
</Stack>
<UptimeDataTable
isAdmin={isAdmin}
isSearching={isSearching}
filteredMonitors={monitorsWithChecks}
sort={sort}
setSort={setSort}
monitorsAreLoading={monitorsWithChecksIsLoading}
triggerUpdate={triggerUpdate}
/>
<Pagination
itemCount={monitorsWithChecksCount}
paginationLabel="monitors"
page={page}
rowsPerPage={rowsPerPage}
handleChangePage={handleChangePage}
handleChangeRowsPerPage={handleChangeRowsPerPage}
/>
</Stack>
);
};
export default UptimeMonitors;