From 205e16a96d3b21b8783ee6aa544c417dd12ee69c Mon Sep 17 00:00:00 2001 From: Br0wnHammer Date: Fri, 20 Jun 2025 02:54:09 +0530 Subject: [PATCH 01/10] Resolved Filter in FE --- .../Pages/Incidents/Components/IncidentTable/index.jsx | 10 ++++++---- .../Pages/Incidents/Components/OptionsHeader/index.jsx | 7 +++++++ client/src/locales/en.json | 3 ++- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/client/src/Pages/Incidents/Components/IncidentTable/index.jsx b/client/src/Pages/Incidents/Components/IncidentTable/index.jsx index 3b2e07238..b3e2d2f30 100644 --- a/client/src/Pages/Incidents/Components/IncidentTable/index.jsx +++ b/client/src/Pages/Incidents/Components/IncidentTable/index.jsx @@ -32,15 +32,17 @@ const IncidentTable = ({ const selectedMonitorDetails = monitors?.[selectedMonitor]; const selectedMonitorType = selectedMonitorDetails?.type; + const status = filter === "resolved" ? true : false; + const [checksMonitor, checksCountMonitor, isLoadingMonitor, networkErrorMonitor] = useFetchChecksByMonitor({ monitorId: selectedMonitor === "0" ? undefined : selectedMonitor, type: selectedMonitorType, - status: false, + status: status, sortOrder: "desc", limit: null, dateRange, - filter: filter, + filter: filter === "resolved" ? "resolve" : filter, page: page, rowsPerPage: rowsPerPage, enabled: selectedMonitor !== "0", @@ -48,11 +50,11 @@ const IncidentTable = ({ const [checksTeam, checksCountTeam, isLoadingTeam, networkErrorTeam] = useFetchChecksTeam({ - status: false, + status: status, sortOrder: "desc", limit: null, dateRange, - filter: filter, + filter: filter === "resolved" ? "resolve" : filter, page: page, rowsPerPage: rowsPerPage, enabled: selectedMonitor === "0", diff --git a/client/src/Pages/Incidents/Components/OptionsHeader/index.jsx b/client/src/Pages/Incidents/Components/OptionsHeader/index.jsx index 20140e8c4..08a9bcf1c 100644 --- a/client/src/Pages/Incidents/Components/OptionsHeader/index.jsx +++ b/client/src/Pages/Incidents/Components/OptionsHeader/index.jsx @@ -87,6 +87,13 @@ const OptionsHeader = ({ > {t("incidentsOptionsHeaderFilterCannotResolve")} + diff --git a/client/src/locales/en.json b/client/src/locales/en.json index ff878c3da..ec943dd65 100644 --- a/client/src/locales/en.json +++ b/client/src/locales/en.json @@ -187,6 +187,7 @@ "incidentsOptionsHeaderFilterAll": "All", "incidentsOptionsHeaderFilterDown": "Down", "incidentsOptionsHeaderFilterCannotResolve": "Cannot resolve", + "incidentsOptionsHeaderFilterResolved": "Resolved", "incidentsOptionsHeaderShow": "Show:", "incidentsOptionsHeaderLastHour": "Last hour", "incidentsOptionsHeaderLastDay": "Last day", @@ -746,4 +747,4 @@ "settingsEmailPool": "Pool - Enable connection pooling", "sendTestNotifications": "Send test notifications", "selectAll": "Select all" -} \ No newline at end of file +} From e8908351a27c0b0292df44aa96e8ebc185b40a39 Mon Sep 17 00:00:00 2001 From: Br0wnHammer Date: Fri, 20 Jun 2025 15:39:13 +0530 Subject: [PATCH 02/10] Route for Updating a single Incident Status --- .../Components/IncidentTable/index.jsx | 4 +-- client/src/Utils/NetworkService.js | 18 +++++++++++ server/controllers/checkController.js | 27 ++++++++++++++++- server/db/mongo/modules/checkModule.js | 30 +++++++++++++++++-- server/routes/checkRoute.js | 2 ++ server/validation/joi.js | 5 ++++ 6 files changed, 81 insertions(+), 5 deletions(-) diff --git a/client/src/Pages/Incidents/Components/IncidentTable/index.jsx b/client/src/Pages/Incidents/Components/IncidentTable/index.jsx index b3e2d2f30..b4bfbe9dc 100644 --- a/client/src/Pages/Incidents/Components/IncidentTable/index.jsx +++ b/client/src/Pages/Incidents/Components/IncidentTable/index.jsx @@ -42,7 +42,7 @@ const IncidentTable = ({ sortOrder: "desc", limit: null, dateRange, - filter: filter === "resolved" ? "resolve" : filter, + filter: filter === "resolved" ? "all" : filter, page: page, rowsPerPage: rowsPerPage, enabled: selectedMonitor !== "0", @@ -54,7 +54,7 @@ const IncidentTable = ({ sortOrder: "desc", limit: null, dateRange, - filter: filter === "resolved" ? "resolve" : filter, + filter: filter === "resolved" ? "all" : filter, page: page, rowsPerPage: rowsPerPage, enabled: selectedMonitor === "0", diff --git a/client/src/Utils/NetworkService.js b/client/src/Utils/NetworkService.js index eee795268..8625b69e3 100644 --- a/client/src/Utils/NetworkService.js +++ b/client/src/Utils/NetworkService.js @@ -598,6 +598,24 @@ class NetworkService { return this.axiosInstance.get(`/checks/team?${params.toString()}`); }; + /** + * ************************************ + * Update the status of a check + * ************************************ + * + * @async + * @param {Object} config - The configuration object. + * @param {string} config.checkId - The ID of the check to update. + * @param {boolean} config.status - The status to update the check to. + * @returns {Promise} The response from the axios PUT request. + * + */ + async updateCheckStatus(config) { + return this.axiosInstance.put(`/checks/${config.checkId}`, { + status: config.status, + }); + } + /** * ************************************ * Get all checks for a given user diff --git a/server/controllers/checkController.js b/server/controllers/checkController.js index 387839beb..0dece0a6d 100755 --- a/server/controllers/checkController.js +++ b/server/controllers/checkController.js @@ -8,6 +8,7 @@ import { deleteChecksParamValidation, deleteChecksByTeamIdParamValidation, updateChecksTTLBodyValidation, + updateCheckStatusBodyValidation, } from "../validation/joi.js"; import jwt from "jsonwebtoken"; import { getTokenFromHeaders } from "../utils/utils.js"; @@ -85,7 +86,7 @@ class CheckController { return; } try { - let { sortOrder, dateRange, filter, page, rowsPerPage } = req.query; + let { sortOrder, dateRange, filter, page, rowsPerPage, status } = req.query; const { teamId } = req.user; const checkData = await this.db.getChecksByTeam({ @@ -95,6 +96,7 @@ class CheckController { page, rowsPerPage, teamId, + status, }); return res.success({ msg: this.stringService.checkGet, @@ -105,6 +107,29 @@ class CheckController { } }; + updateCheckStatus = async (req, res, next) => { + try { + await updateCheckStatusBodyValidation.validateAsync(req.body); + } catch (error) { + next(handleValidationError(error, SERVICE_NAME)); + return; + } + + try { + const { checkId } = req.params; + const { status } = req.body; + + const updatedCheck = await this.db.updateCheckStatus(checkId, status); + + return res.success({ + msg: this.stringService.checkUpdateStatus, + data: updatedCheck, + }); + } catch (error) { + next(handleError(error, SERVICE_NAME, "updateCheckStatus")); + } + }; + deleteChecks = async (req, res, next) => { try { await deleteChecksParamValidation.validateAsync(req.params); diff --git a/server/db/mongo/modules/checkModule.js b/server/db/mongo/modules/checkModule.js index f409fd3d2..97f088953 100755 --- a/server/db/mongo/modules/checkModule.js +++ b/server/db/mongo/modules/checkModule.js @@ -68,7 +68,7 @@ const getChecksByMonitor = async ({ status, }) => { try { - status = typeof status !== "undefined" ? false : undefined; + status = status === "true" ? true : status === "false" ? false : undefined; page = parseInt(page); rowsPerPage = parseInt(rowsPerPage); // Match @@ -156,13 +156,15 @@ const getChecksByTeam = async ({ page, rowsPerPage, teamId, + status, }) => { try { + status = status === "true" ? true : false; page = parseInt(page); rowsPerPage = parseInt(rowsPerPage); const matchStage = { teamId: ObjectId.createFromHexString(teamId), - status: false, + status: status, ...(dateRangeLookup[dateRange] && { createdAt: { $gte: dateRangeLookup[dateRange], @@ -236,6 +238,29 @@ const getChecksByTeam = async ({ } }; +/** + * Update the status of a check + * @async + * @param {string} checkId + * @param {boolean} status + * @returns {Promise} + * @throws {Error} + */ +const updateCheckStatus = async (checkId, status) => { + try { + const updatedCheck = await Check.findOneAndUpdate( + { _id: checkId }, + { status }, + { new: true } + ); + return updatedCheck; + } catch (error) { + error.service = SERVICE_NAME; + error.method = "updateCheckStatus"; + throw error; + } +}; + /** * Delete all checks for a monitor * @async @@ -317,6 +342,7 @@ export { createChecks, getChecksByMonitor, getChecksByTeam, + updateCheckStatus, deleteChecks, deleteChecksByTeamId, updateChecksTTL, diff --git a/server/routes/checkRoute.js b/server/routes/checkRoute.js index aedca991a..d2b0590a0 100755 --- a/server/routes/checkRoute.js +++ b/server/routes/checkRoute.js @@ -20,6 +20,8 @@ class CheckRoutes { this.router.get("/:monitorId", this.checkController.getChecksByMonitor); + this.router.put("/:checkId", this.checkController.updateCheckStatus); + this.router.post( "/:monitorId", verifyOwnership(Monitor, "monitorId"), diff --git a/server/validation/joi.js b/server/validation/joi.js index e684cefa2..3c893260d 100755 --- a/server/validation/joi.js +++ b/server/validation/joi.js @@ -289,6 +289,10 @@ const createCheckBodyValidation = joi.object({ message: joi.string().required(), }); +const updateCheckStatusBodyValidation = joi.object({ + status: joi.boolean(), +}); + const getChecksParamValidation = joi.object({ monitorId: joi.string().required(), }); @@ -662,6 +666,7 @@ export { getChecksQueryValidation, getTeamChecksParamValidation, getTeamChecksQueryValidation, + updateCheckStatusBodyValidation, deleteChecksParamValidation, deleteChecksByTeamIdParamValidation, updateChecksTTLBodyValidation, From a9c1d131a5c417d2d1eef9462f3b7623769ed6ce Mon Sep 17 00:00:00 2001 From: Br0wnHammer Date: Fri, 20 Jun 2025 16:11:22 +0530 Subject: [PATCH 03/10] Route Update All Monitor/Team Checks --- server/controllers/checkController.js | 30 ++++++++++++++++++++++++++ server/db/mongo/modules/checkModule.js | 24 +++++++++++++++++++++ server/routes/checkRoute.js | 2 ++ server/validation/joi.js | 12 +++++++++++ 4 files changed, 68 insertions(+) diff --git a/server/controllers/checkController.js b/server/controllers/checkController.js index 0dece0a6d..230d58d0a 100755 --- a/server/controllers/checkController.js +++ b/server/controllers/checkController.js @@ -9,6 +9,8 @@ import { deleteChecksByTeamIdParamValidation, updateChecksTTLBodyValidation, updateCheckStatusBodyValidation, + updateAllChecksStatusBodyValidation, + updateCheckStatusParamValidation, } from "../validation/joi.js"; import jwt from "jsonwebtoken"; import { getTokenFromHeaders } from "../utils/utils.js"; @@ -130,6 +132,34 @@ class CheckController { } }; + updateAllChecksStatus = async (req, res, next) => { + try { + await updateCheckStatusParamValidation.validateAsync(req.params); + await updateAllChecksStatusBodyValidation.validateAsync(req.body); + } catch (error) { + next(handleValidationError(error, SERVICE_NAME)); + return; + } + + try { + const { monitorId, teamId, target } = req.params; + const { status } = req.body; + + const updatedChecks = await this.db.updateAllChecksStatus( + target === "monitor" ? monitorId : teamId, + status, + target + ); + + return res.success({ + msg: this.stringService.checkUpdateStatus, + data: updatedChecks, + }); + } catch (error) { + next(handleError(error, SERVICE_NAME, "updateAllChecksStatus")); + } + }; + deleteChecks = async (req, res, next) => { try { await deleteChecksParamValidation.validateAsync(req.params); diff --git a/server/db/mongo/modules/checkModule.js b/server/db/mongo/modules/checkModule.js index 97f088953..9cae8ed68 100755 --- a/server/db/mongo/modules/checkModule.js +++ b/server/db/mongo/modules/checkModule.js @@ -261,6 +261,29 @@ const updateCheckStatus = async (checkId, status) => { } }; +/** + * Update the status of all checks for a monitor or team + * @async + * @param {string} id + * @param {boolean} status + * @param {string} target + * @returns {Promise} + * @throws {Error} + */ +const updateAllChecksStatus = async (id, status, target) => { + try { + const updatedChecks = await Check.updateMany( + target === "monitor" ? { monitorId: id } : { teamId: id }, + { $set: { status: true } } + ); + return updatedChecks.modifiedCount; + } catch (error) { + error.service = SERVICE_NAME; + error.method = "updateAllChecksStatus"; + throw error; + } +}; + /** * Delete all checks for a monitor * @async @@ -343,6 +366,7 @@ export { getChecksByMonitor, getChecksByTeam, updateCheckStatus, + updateAllChecksStatus, deleteChecks, deleteChecksByTeamId, updateChecksTTL, diff --git a/server/routes/checkRoute.js b/server/routes/checkRoute.js index d2b0590a0..c6d0c584f 100755 --- a/server/routes/checkRoute.js +++ b/server/routes/checkRoute.js @@ -22,6 +22,8 @@ class CheckRoutes { this.router.put("/:checkId", this.checkController.updateCheckStatus); + this.router.put("/:monitorId/:target", this.checkController.updateAllChecksStatus); + this.router.post( "/:monitorId", verifyOwnership(Monitor, "monitorId"), diff --git a/server/validation/joi.js b/server/validation/joi.js index 3c893260d..f8e57dc58 100755 --- a/server/validation/joi.js +++ b/server/validation/joi.js @@ -293,6 +293,16 @@ const updateCheckStatusBodyValidation = joi.object({ status: joi.boolean(), }); +const updateCheckStatusParamValidation = joi.object({ + monitorId: joi.string(), + teamId: joi.string(), + target: joi.string().allow("monitor", "team"), +}); + +const updateAllChecksStatusBodyValidation = joi.object({ + status: joi.boolean(), +}); + const getChecksParamValidation = joi.object({ monitorId: joi.string().required(), }); @@ -667,6 +677,8 @@ export { getTeamChecksParamValidation, getTeamChecksQueryValidation, updateCheckStatusBodyValidation, + updateAllChecksStatusBodyValidation, + updateCheckStatusParamValidation, deleteChecksParamValidation, deleteChecksByTeamIdParamValidation, updateChecksTTLBodyValidation, From faa2a2d965edf452fd0e129f346b779c82e5b9f7 Mon Sep 17 00:00:00 2001 From: Br0wnHammer Date: Fri, 20 Jun 2025 20:42:57 +0530 Subject: [PATCH 04/10] Fixes in the controllers --- server/controllers/checkController.js | 4 ++-- server/db/mongo/modules/checkModule.js | 4 ++-- server/validation/joi.js | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/server/controllers/checkController.js b/server/controllers/checkController.js index 230d58d0a..15f889591 100755 --- a/server/controllers/checkController.js +++ b/server/controllers/checkController.js @@ -142,11 +142,11 @@ class CheckController { } try { - const { monitorId, teamId, target } = req.params; + const { monitorId, target } = req.params; const { status } = req.body; const updatedChecks = await this.db.updateAllChecksStatus( - target === "monitor" ? monitorId : teamId, + monitorId, status, target ); diff --git a/server/db/mongo/modules/checkModule.js b/server/db/mongo/modules/checkModule.js index 9cae8ed68..6c64756ee 100755 --- a/server/db/mongo/modules/checkModule.js +++ b/server/db/mongo/modules/checkModule.js @@ -159,7 +159,7 @@ const getChecksByTeam = async ({ status, }) => { try { - status = status === "true" ? true : false; + status = status === "true"; page = parseInt(page); rowsPerPage = parseInt(rowsPerPage); const matchStage = { @@ -274,7 +274,7 @@ const updateAllChecksStatus = async (id, status, target) => { try { const updatedChecks = await Check.updateMany( target === "monitor" ? { monitorId: id } : { teamId: id }, - { $set: { status: true } } + { $set: { status } } ); return updatedChecks.modifiedCount; } catch (error) { diff --git a/server/validation/joi.js b/server/validation/joi.js index f8e57dc58..4562e303e 100755 --- a/server/validation/joi.js +++ b/server/validation/joi.js @@ -295,7 +295,6 @@ const updateCheckStatusBodyValidation = joi.object({ const updateCheckStatusParamValidation = joi.object({ monitorId: joi.string(), - teamId: joi.string(), target: joi.string().allow("monitor", "team"), }); From 30d85e5712ffa17a688a5b1081d3b523a52fb597 Mon Sep 17 00:00:00 2001 From: Br0wnHammer Date: Mon, 23 Jun 2025 22:07:03 +0530 Subject: [PATCH 05/10] Ack Field in Checks --- .../Components/IncidentTable/index.jsx | 6 ++--- client/src/Utils/NetworkService.js | 2 +- server/controllers/checkController.js | 12 +++------ server/db/models/Check.js | 17 ++++++++++++ server/db/mongo/modules/checkModule.js | 27 +++++++++++-------- server/validation/joi.js | 4 +-- 6 files changed, 42 insertions(+), 26 deletions(-) diff --git a/client/src/Pages/Incidents/Components/IncidentTable/index.jsx b/client/src/Pages/Incidents/Components/IncidentTable/index.jsx index b4bfbe9dc..175649961 100644 --- a/client/src/Pages/Incidents/Components/IncidentTable/index.jsx +++ b/client/src/Pages/Incidents/Components/IncidentTable/index.jsx @@ -32,13 +32,11 @@ const IncidentTable = ({ const selectedMonitorDetails = monitors?.[selectedMonitor]; const selectedMonitorType = selectedMonitorDetails?.type; - const status = filter === "resolved" ? true : false; - const [checksMonitor, checksCountMonitor, isLoadingMonitor, networkErrorMonitor] = useFetchChecksByMonitor({ monitorId: selectedMonitor === "0" ? undefined : selectedMonitor, type: selectedMonitorType, - status: status, + status: false, sortOrder: "desc", limit: null, dateRange, @@ -50,7 +48,7 @@ const IncidentTable = ({ const [checksTeam, checksCountTeam, isLoadingTeam, networkErrorTeam] = useFetchChecksTeam({ - status: status, + status: false, sortOrder: "desc", limit: null, dateRange, diff --git a/client/src/Utils/NetworkService.js b/client/src/Utils/NetworkService.js index 8625b69e3..f953fc143 100644 --- a/client/src/Utils/NetworkService.js +++ b/client/src/Utils/NetworkService.js @@ -612,7 +612,7 @@ class NetworkService { */ async updateCheckStatus(config) { return this.axiosInstance.put(`/checks/${config.checkId}`, { - status: config.status, + ack: config.ack, }); } diff --git a/server/controllers/checkController.js b/server/controllers/checkController.js index 15f889591..e3d3436e2 100755 --- a/server/controllers/checkController.js +++ b/server/controllers/checkController.js @@ -119,9 +119,9 @@ class CheckController { try { const { checkId } = req.params; - const { status } = req.body; + const { ack } = req.body; - const updatedCheck = await this.db.updateCheckStatus(checkId, status); + const updatedCheck = await this.db.updateCheckStatus(checkId, ack); return res.success({ msg: this.stringService.checkUpdateStatus, @@ -143,13 +143,9 @@ class CheckController { try { const { monitorId, target } = req.params; - const { status } = req.body; + const { ack } = req.body; - const updatedChecks = await this.db.updateAllChecksStatus( - monitorId, - status, - target - ); + const updatedChecks = await this.db.updateAllChecksStatus(monitorId, ack, target); return res.success({ msg: this.stringService.checkUpdateStatus, diff --git a/server/db/models/Check.js b/server/db/models/Check.js index 39c5281d2..8bb6cd028 100755 --- a/server/db/models/Check.js +++ b/server/db/models/Check.js @@ -64,6 +64,23 @@ const BaseCheckSchema = mongoose.Schema({ default: Date.now, expires: 60 * 60 * 24 * 30, // 30 days }, + /** + * Acknowledgment of the check. + * + * @type {Boolean} + */ + ack: { + type: Boolean, + default: false, + }, + /** + * Resolution date of the check (when the check was resolved). + * + * @type {Date} + */ + ackAt: { + type: Date, + }, }); /** diff --git a/server/db/mongo/modules/checkModule.js b/server/db/mongo/modules/checkModule.js index 6c64756ee..0a4b1ad63 100755 --- a/server/db/mongo/modules/checkModule.js +++ b/server/db/mongo/modules/checkModule.js @@ -239,20 +239,25 @@ const getChecksByTeam = async ({ }; /** - * Update the status of a check + * Update the acknowledgment status of a check * @async - * @param {string} checkId - * @param {boolean} status + * @param {string} checkId - The ID of the check to update + * @param {boolean} ack - The acknowledgment status to set * @returns {Promise} * @throws {Error} */ -const updateCheckStatus = async (checkId, status) => { +const updateCheckStatus = async (checkId, ack) => { try { const updatedCheck = await Check.findOneAndUpdate( { _id: checkId }, - { status }, + { $set: { ack, ackAt: new Date() } }, { new: true } ); + + if (!updatedCheck) { + throw new Error("Check not found"); + } + return updatedCheck; } catch (error) { error.service = SERVICE_NAME; @@ -262,19 +267,19 @@ const updateCheckStatus = async (checkId, status) => { }; /** - * Update the status of all checks for a monitor or team + * Update the acknowledgment status of all checks for a monitor or team * @async - * @param {string} id - * @param {boolean} status - * @param {string} target + * @param {string} id - The monitor ID or team ID + * @param {boolean} ack - The acknowledgment status to set + * @param {string} target - The target type ('monitor' or 'team') * @returns {Promise} * @throws {Error} */ -const updateAllChecksStatus = async (id, status, target) => { +const updateAllChecksStatus = async (id, ack, target) => { try { const updatedChecks = await Check.updateMany( target === "monitor" ? { monitorId: id } : { teamId: id }, - { $set: { status } } + { $set: { ack, ackAt: new Date() } } ); return updatedChecks.modifiedCount; } catch (error) { diff --git a/server/validation/joi.js b/server/validation/joi.js index 4562e303e..ff1fa65c5 100755 --- a/server/validation/joi.js +++ b/server/validation/joi.js @@ -290,7 +290,7 @@ const createCheckBodyValidation = joi.object({ }); const updateCheckStatusBodyValidation = joi.object({ - status: joi.boolean(), + ack: joi.boolean(), }); const updateCheckStatusParamValidation = joi.object({ @@ -299,7 +299,7 @@ const updateCheckStatusParamValidation = joi.object({ }); const updateAllChecksStatusBodyValidation = joi.object({ - status: joi.boolean(), + ack: joi.boolean(), }); const getChecksParamValidation = joi.object({ From 183c13fe53c4e968c0e86a68dceb0dfe85ee3fe5 Mon Sep 17 00:00:00 2001 From: Br0wnHammer Date: Tue, 24 Jun 2025 14:44:02 +0530 Subject: [PATCH 06/10] Naming Changes in BE --- client/src/Hooks/checkHooks.js | 7 +++++- .../Components/IncidentTable/index.jsx | 2 ++ client/src/Utils/NetworkService.js | 4 ++++ server/controllers/checkController.js | 23 +++++++++++-------- server/db/mongo/modules/checkModule.js | 23 +++++++++++-------- server/routes/checkRoute.js | 4 ++-- server/validation/joi.js | 6 +++-- 7 files changed, 46 insertions(+), 23 deletions(-) diff --git a/client/src/Hooks/checkHooks.js b/client/src/Hooks/checkHooks.js index 683b89b20..98fb0cfd5 100644 --- a/client/src/Hooks/checkHooks.js +++ b/client/src/Hooks/checkHooks.js @@ -8,6 +8,7 @@ const useFetchChecksTeam = ({ limit, dateRange, filter, + ack, page, rowsPerPage, enabled = true, @@ -29,6 +30,7 @@ const useFetchChecksTeam = ({ limit, dateRange, filter, + ack, page, rowsPerPage, }; @@ -47,7 +49,7 @@ const useFetchChecksTeam = ({ }; fetchChecks(); - }, [status, sortOrder, limit, dateRange, filter, page, rowsPerPage, enabled]); + }, [status, sortOrder, limit, dateRange, filter, ack, page, rowsPerPage, enabled]); return [checks, checksCount, isLoading, networkError]; }; @@ -60,6 +62,7 @@ const useFetchChecksByMonitor = ({ limit, dateRange, filter, + ack, page, rowsPerPage, enabled = true, @@ -83,6 +86,7 @@ const useFetchChecksByMonitor = ({ limit, dateRange, filter, + ack, page, rowsPerPage, }; @@ -109,6 +113,7 @@ const useFetchChecksByMonitor = ({ limit, dateRange, filter, + ack, page, rowsPerPage, enabled, diff --git a/client/src/Pages/Incidents/Components/IncidentTable/index.jsx b/client/src/Pages/Incidents/Components/IncidentTable/index.jsx index 175649961..bc5eaa5ca 100644 --- a/client/src/Pages/Incidents/Components/IncidentTable/index.jsx +++ b/client/src/Pages/Incidents/Components/IncidentTable/index.jsx @@ -41,6 +41,7 @@ const IncidentTable = ({ limit: null, dateRange, filter: filter === "resolved" ? "all" : filter, + ack: filter === "resolved" ? true : false, page: page, rowsPerPage: rowsPerPage, enabled: selectedMonitor !== "0", @@ -53,6 +54,7 @@ const IncidentTable = ({ limit: null, dateRange, filter: filter === "resolved" ? "all" : filter, + ack: filter === "resolved" ? true : false, page: page, rowsPerPage: rowsPerPage, enabled: selectedMonitor === "0", diff --git a/client/src/Utils/NetworkService.js b/client/src/Utils/NetworkService.js index f953fc143..718b593de 100644 --- a/client/src/Utils/NetworkService.js +++ b/client/src/Utils/NetworkService.js @@ -549,6 +549,7 @@ class NetworkService { * @param {number} config.limit - The maximum number of checks to retrieve. * @param {string} config.dateRange - The range of dates for which to retrieve checks. * @param {string} config.filter - The filter to apply to the checks. + * @param {boolean} config.ack - The acknowledgment status to apply to the checks. * @param {number} config.page - The page number to retrieve in a paginated list. * @param {number} config.rowsPerPage - The number of rows per page in a paginated list. * @returns {Promise} The response from the axios GET request. @@ -562,6 +563,7 @@ class NetworkService { if (config.limit) params.append("limit", config.limit); if (config.dateRange) params.append("dateRange", config.dateRange); if (config.filter) params.append("filter", config.filter); + if (config.ack !== undefined) params.append("ack", config.ack); if (config.page) params.append("page", config.page); if (config.rowsPerPage) params.append("rowsPerPage", config.rowsPerPage); if (config.status !== undefined) params.append("status", config.status); @@ -581,6 +583,7 @@ class NetworkService { * @param {number} config.limit - The maximum number of checks to retrieve. * @param {string} config.dateRange - The range of dates for which to retrieve checks. * @param {string} config.filter - The filter to apply to the checks. + * @param {boolean} config.ack - The acknowledgment status to apply to the checks. * @param {number} config.page - The page number to retrieve in a paginated list. * @param {number} config.rowsPerPage - The number of rows per page in a paginated list. * @returns {Promise} The response from the axios GET request. @@ -592,6 +595,7 @@ class NetworkService { if (config.limit) params.append("limit", config.limit); if (config.dateRange) params.append("dateRange", config.dateRange); if (config.filter) params.append("filter", config.filter); + if (config.ack !== undefined) params.append("ack", config.ack); if (config.page) params.append("page", config.page); if (config.rowsPerPage) params.append("rowsPerPage", config.rowsPerPage); if (config.status !== undefined) params.append("status", config.status); diff --git a/server/controllers/checkController.js b/server/controllers/checkController.js index e3d3436e2..0c7b145e8 100755 --- a/server/controllers/checkController.js +++ b/server/controllers/checkController.js @@ -58,13 +58,15 @@ class CheckController { try { const { monitorId } = req.params; - let { type, sortOrder, dateRange, filter, page, rowsPerPage, status } = req.query; + let { type, sortOrder, dateRange, filter, ack, page, rowsPerPage, status } = + req.query; const result = await this.db.getChecksByMonitor({ monitorId, type, sortOrder, dateRange, filter, + ack, page, rowsPerPage, status, @@ -88,13 +90,14 @@ class CheckController { return; } try { - let { sortOrder, dateRange, filter, page, rowsPerPage, status } = req.query; + let { sortOrder, dateRange, filter, ack, page, rowsPerPage, status } = req.query; const { teamId } = req.user; const checkData = await this.db.getChecksByTeam({ sortOrder, dateRange, filter, + ack, page, rowsPerPage, teamId, @@ -109,7 +112,7 @@ class CheckController { } }; - updateCheckStatus = async (req, res, next) => { + ackCheck = async (req, res, next) => { try { await updateCheckStatusBodyValidation.validateAsync(req.body); } catch (error) { @@ -120,19 +123,20 @@ class CheckController { try { const { checkId } = req.params; const { ack } = req.body; + const { teamId } = req.user; - const updatedCheck = await this.db.updateCheckStatus(checkId, ack); + const updatedCheck = await this.db.ackCheck(checkId, teamId, ack); return res.success({ msg: this.stringService.checkUpdateStatus, data: updatedCheck, }); } catch (error) { - next(handleError(error, SERVICE_NAME, "updateCheckStatus")); + next(handleError(error, SERVICE_NAME, "ackCheck")); } }; - updateAllChecksStatus = async (req, res, next) => { + ackAllChecks = async (req, res, next) => { try { await updateCheckStatusParamValidation.validateAsync(req.params); await updateAllChecksStatusBodyValidation.validateAsync(req.body); @@ -142,17 +146,18 @@ class CheckController { } try { - const { monitorId, target } = req.params; + const { monitorId, path } = req.params; const { ack } = req.body; + const { teamId } = req.user; - const updatedChecks = await this.db.updateAllChecksStatus(monitorId, ack, target); + const updatedChecks = await this.db.ackAllChecks(monitorId, teamId, ack, path); return res.success({ msg: this.stringService.checkUpdateStatus, data: updatedChecks, }); } catch (error) { - next(handleError(error, SERVICE_NAME, "updateAllChecksStatus")); + next(handleError(error, SERVICE_NAME, "ackAllChecks")); } }; diff --git a/server/db/mongo/modules/checkModule.js b/server/db/mongo/modules/checkModule.js index 0a4b1ad63..96c07e52e 100755 --- a/server/db/mongo/modules/checkModule.js +++ b/server/db/mongo/modules/checkModule.js @@ -63,6 +63,7 @@ const getChecksByMonitor = async ({ sortOrder, dateRange, filter, + ack, page, rowsPerPage, status, @@ -75,6 +76,7 @@ const getChecksByMonitor = async ({ const matchStage = { monitorId: ObjectId.createFromHexString(monitorId), ...(typeof status !== "undefined" && { status }), + ...(typeof ack !== "undefined" && { ack: ack === "true" ? true : false }), ...(dateRangeLookup[dateRange] && { createdAt: { $gte: dateRangeLookup[dateRange], @@ -153,6 +155,7 @@ const getChecksByTeam = async ({ sortOrder, dateRange, filter, + ack, page, rowsPerPage, teamId, @@ -165,6 +168,7 @@ const getChecksByTeam = async ({ const matchStage = { teamId: ObjectId.createFromHexString(teamId), status: status, + ...(typeof ack !== "undefined" && { ack: ack === "true" ? true : false }), ...(dateRangeLookup[dateRange] && { createdAt: { $gte: dateRangeLookup[dateRange], @@ -242,14 +246,15 @@ const getChecksByTeam = async ({ * Update the acknowledgment status of a check * @async * @param {string} checkId - The ID of the check to update + * @param {string} teamId - The ID of the team * @param {boolean} ack - The acknowledgment status to set * @returns {Promise} * @throws {Error} */ -const updateCheckStatus = async (checkId, ack) => { +const ackCheck = async (checkId, teamId, ack) => { try { const updatedCheck = await Check.findOneAndUpdate( - { _id: checkId }, + { _id: checkId, teamId: teamId }, { $set: { ack, ackAt: new Date() } }, { new: true } ); @@ -261,7 +266,7 @@ const updateCheckStatus = async (checkId, ack) => { return updatedCheck; } catch (error) { error.service = SERVICE_NAME; - error.method = "updateCheckStatus"; + error.method = "ackCheck"; throw error; } }; @@ -271,20 +276,20 @@ const updateCheckStatus = async (checkId, ack) => { * @async * @param {string} id - The monitor ID or team ID * @param {boolean} ack - The acknowledgment status to set - * @param {string} target - The target type ('monitor' or 'team') + * @param {string} path - The path type ('monitor' or 'team') * @returns {Promise} * @throws {Error} */ -const updateAllChecksStatus = async (id, ack, target) => { +const ackAllChecks = async (monitorId, teamId, ack, path) => { try { const updatedChecks = await Check.updateMany( - target === "monitor" ? { monitorId: id } : { teamId: id }, + path === "monitor" ? { monitorId } : { teamId }, { $set: { ack, ackAt: new Date() } } ); return updatedChecks.modifiedCount; } catch (error) { error.service = SERVICE_NAME; - error.method = "updateAllChecksStatus"; + error.method = "ackAllChecks"; throw error; } }; @@ -370,8 +375,8 @@ export { createChecks, getChecksByMonitor, getChecksByTeam, - updateCheckStatus, - updateAllChecksStatus, + ackCheck, + ackAllChecks, deleteChecks, deleteChecksByTeamId, updateChecksTTL, diff --git a/server/routes/checkRoute.js b/server/routes/checkRoute.js index c6d0c584f..19a03643c 100755 --- a/server/routes/checkRoute.js +++ b/server/routes/checkRoute.js @@ -20,9 +20,9 @@ class CheckRoutes { this.router.get("/:monitorId", this.checkController.getChecksByMonitor); - this.router.put("/:checkId", this.checkController.updateCheckStatus); + this.router.put("/:checkId", this.checkController.ackCheck); - this.router.put("/:monitorId/:target", this.checkController.updateAllChecksStatus); + this.router.put("/:path/:monitorId?", this.checkController.ackAllChecks); this.router.post( "/:monitorId", diff --git a/server/validation/joi.js b/server/validation/joi.js index ff1fa65c5..593823f35 100755 --- a/server/validation/joi.js +++ b/server/validation/joi.js @@ -294,8 +294,8 @@ const updateCheckStatusBodyValidation = joi.object({ }); const updateCheckStatusParamValidation = joi.object({ - monitorId: joi.string(), - target: joi.string().allow("monitor", "team"), + monitorId: joi.string().optional(), + path: joi.string().valid("monitor", "team").required(), }); const updateAllChecksStatusBodyValidation = joi.object({ @@ -312,6 +312,7 @@ const getChecksQueryValidation = joi.object({ limit: joi.number(), dateRange: joi.string().valid("recent", "hour", "day", "week", "month", "all"), filter: joi.string().valid("all", "down", "resolve"), + ack: joi.boolean(), page: joi.number(), rowsPerPage: joi.number(), status: joi.boolean(), @@ -324,6 +325,7 @@ const getTeamChecksQueryValidation = joi.object({ limit: joi.number(), dateRange: joi.string().valid("hour", "day", "week", "month", "all"), filter: joi.string().valid("all", "down", "resolve"), + ack: joi.boolean(), page: joi.number(), rowsPerPage: joi.number(), status: joi.boolean(), From 78a2e5d106efb7c78b812acebe6dbd2a86afb942 Mon Sep 17 00:00:00 2001 From: Br0wnHammer Date: Wed, 25 Jun 2025 11:52:38 +0530 Subject: [PATCH 07/10] VerifyTemAccess Middleware --- server/controllers/checkController.js | 12 ++++++------ server/db/mongo/modules/checkModule.js | 4 ++-- server/routes/checkRoute.js | 4 +++- server/validation/joi.js | 12 ++++++------ 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/server/controllers/checkController.js b/server/controllers/checkController.js index 0c7b145e8..13fd25694 100755 --- a/server/controllers/checkController.js +++ b/server/controllers/checkController.js @@ -8,9 +8,9 @@ import { deleteChecksParamValidation, deleteChecksByTeamIdParamValidation, updateChecksTTLBodyValidation, - updateCheckStatusBodyValidation, - updateAllChecksStatusBodyValidation, - updateCheckStatusParamValidation, + ackCheckBodyValidation, + ackAllChecksParamValidation, + ackAllChecksBodyValidation, } from "../validation/joi.js"; import jwt from "jsonwebtoken"; import { getTokenFromHeaders } from "../utils/utils.js"; @@ -114,7 +114,7 @@ class CheckController { ackCheck = async (req, res, next) => { try { - await updateCheckStatusBodyValidation.validateAsync(req.body); + await ackCheckBodyValidation.validateAsync(req.body); } catch (error) { next(handleValidationError(error, SERVICE_NAME)); return; @@ -138,8 +138,8 @@ class CheckController { ackAllChecks = async (req, res, next) => { try { - await updateCheckStatusParamValidation.validateAsync(req.params); - await updateAllChecksStatusBodyValidation.validateAsync(req.body); + await ackAllChecksParamValidation.validateAsync(req.params); + await ackAllChecksBodyValidation.validateAsync(req.body); } catch (error) { next(handleValidationError(error, SERVICE_NAME)); return; diff --git a/server/db/mongo/modules/checkModule.js b/server/db/mongo/modules/checkModule.js index 96c07e52e..ca7d02b1c 100755 --- a/server/db/mongo/modules/checkModule.js +++ b/server/db/mongo/modules/checkModule.js @@ -76,7 +76,7 @@ const getChecksByMonitor = async ({ const matchStage = { monitorId: ObjectId.createFromHexString(monitorId), ...(typeof status !== "undefined" && { status }), - ...(typeof ack !== "undefined" && { ack: ack === "true" ? true : false }), + ...(typeof ack !== "undefined" && { ack: ack === "true" }), ...(dateRangeLookup[dateRange] && { createdAt: { $gte: dateRangeLookup[dateRange], @@ -168,7 +168,7 @@ const getChecksByTeam = async ({ const matchStage = { teamId: ObjectId.createFromHexString(teamId), status: status, - ...(typeof ack !== "undefined" && { ack: ack === "true" ? true : false }), + ...(typeof ack !== "undefined" && { ack: ack === "true" }), ...(dateRangeLookup[dateRange] && { createdAt: { $gte: dateRangeLookup[dateRange], diff --git a/server/routes/checkRoute.js b/server/routes/checkRoute.js index 19a03643c..c0be6f92e 100755 --- a/server/routes/checkRoute.js +++ b/server/routes/checkRoute.js @@ -1,7 +1,9 @@ import { Router } from "express"; import { verifyOwnership } from "../middleware/verifyOwnership.js"; +import { verifyTeamAccess } from "../middleware/verifyTeamAccess.js"; import { isAllowed } from "../middleware/isAllowed.js"; import Monitor from "../db/models/Monitor.js"; +import Check from "../db/models/Check.js"; class CheckRoutes { constructor(checkController) { @@ -20,7 +22,7 @@ class CheckRoutes { this.router.get("/:monitorId", this.checkController.getChecksByMonitor); - this.router.put("/:checkId", this.checkController.ackCheck); + this.router.put("/:checkId", verifyTeamAccess(Check, "checkId"), this.checkController.ackCheck); this.router.put("/:path/:monitorId?", this.checkController.ackAllChecks); diff --git a/server/validation/joi.js b/server/validation/joi.js index c3afa51f2..74307a124 100755 --- a/server/validation/joi.js +++ b/server/validation/joi.js @@ -289,16 +289,16 @@ const createCheckBodyValidation = joi.object({ message: joi.string().required(), }); -const updateCheckStatusBodyValidation = joi.object({ +const ackCheckBodyValidation = joi.object({ ack: joi.boolean(), }); -const updateCheckStatusParamValidation = joi.object({ +const ackAllChecksParamValidation = joi.object({ monitorId: joi.string().optional(), path: joi.string().valid("monitor", "team").required(), }); -const updateAllChecksStatusBodyValidation = joi.object({ +const ackAllChecksBodyValidation = joi.object({ ack: joi.boolean(), }); @@ -669,9 +669,9 @@ export { getChecksQueryValidation, getTeamChecksParamValidation, getTeamChecksQueryValidation, - updateCheckStatusBodyValidation, - updateAllChecksStatusBodyValidation, - updateCheckStatusParamValidation, + ackCheckBodyValidation, + ackAllChecksParamValidation, + ackAllChecksBodyValidation, deleteChecksParamValidation, deleteChecksByTeamIdParamValidation, updateChecksTTLBodyValidation, From 6457984dd4b91035352906787cdf7d3f655783b1 Mon Sep 17 00:00:00 2001 From: Br0wnHammer Date: Wed, 25 Jun 2025 14:16:00 +0530 Subject: [PATCH 08/10] ackStage Backword Compatible --- client/src/Utils/NetworkService.js | 5 ++--- server/controllers/checkController.js | 3 +-- server/db/mongo/modules/checkModule.js | 22 ++++++++++++++++------ server/routes/checkRoute.js | 6 +++++- server/validation/joi.js | 1 - 5 files changed, 24 insertions(+), 13 deletions(-) diff --git a/client/src/Utils/NetworkService.js b/client/src/Utils/NetworkService.js index 261928de6..414c45a22 100644 --- a/client/src/Utils/NetworkService.js +++ b/client/src/Utils/NetworkService.js @@ -598,7 +598,6 @@ class NetworkService { if (config.ack !== undefined) params.append("ack", config.ack); if (config.page) params.append("page", config.page); if (config.rowsPerPage) params.append("rowsPerPage", config.rowsPerPage); - if (config.status !== undefined) params.append("status", config.status); return this.axiosInstance.get(`/checks/team?${params.toString()}`); }; @@ -610,12 +609,12 @@ class NetworkService { * @async * @param {Object} config - The configuration object. * @param {string} config.checkId - The ID of the check to update. - * @param {boolean} config.status - The status to update the check to. + * @param {boolean} config.ack - The acknowledgment to update the check to. * @returns {Promise} The response from the axios PUT request. * */ async updateCheckStatus(config) { - return this.axiosInstance.put(`/checks/${config.checkId}`, { + return this.axiosInstance.put(`/checks/check/${config.checkId}`, { ack: config.ack, }); } diff --git a/server/controllers/checkController.js b/server/controllers/checkController.js index 13fd25694..8f9d0fbb5 100755 --- a/server/controllers/checkController.js +++ b/server/controllers/checkController.js @@ -90,7 +90,7 @@ class CheckController { return; } try { - let { sortOrder, dateRange, filter, ack, page, rowsPerPage, status } = req.query; + let { sortOrder, dateRange, filter, ack, page, rowsPerPage } = req.query; const { teamId } = req.user; const checkData = await this.db.getChecksByTeam({ @@ -101,7 +101,6 @@ class CheckController { page, rowsPerPage, teamId, - status, }); return res.success({ msg: this.stringService.checkGet, diff --git a/server/db/mongo/modules/checkModule.js b/server/db/mongo/modules/checkModule.js index ca7d02b1c..33e68f01e 100755 --- a/server/db/mongo/modules/checkModule.js +++ b/server/db/mongo/modules/checkModule.js @@ -72,11 +72,17 @@ const getChecksByMonitor = async ({ status = status === "true" ? true : status === "false" ? false : undefined; page = parseInt(page); rowsPerPage = parseInt(rowsPerPage); + + const ackStage = + ack === "true" + ? { ack: true } + : { $or: [{ ack: false }, { ack: { $exists: false } }] }; + // Match const matchStage = { monitorId: ObjectId.createFromHexString(monitorId), ...(typeof status !== "undefined" && { status }), - ...(typeof ack !== "undefined" && { ack: ack === "true" }), + ...(typeof ack !== "undefined" && ackStage), ...(dateRangeLookup[dateRange] && { createdAt: { $gte: dateRangeLookup[dateRange], @@ -159,16 +165,20 @@ const getChecksByTeam = async ({ page, rowsPerPage, teamId, - status, }) => { try { - status = status === "true"; page = parseInt(page); rowsPerPage = parseInt(rowsPerPage); + + const ackStage = + ack === "true" + ? { ack: true } + : { $or: [{ ack: false }, { ack: { $exists: false } }] }; + const matchStage = { - teamId: ObjectId.createFromHexString(teamId), - status: status, - ...(typeof ack !== "undefined" && { ack: ack === "true" }), + teamId: new ObjectId(teamId), + status: false, + ...(typeof ack !== "undefined" && ackStage), ...(dateRangeLookup[dateRange] && { createdAt: { $gte: dateRangeLookup[dateRange], diff --git a/server/routes/checkRoute.js b/server/routes/checkRoute.js index c0be6f92e..7f91dbe31 100755 --- a/server/routes/checkRoute.js +++ b/server/routes/checkRoute.js @@ -22,7 +22,11 @@ class CheckRoutes { this.router.get("/:monitorId", this.checkController.getChecksByMonitor); - this.router.put("/:checkId", verifyTeamAccess(Check, "checkId"), this.checkController.ackCheck); + this.router.put( + "/check/:checkId", + verifyTeamAccess(Check, "checkId"), + this.checkController.ackCheck + ); this.router.put("/:path/:monitorId?", this.checkController.ackAllChecks); diff --git a/server/validation/joi.js b/server/validation/joi.js index 74307a124..d44bb14eb 100755 --- a/server/validation/joi.js +++ b/server/validation/joi.js @@ -328,7 +328,6 @@ const getTeamChecksQueryValidation = joi.object({ ack: joi.boolean(), page: joi.number(), rowsPerPage: joi.number(), - status: joi.boolean(), }); const deleteChecksParamValidation = joi.object({ From e5028c95b341bde2c1835b78c78ed8560f5cf40b Mon Sep 17 00:00:00 2001 From: Br0wnHammer Date: Wed, 25 Jun 2025 14:26:11 +0530 Subject: [PATCH 09/10] Conflicts in en.json --- client/src/locales/en.json | 84 -------------------------------------- 1 file changed, 84 deletions(-) diff --git a/client/src/locales/en.json b/client/src/locales/en.json index f86c5974c..691011911 100644 --- a/client/src/locales/en.json +++ b/client/src/locales/en.json @@ -634,94 +634,10 @@ "retryButton": { "default": "Retry connection", "processing": "Connecting..." - }, - "toasts": { - "reconnected": "Successfully reconnected to the server.", - "stillUnreachable": "Server is still unreachable. Please try again later." } } }, - "expectedValue": "Expected value", - "export": { - "failed": "Failed to export monitors", - "success": "Monitors exported successfully!", - "title": "Export Monitors" - }, - "failedToSendEmail": "Failed to send email", - "features": "Features", - "frequency": "Frequency", - "friendlyNameInput": "Friendly name", - "friendlyNamePlaceholder": "Maintenance at __ : __ for ___ minutes", - "gb": "GB", - "greeting": { - "append": "The afternoon is your playground—let's make it epic!", - "overview": "Here's an overview of your {{type}} monitors.", - "prepend": "Hey there" - }, - "high": "high", - "host": "Host", - "http": "HTTP", - "https": "HTTPS", - "ignoreTLSError": "Ignore TLS/SSL error", - "ignoreTLSErrorDescription": "Ignore TLS/SSL errors and continue checking the website's availability", - "incidentsOptionsHeader": "Incidents for:", - "incidentsOptionsHeaderFilterAll": "All", - "incidentsOptionsHeaderFilterBy": "Filter by:", - "incidentsOptionsHeaderFilterCannotResolve": "Cannot resolve", - "incidentsOptionsHeaderFilterDown": "Down", "incidentsOptionsHeaderFilterResolved": "Resolved", - "incidentsOptionsHeaderLastDay": "Last day", - "incidentsOptionsHeaderLastHour": "Last hour", - "incidentsOptionsHeaderLastWeek": "Last week", - "incidentsOptionsHeaderShow": "Show:", - "incidentsOptionsPlaceholderAllServers": "All servers", - "incidentsPageTitle": "Incidents", - "incidentsTableDateTime": "Date & Time", - "incidentsTableMessage": "Message", - "incidentsTableMonitorName": "Monitor Name", - "incidentsTableNoIncidents": "No incidents recorded", - "incidentsTablePaginationLabel": "incidents", - "incidentsTableStatus": "Status", - "incidentsTableStatusCode": "Status Code", - "infrastructureAlertNotificationDescription": "Send a notification to user(s) when thresholds exceed a specified percentage.", - "infrastructureAuthorizationSecretLabel": "Authorization secret", - "infrastructureCreateGeneralSettingsDescription": "Here you can select the URL of the host, together with the friendly name and authorization secret to connect to the server agent.", - "infrastructureCreateMonitor": "Create Infrastructure Monitor", - "infrastructureCreateYour": "Create your", - "infrastructureCustomizeAlerts": "Customize alerts", - "infrastructureDisplayNameLabel": "Display name", - "infrastructureEditMonitor": "Save Infrastructure Monitor", - "infrastructureEditYour": "Edit your", - "infrastructureMonitorCreated": "Infrastructure monitor created successfully!", - "infrastructureMonitorUpdated": "Infrastructure monitor updated successfully!", - "infrastructureProtocol": "Protocol", - "infrastructureServerRequirement": "The server you are monitoring must be running the", - "infrastructureServerUrlLabel": "Server URL", - "integrations": "Integrations", - "integrationsDiscord": "Discord", - "integrationsDiscordInfo": "Connect with Discord and view incidents directly in a channel", - "integrationsPrism": "Connect Prism to your favorite service.", - "integrationsSlack": "Slack", - "integrationsSlackInfo": "Connect with Slack and see incidents in a channel", - "integrationsZapier": "Zapier", - "integrationsZapierInfo": "Send all incidents to Zapier, and then see them everywhere", - "invalidFileFormat": "Unsupported file format!", - "invalidFileSize": "File size is too large!", - "inviteNoTokenFound": "No invite token found", - "loginHere": "Login here", - "logsPage": { - "description": "This page shows the latest 1000 lines of logs from the Checkmate server", - "logLevelSelect": { - "title": "Log level", - "values": { - "all": "All", - "debug": "Debug", - "error": "Error", - "info": "Info", - "warn": "Warn" - } - } - }, "createNotifications": { "title": "Create notification channel", "nameSettings": { From d9dbfc6d6e9b1e5103bc904acd066feefce14843 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Thu, 26 Jun 2025 09:33:39 +0800 Subject: [PATCH 10/10] hide resolved --- client/src/Pages/Incidents/Components/OptionsHeader/index.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/Pages/Incidents/Components/OptionsHeader/index.jsx b/client/src/Pages/Incidents/Components/OptionsHeader/index.jsx index 08a9bcf1c..457c6fd96 100644 --- a/client/src/Pages/Incidents/Components/OptionsHeader/index.jsx +++ b/client/src/Pages/Incidents/Components/OptionsHeader/index.jsx @@ -87,13 +87,13 @@ const OptionsHeader = ({ > {t("incidentsOptionsHeaderFilterCannotResolve")} - + */}