From cec8ecd98529c3cc072a33d5791887128e49ebd5 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Thu, 5 Sep 2024 11:17:31 -0700 Subject: [PATCH 1/7] add DB and controller methods --- Server/controllers/monitorController.js | 40 +++++++++++++++++++++++- Server/db/mongo/MongoDB.js | 4 +-- Server/db/mongo/modules/monitorModule.js | 37 ++++++++++++++++++++++ 3 files changed, 78 insertions(+), 3 deletions(-) diff --git a/Server/controllers/monitorController.js b/Server/controllers/monitorController.js index 091d41e2a..f5c42607c 100644 --- a/Server/controllers/monitorController.js +++ b/Server/controllers/monitorController.js @@ -16,6 +16,9 @@ const { const sslChecker = require("ssl-checker"); const SERVICE_NAME = "monitorController"; const { errorMessages, successMessages } = require("../utils/messages"); +const { + getMonitorsAndSummaryByTeamId, +} = require("../db/mongo/modules/monitorModule"); /** * Returns all monitors @@ -186,7 +189,41 @@ const getMonitorById = async (req, res, next) => { }; /** - * Returns all monitors belong to User with UserID + * Returns all monitors and a sumamry for a team with TeamID + * @async + * @param {Express.Request} req + * @param {Express.Response} res + * @returns {Promise} + * @throws {Error} + */ + +const getMonitorsAndSumamryByTeamId = async (req, res, next) => { + try { + //validation + } catch (error) { + error.status = 422; + error.service = SERVICE_NAME; + error.method === undefined && + error.method === "getMonitorsAndSummaryByTeamId"; + error.message = + error.details?.[0]?.message || error.message || "Validation Error"; + next(error); + return; + } + + try { + const { teamId, type } = req.params; + await req.db.getMonitorsAndSummaryByTeamId(req, res); + } catch (error) { + error.service = SERVICE_NAME; + error.method === undefined && + error.method === "getMonitorsAndSummaryByTeamId"; + next(error); + } +}; + +/** + * Returns all monitors belong to team with TeamID * @async * @param {Express.Request} req * @param {Express.Response} res @@ -424,6 +461,7 @@ module.exports = { getMonitorStatsById, getMonitorCertificate, getMonitorById, + getMonitorsAndSummaryByTeamId, getMonitorsByTeamId, createMonitor, deleteMonitor, diff --git a/Server/db/mongo/MongoDB.js b/Server/db/mongo/MongoDB.js index 29233b73a..d6a4a243f 100644 --- a/Server/db/mongo/MongoDB.js +++ b/Server/db/mongo/MongoDB.js @@ -64,10 +64,9 @@ const { const { getAllMonitors, - getMonitorAggregateStats, - testMethod, getMonitorStatsById, getMonitorById, + getMonitorsAndSummaryByTeamId, getMonitorsByTeamId, createMonitor, deleteMonitor, @@ -148,6 +147,7 @@ module.exports = { getAllMonitors, getMonitorStatsById, getMonitorById, + getMonitorsAndSummaryByTeamId, getMonitorsByTeamId, createMonitor, deleteMonitor, diff --git a/Server/db/mongo/modules/monitorModule.js b/Server/db/mongo/modules/monitorModule.js index 0b1a38140..d8b11d5a1 100644 --- a/Server/db/mongo/modules/monitorModule.js +++ b/Server/db/mongo/modules/monitorModule.js @@ -292,6 +292,42 @@ const getMonitorById = async (monitorId) => { } }; +/** + * Get monitors and Summary by TeamID + * @async + * @param {Express.Request} req + * @param {Express.Response} res + * @returns {Promise>} + * @throws {Error} + */ + +const getMonitorsAndSummaryByTeamId = async (teamId, type) => { + try { + const monitors = await Monitor.find({ teamId, type }); + const monitorCounts = monitors.reduce( + (acc, monitor) => { + if (monitor.status === true) { + acc.up += 1; + } + + if (monitor.status === false) { + acc.up += 1; + } + + if (monitor.isActive === false) { + acc.paused += 1; + } + }, + { up: 0, down: 0, paused: 0 } + ); + monitorCounts.total = monitors.length; + return { monitors, monitorCounts }; + } catch (error) { + error.methodName = "getMonitorsAndSummaryByTeamId"; + throw error; + } +}; + /** * Get monitors by TeamID * @async @@ -464,6 +500,7 @@ module.exports = { getAllMonitors, getMonitorStatsById, getMonitorById, + getMonitorsAndSummaryByTeamId, getMonitorsByTeamId, createMonitor, deleteMonitor, From 9eaab0da1a0669327407ce3a5a6e4aaa0eabe2b4 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Thu, 5 Sep 2024 12:16:29 -0700 Subject: [PATCH 2/7] Add network requests and validation --- .../UptimeMonitors/uptimeMonitorsSlice.js | 8 ++---- Client/src/Utils/NetworkService.js | 21 +++++++++++++++- Server/controllers/monitorController.js | 25 +++++++++++++------ Server/db/mongo/modules/monitorModule.js | 6 +++-- Server/routes/monitorRoute.js | 4 +++ Server/validation/joi.js | 15 +++++++++++ 6 files changed, 63 insertions(+), 16 deletions(-) diff --git a/Client/src/Features/UptimeMonitors/uptimeMonitorsSlice.js b/Client/src/Features/UptimeMonitors/uptimeMonitorsSlice.js index 79789e16b..59a40e1c4 100644 --- a/Client/src/Features/UptimeMonitors/uptimeMonitorsSlice.js +++ b/Client/src/Features/UptimeMonitors/uptimeMonitorsSlice.js @@ -53,14 +53,10 @@ export const getUptimeMonitorsByTeamId = createAsyncThunk( async (token, thunkApi) => { const user = jwtDecode(token); try { - const res = await networkService.getMonitorsByTeamId( + const res = await networkService.getMonitorsAndSummaryByTeamId( token, user.teamId, - 25, - ["http", "ping"], - null, - "desc", - true + ["http", "ping"] ); return res.data; } catch (error) { diff --git a/Client/src/Utils/NetworkService.js b/Client/src/Utils/NetworkService.js index 4c8dd57e8..e4b7be526 100644 --- a/Client/src/Utils/NetworkService.js +++ b/Client/src/Utils/NetworkService.js @@ -58,9 +58,28 @@ class NetworkService { }); } + async getMonitorsAndSummaryByTeamId(authToken, teamId, types) { + const params = new URLSearchParams(); + + if (types) { + types.forEach((type) => { + params.append("type", type); + }); + } + return this.axiosInstance.get( + `/monitors/team/summary/${teamId}?${params.toString()}`, + { + headers: { + Authorization: `Bearer ${authToken}`, + "Content-Type": "application/json", + }, + } + ); + } + /** * ************************************ - * Get all uptime monitors for a user + * Get all uptime monitors for a Team * ************************************ * * @async diff --git a/Server/controllers/monitorController.js b/Server/controllers/monitorController.js index f5c42607c..9be234353 100644 --- a/Server/controllers/monitorController.js +++ b/Server/controllers/monitorController.js @@ -4,6 +4,8 @@ const { getMonitorsByTeamIdValidation, createMonitorBodyValidation, editMonitorBodyValidation, + getMonitorsAndSumamryByTeamIdParamValidation, + getMonitorsAndSummaryByTeamIdQueryValidation, getMonitorsByTeamIdQueryValidation, pauseMonitorParamValidation, getMonitorStatsByIdParamValidation, @@ -16,10 +18,6 @@ const { const sslChecker = require("ssl-checker"); const SERVICE_NAME = "monitorController"; const { errorMessages, successMessages } = require("../utils/messages"); -const { - getMonitorsAndSummaryByTeamId, -} = require("../db/mongo/modules/monitorModule"); - /** * Returns all monitors * @async @@ -197,8 +195,12 @@ const getMonitorById = async (req, res, next) => { * @throws {Error} */ -const getMonitorsAndSumamryByTeamId = async (req, res, next) => { +const getMonitorsAndSummaryByTeamId = async (req, res, next) => { try { + await getMonitorsAndSumamryByTeamIdParamValidation.validateAsync( + req.params + ); + await getMonitorsAndSummaryByTeamIdQueryValidation.validateAsync(req.query); //validation } catch (error) { error.status = 422; @@ -212,8 +214,17 @@ const getMonitorsAndSumamryByTeamId = async (req, res, next) => { } try { - const { teamId, type } = req.params; - await req.db.getMonitorsAndSummaryByTeamId(req, res); + const { teamId } = req.params; + const { type } = req.query; + const monitorsSummary = await req.db.getMonitorsAndSummaryByTeamId( + teamId, + type + ); + return res.status(200).json({ + success: true, + msg: successMessages.MONITOR_GET_BY_USER_ID(teamId), + data: monitorsSummary, + }); } catch (error) { error.service = SERVICE_NAME; error.method === undefined && diff --git a/Server/db/mongo/modules/monitorModule.js b/Server/db/mongo/modules/monitorModule.js index d8b11d5a1..dd96e6450 100644 --- a/Server/db/mongo/modules/monitorModule.js +++ b/Server/db/mongo/modules/monitorModule.js @@ -311,19 +311,21 @@ const getMonitorsAndSummaryByTeamId = async (teamId, type) => { } if (monitor.status === false) { - acc.up += 1; + acc.down += 1; } if (monitor.isActive === false) { acc.paused += 1; } + return acc; }, { up: 0, down: 0, paused: 0 } ); + console.log(monitorCounts); monitorCounts.total = monitors.length; return { monitors, monitorCounts }; } catch (error) { - error.methodName = "getMonitorsAndSummaryByTeamId"; + error.method = "getMonitorsAndSummaryByTeamId"; throw error; } }; diff --git a/Server/routes/monitorRoute.js b/Server/routes/monitorRoute.js index 7831f42f7..b29b7130a 100644 --- a/Server/routes/monitorRoute.js +++ b/Server/routes/monitorRoute.js @@ -7,6 +7,10 @@ router.get("/aggregate/:monitorId", monitorController.getMonitorAggregateStats); router.get("/stats/:monitorId", monitorController.getMonitorStatsById); router.get("/certificate/:monitorId", monitorController.getMonitorCertificate); router.get("/:monitorId", monitorController.getMonitorById); +router.get( + "/team/summary/:teamId", + monitorController.getMonitorsAndSummaryByTeamId +); router.get("/team/:teamId", monitorController.getMonitorsByTeamId); router.post( diff --git a/Server/validation/joi.js b/Server/validation/joi.js index 090a49a7a..22aec5eb8 100644 --- a/Server/validation/joi.js +++ b/Server/validation/joi.js @@ -161,6 +161,19 @@ const getMonitorByIdQueryValidation = joi.object({ normalize: joi.boolean(), }); +const getMonitorsAndSumamryByTeamIdParamValidation = joi.object({ + teamId: joi.string().required(), +}); + +const getMonitorsAndSummaryByTeamIdQueryValidation = joi.object({ + type: joi + .alternatives() + .try( + joi.string().valid("http", "ping", "pagespeed"), + joi.array().items(joi.string().valid("http", "ping", "pagespeed")) + ), +}); + const getMonitorsByTeamIdValidation = joi.object({ teamId: joi.string().required(), }); @@ -381,6 +394,8 @@ module.exports = { createMonitorBodyValidation, getMonitorByIdParamValidation, getMonitorByIdQueryValidation, + getMonitorsAndSumamryByTeamIdParamValidation, + getMonitorsAndSummaryByTeamIdQueryValidation, getMonitorsByTeamIdValidation, getMonitorsByTeamIdQueryValidation, getMonitorStatsByIdParamValidation, From 0487095d05787b7b56d85c536bf056a043a6f136 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Thu, 5 Sep 2024 12:47:27 -0700 Subject: [PATCH 3/7] Updated uptime redux state --- .../UptimeMonitors/uptimeMonitorsSlice.js | 6 +-- Client/src/Pages/Monitors/Home/index.jsx | 48 +++++++++---------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/Client/src/Features/UptimeMonitors/uptimeMonitorsSlice.js b/Client/src/Features/UptimeMonitors/uptimeMonitorsSlice.js index 59a40e1c4..ac3ce1d6f 100644 --- a/Client/src/Features/UptimeMonitors/uptimeMonitorsSlice.js +++ b/Client/src/Features/UptimeMonitors/uptimeMonitorsSlice.js @@ -3,7 +3,7 @@ import { jwtDecode } from "jwt-decode"; import { networkService } from "../../main"; const initialState = { isLoading: false, - monitors: [], + monitorsSummary: [], success: null, msg: null, }; @@ -171,7 +171,7 @@ const uptimeMonitorsSlice = createSlice({ reducers: { clearUptimeMonitorState: (state) => { state.isLoading = false; - state.monitors = []; + state.monitorsSummary = []; state.success = null; state.msg = null; }, @@ -188,7 +188,7 @@ const uptimeMonitorsSlice = createSlice({ .addCase(getUptimeMonitorsByTeamId.fulfilled, (state, action) => { state.isLoading = false; state.success = action.payload.msg; - state.monitors = action.payload.data; + state.monitorsSummary = action.payload.data; }) .addCase(getUptimeMonitorsByTeamId.rejected, (state, action) => { state.isLoading = false; diff --git a/Client/src/Pages/Monitors/Home/index.jsx b/Client/src/Pages/Monitors/Home/index.jsx index 8bff60d19..19d8eb5a6 100644 --- a/Client/src/Pages/Monitors/Home/index.jsx +++ b/Client/src/Pages/Monitors/Home/index.jsx @@ -23,23 +23,9 @@ const Monitors = ({ isAdmin }) => { useEffect(() => { dispatch(getUptimeMonitorsByTeamId(authState.authToken)); }, [authState.authToken, dispatch]); - - const monitorStats = monitorState?.monitors?.monitors?.reduce( - (acc, monitor) => { - if (monitor.isActive === false) { - acc["paused"] += 1; - } else if (monitor.status === true) { - acc["up"] += 1; - } else { - acc["down"] += 1; - } - return acc; - }, - { paused: 0, up: 0, down: 0 } - ); - - let loading = monitorState.isLoading && monitorState.monitors.length === 0; - + let loading = + monitorState?.isLoading && + monitorState?.monitorsSummary?.monitors?.length === 0; return ( {loading ? ( @@ -55,7 +41,7 @@ const Monitors = ({ isAdmin }) => { mt={theme.spacing(5)} > - {monitorState.monitors?.length !== 0 && ( + {monitorState?.montiorsSummary?.monitors?.length !== 0 && (