diff --git a/Client/src/Components/BasicTable/index.css b/Client/src/Components/BasicTable/index.css new file mode 100644 index 000000000..e69de29bb diff --git a/Client/src/Components/BasicTable/index.jsx b/Client/src/Components/BasicTable/index.jsx new file mode 100644 index 000000000..a80c7bfb6 --- /dev/null +++ b/Client/src/Components/BasicTable/index.jsx @@ -0,0 +1,146 @@ +import { + TableContainer, + Paper, + Table, + TableHead, + TableRow, + TableCell, + TableBody, + TablePagination, +} from "@mui/material"; +import React, { useState } from "react"; +import PropTypes from "prop-types"; + +/** + * BasicTable Component + * Renders a table with optional pagination. + * + * @component + * @param {Object} props - Component props. + * @param {Array} props.headers - Array of header titles for the table. + * @param {Array} props.rowItems - Array of row data objects for the table. + * @param {boolean} props.paginated - Flag to enable pagination. + * + * @example + * + * Headers is an array of objets that have a unique ID and a name + * Rows is an array of objects that have a unique ID and some data to display + * Row data can be any valid React node + * Rows are split into groups according to the number of headers, so if you have 3 headers then + * Rows will go under the index % 3 column. + * ie: Row 0 -> col 0 % 3 = 0 + * ie: Row 1 -> col 1 % 3 = 1 + * ie: Row 2 -> col 2 % 3 = 2 + * ie: Row 3 -> col 3 % 3 = 0 + * + * Thus items are put in their correct columns + * + * + * const headers = [ + * { id: 1, name: "ID" }, + * { id: 2, name: "Name" }, + * { id: 3, name: "Age" }, + * ]; + * const rows = [ + * { id: 1, data: 999 }, + * { id: 2, data:
Alex Holliday
}, + * { id: 3, data:
5
}, + * // More rows... + * ]; + * + */ + +const BasicTable = ({ headers, rowItems, paginated }) => { + // Add headers to props validation + + const [page, setPage] = useState(0); + const [rowsPerPage, setRowsPerPage] = useState(5); + + const handleChangePage = (event, newPage) => { + setPage(newPage); + }; + + const handleChangeRowsPerPage = (event) => { + setRowsPerPage(parseInt(event.target.value, 10)); + setPage(0); // Reset to first page after changing rows per page + }; + + const numOfCols = headers.length; + + const groupedRowItems = rowItems.reduce((acc, item, idx) => { + const rowIndex = Math.floor((item.id - 1) / numOfCols); + if (!acc[rowIndex]) acc[rowIndex] = { items: [], idx }; + acc[rowIndex].items.push({ item }); + return acc; + }, {}); + + const paginatedRowsKeys = Object.keys(groupedRowItems).slice( + page * rowsPerPage, + page * rowsPerPage + rowsPerPage + ); + + return ( + <> + + + + + {headers.map((header) => { + return {header.name}; + })} + + + + {paginated === false && + Object.keys(groupedRowItems).map((key) => { + return ( + + {groupedRowItems[key].items.map(({ item }) => { + return {item.data}; + })} + + ); + })} + {paginated === true && + paginatedRowsKeys.map((key) => ( + + {groupedRowItems[key].items.map(({ item }) => ( + {item.data} + ))} + + ))} + +
+
+ {paginated === true && ( + + )} + + ); +}; + +BasicTable.propTypes = { + headers: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, + name: PropTypes.string.isRequired, + }) + ).isRequired, + rowItems: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, + data: PropTypes.node, + }) + ).isRequired, + paginated: PropTypes.bool, +}; + +export default BasicTable; diff --git a/Client/src/Components/MonitorTable/index.jsx b/Client/src/Components/MonitorTable/index.jsx index 5bb06935b..338ebb793 100644 --- a/Client/src/Components/MonitorTable/index.jsx +++ b/Client/src/Components/MonitorTable/index.jsx @@ -1,23 +1,8 @@ import "./index.css"; -import { useState } from "react"; import PropTypes from "prop-types"; import ResponseTimeChart from "../Charts/ResponseTimeChart"; -import { - Table, - TableBody, - TableCell, - TableContainer, - TableHead, - TableRow, - Paper, - Pagination, - PaginationItem, -} from "@mui/material"; -import ArrowDownwardRoundedIcon from "@mui/icons-material/ArrowDownwardRounded"; +import BasicTable from "../BasicTable"; import OpenInNewPage from "../../assets/icons/open-in-new-page.svg?react"; -import ArrowBackRoundedIcon from "@mui/icons-material/ArrowBackRounded"; -import ArrowForwardRoundedIcon from "@mui/icons-material/ArrowForwardRounded"; -import { useNavigate } from "react-router-dom"; /** * Host component. @@ -95,100 +80,42 @@ const Status = ({ params }) => { * @returns {React.Component} Returns a table with the monitor data. */ const MonitorTable = ({ monitors = [] }) => { - const navigate = useNavigate(); - const [page, setPage] = useState(0); - const rowsPerPage = 5; - - const handleChangePage = (event, newPage) => { - setPage(newPage); - }; - - const mappedRows = monitors - .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) - .map((monitor) => { - const params = { - url: monitor.url, - title: monitor.name, - precentage: 100, - percentageColor: - monitor.status === true - ? "var(--env-var-color-17)" - : "var(--env-var-color-19)", - status: monitor.status === true ? "up" : "down", - backgroundColor: - monitor.status === true - ? "var(--env-var-color-20)" - : "var(--env-var-color-21)", - statusDotColor: - monitor.status === true - ? "var(--env-var-color-17)" - : "var(--env-var-color-19)", - }; - - return ( - { - navigate(`/monitors/${monitor._id}`); - }} - > - - - - - - - - - - TODO Add Actions - - ); + const headers = [ + { id: 1, name: "Host" }, + { id: 2, name: "Status" }, + { id: 3, name: "Response Time" }, + { id: 4, name: "Actions" }, + ]; + const data = []; + monitors.forEach((monitor) => { + const params = { + url: monitor.url, + title: monitor.name, + precentage: 100, + percentageColor: + monitor.status === true + ? "var(--env-var-color-17)" + : "var(--env-var-color-19)", + status: monitor.status === true ? "up" : "down", + backgroundColor: + monitor.status === true + ? "var(--env-var-color-20)" + : "var(--env-var-color-21)", + statusDotColor: + monitor.status === true + ? "var(--env-var-color-17)" + : "var(--env-var-color-19)", + }; + data.push({ id: data.length + 1, data: }); + data.push({ id: data.length + 1, data: }); + data.push({ + id: data.length + 1, + data: , }); + data.push({ id: data.length + 1, data: "TODO" }); + }); - return ( - <> - - - - - Host - - Status - - - - - Response Time - Actions - - - {mappedRows} -
-
- handleChangePage(event, value - 1)} - shape="rounded" - renderItem={(item) => ( - - )} - /> - - ); + return ; }; MonitorTable.propTypes = {