From 3c6fdbd726175b0fcbefc93666fe935aac387743 Mon Sep 17 00:00:00 2001 From: "Gorkem Cetin (BWL)" <167266851+gorkem-bwl@users.noreply.github.com> Date: Wed, 17 Jul 2024 14:22:38 -0400 Subject: [PATCH 1/5] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a11d6f770..31e38f10a 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ BlueWave Uptime is an open source server monitoring application. It is a tool us ## Contributing -You are welcome to provide contributions to the project. It uses React on the FE, and Nodejs and MongoDB on the BE, hence if you are comfortable with working with those technologies, you are encouraged to send your PRs. Please read [Contributor's guideline](https://github.com/bluewave-labs/bluewave-uptime/blob/master/CONTRIBUTING.md) +You are welcome to provide contributions to the project. It uses React on the FE, and Nodejs and MongoDB on the BE, hence if you are comfortable with working with those technologies, you are encouraged to send your PRs. Please read [Contributor's guideline](https://github.com/bluewave-labs/bluewave-uptime/blob/master/CONTRIBUTING.md). Once you start contributing, we'd be happy to add you to our weekly team calls as well. Note that We have a Figma file that includes: From 1714cd9054bf7b8175e3f7dc8a9c2b37e966bc07 Mon Sep 17 00:00:00 2001 From: "Gorkem Cetin (BWL)" <167266851+gorkem-bwl@users.noreply.github.com> Date: Wed, 17 Jul 2024 14:24:26 -0400 Subject: [PATCH 2/5] Fix README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 31e38f10a..16d5232c9 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,11 @@ # BlueWave Uptime -BlueWave Uptime is an open source server monitoring application. It is a tool used to track the operational status and performance of servers and websites. It regularly checks whether a server/website is accessible and performing optimally, providing real-time alerts and reports on the availability, downtime, and response time of the monitored services. +BlueWave Uptime is an open source server monitoring application. It is used to track the operational status and performance of servers and websites. It regularly checks whether a server/website is accessible and performs optimally, providing real-time alerts and reports on the monitored services' availability, downtime, and response time. ## Contributing -You are welcome to provide contributions to the project. It uses React on the FE, and Nodejs and MongoDB on the BE, hence if you are comfortable with working with those technologies, you are encouraged to send your PRs. Please read [Contributor's guideline](https://github.com/bluewave-labs/bluewave-uptime/blob/master/CONTRIBUTING.md). Once you start contributing, we'd be happy to add you to our weekly team calls as well. +You are welcome to provide contributions to the project. It uses React on the FE, and Nodejs and MongoDB on the BE, hence if you are comfortable with working with those technologies, you are encouraged to send your PRs. Please read [Contributor's guideline](https://github.com/bluewave-labs/bluewave-uptime/blob/master/CONTRIBUTING.md). Once you start contributing, we can also add you to our weekly team calls (every Thursday). Note that We have a Figma file that includes: From 70e06d62f18a6fcc6a576cfb1d70aef09f4a48cc Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Wed, 17 Jul 2024 11:29:25 -0700 Subject: [PATCH 3/5] Add status label and StatBox component --- Client/src/Pages/Details/index.jsx | 102 +++++++++++++++++++++++------ Client/src/main.jsx | 20 +++--- 2 files changed, 90 insertions(+), 32 deletions(-) diff --git a/Client/src/Pages/Details/index.jsx b/Client/src/Pages/Details/index.jsx index c53054ccd..9764a66fc 100644 --- a/Client/src/Pages/Details/index.jsx +++ b/Client/src/Pages/Details/index.jsx @@ -1,9 +1,38 @@ import React, { useEffect, useState } from "react"; +import PropTypes from "prop-types"; import { Box, Typography, useTheme } from "@mui/material"; import { useSelector } from "react-redux"; import { useParams } from "react-router-dom"; import axiosInstance from "../../Utils/axiosConfig"; import BasicTable from "../../Components/BasicTable"; +import StatusLabel from "../../Components/StatusLabel"; + +const formatDuration = (ms) => { + const seconds = Math.floor(ms / 1000); + const minutes = Math.floor(seconds / 60); + const hours = Math.floor(minutes / 60); + const days = Math.floor(hours / 24); + + let dateStr = ""; + + days && (dateStr += `${days}d `); + hours && (dateStr += `${hours % 24}h `); + minutes && (dateStr += `${minutes % 60}m `); + seconds && (dateStr += `${seconds % 60}s `); + + dateStr === "" && (dateStr = "0s"); + + return dateStr; +}; + +const StatBox = ({ title, value }) => { + return ( + + {title} + {value} + + ); +}; /** * Details page component displaying monitor details and related information. @@ -29,10 +58,22 @@ const DetailsPage = () => { { id: 3, name: "Message" }, ], rows: res.data.data.checks.map((check, idx) => { + const params = { + status: check.status === true ? "up" : "down", + backgroundColor: + check.status === true + ? "var(--env-var-color-20)" + : "var(--env-var-color-21)", + statusDotColor: + check.status === true + ? "var(--env-var-color-17)" + : "var(--env-var-color-19)", + }; + return { id: check._id, data: [ - { id: idx, data: check.status ? "Up" : "Down" }, + { id: idx, data: }, { id: idx + 1, data: new Date(check.createdAt).toLocaleString() }, { id: idx + 2, data: check.statusCode }, ], @@ -52,43 +93,47 @@ const DetailsPage = () => { * @param {Array} checks Array of check objects. * @returns {number} Uptime duration in ms. */ + + // TODO: This can be done more efficiently by iteratting backwards + // and breaking when the first down check is found, calculate current time - downtime const calculateUptimeDuration = (checks) => { if (!checks || checks.length === 0) { return 0; } - let longestDuration = 0; - let lastDownTimestamp = null; - let currentDuration = longestDuration; + const arr = [...checks]; - // Loop over the checks to find the most recent uptime duration - checks.forEach((check) => { + let lastDownTimestamp = null; + let lastUpTimestamp = null; + + arr.sort((a, b) => new Date(a.createdAt) - new Date(b.createdAt)); + arr.forEach((check) => { if (check.status === false) { - lastDownTimestamp = check.createdAt; - } else if (check.status === true && lastDownTimestamp) { - currentDuration = check.createdAt - lastDownTimestamp; - if (currentDuration > longestDuration) { - longestDuration = currentDuration; - } - lastDownTimestamp = null; + lastDownTimestamp = new Date(check.createdAt); + } else if (check.status === true) { + lastUpTimestamp = new Date(check.createdAt); } }); - lastDownTimestamp = null; - return longestDuration; + + if (lastDownTimestamp === null) { + return new Date() - new Date(arr[0].createdAt); + } else if (lastUpTimestamp === null) { + return 0; + } else if (lastDownTimestamp && lastUpTimestamp) { + return lastUpTimestamp - lastDownTimestamp; + } }; /** - * Helper function to get timestamp of the most recent check. + * Helper function to get duration since last check * @param {Array} checks Array of check objects. * @returns {number} Timestamp of the most recent check. */ - const getLastCheckedTimestamp = (checks) => { + const getLastChecked = (checks) => { if (!checks || checks.length === 0) { return 0; // Handle case when no checks are available } - - const mostRecentCheck = checks[0]; - return mostRecentCheck.createdAt; + return new Date() - new Date(checks[0].createdAt); }; /** @@ -101,15 +146,30 @@ const DetailsPage = () => { return 0; // Handle case when no checks are available } return checks.reduce((acc, check) => { - check.status === false ? (acc += 1) : acc; + return check.status === false ? (acc += 1) : acc; }, 0); }; return (
+
+ + + +
); }; +StatBox.propTypes = { + title: PropTypes.string, + value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), +}; export default DetailsPage; diff --git a/Client/src/main.jsx b/Client/src/main.jsx index 09754147d..f9fa3d640 100644 --- a/Client/src/main.jsx +++ b/Client/src/main.jsx @@ -13,15 +13,13 @@ import { injectStore } from "./Utils/axiosConfig.js"; injectStore(store); ReactDOM.createRoot(document.getElementById("root")).render( - - - - - - - - - - - + + + + + + + + + ); From b7e6e44b88d1c16f27f84ec7b298b177e65f34d7 Mon Sep 17 00:00:00 2001 From: Daniel Cojocea Date: Wed, 17 Jul 2024 14:33:32 -0400 Subject: [PATCH 4/5] Added styling to basic table component --- Client/src/Components/BasicTable/index.css | 118 +++++++++++++++++++ Client/src/Components/BasicTable/index.jsx | 44 ++++--- Client/src/Components/MonitorTable/index.css | 4 +- Client/src/Components/MonitorTable/index.jsx | 13 +- 4 files changed, 161 insertions(+), 18 deletions(-) diff --git a/Client/src/Components/BasicTable/index.css b/Client/src/Components/BasicTable/index.css index e69de29bb..723f6c796 100644 --- a/Client/src/Components/BasicTable/index.css +++ b/Client/src/Components/BasicTable/index.css @@ -0,0 +1,118 @@ +.MuiTable-root .host-row { + display: flex; + align-items: center; +} + +.MuiTable-root .host-row a { + width: var(--env-var-img-width-2); + height: var(--env-var-img-width-2); + color: var(--env-var-color-5); + margin-right: 10px; + margin-bottom: 2px; +} +.MuiTable-root .host-row a svg { + width: var(--env-var-font-size-large); + height: var(--env-var-font-size-large); +} +.MuiTable-root .host-row .host-percentage { + font-size: var(--env-var-font-size-small); +} + +.MuiTable-root .host-name { + width: fit-content; + margin-right: 10px; + font-weight: 700; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; +} + +.MuiPaper-root:has(table.MuiTable-root) { + box-shadow: none; + border: solid 1px var(--env-var-color-16); + border-radius: var(--env-var-radius-1); +} +.MuiTable-root + .MuiTableBody-root + .MuiTableRow-root:last-child + .MuiTableCell-root { + border: none; +} +.MuiTable-root .MuiTableHead-root, +.MuiTable-root .MuiTableRow-root:hover { + background-color: var(--env-var-color-13); +} +.MuiTable-root .MuiTableHead-root .MuiTableCell-root, +.MuiTable-root .MuiTableBody-root .MuiTableCell-root { + font-size: var(--env-var-font-size-medium); +} +.MuiTable-root .MuiTableHead-root .MuiTableCell-root { + padding: var(--env-var-spacing-1) var(--env-var-spacing-2); + font-weight: 500; + color: var(--env-var-color-2); +} +.MuiTable-root .MuiTableHead-root span { + display: inline-block; + height: 17px; + width: 20px; + overflow: hidden; + margin-bottom: -3px; + margin-left: 3px; +} +.MuiTable-root .MuiTableHead-root span svg { + width: 20px; + height: 20px; +} +.MuiTable-root .MuiTableBody-root .MuiTableCell-root { + color: var(--env-var-color-5); + padding: 6px var(--env-var-spacing-2); +} + +.MuiPaper-root + .MuiPagination-root { + flex: 1; + margin-top: 35px; + border: solid 1px var(--env-var-color-16); + border-radius: var(--env-var-radius-1); + padding: var(--env-var-spacing-1-plus) var(--env-var-spacing-2); +} +.MuiPaper-root + .MuiPagination-root ul { + justify-content: center; +} +.MuiPaper-root + .MuiPagination-root ul li button { + font-size: var(--env-var-font-size-medium); + color: var(--env-var-color-5); + font-weight: 500; +} +.MuiPaper-root + .MuiPagination-root ul li:first-child { + margin-right: auto; +} +.MuiPaper-root + .MuiPagination-root ul li:last-child { + margin-left: auto; +} +.MuiPaper-root + .MuiPagination-root ul li:first-child button, +.MuiPaper-root + .MuiPagination-root ul li:last-child button { + border: solid 1px var(--env-var-color-16); + border-radius: var(--env-var-radius-1); +} +.MuiPaper-root + .MuiPagination-root ul li:first-child button { + padding: 0 var(--env-var-spacing-1) 0 var(--env-var-spacing-1-plus); +} +.MuiPaper-root + .MuiPagination-root ul li:last-child button { + padding: 0 var(--env-var-spacing-1-plus) 0 var(--env-var-spacing-1); +} +.MuiPaper-root + .MuiPagination-root ul li:first-child button::after, +.MuiPaper-root + .MuiPagination-root ul li:last-child button::before { + position: relative; + display: inline-block; +} +.MuiPaper-root + .MuiPagination-root ul li:first-child button::after { + content: "Previous"; + margin-left: 15px; +} +.MuiPaper-root + .MuiPagination-root ul li:last-child button::before { + content: "Next"; + margin-right: 15px; +} +.MuiPaper-root + .MuiPagination-root .MuiPaginationItem-root.Mui-selected { + background-color: var(--env-var-color-15); +} diff --git a/Client/src/Components/BasicTable/index.jsx b/Client/src/Components/BasicTable/index.jsx index bd716d793..393ba18ca 100644 --- a/Client/src/Components/BasicTable/index.jsx +++ b/Client/src/Components/BasicTable/index.jsx @@ -6,10 +6,14 @@ import { TableRow, TableCell, TableBody, - TablePagination, + Pagination, + PaginationItem, } from "@mui/material"; import React, { useState } from "react"; import PropTypes from "prop-types"; +import "./index.css"; +import ArrowBackRoundedIcon from "@mui/icons-material/ArrowBackRounded"; +import ArrowForwardRoundedIcon from "@mui/icons-material/ArrowForwardRounded"; /** * BasicTable Component @@ -66,17 +70,12 @@ const BasicTable = ({ data, paginated }) => { // Add headers to props validation const [page, setPage] = useState(0); - const [rowsPerPage, setRowsPerPage] = useState(5); + const rowsPerPage = 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 - }; - let displayData = []; if (data && data.rows) { @@ -118,14 +117,29 @@ const BasicTable = ({ data, paginated }) => { {paginated === true && ( - handleChangePage(event, value - 1)} + shape="rounded" + renderItem={(item) => ( + + )} /> )} diff --git a/Client/src/Components/MonitorTable/index.css b/Client/src/Components/MonitorTable/index.css index 4339f261b..53ef45f30 100644 --- a/Client/src/Components/MonitorTable/index.css +++ b/Client/src/Components/MonitorTable/index.css @@ -1,4 +1,4 @@ -.host-row { +/* .host-row { display: flex; align-items: center; } @@ -109,4 +109,4 @@ .monitors .MuiPagination-root ul li:last-child button::before { content: "Next"; margin-right: 15px; -} +} */ diff --git a/Client/src/Components/MonitorTable/index.jsx b/Client/src/Components/MonitorTable/index.jsx index 57bfd125c..58ebf6689 100644 --- a/Client/src/Components/MonitorTable/index.jsx +++ b/Client/src/Components/MonitorTable/index.jsx @@ -5,6 +5,7 @@ import BasicTable from "../BasicTable"; import OpenInNewPage from "../../assets/icons/open-in-new-page.svg?react"; import { useNavigate } from "react-router-dom"; import StatusLabel from "../StatusLabel"; +import ArrowDownwardRoundedIcon from "@mui/icons-material/ArrowDownwardRounded"; /** * Host component. @@ -54,7 +55,17 @@ const MonitorTable = ({ monitors = [] }) => { const data = { cols: [ { id: 1, name: "Host" }, - { id: 2, name: "Status" }, + { + id: 2, + name: ( + <> + Status + + + + + ), + }, { id: 3, name: "Response Time" }, { id: 4, name: "Actions" }, ], From 5c8aaccad8961c45833d50e265c4a8f9e08a618c Mon Sep 17 00:00:00 2001 From: Daniel Cojocea Date: Wed, 17 Jul 2024 14:59:37 -0400 Subject: [PATCH 5/5] Added some styling to monitor details page --- Client/src/Components/BasicTable/index.css | 3 +++ Client/src/Layouts/HomeLayout/index.css | 2 +- Client/src/Pages/Details/index.jsx | 10 +++++++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Client/src/Components/BasicTable/index.css b/Client/src/Components/BasicTable/index.css index 723f6c796..a1fe7845d 100644 --- a/Client/src/Components/BasicTable/index.css +++ b/Client/src/Components/BasicTable/index.css @@ -67,6 +67,9 @@ color: var(--env-var-color-5); padding: 6px var(--env-var-spacing-2); } +.MuiTable-root .MuiTableBody-root .MuiTableRow-root { + height: 50px; +} .MuiPaper-root + .MuiPagination-root { flex: 1; diff --git a/Client/src/Layouts/HomeLayout/index.css b/Client/src/Layouts/HomeLayout/index.css index c9faf48d4..76065015b 100644 --- a/Client/src/Layouts/HomeLayout/index.css +++ b/Client/src/Layouts/HomeLayout/index.css @@ -8,6 +8,6 @@ .main-content>div:nth-child(2){ position: relative; - overflow-y: auto; + /* overflow-y: auto; */ flex: 1; } diff --git a/Client/src/Pages/Details/index.jsx b/Client/src/Pages/Details/index.jsx index c53054ccd..c5f57383a 100644 --- a/Client/src/Pages/Details/index.jsx +++ b/Client/src/Pages/Details/index.jsx @@ -106,7 +106,15 @@ const DetailsPage = () => { }; return ( -
+
+ + History +
);