reactor infrastructure monitors page
This commit is contained in:
1 parent
880195efde
commit
b928210f8a
7 files changed
+297
-302
No files matched your search
@@ -0,0 +1,134 @@
|
||||
// Components
|
||||
import DataTable from "../../../../../Components/Table";
|
||||
import Host from "../../../../Uptime/Monitors/Components/Host";
|
||||
import { StatusLabel } from "../../../../../Components/Label";
|
||||
import { Stack } from "@mui/material";
|
||||
import { InfrastructureMenu } from "../MonitorsTableMenu";
|
||||
// Assets
|
||||
import CPUChipIcon from "../../../../../assets/icons/cpu-chip.svg?react";
|
||||
import CustomGauge from "../../../../../Components/Charts/CustomGauge";
|
||||
|
||||
// Utils
|
||||
import { useTheme } from "@emotion/react";
|
||||
import useUtils from "../../../../Uptime/Monitors/Hooks/useUtils";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
const MonitorsTable = ({ shouldRender, monitors, isAdmin, handleActionMenuDelete }) => {
|
||||
// Utils
|
||||
const theme = useTheme();
|
||||
const { determineState } = useUtils();
|
||||
const navigate = useNavigate();
|
||||
|
||||
// Handlers
|
||||
const openDetails = (id) => {
|
||||
navigate(`/infrastructure/${id}`);
|
||||
};
|
||||
const headers = [
|
||||
{
|
||||
id: "host",
|
||||
content: "Host",
|
||||
render: (row) => (
|
||||
<Host
|
||||
title={row.name}
|
||||
url={row.url}
|
||||
percentage={row.uptimePercentage}
|
||||
percentageColor={row.percentageColor}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "status",
|
||||
content: "Status",
|
||||
render: (row) => (
|
||||
<StatusLabel
|
||||
status={row.status}
|
||||
text={row.status}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "frequency",
|
||||
content: "Frequency",
|
||||
render: (row) => (
|
||||
<Stack
|
||||
direction={"row"}
|
||||
justifyContent={"center"}
|
||||
alignItems={"center"}
|
||||
gap=".25rem"
|
||||
>
|
||||
<CPUChipIcon
|
||||
width={20}
|
||||
height={20}
|
||||
/>
|
||||
{row.processor}
|
||||
</Stack>
|
||||
),
|
||||
},
|
||||
{ id: "cpu", content: "CPU", render: (row) => <CustomGauge progress={row.cpu} /> },
|
||||
{ id: "mem", content: "Mem", render: (row) => <CustomGauge progress={row.mem} /> },
|
||||
{ id: "disk", content: "Disk", render: (row) => <CustomGauge progress={row.disk} /> },
|
||||
{
|
||||
id: "actions",
|
||||
content: "Actions",
|
||||
render: (row) => (
|
||||
<InfrastructureMenu
|
||||
monitor={row}
|
||||
isAdmin={isAdmin}
|
||||
updateCallback={handleActionMenuDelete}
|
||||
/>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const data = monitors?.map((monitor) => {
|
||||
const processor =
|
||||
((monitor.checks[0]?.cpu?.frequency ?? 0) / 1000).toFixed(2) + " GHz";
|
||||
const cpu = (monitor?.checks[0]?.cpu.usage_percent ?? 0) * 100;
|
||||
const mem = (monitor?.checks[0]?.memory.usage_percent ?? 0) * 100;
|
||||
const disk = (monitor?.checks[0]?.disk[0]?.usage_percent ?? 0) * 100;
|
||||
const status = determineState(monitor);
|
||||
const uptimePercentage = ((monitor?.uptimePercentage ?? 0) * 100)
|
||||
.toFixed(2)
|
||||
.toString();
|
||||
const percentageColor =
|
||||
monitor.uptimePercentage < 0.25
|
||||
? theme.palette.error.main
|
||||
: monitor.uptimePercentage < 0.5
|
||||
? theme.palette.warning.main
|
||||
: theme.palette.success.main;
|
||||
|
||||
return {
|
||||
id: monitor._id,
|
||||
name: monitor.name,
|
||||
url: monitor.url,
|
||||
processor,
|
||||
cpu,
|
||||
mem,
|
||||
disk,
|
||||
status,
|
||||
uptimePercentage,
|
||||
percentageColor,
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
<DataTable
|
||||
shouldRender={shouldRender}
|
||||
headers={headers}
|
||||
data={data}
|
||||
config={{
|
||||
/* TODO this behavior seems to be repeated. Put it on the root table? */
|
||||
rowSX: {
|
||||
cursor: "pointer",
|
||||
"&:hover td": {
|
||||
backgroundColor: theme.palette.tertiary.main,
|
||||
transition: "background-color .3s ease",
|
||||
},
|
||||
},
|
||||
onRowClick: (row) => openDetails(row.id),
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default MonitorsTable;
|
||||
+4
-4
@@ -4,12 +4,12 @@ import { useRef, useState } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { createToast } from "../../../../Utils/toastUtils";
|
||||
import { createToast } from "../../../../../Utils/toastUtils";
|
||||
import { IconButton, Menu, MenuItem } from "@mui/material";
|
||||
import Settings from "../../../../assets/icons/settings-bold.svg?react";
|
||||
import Settings from "../../../../../assets/icons/settings-bold.svg?react";
|
||||
import PropTypes from "prop-types";
|
||||
import Dialog from "../../../../Components/Dialog";
|
||||
import { networkService } from "../../../../Utils/NetworkService.js";
|
||||
import Dialog from "../../../../../Components/Dialog";
|
||||
import { networkService } from "../../../../../Utils/NetworkService.js";
|
||||
|
||||
/**
|
||||
* InfrastructureMenu Component
|
||||
@@ -0,0 +1,45 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { networkService } from "../../../../main";
|
||||
import { createToast } from "../../../../Utils/toastUtils";
|
||||
|
||||
const useMonitorFetch = ({ page, rowsPerPage, updateTrigger }) => {
|
||||
// Redux state
|
||||
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 [summary, setSummary] = useState(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchMonitors = async () => {
|
||||
try {
|
||||
const response = await networkService.getMonitorsByTeamId({
|
||||
authToken,
|
||||
teamId: user.teamId,
|
||||
limit: 1,
|
||||
types: ["hardware"],
|
||||
page: page,
|
||||
rowsPerPage: rowsPerPage,
|
||||
});
|
||||
setMonitors(response?.data?.data?.filteredMonitors ?? []);
|
||||
setSummary(response?.data?.data?.summary ?? {});
|
||||
} catch (error) {
|
||||
setNetworkError(true);
|
||||
createToast({
|
||||
body: error.message,
|
||||
});
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchMonitors();
|
||||
}, [page, rowsPerPage, authToken, user.teamId, updateTrigger]);
|
||||
|
||||
return { monitors, summary, isLoading, networkError };
|
||||
};
|
||||
|
||||
export { useMonitorFetch };
|
||||
@@ -0,0 +1,110 @@
|
||||
// Components
|
||||
import { Stack, Typography } from "@mui/material";
|
||||
import Breadcrumbs from "../../../Components/Breadcrumbs";
|
||||
import MonitorCountHeader from "../../../Components/MonitorCountHeader";
|
||||
import MonitorCreateHeader from "../../../Components/MonitorCreateHeader";
|
||||
import MonitorsTable from "./Components/MonitorsTable";
|
||||
import Pagination from "../../..//Components/Table/TablePagination";
|
||||
import GenericFallback from "../../../Components/GenericFallback";
|
||||
import Fallback from "../../../Components/Fallback";
|
||||
// Utils
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useMonitorFetch } from "./Hooks/useMonitorFetch";
|
||||
import { useState } from "react";
|
||||
import { useIsAdmin } from "../../../Hooks/useIsAdmin";
|
||||
// Constants
|
||||
const BREADCRUMBS = [{ name: `infrastructure`, path: "/infrastructure" }];
|
||||
|
||||
const InfrastructureMonitors = () => {
|
||||
// Redux state
|
||||
const [page, setPage] = useState(0);
|
||||
const [rowsPerPage, setRowsPerPage] = useState(5);
|
||||
const [updateTrigger, setUpdateTrigger] = useState(false);
|
||||
|
||||
// Utils
|
||||
const theme = useTheme();
|
||||
const isAdmin = useIsAdmin();
|
||||
|
||||
// Handlers
|
||||
const handleActionMenuDelete = () => {
|
||||
setUpdateTrigger(!updateTrigger);
|
||||
};
|
||||
|
||||
const handleChangePage = (event, newPage) => {
|
||||
setPage(newPage);
|
||||
};
|
||||
|
||||
const handleChangeRowsPerPage = (event) => {
|
||||
setRowsPerPage(event.target.value);
|
||||
};
|
||||
|
||||
const { monitors, summary, isLoading, networkError } = useMonitorFetch({
|
||||
page,
|
||||
rowsPerPage,
|
||||
updateTrigger,
|
||||
});
|
||||
|
||||
if (networkError === true) {
|
||||
return (
|
||||
<GenericFallback>
|
||||
<Typography
|
||||
variant="h1"
|
||||
marginY={theme.spacing(4)}
|
||||
color={theme.palette.primary.contrastTextTertiary}
|
||||
>
|
||||
Network error
|
||||
</Typography>
|
||||
<Typography>Please check your connection</Typography>
|
||||
</GenericFallback>
|
||||
);
|
||||
}
|
||||
|
||||
if (!isLoading && monitors?.length === 0) {
|
||||
return (
|
||||
<Fallback
|
||||
vowelStart={true}
|
||||
title="infrastructure monitor"
|
||||
checks={[
|
||||
"Track the performance of your servers",
|
||||
"Identify bottlenecks and optimize usage",
|
||||
"Ensure reliability with real-time monitoring",
|
||||
]}
|
||||
link="/infrastructure/create"
|
||||
isAdmin={isAdmin}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
console.log(isLoading);
|
||||
return (
|
||||
<Stack gap={theme.spacing(10)}>
|
||||
<Breadcrumbs list={BREADCRUMBS} />
|
||||
<MonitorCreateHeader
|
||||
isAdmin={isAdmin}
|
||||
shouldRender={!isLoading}
|
||||
path="/infrastructure/create"
|
||||
/>
|
||||
<MonitorCountHeader
|
||||
shouldRender={!isLoading}
|
||||
heading="Infrastructure monitors"
|
||||
monitorCount={summary?.totalMonitors ?? 0}
|
||||
/>
|
||||
<MonitorsTable
|
||||
shouldRender={!isLoading}
|
||||
monitors={monitors}
|
||||
isAdmin={isAdmin}
|
||||
handleActionMenuDelete={handleActionMenuDelete}
|
||||
/>
|
||||
<Pagination
|
||||
itemCount={summary?.totalMonitors}
|
||||
paginationLabel="monitors"
|
||||
page={page}
|
||||
rowsPerPage={rowsPerPage}
|
||||
handleChangePage={handleChangePage}
|
||||
handleChangeRowsPerPage={handleChangeRowsPerPage}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default InfrastructureMonitors;
|
||||
@@ -1,295 +0,0 @@
|
||||
import { useEffect, useState, useCallback } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { /* useDispatch, */ useSelector } from "react-redux";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import useUtils from "../Uptime/Monitors/Hooks/useUtils.jsx";
|
||||
import { jwtDecode } from "jwt-decode";
|
||||
import SkeletonLayout from "./skeleton";
|
||||
import Fallback from "../../Components/Fallback";
|
||||
// import GearIcon from "../../Assets/icons/settings-bold.svg?react";
|
||||
import CPUChipIcon from "../../assets/icons/cpu-chip.svg?react";
|
||||
import DataTable from "../../Components/Table";
|
||||
import { Box, Button, IconButton, Stack } from "@mui/material";
|
||||
import Breadcrumbs from "../../Components/Breadcrumbs";
|
||||
import { StatusLabel } from "../../Components/Label";
|
||||
import { Heading } from "../../Components/Heading";
|
||||
import Pagination from "../../Components/Table/TablePagination/index.jsx";
|
||||
// import { getInfrastructureMonitorsByTeamId } from "../../Features/InfrastructureMonitors/infrastructureMonitorsSlice";
|
||||
import { networkService } from "../../Utils/NetworkService.js";
|
||||
import CustomGauge from "../../Components/Charts/CustomGauge/index.jsx";
|
||||
import Host from "../Uptime/Monitors/Components/Host/index.jsx";
|
||||
import { useIsAdmin } from "../../Hooks/useIsAdmin.js";
|
||||
import { InfrastructureMenu } from "./components/Menu";
|
||||
|
||||
const BREADCRUMBS = [{ name: `infrastructure`, path: "/infrastructure" }];
|
||||
|
||||
/**
|
||||
* This is the Infrastructure monitoring page. This is a work in progress
|
||||
*
|
||||
* @param - Define params.
|
||||
* @returns {JSX.Element} The infrastructure monitoring page.
|
||||
*/
|
||||
|
||||
function Infrastructure() {
|
||||
/* Adding this custom hook so we can avoid using the HOC approach that can lower performance (we are calling the admin logic N times on initializing the project. using a custom hook will cal it ass needed ) */
|
||||
const isAdmin = useIsAdmin();
|
||||
const theme = useTheme();
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
const navigate = useNavigate();
|
||||
const navigateToCreate = () => navigate("/infrastructure/create");
|
||||
|
||||
const [page, setPage] = useState(0);
|
||||
/* TODO refactor this, so it is not aware of the MUI implementation. First argument only exists because of MUI. This should require onlu the new page. Adapting for MUI should happen inside of table pagination component */
|
||||
const handleChangePage = (_, newPage) => {
|
||||
setPage(newPage);
|
||||
};
|
||||
|
||||
const [rowsPerPage, setRowsPerPage] = useState(5);
|
||||
const handleChangeRowsPerPage = (event) => {
|
||||
setRowsPerPage(parseInt(event.target.value));
|
||||
setPage(0);
|
||||
};
|
||||
const [monitors, setMonitors] = useState([]);
|
||||
const [summary, setSummary] = useState({});
|
||||
|
||||
const { authToken } = useSelector((state) => state.auth);
|
||||
const user = jwtDecode(authToken);
|
||||
|
||||
const fetchMonitors = useCallback(async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const response = await networkService.getMonitorsByTeamId({
|
||||
authToken,
|
||||
teamId: user.teamId,
|
||||
limit: 1,
|
||||
types: ["hardware"],
|
||||
page: page,
|
||||
rowsPerPage: rowsPerPage,
|
||||
});
|
||||
setMonitors(response?.data?.data?.filteredMonitors ?? []);
|
||||
setSummary(response?.data?.data?.summary ?? {});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, [page, rowsPerPage, authToken, user.teamId]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchMonitors();
|
||||
}, [fetchMonitors]);
|
||||
|
||||
const { determineState } = useUtils();
|
||||
// do it here
|
||||
function openDetails(id) {
|
||||
navigate(`/infrastructure/${id}`);
|
||||
}
|
||||
function handleActionMenuDelete() {
|
||||
fetchMonitors();
|
||||
}
|
||||
|
||||
const headers = [
|
||||
{
|
||||
id: "host",
|
||||
content: "Host",
|
||||
render: (row) => (
|
||||
<Host
|
||||
title={row.name}
|
||||
url={row.url}
|
||||
percentage={row.uptimePercentage}
|
||||
percentageColor={row.percentageColor}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "status",
|
||||
content: "Status",
|
||||
render: (row) => (
|
||||
<StatusLabel
|
||||
status={row.status}
|
||||
text={row.status}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "frequency",
|
||||
content: "Frequency",
|
||||
render: (row) => (
|
||||
<Stack
|
||||
direction={"row"}
|
||||
justifyContent={"center"}
|
||||
alignItems={"center"}
|
||||
gap=".25rem"
|
||||
>
|
||||
<CPUChipIcon
|
||||
width={20}
|
||||
height={20}
|
||||
/>
|
||||
{row.processor}
|
||||
</Stack>
|
||||
),
|
||||
},
|
||||
{ id: "cpu", content: "CPU", render: (row) => <CustomGauge progress={row.cpu} /> },
|
||||
{ id: "mem", content: "Mem", render: (row) => <CustomGauge progress={row.mem} /> },
|
||||
{ id: "disk", content: "Disk", render: (row) => <CustomGauge progress={row.disk} /> },
|
||||
{
|
||||
id: "actions",
|
||||
content: "Actions",
|
||||
render: (row) => (
|
||||
<InfrastructureMenu
|
||||
monitor={row}
|
||||
isAdmin={isAdmin}
|
||||
updateCallback={handleActionMenuDelete}
|
||||
/>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const monitorsAsRows = monitors.map((monitor) => {
|
||||
const processor =
|
||||
((monitor.checks[0]?.cpu?.frequency ?? 0) / 1000).toFixed(2) + " GHz";
|
||||
const cpu = (monitor?.checks[0]?.cpu.usage_percent ?? 0) * 100;
|
||||
const mem = (monitor?.checks[0]?.memory.usage_percent ?? 0) * 100;
|
||||
const disk = (monitor?.checks[0]?.disk[0]?.usage_percent ?? 0) * 100;
|
||||
const status = determineState(monitor);
|
||||
const uptimePercentage = ((monitor?.uptimePercentage ?? 0) * 100)
|
||||
.toFixed(2)
|
||||
.toString();
|
||||
const percentageColor =
|
||||
monitor.uptimePercentage < 0.25
|
||||
? theme.palette.error.main
|
||||
: monitor.uptimePercentage < 0.5
|
||||
? theme.palette.warning.main
|
||||
: theme.palette.success.main;
|
||||
|
||||
return {
|
||||
id: monitor._id,
|
||||
name: monitor.name,
|
||||
url: monitor.url,
|
||||
processor,
|
||||
cpu,
|
||||
mem,
|
||||
disk,
|
||||
status,
|
||||
uptimePercentage,
|
||||
percentageColor,
|
||||
};
|
||||
});
|
||||
|
||||
let isActuallyLoading = isLoading && monitors?.length === 0;
|
||||
return (
|
||||
<Box
|
||||
className="infrastructure-monitor"
|
||||
sx={{
|
||||
':has(> [class*="fallback__"])': {
|
||||
position: "relative",
|
||||
border: 1,
|
||||
borderColor: theme.palette.primary.lowContrast,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
borderStyle: "dashed",
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
overflow: "hidden",
|
||||
},
|
||||
}}
|
||||
>
|
||||
{isActuallyLoading ? (
|
||||
<SkeletonLayout />
|
||||
) : monitors?.length !== 0 ? (
|
||||
<Stack gap={theme.spacing(8)}>
|
||||
<Box>
|
||||
<Breadcrumbs list={BREADCRUMBS} />
|
||||
<Stack
|
||||
direction="row"
|
||||
justifyContent="end"
|
||||
alignItems="center"
|
||||
mt={theme.spacing(5)}
|
||||
>
|
||||
{isAdmin && (
|
||||
<Button
|
||||
variant="contained"
|
||||
color="accent"
|
||||
onClick={navigateToCreate}
|
||||
sx={{ fontWeight: 500, whiteSpace: "nowrap" }}
|
||||
>
|
||||
Create new
|
||||
</Button>
|
||||
)}
|
||||
</Stack>
|
||||
</Box>
|
||||
<Stack
|
||||
sx={{
|
||||
gap: "1rem",
|
||||
}}
|
||||
>
|
||||
<Stack
|
||||
direction="row"
|
||||
sx={{
|
||||
alignItems: "center",
|
||||
gap: ".25rem",
|
||||
flexWrap: "wrap",
|
||||
}}
|
||||
>
|
||||
<Heading component="h2">Infrastructure monitors</Heading>
|
||||
{/* TODO Same as the one in UptimaDataTable. Create component */}
|
||||
<Box
|
||||
component="span"
|
||||
color={theme.palette.tertiary.contrastText}
|
||||
border={2}
|
||||
borderColor={theme.palette.accent.main}
|
||||
backgroundColor={theme.palette.tertiary.main}
|
||||
sx={{
|
||||
padding: ".25em .75em",
|
||||
borderRadius: "10000px",
|
||||
fontSize: "12px",
|
||||
fontWeight: 500,
|
||||
}}
|
||||
>
|
||||
{summary?.totalMonitors ?? 0}
|
||||
</Box>
|
||||
</Stack>
|
||||
|
||||
<DataTable
|
||||
config={{
|
||||
/* TODO this behavior seems to be repeated. Put it on the root table? */
|
||||
rowSX: {
|
||||
cursor: "pointer",
|
||||
"&:hover td": {
|
||||
backgroundColor: theme.palette.tertiary.main,
|
||||
transition: "background-color .3s ease",
|
||||
},
|
||||
},
|
||||
onRowClick: (row) => openDetails(row.id),
|
||||
}}
|
||||
headers={headers}
|
||||
data={monitorsAsRows}
|
||||
/>
|
||||
|
||||
<Pagination
|
||||
itemCount={summary?.totalMonitors ?? 0}
|
||||
paginationLabel="monitors"
|
||||
page={page}
|
||||
rowsPerPage={rowsPerPage}
|
||||
handleChangePage={handleChangePage}
|
||||
handleChangeRowsPerPage={handleChangeRowsPerPage}
|
||||
/>
|
||||
</Stack>
|
||||
</Stack>
|
||||
) : (
|
||||
<Fallback
|
||||
vowelStart={true}
|
||||
title="infrastructure monitor"
|
||||
checks={[
|
||||
"Track the performance of your servers",
|
||||
"Identify bottlenecks and optimize usage",
|
||||
"Ensure reliability with real-time monitoring",
|
||||
]}
|
||||
link="/infrastructure/create"
|
||||
isAdmin={isAdmin}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export { Infrastructure };
|
||||
@@ -1,7 +1,7 @@
|
||||
// Components
|
||||
import Breadcrumbs from "../../../Components/Breadcrumbs";
|
||||
import { Stack, Typography } from "@mui/material";
|
||||
import CreateMonitorHeader from "../../../Components/CreateMonitorHeader";
|
||||
import CreateMonitorHeader from "../../../Components/MonitorCreateHeader";
|
||||
import MonitorCountHeader from "../../../Components/MonitorCountHeader";
|
||||
import MonitorGrid from "./Components/MonitorGrid";
|
||||
import Fallback from "../../../Components/Fallback";
|
||||
|
||||
@@ -4,7 +4,7 @@ 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/CreateMonitorHeader";
|
||||
import CreateMonitorHeader from "../../../Components/MonitorCreateHeader";
|
||||
import Fallback from "../../../Components/Fallback";
|
||||
import GenericFallback from "../../../Components/GenericFallback";
|
||||
import SearchComponent from "./Components/SearchComponent";
|
||||
@@ -107,7 +107,7 @@ const UptimeMonitors = () => {
|
||||
order: sort?.order,
|
||||
triggerUpdate: monitorUpdateTrigger,
|
||||
});
|
||||
const totalMonitors = monitorsSummary?.totalMonitors ?? 0;
|
||||
const totalMonitors = monitorsSummary?.totalMonitors;
|
||||
|
||||
if (networkError) {
|
||||
return (
|
||||
@@ -135,6 +135,7 @@ const UptimeMonitors = () => {
|
||||
/>
|
||||
);
|
||||
}
|
||||
console.log({ isLoading });
|
||||
|
||||
return (
|
||||
<Stack
|
||||
|
||||
Reference in new issue
Block a user