From b0182cff6d38cb7a09da82e240a2ecb0c3dffba5 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Fri, 4 Oct 2024 14:10:16 +0800 Subject: [PATCH] Add maintenance table --- .../Maintenance/MaintenanceTable/index.jsx | 289 ++++++++++++++++++ Client/src/Pages/Maintenance/index.jsx | 46 ++- 2 files changed, 325 insertions(+), 10 deletions(-) create mode 100644 Client/src/Pages/Maintenance/MaintenanceTable/index.jsx diff --git a/Client/src/Pages/Maintenance/MaintenanceTable/index.jsx b/Client/src/Pages/Maintenance/MaintenanceTable/index.jsx new file mode 100644 index 000000000..29c651add --- /dev/null +++ b/Client/src/Pages/Maintenance/MaintenanceTable/index.jsx @@ -0,0 +1,289 @@ +import PropTypes from "prop-types"; +import { + TableContainer, + Table, + TableHead, + TableRow, + TableCell, + TableBody, + Paper, + Box, + TablePagination, + Stack, + Typography, + Button, +} from "@mui/material"; +import ArrowDownwardRoundedIcon from "@mui/icons-material/ArrowDownwardRounded"; +import ArrowUpwardRoundedIcon from "@mui/icons-material/ArrowUpwardRounded"; + +import { useState, useEffect, memo, useCallback, useRef } from "react"; +import { useDispatch } from "react-redux"; +import { useTheme } from "@emotion/react"; +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 ActionsMenu from "../actionsMenu"; + +/** + * 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 ( + + + + + + + ); +}; + +TablePaginationActions.propTypes = { + count: PropTypes.number.isRequired, + page: PropTypes.number.isRequired, + rowsPerPage: PropTypes.number.isRequired, + onPageChange: PropTypes.func.isRequired, +}; + +const MaintenanceTable = ({ + page, + setPage, + rowsPerPage, + setRowsPerPage, + sort, + setSort, + maintenanceWindows, + maintenanceWindowCount, +}) => { + const theme = useTheme(); + const dispatch = useDispatch(); + + const handleChangePage = (event, newPage) => { + setPage(newPage); + }; + + const handleChangeRowsPerPage = (event) => { + dispatch( + setRowsPerPage({ + value: parseInt(event.target.value, 10), + table: "monitors", + }) + ); + setPage(0); + }; + + /** + * 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, + maintenanceWindowCount + ); + return `${start} - ${end}`; + }; + + const handleSort = async (field) => { + let order = ""; + if (sort.field !== field) { + order = "desc"; + } else { + order = sort.order === "asc" ? "desc" : "asc"; + } + setSort({ field, order }); + }; + + return ( + <> + + + + + handleSort("name")} + > + + Host + + {sort.order === "asc" ? ( + + ) : ( + + )} + + + + handleSort("status")} + > + {" "} + + {" "} + Status + + {sort.order === "asc" ? ( + + ) : ( + + )} + + + + Response Time + Type + Actions + + + +
+
+ + + Showing {getRange()} of {maintenanceWindowCount} maintenance window(s) + + + `Page ${page + 1} of ${Math.max(0, Math.ceil(count / rowsPerPage))}` + } + slotProps={{ + select: { + MenuProps: { + keepMounted: true, + disableScrollLock: 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.background.main, + }, + }, + }, + }} + sx={{ + mt: theme.spacing(6), + color: theme.palette.text.secondary, + "& svg path": { + stroke: theme.palette.text.tertiary, + strokeWidth: 1.3, + }, + "& .MuiSelect-select": { + border: 1, + borderColor: theme.palette.border.light, + borderRadius: theme.shape.borderRadius, + }, + }} + /> + + + ); +}; + +MaintenanceTable.propTypes = { + isAdmin: PropTypes.bool, + page: PropTypes.number, + setPage: PropTypes.func, + rowsPerPage: PropTypes.number, + setRowsPerPage: PropTypes.func, + sort: PropTypes.object, + setSort: PropTypes.func, + maintenanceWindows: PropTypes.array, + maintenanceWindowCount: PropTypes.number, +}; + +const MemoizedMaintenanceTable = memo(MaintenanceTable); +export default MemoizedMaintenanceTable; diff --git a/Client/src/Pages/Maintenance/index.jsx b/Client/src/Pages/Maintenance/index.jsx index 5c23a789c..d34035258 100644 --- a/Client/src/Pages/Maintenance/index.jsx +++ b/Client/src/Pages/Maintenance/index.jsx @@ -1,10 +1,22 @@ import { Box } from "@mui/material"; import { useTheme } from "@emotion/react"; import Fallback from "../../Components/Fallback"; +import { useState, useEffect } from "react"; import "./index.css"; +import MaintenanceTable from "./MaintenanceTable"; +import { useSelector } from "react-redux"; const Maintenance = ({ isAdmin }) => { const theme = useTheme(); + const authState = useSelector((state) => state.auth); + + const [maintenanceWindows, setMaintenanceWindows] = useState([]); + const [maintenanceWindowCount, setMaintenanceWindowCount] = useState(0); + const [page, setPage] = useState(0); + const [rowsPerPage, setRowsPerPage] = useState(5); + const [sort, setSort] = useState({}); + + useEffect(() => {}); return ( { }, }} > - + {maintenanceWindows.length > 0 && ( + + )} + {isAdmin && maintenanceWindows.length === 0 && ( + + )} ); };