From 229135513d3c2d29e0c5ebb17a485bfff198cd40 Mon Sep 17 00:00:00 2001 From: Caio Cabral Date: Fri, 15 Nov 2024 14:55:05 -0500 Subject: [PATCH 01/26] feat: creating general structure for Infrastructure page desktop mode --- Client/src/Pages/Infrastructure/index.jsx | 173 ++++++++++++++++++++-- 1 file changed, 161 insertions(+), 12 deletions(-) diff --git a/Client/src/Pages/Infrastructure/index.jsx b/Client/src/Pages/Infrastructure/index.jsx index 324268af7..f079abfca 100644 --- a/Client/src/Pages/Infrastructure/index.jsx +++ b/Client/src/Pages/Infrastructure/index.jsx @@ -1,5 +1,78 @@ -import { Box, Button } from "@mui/material"; +import { + Box, + Button, + Stack, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, +} from "@mui/material"; import { Heading } from "../../Components/Heading"; +import { useTheme } from "@emotion/react"; +import Greeting from "../../Utils/greeting"; +import Breadcrumbs from "../../Components/Breadcrumbs"; + +const mockedData = { + ip: "https://192.168.1.30", + status: "Up", + processor: "2Ghz", + cpu: 80, + mem: 50, + disk: 70, +}; + +const ROWS = Array.from(Array(5).keys()).map(() => mockedData); +console.log(ROWS); + +const columns = [ + { + label: "Host", + /* id: "name", */ + /* minWidth: 170 */ + }, + { + /* id: "code", */ + label: "Status", + /* minWidth: 100 */ + }, + { + /* id: "population", */ + label: "Frequency", + /* minWidth: 170, + align: "right", */ + /* format: (value) => value.toLocaleString("en-US"), */ + }, + { + /* id: "size", */ + label: "CPU", + /* minWidth: 170, */ + /* align: "right", */ + /* format: (value) => value.toLocaleString("en-US"), */ + }, + { + /* id: "density", */ + label: "Mem", + /* minWidth: 170, */ + /* align: "right", + format: (value) => value.toFixed(2), */ + }, + { + label: "Disk", + }, + { + label: "Actions", + }, +]; + +/* TODO steps + +1) Extract Client\src\Pages\Monitors\Home\MonitorTable\index.jsx to reusable component + +... +z) Check error pointed by Shemy on theme +*/ /** * This is the Infrastructure monitoring page. This is a work in progress @@ -9,20 +82,96 @@ import { Heading } from "../../Components/Heading"; */ function Infrastructure() { + const theme = useTheme(); return ( - - - Infrastructure monitors - + + + + + + Infrastructure monitors + {/* TODO Correct the class, messy stuff */} + + 5 + + + + + + + {columns.map((column, index) => ( + + {column.label} + + ))} + + + + {ROWS.map((row, index) => ( + + {/* TODO iterate over column and get column id, applying row[column.id] */} + {row.ip} + {row.status} + {row.processor} + {row.cpu} + {row.mem} + {row.disk} + actions + + ))} + +
+
+
+ ); } From 66cd8136958afe023ad710532ffa9747f35aa6d0 Mon Sep 17 00:00:00 2001 From: Caio Cabral Date: Sat, 16 Nov 2024 22:48:46 -0500 Subject: [PATCH 02/26] feat: wrapping Chart Gauge adaptations --- Client/src/Components/Charts/Gauge/index.jsx | 111 +++++++++++------- .../Components/Layouts/HomeLayout/index.css | 7 ++ Client/src/Pages/Infrastructure/index.jsx | 51 ++++++-- .../Monitors/Home/MonitorTable/index.jsx | 1 + 4 files changed, 122 insertions(+), 48 deletions(-) diff --git a/Client/src/Components/Charts/Gauge/index.jsx b/Client/src/Components/Charts/Gauge/index.jsx index 0ae872e3f..2757858e6 100644 --- a/Client/src/Components/Charts/Gauge/index.jsx +++ b/Client/src/Components/Charts/Gauge/index.jsx @@ -1,42 +1,32 @@ -import { RadialBarChart, RadialBar, ResponsiveContainer } from "recharts"; +import { RadialBarChart, RadialBar, ResponsiveContainer, Text, Legend } from "recharts"; import PropTypes from "prop-types"; import { useTheme } from "@emotion/react"; const MINIMUM_VALUE = 0; const MAXIMUM_VALUE = 100; -const DATA = [{ value: MAXIMUM_VALUE }]; const PROGRESS_THRESHOLD = 50; -const DEFAULT_CONTAINER_HEIGHT = 160; -const TEXT_POSITIONS = { - value: { x: "50%", y: "45%" }, - label: { x: "50%", y: "55%" }, -}; -const COMMON_RADIAL_BAR_PROPS = { - minAngle: 15, - clockWise: true, - dataKey: "value", - cornerRadius: 0, -}; +const DEFAULT_WIDTH = 60; +// const DEFAULT_CONTAINER_HEIGHT = 160; +// const TEXT_POSITIONS = { +// value: { x: "50%", y: "45%" }, +// label: { x: "50%", y: "55%" }, +// }; +const RADIUS = "90%"; +const START_ANGLE = 90; +const CHART_RANGE = 360; const RADIAL_BAR_CHART_PROPS = { - cx: "50%", - cy: "50%", - innerRadius: "45%", - outerRadius: "100%", - startAngle: 90, - endAngle: -270, + innerRadius: RADIUS, + outerRadius: RADIUS, + barSize: 6, + startAngle: START_ANGLE, + endAngle: START_ANGLE - CHART_RANGE, + margin: { top: 0, right: 0, bottom: 0, left: 0 }, }; -const RADIAL_BAR_OVERLAY_PROPS = { - transform: "rotate(180deg)", - position: "absolute", - top: "0", - left: "0", -}; - -const COMMON_HEADER_PROPS = { - textAnchor: "middle", - dominantBaseline: "middle", +const COMMON_RADIAL_BAR_PROPS = { + dataKey: "value", + cornerRadius: 8, }; /** @@ -64,19 +54,40 @@ const COMMON_HEADER_PROPS = { */ const Gauge = ({ progressValue, - displayText, - containerHeight, - gaugeHeader, - gaugeSubheader, + containerWidth, + // displayText, + // containerHeight, + // gaugeHeader, + // gaugeSubheader, }) => { const theme = useTheme(); const myProgressValue = Math.max(MINIMUM_VALUE, Math.min(progressValue, MAXIMUM_VALUE)); + const chartData = [ + { + value: MAXIMUM_VALUE, + fill: "transparent", + }, + { + value: myProgressValue, + fill: + progressValue > PROGRESS_THRESHOLD + ? theme.palette.primary.main + : theme.palette.percentage.uptimePoor, + }, + ]; + const width = containerWidth ?? DEFAULT_WIDTH; return ( - + ( + {`${myProgressValue}%`} + ), + }} + /* data={[{ value: myProgressValue }]} */ /> - - */} + {/* TODO what is the text tag? */} + {/* {`${displayText}`} - + */} ); @@ -121,4 +150,4 @@ Gauge.propTypes = { gaugeHeader: PropTypes.object, gaugeSubheader: PropTypes.object, }; -export default Gauge; +export { Gauge }; diff --git a/Client/src/Components/Layouts/HomeLayout/index.css b/Client/src/Components/Layouts/HomeLayout/index.css index 1a7ae4ceb..e08904f8e 100644 --- a/Client/src/Components/Layouts/HomeLayout/index.css +++ b/Client/src/Components/Layouts/HomeLayout/index.css @@ -6,6 +6,13 @@ padding: var(--env-var-spacing-2); } +/* TODO go for this approach for responsiveness. The aside needs to be taken care of */ +/* @media (max-width: 1000px) { + .home-layout { + flex-direction: column !important; + } +} */ + .home-layout aside { position: sticky; top: var(--env-var-spacing-2); diff --git a/Client/src/Pages/Infrastructure/index.jsx b/Client/src/Pages/Infrastructure/index.jsx index f079abfca..b58a306cd 100644 --- a/Client/src/Pages/Infrastructure/index.jsx +++ b/Client/src/Pages/Infrastructure/index.jsx @@ -6,24 +6,28 @@ import { TableBody, TableCell, TableContainer, + TableFooter, TableHead, + TablePagination, TableRow, } from "@mui/material"; import { Heading } from "../../Components/Heading"; import { useTheme } from "@emotion/react"; import Greeting from "../../Utils/greeting"; import Breadcrumbs from "../../Components/Breadcrumbs"; +import { StatusLabel } from "../../Components/Label"; +import { Gauge } from "../../Components/Charts/Gauge"; const mockedData = { ip: "https://192.168.1.30", - status: "Up", + status: "up", processor: "2Ghz", cpu: 80, mem: 50, disk: 70, }; -const ROWS = Array.from(Array(5).keys()).map(() => mockedData); +const ROWS = Array.from(Array(20).keys()).map(() => mockedData); console.log(ROWS); const columns = [ @@ -100,7 +104,9 @@ function Infrastructure() { marginBottom: "3rem", }} > - + + + - - - - - ); -}; - -TablePaginationActions.propTypes = { - count: PropTypes.number.isRequired, - page: PropTypes.number.isRequired, - rowsPerPage: PropTypes.number.isRequired, - onPageChange: PropTypes.func.isRequired, -}; +import { Pagination } from "../../../Infrastructure/components/TablePagination"; const MonitorTable = ({ isAdmin, filter, setIsSearching, isSearching }) => { const theme = useTheme(); @@ -117,6 +40,7 @@ const MonitorTable = ({ isAdmin, filter, setIsSearching, isSearching }) => { const { rowsPerPage } = useSelector((state) => state.ui.monitors); const authState = useSelector((state) => state.auth); + const [page, setPage] = useState(0); const [monitors, setMonitors] = useState([]); const [monitorCount, setMonitorCount] = useState(0); @@ -195,11 +119,11 @@ const MonitorTable = ({ isAdmin, filter, setIsSearching, isSearching }) => { * 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, monitorCount); - return `${start} - ${end}`; - }; + // const getRange = () => { + // let start = page * rowsPerPage + 1; + // let end = Math.min(page * rowsPerPage + rowsPerPage, monitorCount); + // return `${start} - ${end}`; + // }; const handleSort = async (field) => { let order = ""; @@ -392,78 +316,13 @@ const MonitorTable = ({ isAdmin, filter, setIsSearching, isSearching }) => { - - - Showing {getRange()} of {monitorCount} monitor(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={{ - 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, - }, - }} - /> - + ); }; diff --git a/Client/src/Pages/Monitors/Home/index.jsx b/Client/src/Pages/Monitors/Home/index.jsx index 345a0a88e..59655af92 100644 --- a/Client/src/Pages/Monitors/Home/index.jsx +++ b/Client/src/Pages/Monitors/Home/index.jsx @@ -20,6 +20,8 @@ const Monitors = ({ isAdmin }) => { const authState = useSelector((state) => state.auth); const dispatch = useDispatch({}); + console.log({ monitorState }); + useEffect(() => { dispatch(getUptimeMonitorsByTeamId(authState.authToken)); }, [authState.authToken, dispatch]); diff --git a/Client/src/Pages/Monitors/utils.jsx b/Client/src/Pages/Monitors/utils.jsx index 4dc4260cd..1c351d4ad 100644 --- a/Client/src/Pages/Monitors/utils.jsx +++ b/Client/src/Pages/Monitors/utils.jsx @@ -1,13 +1,15 @@ import { useTheme } from "@mui/material"; const useUtils = () => { - const theme = useTheme(); const determineState = (monitor) => { if (monitor.isActive === false) return "paused"; if (monitor?.status === undefined) return "pending"; return monitor?.status == true ? "up" : "down"; }; + /* TODO Refactor: from here on shouldn't live in a custom hook, but on theme, or constants */ + const theme = useTheme(); + const statusColor = { up: theme.palette.success.main, down: theme.palette.error.main, From 29db5ec50a2d25051850d0e937bee0761d8dbe72 Mon Sep 17 00:00:00 2001 From: Caio Cabral Date: Wed, 27 Nov 2024 21:24:04 -0500 Subject: [PATCH 10/26] refactor: changing the fetch for the infrastructure monitor --- .../infrastructureMonitorsSlice.js | 1 + Client/src/Pages/Infrastructure/index.jsx | 103 +++++++++++------- .../Monitors/Home/MonitorTable/index.jsx | 12 +- 3 files changed, 68 insertions(+), 48 deletions(-) diff --git a/Client/src/Features/InfrastructureMonitors/infrastructureMonitorsSlice.js b/Client/src/Features/InfrastructureMonitors/infrastructureMonitorsSlice.js index 7e0739cbd..f0282b28b 100644 --- a/Client/src/Features/InfrastructureMonitors/infrastructureMonitorsSlice.js +++ b/Client/src/Features/InfrastructureMonitors/infrastructureMonitorsSlice.js @@ -88,6 +88,7 @@ export const getInfrastructureMonitorsByTeamId = createAsyncThunk( teamId: user.teamId, types: ["hardware"], limit: 1, + rowsPerPage: 0, }); return res.data; } catch (error) { diff --git a/Client/src/Pages/Infrastructure/index.jsx b/Client/src/Pages/Infrastructure/index.jsx index 2d45fdb74..09e1c4559 100644 --- a/Client/src/Pages/Infrastructure/index.jsx +++ b/Client/src/Pages/Infrastructure/index.jsx @@ -1,3 +1,12 @@ +import { useCallback, useEffect, useState } from "react"; +import { useNavigate } from "react-router-dom"; +import { /* useDispatch, */ useSelector } from "react-redux"; +import { useTheme } from "@emotion/react"; +import useUtils from "../Monitors/utils"; +import { jwtDecode } from "jwt-decode"; +import Greeting from "../../Utils/greeting"; +import GearIcon from "../../Assets/icons/settings-bold.svg?react"; +import CPUChipIcon from "../../Assets/icons/cpu-chip.svg?react"; import { Box, Button, @@ -10,23 +19,14 @@ import { TableContainer, TableHead, TableRow, - // TablePagination, - // Typography, } from "@mui/material"; -import { useEffect } from "react"; -import { useNavigate } from "react-router-dom"; -import { useDispatch, useSelector } from "react-redux"; -import { useTheme } from "@emotion/react"; -import Greeting from "../../Utils/greeting"; -import GearIcon from "../../Assets/icons/settings-bold.svg?react"; -import CPUChipIcon from "../../Assets/icons/cpu-chip.svg?react"; import Breadcrumbs from "../../Components/Breadcrumbs"; import { StatusLabel } from "../../Components/Label"; import { Heading } from "../../Components/Heading"; import { Gauge } from "../../Components/Charts/Gauge"; -import { getInfrastructureMonitorsByTeamId } from "../../Features/InfrastructureMonitors/infrastructureMonitorsSlice"; -import useUtils from "../Monitors/utils"; import { Pagination } from "./components/TablePagination"; +// import { getInfrastructureMonitorsByTeamId } from "../../Features/InfrastructureMonitors/infrastructureMonitorsSlice"; +import { networkService } from "../../Utils/NetworkService.js"; // const ROWS = Array.from(Array(20).keys()).map(() => mockedData); @@ -73,17 +73,54 @@ Analyze existing BasicTable function Infrastructure(/* {isAdmin} */) { const theme = useTheme(); - const { determineState } = useUtils(); - const navigate = useNavigate(); - const dispatch = useDispatch(); - const { authToken } = useSelector((state) => state.auth); - const { isLoading, monitorsSummary, msg, success, ...rest } = useSelector( - (state) => state.infrastructureMonitors - ); - const { monitorCounts = {}, monitors = [] } = monitorsSummary; - const { total: totalMonitors = 0 } = monitorCounts; - console.log({ monitors }); + 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 [monitorState, setMonitorState] = useState({ monitors: [], total: 0 }); + + const { authToken } = useSelector((state) => state.auth); + const user = jwtDecode(authToken); + + const fetchMonitors = useCallback(async () => { + try { + const response = await networkService.getMonitorsByTeamId({ + authToken, + teamId: user.teamId, + limit: 1, + types: ["hardware"], + status: null, + checkOrder: "desc", + normalize: true, + page: page, + rowsPerPage: rowsPerPage, + }); + setMonitorState({ + monitors: response?.data?.data?.monitors ?? [], + total: response?.data?.data?.monitorCount ?? 0, + }); + } catch (error) { + console.error(error); + } + }, [page, rowsPerPage, authToken]); + + useEffect(() => { + fetchMonitors(); + }, [page, rowsPerPage]); + + const { determineState } = useUtils(); + const { monitors, total: totalMonitors } = monitorState; const monitorsAsRows = monitors.map((monitor) => ({ ip: monitor.name, status: determineState(monitor), @@ -93,11 +130,6 @@ function Infrastructure(/* {isAdmin} */) { disk: 70 /* How to retrieve that? */, })); - useEffect(() => { - dispatch(getInfrastructureMonitorsByTeamId(authToken)); - }, [authToken]); - // console.log({ isLoading, monitorsSummary, msg, success, rest }); - return ( { - navigate("/infrastructure/create"); - }} + onClick={navigateToCreate} sx={{ fontWeight: 500 }} > Create infrastructure monitor @@ -254,14 +284,13 @@ function Infrastructure(/* {isAdmin} */) { - {/* - TODO continue creating pagination component. It should change the current page, which will trigger refetch? - - */} - {/* */} + ); diff --git a/Client/src/Pages/Monitors/Home/MonitorTable/index.jsx b/Client/src/Pages/Monitors/Home/MonitorTable/index.jsx index bb3f5a65a..5370496bb 100644 --- a/Client/src/Pages/Monitors/Home/MonitorTable/index.jsx +++ b/Client/src/Pages/Monitors/Home/MonitorTable/index.jsx @@ -115,16 +115,6 @@ const MonitorTable = ({ isAdmin, filter, setIsSearching, isSearching }) => { prevFilter.current = filter; }, [filter, fetchPage]); - /** - * 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, monitorCount); - // return `${start} - ${end}`; - // }; - const handleSort = async (field) => { let order = ""; if (sort.field !== field) { @@ -317,11 +307,11 @@ const MonitorTable = ({ isAdmin, filter, setIsSearching, isSearching }) => { ); From 221ec015435bae357afe743cabd1c531a96957de Mon Sep 17 00:00:00 2001 From: Caio Cabral Date: Thu, 28 Nov 2024 17:54:04 -0500 Subject: [PATCH 11/26] feat: updating CustomGauge --- .../Components/Charts/CustomGauge/index.jsx | 31 +++++++++++-------- Client/src/Pages/Infrastructure/index.jsx | 6 ++-- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/Client/src/Components/Charts/CustomGauge/index.jsx b/Client/src/Components/Charts/CustomGauge/index.jsx index f3ad15b0b..cb74caf9e 100644 --- a/Client/src/Components/Charts/CustomGauge/index.jsx +++ b/Client/src/Components/Charts/CustomGauge/index.jsx @@ -4,6 +4,9 @@ import { Box, Typography } from "@mui/material"; import PropTypes from "prop-types"; import "./index.css"; +const MINIMUM_VALUE = 0; +const MAXIMUM_VALUE = 100; + /** * A Performant SVG based circular gauge * @@ -11,25 +14,21 @@ import "./index.css"; * @param {Object} props - Component properties * @param {number} [props.progress=0] - Progress percentage (0-100) * @param {number} [props.radius=60] - Radius of the gauge circle - * @param {string} [props.color="#000000"] - Color of the progress stroke * @param {number} [props.strokeWidth=15] - Width of the gauge stroke + * @param {number} [props.threshold=50] - Threshold for color change * * @example * * * @returns {React.ReactElement} Rendered CustomGauge component */ -const CustomGauge = ({ - progress = 0, - radius = 60, - color = "#000000", - strokeWidth = 15, -}) => { +const CustomGauge = ({ progress = 0, radius = 70, strokeWidth = 15, threshold = 50 }) => { + const theme = useTheme(); // Calculate the length of the stroke for the circle const { circumference, totalSize, strokeLength } = useMemo( () => ({ @@ -39,10 +38,9 @@ const CustomGauge = ({ }), [radius, strokeWidth, progress] ); - const [offset, setOffset] = useState(circumference); - const theme = useTheme(); // Handle initial animation + const [offset, setOffset] = useState(circumference); useEffect(() => { setOffset(circumference); const timer = setTimeout(() => { @@ -52,6 +50,13 @@ const CustomGauge = ({ return () => clearTimeout(timer); }, [progress, circumference, strokeLength]); + const progressWithinRange = Math.max(MINIMUM_VALUE, Math.min(progress, MAXIMUM_VALUE)); + + const fillColor = + progressWithinRange > threshold + ? theme.palette.primary.main + : theme.palette.percentage.uptimePoor; + return ( - {`${progress.toFixed(2)}%`} + {`${progressWithinRange.toFixed(1)}%`} ); @@ -108,6 +113,6 @@ export default CustomGauge; CustomGauge.propTypes = { progress: PropTypes.number, radius: PropTypes.number, - color: PropTypes.string, strokeWidth: PropTypes.number, + threshold: PropTypes.number, }; diff --git a/Client/src/Pages/Infrastructure/index.jsx b/Client/src/Pages/Infrastructure/index.jsx index 09e1c4559..f9b6ae41f 100644 --- a/Client/src/Pages/Infrastructure/index.jsx +++ b/Client/src/Pages/Infrastructure/index.jsx @@ -27,6 +27,7 @@ import { Gauge } from "../../Components/Charts/Gauge"; import { Pagination } from "./components/TablePagination"; // import { getInfrastructureMonitorsByTeamId } from "../../Features/InfrastructureMonitors/infrastructureMonitorsSlice"; import { networkService } from "../../Utils/NetworkService.js"; +import CustomGauge from "../../Components/Charts/CustomGauge/index.jsx"; // const ROWS = Array.from(Array(20).keys()).map(() => mockedData); @@ -246,10 +247,11 @@ function Infrastructure(/* {isAdmin} */) { - + /> */} + Date: Fri, 29 Nov 2024 10:17:09 -0500 Subject: [PATCH 12/26] refactor: changing friendly to display name --- .../Components/Charts/CustomGauge/index.jsx | 4 +-- Client/src/Components/Charts/Gauge/index.jsx | 2 ++ .../Infrastructure/CreateMonitor/index.jsx | 3 +- Client/src/Pages/Infrastructure/index.jsx | 36 +++++++++---------- 4 files changed, 22 insertions(+), 23 deletions(-) diff --git a/Client/src/Components/Charts/CustomGauge/index.jsx b/Client/src/Components/Charts/CustomGauge/index.jsx index cb74caf9e..44512aa60 100644 --- a/Client/src/Components/Charts/CustomGauge/index.jsx +++ b/Client/src/Components/Charts/CustomGauge/index.jsx @@ -54,8 +54,8 @@ const CustomGauge = ({ progress = 0, radius = 70, strokeWidth = 15, threshold = const fillColor = progressWithinRange > threshold - ? theme.palette.primary.main - : theme.palette.percentage.uptimePoor; + ? theme.palette.percentage.uptimePoor + : theme.palette.primary.main; return ( { mockedData); - const columns = [ { label: "Host" }, { label: "Status" }, @@ -41,6 +38,8 @@ const columns = [ { label: "Actions" }, ]; +const BREADCRUMBS = [{ name: `infrastructure`, path: "/infrastructure" }]; + /* TODO Create reusable table component. It should receive as a parameter the following object: @@ -122,21 +121,28 @@ function Infrastructure(/* {isAdmin} */) { const { determineState } = useUtils(); const { monitors, total: totalMonitors } = monitorState; + console.log({ monitors }); + console.log(monitors[0]?.checks[0]?.memory.usage_percent); const monitorsAsRows = monitors.map((monitor) => ({ ip: monitor.name, status: determineState(monitor), - processor: "2Ghz" /* How to retrieve that? */, - cpu: 80 /* How to retrieve that? */, - mem: 50 /* How to retrieve that? */, - disk: 70 /* How to retrieve that? */, + processor: (monitor?.checks[0]?.cpu.frequency / 1000).toFixed(2) + " GHz", + cpu: monitor?.checks[0]?.cpu.usage_percent * 100, + mem: monitor?.checks[0]?.memory.usage_percent * 100, + disk: monitor?.checks[0]?.disk[0]?.usage_percent * 100, })); + /* TODO when friendyly name i added, it shoul display frindly name + url */ + /* TODO remove table scrollbar */ + /* Fix search in monitors page */ + /* Adding actions to the table */ + /* Adding click on row action */ return ( - + - {/* */} - + - + {/* Get ActionsMenu from Monitor Table and create a component */} From 5ad2df1d8463bc9f7f8e814dbfd133993e1c1841 Mon Sep 17 00:00:00 2001 From: Caio Cabral Date: Fri, 29 Nov 2024 10:35:07 -0500 Subject: [PATCH 13/26] feat: adding Host component to Infrastructure and adapting it --- Client/src/Pages/Infrastructure/index.jsx | 11 ++++- .../Monitors/Home/MonitorTable/index.jsx | 5 ++- Client/src/Pages/Monitors/Home/host.jsx | 40 ++++++++++--------- 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/Client/src/Pages/Infrastructure/index.jsx b/Client/src/Pages/Infrastructure/index.jsx index f7c02eae9..84df4bf6c 100644 --- a/Client/src/Pages/Infrastructure/index.jsx +++ b/Client/src/Pages/Infrastructure/index.jsx @@ -27,6 +27,7 @@ import { Pagination } from "./components/TablePagination"; // import { getInfrastructureMonitorsByTeamId } from "../../Features/InfrastructureMonitors/infrastructureMonitorsSlice"; import { networkService } from "../../Utils/NetworkService.js"; import CustomGauge from "../../Components/Charts/CustomGauge/index.jsx"; +import Host from "../Monitors/Home/host.jsx"; const columns = [ { label: "Host" }, @@ -124,7 +125,8 @@ function Infrastructure(/* {isAdmin} */) { console.log({ monitors }); console.log(monitors[0]?.checks[0]?.memory.usage_percent); const monitorsAsRows = monitors.map((monitor) => ({ - ip: monitor.name, + url: monitor.url, + name: monitor.name, status: determineState(monitor), processor: (monitor?.checks[0]?.cpu.frequency / 1000).toFixed(2) + " GHz", cpu: monitor?.checks[0]?.cpu.usage_percent * 100, @@ -228,7 +230,12 @@ function Infrastructure(/* {isAdmin} */) { /* ROWS */ monitorsAsRows.map((row, index) => ( {/* TODO iterate over column and get column id, applying row[column.id] */} - {row.ip} + + + { diff --git a/Client/src/Pages/Monitors/Home/host.jsx b/Client/src/Pages/Monitors/Home/host.jsx index 104eb29e7..68871cfe7 100644 --- a/Client/src/Pages/Monitors/Home/host.jsx +++ b/Client/src/Pages/Monitors/Home/host.jsx @@ -6,12 +6,14 @@ import PropTypes from "prop-types"; * * @component * @param {Object} params - An object containing the following properties: + * @param {string} params.url - The URL of the host. * @param {string} params.title - The name of the host. * @param {string} params.percentageColor - The color of the percentage text. * @param {number} params.percentage - The percentage to display. * @returns {React.ElementType} Returns a div element with the host details. */ -const Host = ({ params }) => { +const Host = ({ url, title, percentageColor, percentage }) => { + const noTitle = title === undefined || title === url; return ( { }, }} > - {params.title} + {title} - - {params.percentage}% - - {params.url} + {percentageColor && percentage && ( + + {percentage}% + + )} + {!noTitle && {url}} ); }; Host.propTypes = { - params: PropTypes.shape({ - title: PropTypes.string, - percentageColor: PropTypes.string, - percentage: PropTypes.string, - url: PropTypes.string, - }).isRequired, + title: PropTypes.string, + percentageColor: PropTypes.string, + percentage: PropTypes.string, + url: PropTypes.string, }; export default Host; From a04d81d6a6c7d18e01e84d0cac9c33348fa35a82 Mon Sep 17 00:00:00 2001 From: Caio Cabral Date: Fri, 29 Nov 2024 10:38:31 -0500 Subject: [PATCH 14/26] fix: remove scrollbar from table and remove greeting from infratructure page --- Client/src/Pages/Infrastructure/index.jsx | 29 ++++++----------------- 1 file changed, 7 insertions(+), 22 deletions(-) diff --git a/Client/src/Pages/Infrastructure/index.jsx b/Client/src/Pages/Infrastructure/index.jsx index 84df4bf6c..dcf8297c4 100644 --- a/Client/src/Pages/Infrastructure/index.jsx +++ b/Client/src/Pages/Infrastructure/index.jsx @@ -4,7 +4,6 @@ import { /* useDispatch, */ useSelector } from "react-redux"; import { useTheme } from "@emotion/react"; import useUtils from "../Monitors/utils"; import { jwtDecode } from "jwt-decode"; -import Greeting from "../../Utils/greeting"; import GearIcon from "../../Assets/icons/settings-bold.svg?react"; import CPUChipIcon from "../../Assets/icons/cpu-chip.svg?react"; import { @@ -133,8 +132,7 @@ function Infrastructure(/* {isAdmin} */) { mem: monitor?.checks[0]?.memory.usage_percent * 100, disk: monitor?.checks[0]?.disk[0]?.usage_percent * 100, })); - /* TODO when friendyly name i added, it shoul display frindly name + url */ - /* TODO remove table scrollbar */ + /* Fix search in monitors page */ /* Adding actions to the table */ /* Adding click on row action */ @@ -148,16 +146,18 @@ function Infrastructure(/* {isAdmin} */) { + {/* + This will be removed from here, but keeping the commented code to remind me to add a max width to the greeting component - + */}