Merge pull request #1656 from bluewave-labs/fix/fe/pagespeed-refactor
fix: fe/pagespeed refactor
This commit is contained in:
41 files changed
+401
-703
No files matched your search
@@ -1,360 +0,0 @@
|
||||
/* TODO
|
||||
|
||||
Should we delete this?
|
||||
*/
|
||||
|
||||
import PropTypes from "prop-types";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import {
|
||||
TableContainer,
|
||||
Paper,
|
||||
Table,
|
||||
TableHead,
|
||||
TableRow,
|
||||
TableCell,
|
||||
TableBody,
|
||||
TablePagination,
|
||||
Box,
|
||||
Typography,
|
||||
Stack,
|
||||
Button,
|
||||
} from "@mui/material";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { setRowsPerPage } from "../../Features/UI/uiSlice";
|
||||
import LeftArrowDouble from "../../assets/icons/left-arrow-double.svg?react";
|
||||
import RightArrowDouble from "../../assets/icons/right-arrow-double.svg?react";
|
||||
import LeftArrow from "../../assets/icons/left-arrow.svg?react";
|
||||
import RightArrow from "../../assets/icons/right-arrow.svg?react";
|
||||
import SelectorVertical from "../../assets/icons/selector-vertical.svg?react";
|
||||
import "./index.css";
|
||||
/**
|
||||
* Component for pagination actions (first, previous, next, last).
|
||||
*
|
||||
* @component
|
||||
* @param {Object} props
|
||||
* @param {number} props.count - Total number of items.
|
||||
* @param {number} props.page - Current page number.
|
||||
* @param {number} props.rowsPerPage - Number of rows per page.
|
||||
* @param {function} props.onPageChange - Callback function to handle page change.
|
||||
*
|
||||
* @returns {JSX.Element} Pagination actions component.
|
||||
*/
|
||||
const TablePaginationActions = (props) => {
|
||||
const { count, page, rowsPerPage, onPageChange } = props;
|
||||
|
||||
const handleFirstPageButtonClick = (event) => {
|
||||
onPageChange(event, 0);
|
||||
};
|
||||
const handleBackButtonClick = (event) => {
|
||||
onPageChange(event, page - 1);
|
||||
};
|
||||
const handleNextButtonClick = (event) => {
|
||||
onPageChange(event, page + 1);
|
||||
};
|
||||
const handleLastPageButtonClick = (event) => {
|
||||
onPageChange(event, Math.max(0, Math.ceil(count / rowsPerPage) - 1));
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{ flexShrink: 0, ml: "24px" }}>
|
||||
<Button
|
||||
variant="group"
|
||||
onClick={handleFirstPageButtonClick}
|
||||
disabled={page === 0}
|
||||
aria-label="first page"
|
||||
>
|
||||
<LeftArrowDouble />
|
||||
</Button>
|
||||
<Button
|
||||
variant="group"
|
||||
onClick={handleBackButtonClick}
|
||||
disabled={page === 0}
|
||||
aria-label="previous page"
|
||||
>
|
||||
<LeftArrow />
|
||||
</Button>
|
||||
<Button
|
||||
variant="group"
|
||||
onClick={handleNextButtonClick}
|
||||
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
|
||||
aria-label="next page"
|
||||
>
|
||||
<RightArrow />
|
||||
</Button>
|
||||
<Button
|
||||
variant="group"
|
||||
onClick={handleLastPageButtonClick}
|
||||
disabled={page >= Math.ceil(count / rowsPerPage) - 1}
|
||||
aria-label="last page"
|
||||
>
|
||||
<RightArrowDouble />
|
||||
</Button>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
TablePaginationActions.propTypes = {
|
||||
count: PropTypes.number.isRequired,
|
||||
page: PropTypes.number.isRequired,
|
||||
rowsPerPage: PropTypes.number.isRequired,
|
||||
onPageChange: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
/**
|
||||
* BasicTable Component
|
||||
* Renders a table with optional pagination.
|
||||
*
|
||||
* @component
|
||||
* @param {Object} props - Component props.
|
||||
* @param {Object} props.data - Data for the table including columns and rows.
|
||||
* @param {Array} props.data.cols - Array of objects for column headers.
|
||||
* @param {number} props.data.cols[].id - Unique identifier for the column.
|
||||
* @param {string} props.data.cols[].name - Name of the column to display as header.
|
||||
* @param {Array} props.data.rows - Array of row objects.
|
||||
* @param {number} props.data.rows[].id - Unique identifier for the row.
|
||||
* @param {Array} props.data.rows[].data - Array of cell data objects for the row.
|
||||
* @param {number} props.data.rows[].data[].id - Unique identifier for the cell.
|
||||
* @param {JSX.Element} props.data.rows[].data[].data - The content to display in the cell.
|
||||
* @param {function} props.data.rows.data.handleClick - Function to call when the row is clicked.
|
||||
* @param {boolean} [props.paginated=false] - Flag to enable pagination.
|
||||
* @param {boolean} [props.reversed=false] - Flag to enable reverse order.
|
||||
* @param {number} props.rowsPerPage- Number of rows per page (table).
|
||||
* @param {string} props.emptyMessage - Message to display when there is no data.
|
||||
* @example
|
||||
* const data = {
|
||||
* cols: [
|
||||
* { id: 1, name: "First Col" },
|
||||
* { id: 2, name: "Second Col" },
|
||||
* { id: 3, name: "Third Col" },
|
||||
* { id: 4, name: "Fourth Col" },
|
||||
* ],
|
||||
* rows: [
|
||||
* {
|
||||
* id: 1,
|
||||
* data: [
|
||||
* { id: 1, data: <div>Data for Row 1 Col 1</div> },
|
||||
* { id: 2, data: <div>Data for Row 1 Col 2</div> },
|
||||
* { id: 3, data: <div>Data for Row 1 Col 3</div> },
|
||||
* { id: 4, data: <div>Data for Row 1 Col 4</div> },
|
||||
* ],
|
||||
* },
|
||||
* {
|
||||
* id: 2,
|
||||
* data: [
|
||||
* { id: 5, data: <div>Data for Row 2 Col 1</div> },
|
||||
* { id: 6, data: <div>Data for Row 2 Col 2</div> },
|
||||
* { id: 7, data: <div>Data for Row 2 Col 3</div> },
|
||||
* { id: 8, data: <div>Data for Row 2 Col 4</div> },
|
||||
* ],
|
||||
* },
|
||||
* ],
|
||||
* };
|
||||
*
|
||||
* <BasicTable data={data} rows={rows} paginated={true} />
|
||||
*/
|
||||
|
||||
const BasicTable = ({ data, paginated, reversed, table, emptyMessage = "No data" }) => {
|
||||
const DEFAULT_ROWS_PER_PAGE = 5;
|
||||
const theme = useTheme();
|
||||
const dispatch = useDispatch();
|
||||
const uiState = useSelector((state) => state.ui);
|
||||
let rowsPerPage = uiState?.[table]?.rowsPerPage ?? DEFAULT_ROWS_PER_PAGE;
|
||||
const [page, setPage] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
setPage(0);
|
||||
}, [data]);
|
||||
|
||||
const handleChangePage = (event, newPage) => {
|
||||
setPage(newPage);
|
||||
};
|
||||
|
||||
const handleChangeRowsPerPage = (event) => {
|
||||
dispatch(
|
||||
setRowsPerPage({
|
||||
value: parseInt(event.target.value, 10),
|
||||
table: table,
|
||||
})
|
||||
);
|
||||
setPage(0);
|
||||
};
|
||||
|
||||
let displayData = [];
|
||||
|
||||
if (data && data.rows) {
|
||||
let rows = reversed ? [...data.rows].reverse() : data.rows;
|
||||
displayData = paginated
|
||||
? rows.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
|
||||
: rows;
|
||||
}
|
||||
|
||||
if (!data || !data.cols || !data.rows) {
|
||||
return <div>No data</div>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to calculate the range of displayed rows.
|
||||
* @returns {string}
|
||||
*/
|
||||
const getRange = () => {
|
||||
let start = page * rowsPerPage + 1;
|
||||
let end = Math.min(page * rowsPerPage + rowsPerPage, data.rows.length);
|
||||
return `${start} - ${end}`;
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<TableContainer component={Paper}>
|
||||
<Table
|
||||
sx={{
|
||||
"&.MuiTable-root :is(.MuiTableHead-root, .MuiTableBody-root) :is(th, td)": {
|
||||
paddingLeft: theme.spacing(12),
|
||||
},
|
||||
"& th": {
|
||||
backgroundColor: theme.palette.secondary.main,
|
||||
color: theme.palette.secondary.contrastText,
|
||||
/*
|
||||
TODO all general styling for th should live here
|
||||
*/
|
||||
},
|
||||
"& td": {
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
color: theme.palette.primary.contrastTextSecondary,
|
||||
/*
|
||||
TODO all general styling for td should live here
|
||||
*/
|
||||
},
|
||||
}}
|
||||
>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
{data.cols.map((col) => (
|
||||
<TableCell key={col.id}>{col.name}</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{displayData.map((row) => {
|
||||
return (
|
||||
<TableRow
|
||||
sx={{
|
||||
cursor: row.handleClick ? "pointer" : "default",
|
||||
"&:hover": {
|
||||
filter: "brightness(.75)",
|
||||
opacity: 0.75,
|
||||
transition: "filter 0.3s ease, opacity 0.3s ease",
|
||||
},
|
||||
}}
|
||||
key={row.id}
|
||||
onClick={row.handleClick ? row.handleClick : null}
|
||||
>
|
||||
{row.data.map((cell) => {
|
||||
return <TableCell key={cell.id}>{cell.data}</TableCell>;
|
||||
})}
|
||||
</TableRow>
|
||||
);
|
||||
})}
|
||||
{displayData.length === 0 && (
|
||||
<TableRow>
|
||||
<TableCell
|
||||
sx={{ textAlign: "center" }}
|
||||
colSpan={data.cols.length}
|
||||
>
|
||||
{emptyMessage}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
{paginated && (
|
||||
<Stack
|
||||
direction="row"
|
||||
alignItems="center"
|
||||
justifyContent="space-between"
|
||||
px={theme.spacing(4)}
|
||||
sx={{
|
||||
"& p": {
|
||||
color: theme.palette.primary.contrastTextTertiary,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
px={theme.spacing(2)}
|
||||
fontSize={12}
|
||||
sx={{ opacity: 0.7 }}
|
||||
>
|
||||
Showing {getRange()} of {data.rows.length} monitor(s)
|
||||
</Typography>
|
||||
<TablePagination
|
||||
component="div"
|
||||
count={data.rows.length}
|
||||
page={page}
|
||||
onPageChange={handleChangePage}
|
||||
rowsPerPage={rowsPerPage}
|
||||
rowsPerPageOptions={[5, 10, 15, 25]}
|
||||
onRowsPerPageChange={handleChangeRowsPerPage}
|
||||
ActionsComponent={TablePaginationActions}
|
||||
labelRowsPerPage="Rows per page"
|
||||
labelDisplayedRows={({ page, count }) =>
|
||||
`Page ${page + 1} of ${Math.max(0, Math.ceil(count / rowsPerPage))}`
|
||||
}
|
||||
slotProps={{
|
||||
select: {
|
||||
MenuProps: {
|
||||
keepMounted: true,
|
||||
PaperProps: {
|
||||
className: "pagination-dropdown",
|
||||
sx: {
|
||||
mt: 0,
|
||||
mb: theme.spacing(2),
|
||||
},
|
||||
},
|
||||
transformOrigin: { vertical: "bottom", horizontal: "left" },
|
||||
anchorOrigin: { vertical: "top", horizontal: "left" },
|
||||
sx: { mt: theme.spacing(-2) },
|
||||
},
|
||||
inputProps: { id: "pagination-dropdown" },
|
||||
IconComponent: SelectorVertical,
|
||||
sx: {
|
||||
ml: theme.spacing(4),
|
||||
mr: theme.spacing(12),
|
||||
minWidth: theme.spacing(20),
|
||||
textAlign: "left",
|
||||
"&.Mui-focused > div": {
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
sx={{
|
||||
mt: theme.spacing(6),
|
||||
color: theme.palette.primary.contrastTextSecondary,
|
||||
"& svg path": {
|
||||
stroke: theme.palette.primary.contrastTextTertiary,
|
||||
strokeWidth: 1.3,
|
||||
},
|
||||
"& .MuiSelect-select": {
|
||||
border: 1,
|
||||
borderColor: theme.palette.primary.lowContrast,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
BasicTable.propTypes = {
|
||||
data: PropTypes.object.isRequired,
|
||||
paginated: PropTypes.bool,
|
||||
reversed: PropTypes.bool,
|
||||
rowPerPage: PropTypes.number,
|
||||
table: PropTypes.string,
|
||||
emptyMessage: PropTypes.string,
|
||||
};
|
||||
|
||||
export default BasicTable;
|
||||
@@ -0,0 +1,33 @@
|
||||
import { Stack, Button } from "@mui/material";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import PropTypes from "prop-types";
|
||||
import SkeletonLayout from "./skeleton";
|
||||
|
||||
const CreateMonitorHeader = ({ isAdmin, shouldRender, path }) => {
|
||||
const navigate = useNavigate();
|
||||
if (!isAdmin) return null;
|
||||
if (!shouldRender) return <SkeletonLayout />;
|
||||
return (
|
||||
<Stack
|
||||
direction="row"
|
||||
justifyContent="end"
|
||||
alignItems="center"
|
||||
>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="accent"
|
||||
onClick={() => navigate(path)}
|
||||
>
|
||||
Create new
|
||||
</Button>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default CreateMonitorHeader;
|
||||
|
||||
CreateMonitorHeader.propTypes = {
|
||||
isAdmin: PropTypes.bool.isRequired,
|
||||
shouldRender: PropTypes.bool.isRequired,
|
||||
path: PropTypes.string.isRequired,
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
import { Stack, Skeleton } from "@mui/material";
|
||||
|
||||
const SkeletonLayout = () => {
|
||||
return (
|
||||
<Stack
|
||||
direction="row"
|
||||
justifyContent="end"
|
||||
alignItems="center"
|
||||
>
|
||||
<Skeleton
|
||||
variant="rectangular"
|
||||
width={100}
|
||||
height={36}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default SkeletonLayout;
|
||||
@@ -26,58 +26,69 @@ const Fallback = ({ title, checks, link = "/", isAdmin, vowelStart = false }) =>
|
||||
const mode = useSelector((state) => state.ui.mode);
|
||||
|
||||
return (
|
||||
<Stack
|
||||
className={`fallback__${title.trim().split(" ")[0]}`}
|
||||
alignItems="center"
|
||||
gap={theme.spacing(20)}
|
||||
<Box
|
||||
className="page-speed"
|
||||
position="relative"
|
||||
border={1}
|
||||
borderColor={theme.palette.primary.lowContrast}
|
||||
borderRadius={theme.shape.borderRadius}
|
||||
borderStyle="dashed"
|
||||
backgroundColor={theme.palette.primary.main}
|
||||
overflow="hidden"
|
||||
>
|
||||
{mode === "light" ? (
|
||||
<Skeleton style={{ zIndex: 1 }} />
|
||||
) : (
|
||||
<SkeletonDark style={{ zIndex: 1 }} />
|
||||
)}
|
||||
<Box
|
||||
className="background-pattern-svg"
|
||||
sx={{
|
||||
"& svg g g:last-of-type path": {
|
||||
stroke: theme.palette.primary.lowContrast,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Background style={{ width: "100%" }} />
|
||||
</Box>
|
||||
<Stack
|
||||
gap={theme.spacing(4)}
|
||||
maxWidth={"300px"}
|
||||
zIndex={1}
|
||||
className={`fallback__${title.trim().split(" ")[0]}`}
|
||||
alignItems="center"
|
||||
gap={theme.spacing(20)}
|
||||
>
|
||||
<Typography
|
||||
component="h1"
|
||||
marginY={theme.spacing(4)}
|
||||
color={theme.palette.primary.contrastTextTertiary}
|
||||
{mode === "light" ? (
|
||||
<Skeleton style={{ zIndex: 1 }} />
|
||||
) : (
|
||||
<SkeletonDark style={{ zIndex: 1 }} />
|
||||
)}
|
||||
<Box
|
||||
className="background-pattern-svg"
|
||||
sx={{
|
||||
"& svg g g:last-of-type path": {
|
||||
stroke: theme.palette.primary.lowContrast,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{vowelStart ? "An" : "A"} {title} is used to:
|
||||
</Typography>
|
||||
{checks.map((check, index) => (
|
||||
<Check
|
||||
text={check}
|
||||
key={`${title.trim().split(" ")[0]}-${index}`}
|
||||
outlined={true}
|
||||
/>
|
||||
))}
|
||||
<Background style={{ width: "100%" }} />
|
||||
</Box>
|
||||
<Stack
|
||||
gap={theme.spacing(4)}
|
||||
maxWidth={"300px"}
|
||||
zIndex={1}
|
||||
>
|
||||
<Typography
|
||||
component="h1"
|
||||
marginY={theme.spacing(4)}
|
||||
color={theme.palette.primary.contrastTextTertiary}
|
||||
>
|
||||
{vowelStart ? "An" : "A"} {title} is used to:
|
||||
</Typography>
|
||||
{checks.map((check, index) => (
|
||||
<Check
|
||||
text={check}
|
||||
key={`${title.trim().split(" ")[0]}-${index}`}
|
||||
outlined={true}
|
||||
/>
|
||||
))}
|
||||
</Stack>
|
||||
{/* TODO - display a different fallback if user is not an admin*/}
|
||||
{isAdmin && (
|
||||
<Button
|
||||
variant="contained"
|
||||
color="accent"
|
||||
sx={{ alignSelf: "center" }}
|
||||
onClick={() => navigate(link)}
|
||||
>
|
||||
Let's create your first{title}
|
||||
</Button>
|
||||
)}
|
||||
</Stack>
|
||||
{/* TODO - display a different fallback if user is not an admin*/}
|
||||
{isAdmin && (
|
||||
<Button
|
||||
variant="contained"
|
||||
color="accent"
|
||||
sx={{ alignSelf: "center" }}
|
||||
onClick={() => navigate(link)}
|
||||
>
|
||||
Let's create your {title}
|
||||
</Button>
|
||||
)}
|
||||
</Stack>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import { Stack } from "@mui/material";
|
||||
import { Heading } from "../Heading";
|
||||
import CircularCount from "../CircularCount";
|
||||
import PropTypes from "prop-types";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import SkeletonLayout from "./skeleton";
|
||||
|
||||
const MonitorCountHeader = ({
|
||||
shouldRender = true,
|
||||
monitorCount,
|
||||
heading,
|
||||
sx,
|
||||
children,
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
if (!shouldRender) return <SkeletonLayout />;
|
||||
|
||||
return (
|
||||
<Stack
|
||||
direction="row"
|
||||
alignItems="center"
|
||||
gap={theme.spacing(2)}
|
||||
sx={{ ...sx }}
|
||||
>
|
||||
<Heading component="h2">{heading}</Heading>
|
||||
<CircularCount count={monitorCount} />
|
||||
{children}
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
MonitorCountHeader.propTypes = {
|
||||
shouldRender: PropTypes.bool,
|
||||
monitorCount: PropTypes.number,
|
||||
heading: PropTypes.string,
|
||||
children: PropTypes.node,
|
||||
sx: PropTypes.object,
|
||||
};
|
||||
|
||||
export default MonitorCountHeader;
|
||||
@@ -0,0 +1,26 @@
|
||||
import { Stack, Skeleton } from "@mui/material";
|
||||
import { useTheme } from "@emotion/react";
|
||||
|
||||
const SkeletonLayout = () => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<Stack
|
||||
direction="row"
|
||||
alignItems="center"
|
||||
gap={theme.spacing(2)}
|
||||
>
|
||||
<Skeleton
|
||||
variant="text"
|
||||
width={100}
|
||||
height={32}
|
||||
/>
|
||||
<Skeleton
|
||||
variant="circular"
|
||||
width={40}
|
||||
height={40}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default SkeletonLayout;
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Box, Typography } from "@mui/material";
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
import PropTypes from "prop-types";
|
||||
import useUtils from "../../Pages/Uptime/Home/Hooks/useUtils";
|
||||
import useUtils from "../../Pages/Uptime/Monitors/Hooks/useUtils";
|
||||
|
||||
/**
|
||||
* StatBox Component
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
import { Box, Stack, Typography } from "@mui/material";
|
||||
import TextInput from "../../../../Components/Inputs/TextInput";
|
||||
import Checkbox from "../../../../Components/Inputs/Checkbox";
|
||||
import TextInput from "../../../../../Components/Inputs/TextInput";
|
||||
import Checkbox from "../../../../../Components/Inputs/Checkbox";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ import { HttpAdornment } from "../../../Components/Inputs/TextInput/Adornments";
|
||||
import { createToast } from "../../../Utils/toastUtils";
|
||||
import Checkbox from "../../../Components/Inputs/Checkbox";
|
||||
import Select from "../../../Components/Inputs/Select";
|
||||
import { CustomThreshold } from "./CustomThreshold";
|
||||
import { CustomThreshold } from "./Components/CustomThreshold";
|
||||
|
||||
const SELECT_VALUES = [
|
||||
{ _id: 0.25, name: "15 seconds" },
|
||||
@@ -8,7 +8,7 @@ import AreaChart from "../../../Components/Charts/AreaChart";
|
||||
import { useSelector } from "react-redux";
|
||||
import { networkService } from "../../../main";
|
||||
import PulseDot from "../../../Components/Animated/PulseDot";
|
||||
import useUtils from "../../Uptime/Home/Hooks/useUtils";
|
||||
import useUtils from "../../Uptime/Monitors/Hooks/useUtils";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import Empty from "./empty";
|
||||
import { logger } from "../../../Utils/Logger";
|
||||
|
||||
@@ -2,7 +2,7 @@ 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/Home/Hooks/useUtils.jsx";
|
||||
import useUtils from "../Uptime/Monitors/Hooks/useUtils.jsx";
|
||||
import { jwtDecode } from "jwt-decode";
|
||||
import SkeletonLayout from "./skeleton";
|
||||
import Fallback from "../../Components/Fallback";
|
||||
@@ -17,7 +17,7 @@ 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/Home/Components/Host";
|
||||
import Host from "../Uptime/Monitors/Components/Host/index.jsx";
|
||||
import { useIsAdmin } from "../../Hooks/useIsAdmin.js";
|
||||
import { InfrastructureMenu } from "./components/Menu";
|
||||
|
||||
@@ -156,12 +156,13 @@ function Infrastructure() {
|
||||
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;
|
||||
|
||||
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,
|
||||
|
||||
@@ -23,7 +23,7 @@ import PulseDot from "../../../Components/Animated/PulseDot";
|
||||
import LoadingButton from "@mui/lab/LoadingButton";
|
||||
import PlayCircleOutlineRoundedIcon from "@mui/icons-material/PlayCircleOutlineRounded";
|
||||
import SkeletonLayout from "./skeleton";
|
||||
import useUtils from "../../Uptime/Home/Hooks/useUtils";
|
||||
import useUtils from "../../Uptime/Monitors/Hooks/useUtils";
|
||||
import "./index.css";
|
||||
import Dialog from "../../../Components/Dialog";
|
||||
|
||||
|
||||
File renamed without changes.
File renamed without changes.
@@ -19,7 +19,7 @@ import PulseDot from "../../../Components/Animated/PulseDot";
|
||||
import PagespeedDetailsAreaChart from "./Charts/AreaChart";
|
||||
import Checkbox from "../../../Components/Inputs/Checkbox";
|
||||
import PieChart from "./Charts/PieChart";
|
||||
import useUtils from "../../Uptime/Home/Hooks/useUtils";
|
||||
import useUtils from "../../Uptime/Monitors/Hooks/useUtils";
|
||||
import "./index.css";
|
||||
import { useIsAdmin } from "../../../Hooks/useIsAdmin";
|
||||
import StatBox from "../../../Components/StatBox";
|
||||
|
||||
+6
-5
@@ -1,15 +1,16 @@
|
||||
import PropTypes from "prop-types";
|
||||
import PageSpeedIcon from "../../assets/icons/page-speed.svg?react";
|
||||
import { StatusLabel } from "../../Components/Label";
|
||||
// import PageSpeedIcon from "../../../../assets/icons/page-speed.svg?react";
|
||||
import PageSpeedIcon from "../../../../../assets/icons/page-speed.svg?react";
|
||||
import { StatusLabel } from "../../../../../Components/Label";
|
||||
import { Box, Grid, Stack, Typography } from "@mui/material";
|
||||
import { useNavigate } from "react-router";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { Area, AreaChart, CartesianGrid, ResponsiveContainer, Tooltip } from "recharts";
|
||||
import { useSelector } from "react-redux";
|
||||
import { formatDateWithTz, formatDurationSplit } from "../../Utils/timeUtils";
|
||||
import useUtils from "../Uptime/Home/Hooks/useUtils";
|
||||
import { formatDateWithTz, formatDurationSplit } from "../../../../../Utils/timeUtils";
|
||||
import useUtils from "../../../../Uptime/Monitors/Hooks/useUtils";
|
||||
import { useState } from "react";
|
||||
import IconBox from "../../Components/IconBox";
|
||||
import IconBox from "../../../../../Components/IconBox";
|
||||
/**
|
||||
* CustomToolTip displays a tooltip with formatted date and score information.
|
||||
* @param {Object} props
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Grid, Grid2 } from "@mui/material";
|
||||
import Card from "../Card";
|
||||
|
||||
const MonitorGrid = ({ shouldRender, monitors }) => {
|
||||
if (!shouldRender) return null;
|
||||
|
||||
return (
|
||||
<Grid
|
||||
container
|
||||
spacing={12}
|
||||
>
|
||||
{monitors?.map((monitor) => (
|
||||
<Card
|
||||
monitor={monitor}
|
||||
key={monitor._id}
|
||||
/>
|
||||
))}
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
export default MonitorGrid;
|
||||
@@ -0,0 +1,43 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { networkService } from "../../../../main";
|
||||
import { createToast } from "../../../../Utils/toastUtils";
|
||||
|
||||
const useMonitorsFetch = ({ authToken, teamId }) => {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [monitors, setMonitors] = useState([]);
|
||||
const [summary, setSummary] = useState({});
|
||||
|
||||
useEffect(() => {
|
||||
const fetchMonitors = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const res = await networkService.getMonitorsByTeamId({
|
||||
authToken: authToken,
|
||||
teamId: teamId,
|
||||
limit: 10,
|
||||
types: ["pagespeed"],
|
||||
page: null,
|
||||
rowsPerPage: null,
|
||||
filter: null,
|
||||
field: null,
|
||||
order: null,
|
||||
});
|
||||
if (res?.data?.data?.filteredMonitors) {
|
||||
setMonitors(res.data.data.filteredMonitors);
|
||||
setSummary(res.data.data.summary);
|
||||
}
|
||||
} catch (error) {
|
||||
createToast({
|
||||
body: error.message,
|
||||
});
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchMonitors();
|
||||
}, [authToken, teamId]);
|
||||
return { isLoading, monitors, summary };
|
||||
};
|
||||
|
||||
export default useMonitorsFetch;
|
||||
@@ -0,0 +1,66 @@
|
||||
// Components
|
||||
import Breadcrumbs from "../../../Components/Breadcrumbs";
|
||||
import { Stack, Box } from "@mui/material";
|
||||
import CreateMonitorHeader from "../../../Components/CreateMonitorHeader";
|
||||
import MonitorCountHeader from "../../../Components/MonitorCountHeader";
|
||||
import MonitorGrid from "./Components/MonitorGrid";
|
||||
import Fallback from "../../../Components/Fallback";
|
||||
|
||||
// Utils
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useIsAdmin } from "../../../Hooks/useIsAdmin";
|
||||
import useMonitorsFetch from "./Hooks/useMonitorsFetch";
|
||||
|
||||
// Constants
|
||||
const BREADCRUMBS = [{ name: `pagespeed`, path: "/pagespeed" }];
|
||||
|
||||
const PageSpeed = () => {
|
||||
const theme = useTheme();
|
||||
const isAdmin = useIsAdmin();
|
||||
const { user, authToken } = useSelector((state) => state.auth);
|
||||
|
||||
const { isLoading, monitors, summary } = useMonitorsFetch({
|
||||
authToken: authToken,
|
||||
teamId: user.teamId,
|
||||
});
|
||||
|
||||
if (!isLoading && monitors?.length === 0) {
|
||||
return (
|
||||
<Fallback
|
||||
title="pagespeed monitor"
|
||||
checks={[
|
||||
"Report on the user experience of a page",
|
||||
"Help analyze webpage speed",
|
||||
"Give suggestions on how the page can be improved",
|
||||
]}
|
||||
link="/pagespeed/create"
|
||||
isAdmin={isAdmin}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack gap={theme.spacing(10)}>
|
||||
<Breadcrumbs list={BREADCRUMBS} />
|
||||
<CreateMonitorHeader
|
||||
isAdmin={isAdmin}
|
||||
shouldRender={!isLoading}
|
||||
path="/pagespeed/create"
|
||||
/>
|
||||
<MonitorCountHeader
|
||||
shouldRender={!isLoading}
|
||||
monitorCount={summary?.totalMonitors}
|
||||
heading="PageSpeed monitors"
|
||||
sx={{ mb: theme.spacing(8) }}
|
||||
/>
|
||||
<MonitorGrid
|
||||
size={6}
|
||||
shouldRender={!isLoading}
|
||||
monitors={monitors}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default PageSpeed;
|
||||
@@ -1,8 +0,0 @@
|
||||
.page-speed .label {
|
||||
padding: 7px;
|
||||
height: 24px;
|
||||
font-size: var(--env-var-font-size-small);
|
||||
}
|
||||
.page-speed:not(:has([class*="fallback__"])) button {
|
||||
min-height: 34px;
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
import { Box, Button, Grid, Stack } from "@mui/material";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useSelector } from "react-redux";
|
||||
import Fallback from "../../Components/Fallback";
|
||||
import "./index.css";
|
||||
import { useNavigate } from "react-router";
|
||||
import PropTypes from "prop-types";
|
||||
import Breadcrumbs from "../../Components/Breadcrumbs";
|
||||
import SkeletonLayout from "./skeleton";
|
||||
import Card from "./card";
|
||||
import { networkService } from "../../main";
|
||||
import { Heading } from "../../Components/Heading";
|
||||
import { useIsAdmin } from "../../Hooks/useIsAdmin";
|
||||
const PageSpeed = () => {
|
||||
const theme = useTheme();
|
||||
const navigate = useNavigate();
|
||||
const isAdmin = useIsAdmin();
|
||||
const { user, authToken } = useSelector((state) => state.auth);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [monitors, setMonitors] = useState([]);
|
||||
const [summary, setSummary] = useState({});
|
||||
|
||||
useEffect(() => {
|
||||
const fetchMonitors = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
const res = await networkService.getMonitorsByTeamId({
|
||||
authToken: authToken,
|
||||
teamId: user.teamId,
|
||||
limit: 10,
|
||||
types: ["pagespeed"],
|
||||
page: null,
|
||||
rowsPerPage: null,
|
||||
filter: null,
|
||||
field: null,
|
||||
order: null,
|
||||
});
|
||||
if (res?.data?.data?.filteredMonitors) {
|
||||
setMonitors(res.data.data.filteredMonitors);
|
||||
setSummary(res.data.data.summary);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchMonitors();
|
||||
}, [authToken, user.teamId]);
|
||||
|
||||
// will show skeletons only on initial load
|
||||
// since monitor state is being added to redux persist, there's no reason to display skeletons on every render
|
||||
let isActuallyLoading = isLoading && monitors?.length === 0;
|
||||
return (
|
||||
<Box
|
||||
className="page-speed"
|
||||
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={[{ name: `pagespeed`, path: "/pagespeed" }]} />
|
||||
<Stack
|
||||
direction="row"
|
||||
justifyContent="end"
|
||||
alignItems="center"
|
||||
mt={theme.spacing(5)}
|
||||
>
|
||||
{isAdmin && (
|
||||
<Button
|
||||
variant="contained"
|
||||
color="accent"
|
||||
onClick={() => navigate("/pagespeed/create")}
|
||||
sx={{ fontWeight: 500, whiteSpace: "nowrap" }}
|
||||
>
|
||||
Create new
|
||||
</Button>
|
||||
)}
|
||||
</Stack>
|
||||
</Box>
|
||||
<Stack
|
||||
direction="row"
|
||||
sx={{
|
||||
alignItems: "center",
|
||||
gap: ".25rem",
|
||||
flexWrap: "wrap",
|
||||
}}
|
||||
>
|
||||
<Heading component="h2">PageSpeed monitors</Heading>
|
||||
{/* TODO Correct the class current-monitors-counter, there are some unnecessary things there */}
|
||||
<Box
|
||||
component="span"
|
||||
className="current-monitors-counter"
|
||||
color={theme.palette.primary.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>
|
||||
<Grid
|
||||
container
|
||||
spacing={theme.spacing(12)}
|
||||
>
|
||||
{monitors?.map((monitor) => (
|
||||
<Card
|
||||
monitor={monitor}
|
||||
key={monitor._id}
|
||||
/>
|
||||
))}
|
||||
</Grid>
|
||||
</Stack>
|
||||
) : (
|
||||
<Fallback
|
||||
title="pagespeed monitor"
|
||||
checks={[
|
||||
"Report on the user experience of a page",
|
||||
"Help analyze webpage speed",
|
||||
"Give suggestions on how the page can be improved",
|
||||
]}
|
||||
link="/pagespeed/create"
|
||||
isAdmin={isAdmin}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
PageSpeed.propTypes = {
|
||||
isAdmin: PropTypes.bool,
|
||||
};
|
||||
|
||||
export default PageSpeed;
|
||||
@@ -1,73 +0,0 @@
|
||||
import { Box, Skeleton, Stack } from "@mui/material";
|
||||
import { useTheme } from "@emotion/react";
|
||||
|
||||
/**
|
||||
* Renders a skeleton layout.
|
||||
*
|
||||
* @returns {JSX.Element}
|
||||
*/
|
||||
const SkeletonLayout = () => {
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<Stack gap={theme.spacing(2)}>
|
||||
<Stack
|
||||
direction="row"
|
||||
justifyContent="space-between"
|
||||
mb={theme.spacing(12)}
|
||||
>
|
||||
<Box width="80%">
|
||||
<Skeleton
|
||||
variant="rounded"
|
||||
width="25%"
|
||||
height={24}
|
||||
/>
|
||||
<Skeleton
|
||||
variant="rounded"
|
||||
width="50%"
|
||||
height={19.5}
|
||||
sx={{ mt: theme.spacing(2) }}
|
||||
/>
|
||||
</Box>
|
||||
<Skeleton
|
||||
variant="rounded"
|
||||
width="20%"
|
||||
height={34}
|
||||
sx={{ alignSelf: "flex-end" }}
|
||||
/>
|
||||
</Stack>
|
||||
<Stack
|
||||
direction="row"
|
||||
flexWrap="wrap"
|
||||
gap={theme.spacing(12)}
|
||||
>
|
||||
<Skeleton
|
||||
variant="rounded"
|
||||
width="100%"
|
||||
height={120}
|
||||
sx={{ flex: "35%" }}
|
||||
/>
|
||||
<Skeleton
|
||||
variant="rounded"
|
||||
width="100%"
|
||||
height={120}
|
||||
sx={{ flex: "35%" }}
|
||||
/>
|
||||
<Skeleton
|
||||
variant="rounded"
|
||||
width="100%"
|
||||
height={120}
|
||||
sx={{ flex: "35%" }}
|
||||
/>
|
||||
<Skeleton
|
||||
variant="rounded"
|
||||
width="100%"
|
||||
height={120}
|
||||
sx={{ flex: "35%" }}
|
||||
/>
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default SkeletonLayout;
|
||||
File renamed without changes.
File renamed without changes.
@@ -2,7 +2,7 @@ import { Stack, Typography } from "@mui/material";
|
||||
import PulseDot from "../../../../../Components/Animated/PulseDot";
|
||||
import Dot from "../../../../../Components/Dot";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import useUtils from "../../../Home/Hooks/useUtils";
|
||||
import useUtils from "../../../Monitors/Hooks/useUtils";
|
||||
import { formatDurationRounded } from "../../../../../Utils/timeUtils";
|
||||
import ConfigButton from "../ConfigButton";
|
||||
import SkeletonLayout from "./skeleton";
|
||||
|
||||
@@ -4,7 +4,7 @@ import StatBox from "../../../../../Components/StatBox";
|
||||
import SkeletonLayout from "./skeleton";
|
||||
// Utils
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
import useUtils from "../../../Home/Hooks/useUtils";
|
||||
import useUtils from "../../../Monitors/Hooks/useUtils";
|
||||
import { getHumanReadableDuration } from "../../../../../Utils/timeUtils";
|
||||
import PropTypes from "prop-types";
|
||||
const StatusBoxes = ({ shouldRender, monitor, certificateExpiry }) => {
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+1
-1
@@ -30,7 +30,7 @@ const StatusBoxes = ({ shouldRender, monitorsSummary }) => {
|
||||
};
|
||||
|
||||
StatusBoxes.propTypes = {
|
||||
monitorsSummary: PropTypes.object.isRequired,
|
||||
monitorsSummary: PropTypes.object,
|
||||
};
|
||||
|
||||
export default StatusBoxes;
|
||||
File renamed without changes.
File renamed without changes.
+8
-8
@@ -12,7 +12,9 @@ import { useState } from "react";
|
||||
import SearchComponent from "../SearchComponent";
|
||||
import CircularCount from "../../../../../Components/CircularCount";
|
||||
import LoadingSpinner from "../LoadingSpinner";
|
||||
import MonitorCountHeader from "../../../../../Components/MonitorCountHeader";
|
||||
import UptimeDataTableSkeleton from "./skeleton";
|
||||
|
||||
// Utils
|
||||
import { useTheme } from "@emotion/react";
|
||||
import useUtils from "../../Hooks/useUtils";
|
||||
@@ -214,21 +216,19 @@ const UptimeDataTable = (props) => {
|
||||
flex={1}
|
||||
py={theme.spacing(8)}
|
||||
>
|
||||
<Stack
|
||||
direction="row"
|
||||
alignItems="center"
|
||||
mb={theme.spacing(8)}
|
||||
gap={theme.spacing(2)}
|
||||
<MonitorCountHeader
|
||||
shouldRender={!monitorsAreLoading}
|
||||
monitorCount={monitorCount}
|
||||
heading="Uptime monitors"
|
||||
sx={{ mb: theme.spacing(8) }}
|
||||
>
|
||||
<Heading component="h2">Uptime monitors</Heading>
|
||||
<CircularCount count={monitorCount} />
|
||||
<SearchComponent
|
||||
monitorsAreLoading={monitorsAreLoading}
|
||||
monitors={monitors}
|
||||
onSearchChange={setSearch}
|
||||
setIsSearching={setIsSearching}
|
||||
/>
|
||||
</Stack>
|
||||
</MonitorCountHeader>
|
||||
|
||||
<MonitorDataTable
|
||||
shouldRender={!monitorsAreLoading}
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+19
-2
@@ -4,7 +4,8 @@ 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 Fallback from "../../../Components/Fallback";
|
||||
// MUI Components
|
||||
import { Stack, Box, Button } from "@mui/material";
|
||||
|
||||
@@ -99,13 +100,29 @@ const UptimeMonitors = () => {
|
||||
});
|
||||
const totalMonitors = monitorsSummary?.totalMonitors ?? 0;
|
||||
|
||||
if (!isLoading && monitors?.length === 0) {
|
||||
return (
|
||||
<Fallback
|
||||
vowelStart={true}
|
||||
title="uptime monitor"
|
||||
checks={["Check if a website or service is up and running"]}
|
||||
link="/uptime/create"
|
||||
isAdmin={isAdmin}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack
|
||||
className="monitors"
|
||||
gap={theme.spacing(10)}
|
||||
>
|
||||
<Breadcrumbs list={BREADCRUMBS} />
|
||||
<CreateMonitorButton shouldRender={true} />
|
||||
<CreateMonitorHeader
|
||||
isAdmin={isAdmin}
|
||||
shouldRender={!isLoading}
|
||||
path="/uptime/create"
|
||||
/>
|
||||
<Greeting type="uptime" />
|
||||
<StatusBoxes
|
||||
monitorsSummary={monitorsSummary}
|
||||
+42
-29
@@ -1,36 +1,49 @@
|
||||
import { Navigate, Route, Routes as LibRoutes } from "react-router";
|
||||
import HomeLayout from "../Components/Layouts/HomeLayout";
|
||||
import { Infrastructure } from "../Pages/Infrastructure";
|
||||
import InfrastructureDetails from "../Pages/Infrastructure/Details";
|
||||
import NotFound from "../Pages/NotFound";
|
||||
import Login from "../Pages/Auth/Login/Login";
|
||||
import Register from "../Pages/Auth/Register/Register";
|
||||
import Account from "../Pages/Account";
|
||||
import Uptime from "../Pages/Uptime/Home";
|
||||
import UptimeDetails from "../Pages/Uptime/Details";
|
||||
|
||||
import CreateMonitor from "../Pages/Uptime/CreateUptime";
|
||||
import CreateInfrastructureMonitor from "../Pages/Infrastructure/CreateMonitor";
|
||||
// Auth
|
||||
import AuthLogin from "../Pages/Auth/Login/Login";
|
||||
import AuthRegister from "../Pages/Auth/Register/Register";
|
||||
import AuthForgotPassword from "../Pages/Auth/ForgotPassword";
|
||||
import AuthCheckEmail from "../Pages/Auth/CheckEmail";
|
||||
import AuthSetNewPassword from "../Pages/Auth/SetNewPassword";
|
||||
import AuthNewPasswordConfirmed from "../Pages/Auth/NewPasswordConfirmed";
|
||||
|
||||
// Uptime
|
||||
import Uptime from "../Pages/Uptime/Monitors";
|
||||
import UptimeDetails from "../Pages/Uptime/Details";
|
||||
import UptimeCreate from "../Pages/Uptime/Create";
|
||||
import UptimeConfigure from "../Pages/Uptime/Configure";
|
||||
|
||||
// PageSpeed
|
||||
// import PageSpeed from "../Pages/PageSpeed";
|
||||
import PageSpeed from "../Pages/PageSpeed/Monitors";
|
||||
import PageSpeedCreate from "../Pages/PageSpeed/Create";
|
||||
import PageSpeedDetails from "../Pages/PageSpeed/Details";
|
||||
import PageSpeedConfigure from "../Pages/PageSpeed/Configure";
|
||||
|
||||
// Infrastructure
|
||||
import InfrastructureCreate from "../Pages/Infrastructure/Create";
|
||||
import InfrastructureDetails from "../Pages/Infrastructure/Details";
|
||||
|
||||
import Incidents from "../Pages/Incidents";
|
||||
import Status from "../Pages/Status";
|
||||
import Integrations from "../Pages/Integrations";
|
||||
|
||||
// Settings
|
||||
import Account from "../Pages/Account";
|
||||
import Settings from "../Pages/Settings";
|
||||
import ForgotPassword from "../Pages/Auth/ForgotPassword";
|
||||
import CheckEmail from "../Pages/Auth/CheckEmail";
|
||||
import SetNewPassword from "../Pages/Auth/SetNewPassword";
|
||||
import NewPasswordConfirmed from "../Pages/Auth/NewPasswordConfirmed";
|
||||
import ProtectedRoute from "../Components/ProtectedRoute";
|
||||
|
||||
import Maintenance from "../Pages/Maintenance";
|
||||
import Configure from "../Pages/Uptime/Configure";
|
||||
import PageSpeed from "../Pages/PageSpeed";
|
||||
import CreatePageSpeed from "../Pages/PageSpeed/CreatePageSpeed";
|
||||
|
||||
import ProtectedRoute from "../Components/ProtectedRoute";
|
||||
import CreateNewMaintenanceWindow from "../Pages/Maintenance/CreateMaintenance";
|
||||
import PageSpeedDetails from "../Pages/PageSpeed/Details";
|
||||
import PageSpeedConfigure from "../Pages/PageSpeed/Configure";
|
||||
import withAdminCheck from "../Components/HOC/withAdminCheck";
|
||||
|
||||
const Routes = () => {
|
||||
const AdminCheckedRegister = withAdminCheck(Register);
|
||||
const AdminCheckedRegister = withAdminCheck(AuthRegister);
|
||||
return (
|
||||
<LibRoutes>
|
||||
<Route
|
||||
@@ -52,7 +65,7 @@ const Routes = () => {
|
||||
|
||||
<Route
|
||||
path="/uptime/create/:monitorId?"
|
||||
element={<CreateMonitor />}
|
||||
element={<UptimeCreate />}
|
||||
/>
|
||||
<Route
|
||||
path="/uptime/:monitorId/"
|
||||
@@ -60,7 +73,7 @@ const Routes = () => {
|
||||
/>
|
||||
<Route
|
||||
path="/uptime/configure/:monitorId/"
|
||||
element={<Configure />}
|
||||
element={<UptimeConfigure />}
|
||||
/>
|
||||
<Route
|
||||
path="pagespeed"
|
||||
@@ -68,7 +81,7 @@ const Routes = () => {
|
||||
/>
|
||||
<Route
|
||||
path="pagespeed/create"
|
||||
element={<CreatePageSpeed />}
|
||||
element={<PageSpeedCreate />}
|
||||
/>
|
||||
<Route
|
||||
path="pagespeed/:monitorId"
|
||||
@@ -84,7 +97,7 @@ const Routes = () => {
|
||||
/>
|
||||
<Route
|
||||
path="infrastructure/create"
|
||||
element={<CreateInfrastructureMonitor />}
|
||||
element={<InfrastructureCreate />}
|
||||
/>
|
||||
<Route
|
||||
path="infrastructure/:monitorId"
|
||||
@@ -131,7 +144,7 @@ const Routes = () => {
|
||||
|
||||
<Route
|
||||
path="/login"
|
||||
element={<Login />}
|
||||
element={<AuthLogin />}
|
||||
/>
|
||||
|
||||
<Route
|
||||
@@ -142,24 +155,24 @@ const Routes = () => {
|
||||
<Route
|
||||
exact
|
||||
path="/register/:token"
|
||||
element={<Register />}
|
||||
element={<AuthRegister />}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path="/forgot-password"
|
||||
element={<ForgotPassword />}
|
||||
element={<AuthForgotPassword />}
|
||||
/>
|
||||
<Route
|
||||
path="/check-email"
|
||||
element={<CheckEmail />}
|
||||
element={<AuthCheckEmail />}
|
||||
/>
|
||||
<Route
|
||||
path="/set-new-password/:token"
|
||||
element={<SetNewPassword />}
|
||||
element={<AuthSetNewPassword />}
|
||||
/>
|
||||
<Route
|
||||
path="/new-password-confirmed"
|
||||
element={<NewPasswordConfirmed />}
|
||||
element={<AuthNewPasswordConfirmed />}
|
||||
/>
|
||||
|
||||
<Route
|
||||
|
||||
Reference in new issue
Block a user