From df97b93a9a082a0f33774363429b2cdbb914b309 Mon Sep 17 00:00:00 2001 From: Br0wnHammer Date: Thu, 24 Jul 2025 01:35:31 +0530 Subject: [PATCH 1/6] Button Text Dynamic --- client/src/Pages/Incidents/index.jsx | 2 +- client/src/locales/en.json | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/client/src/Pages/Incidents/index.jsx b/client/src/Pages/Incidents/index.jsx index 7b4c22e41..c19aea69b 100644 --- a/client/src/Pages/Incidents/index.jsx +++ b/client/src/Pages/Incidents/index.jsx @@ -84,7 +84,7 @@ const Incidents = () => { onClick={handleAckAllChecks} disabled={ackAllLoading} > - {t("incidentsPageActionResolve")} + {selectedMonitor === "0" ? t("incidentsPageActionResolveAll") : t("incidentsPageActionResolveMonitor")} Date: Thu, 24 Jul 2025 01:42:46 +0530 Subject: [PATCH 2/6] Network Service: Monitor Check Func --- client/src/Hooks/checkHooks.js | 18 ++++++++++++++++++ client/src/Utils/NetworkService.js | 6 ++++++ client/src/locales/en.json | 1 + 3 files changed, 25 insertions(+) diff --git a/client/src/Hooks/checkHooks.js b/client/src/Hooks/checkHooks.js index f23e1eaea..3e5567cf6 100644 --- a/client/src/Hooks/checkHooks.js +++ b/client/src/Hooks/checkHooks.js @@ -185,6 +185,23 @@ const useResolveIncident = () => { return [resolveIncident, isLoading]; }; +const useAckMonitorChecks = () => { + const [isLoading, setIsLoading] = useState(false); + const { t } = useTranslation(); + + const ackMonitorChecks = async (monitorId, setUpdateTrigger) => { + try { + setIsLoading(true); + } catch (error) { + createToast({ body: t("checkHooks.failureResolveMonitor") }); + } finally { + setIsLoading(false); + } + }; + + return [ackMonitorChecks, isLoading]; +}; + const useAckAllChecks = () => { const [isLoading, setIsLoading] = useState(false); const { t } = useTranslation(); @@ -209,5 +226,6 @@ export { useFetchChecksTeam, useFetchChecksSummaryByTeamId, useResolveIncident, + useAckMonitorChecks, useAckAllChecks, }; diff --git a/client/src/Utils/NetworkService.js b/client/src/Utils/NetworkService.js index 5b33f97af..a711ceb21 100644 --- a/client/src/Utils/NetworkService.js +++ b/client/src/Utils/NetworkService.js @@ -631,6 +631,12 @@ class NetworkService { }); } + async updateMonitorChecksStatus(config) { + return this.axiosInstance.put(`/checks/monitor/${config.monitorId}`, { + ack: config.ack, + }); + } + async updateAllChecksStatus(config) { return this.axiosInstance.put(`/checks/team/`, { ack: config.ack, diff --git a/client/src/locales/en.json b/client/src/locales/en.json index 131b39952..b88b1d8a1 100644 --- a/client/src/locales/en.json +++ b/client/src/locales/en.json @@ -218,6 +218,7 @@ "checkFrequency": "Check frequency", "checkHooks": { "failureResolveAll": "Failed to resolve all incidents.", + "failureResolveMonitor": "Failed to resolve monitor incidents.", "failureResolveOne": "Failed to resolve incident." }, "checkingEvery": "Checking every", From 3650c400ca7f63de7d1944be415b7033f4f185c6 Mon Sep 17 00:00:00 2001 From: Br0wnHammer Date: Thu, 24 Jul 2025 01:47:42 +0530 Subject: [PATCH 3/6] Feat: Monitor Incidents Resolve --- client/src/Hooks/checkHooks.js | 5 +++++ client/src/Pages/Incidents/index.jsx | 11 ++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/client/src/Hooks/checkHooks.js b/client/src/Hooks/checkHooks.js index 3e5567cf6..f24466792 100644 --- a/client/src/Hooks/checkHooks.js +++ b/client/src/Hooks/checkHooks.js @@ -192,6 +192,11 @@ const useAckMonitorChecks = () => { const ackMonitorChecks = async (monitorId, setUpdateTrigger) => { try { setIsLoading(true); + await networkService.updateMonitorChecksStatus({ + monitorId, + ack: true, + }); + setUpdateTrigger((prev) => !prev); } catch (error) { createToast({ body: t("checkHooks.failureResolveMonitor") }); } finally { diff --git a/client/src/Pages/Incidents/index.jsx b/client/src/Pages/Incidents/index.jsx index c19aea69b..780c91fe8 100644 --- a/client/src/Pages/Incidents/index.jsx +++ b/client/src/Pages/Incidents/index.jsx @@ -11,7 +11,7 @@ import { Box, Button } from "@mui/material"; import { useTheme } from "@emotion/react"; import { useFetchMonitorsByTeamId } from "../../Hooks/monitorHooks"; import { useFetchChecksSummaryByTeamId } from "../../Hooks/checkHooks"; -import { useAckAllChecks } from "../../Hooks/checkHooks"; +import { useAckAllChecks, useAckMonitorChecks } from "../../Hooks/checkHooks"; import { useState, useEffect } from "react"; import NetworkError from "../../Components/GenericFallback/NetworkError"; import { useTranslation } from "react-i18next"; @@ -35,6 +35,7 @@ const Incidents = () => { //Hooks const [ackAllChecks, ackAllLoading] = useAckAllChecks(); + const [ackMonitorChecks, ackMonitorLoading] = useAckMonitorChecks(); //Utils const theme = useTheme(); @@ -63,7 +64,11 @@ const Incidents = () => { }, [monitors]); const handleAckAllChecks = () => { - ackAllChecks(setUpdateTrigger); + if (selectedMonitor === "0") { + ackAllChecks(setUpdateTrigger); + } else { + ackMonitorChecks(selectedMonitor, setUpdateTrigger); + } }; if (networkError || networkErrorSummary) { @@ -82,7 +87,7 @@ const Incidents = () => { variant="contained" color="accent" onClick={handleAckAllChecks} - disabled={ackAllLoading} + disabled={selectedMonitor === "0" ? ackAllLoading : ackMonitorLoading} > {selectedMonitor === "0" ? t("incidentsPageActionResolveAll") : t("incidentsPageActionResolveMonitor")} From b7093b5de54c894650bbfa888b66c1d000e5ca30 Mon Sep 17 00:00:00 2001 From: Br0wnHammer Date: Thu, 24 Jul 2025 01:54:58 +0530 Subject: [PATCH 4/6] Feat: One Hook for Incidents Ack --- client/src/Hooks/checkHooks.js | 27 +++++ client/src/Pages/Incidents/index.jsx | 20 +++- .../SuperSimpleQueueHelper.js | 6 +- server/templates/passwordReset.mjml | 90 +++++++++------ server/templates/serverIsDown.mjml | 108 +++++++++++------- server/templates/welcomeEmail.mjml | 84 ++++++++------ 6 files changed, 212 insertions(+), 123 deletions(-) diff --git a/client/src/Hooks/checkHooks.js b/client/src/Hooks/checkHooks.js index f24466792..6fd48e828 100644 --- a/client/src/Hooks/checkHooks.js +++ b/client/src/Hooks/checkHooks.js @@ -226,6 +226,32 @@ const useAckAllChecks = () => { return [ackAllChecks, isLoading]; }; +const useAcknowledgeChecks = () => { + const [isLoading, setIsLoading] = useState(false); + const { t } = useTranslation(); + + const acknowledge = async (setUpdateTrigger, monitorId = null) => { + setIsLoading(true); + try { + if (monitorId) { + await networkService.updateMonitorChecksStatus({ monitorId, ack: true }); + } else { + await networkService.updateAllChecksStatus({ ack: true }); + } + setUpdateTrigger((prev) => !prev); + } catch (error) { + const toastMessage = monitorId + ? t("checkHooks.failureResolveMonitor") + : t("checkHooks.failureResolveAll"); + createToast({ body: toastMessage }); + } finally { + setIsLoading(false); + } + }; + + return { acknowledge, isLoading }; +}; + export { useFetchChecksByMonitor, useFetchChecksTeam, @@ -233,4 +259,5 @@ export { useResolveIncident, useAckMonitorChecks, useAckAllChecks, + useAcknowledgeChecks, }; diff --git a/client/src/Pages/Incidents/index.jsx b/client/src/Pages/Incidents/index.jsx index 780c91fe8..d963db9e7 100644 --- a/client/src/Pages/Incidents/index.jsx +++ b/client/src/Pages/Incidents/index.jsx @@ -11,7 +11,11 @@ import { Box, Button } from "@mui/material"; import { useTheme } from "@emotion/react"; import { useFetchMonitorsByTeamId } from "../../Hooks/monitorHooks"; import { useFetchChecksSummaryByTeamId } from "../../Hooks/checkHooks"; -import { useAckAllChecks, useAckMonitorChecks } from "../../Hooks/checkHooks"; +import { + useAckAllChecks, + useAckMonitorChecks, + useAcknowledgeChecks, +} from "../../Hooks/checkHooks"; import { useState, useEffect } from "react"; import NetworkError from "../../Components/GenericFallback/NetworkError"; import { useTranslation } from "react-i18next"; @@ -36,6 +40,7 @@ const Incidents = () => { //Hooks const [ackAllChecks, ackAllLoading] = useAckAllChecks(); const [ackMonitorChecks, ackMonitorLoading] = useAckMonitorChecks(); + const { acknowledge, isLoadingAcknowledge } = useAcknowledgeChecks(); //Utils const theme = useTheme(); @@ -71,6 +76,11 @@ const Incidents = () => { } }; + const handleAcknowledge = () => { + const monitorId = selectedMonitor === "0" ? null : selectedMonitor; + acknowledge(setUpdateTrigger, monitorId); + }; + if (networkError || networkErrorSummary) { return ( @@ -86,10 +96,12 @@ const Incidents = () => { - - - - - - - - - - - - - Message from Checkmate Service - - - - - - -

Hello {{ name }}!

-

- You are receiving this email because a password reset request has been made for {{ email }}. Please use the link below on the site to - reset your password. -

- Reset Password -

If you didn't request this, please ignore this email.

+ + + + + + + + + + + + + Message from Checkmate Service + + + + + + +

Hello {{ name }}!

+

+ You are receiving this email because a password reset request has been made for {{ email }}. Please use the link below on the site to + reset your password. +

+ Reset Password +

If you didn't request this, please ignore this email.

-

Thank you.

-
-
- - - -

This email was sent by Checkmate.

-
-
-
-
-
\ No newline at end of file +

Thank you.

+ + + + + +

This email was sent by Checkmate.

+
+
+ + + diff --git a/server/templates/serverIsDown.mjml b/server/templates/serverIsDown.mjml index 5375412ab..bf6424a6b 100755 --- a/server/templates/serverIsDown.mjml +++ b/server/templates/serverIsDown.mjml @@ -1,42 +1,68 @@ - - - - - - - - - - - - - Message from Checkmate Service - - - - - {{ monitor }} is down - - - - - - - -

Hello {{ name }}!

-

We detected an incident on one of your monitors. Your service is currently down. We'll send a message to you once it is up again.

-

Monitor name: {{ monitor }}

-

URL: {{ url }}

-
-
- - - View incident details - -

This email was sent by Checkmate.

-
-
-
-
-
\ No newline at end of file + + + + + + + + + + + + + Message from Checkmate Service + + + + + {{ monitor }} is down + + + + + + + +

Hello {{ name }}!

+

We detected an incident on one of your monitors. Your service is currently down. We'll send a message to you once it is up again.

+

Monitor name: {{ monitor }}

+

URL: {{ url }}

+
+
+ + + View incident details + +

This email was sent by Checkmate.

+
+
+
+
+ diff --git a/server/templates/welcomeEmail.mjml b/server/templates/welcomeEmail.mjml index b5e90ffaf..e9f569e3f 100755 --- a/server/templates/welcomeEmail.mjml +++ b/server/templates/welcomeEmail.mjml @@ -1,37 +1,51 @@ - - - - - - - - - - - - - Message from Checkmate Service - - - - - - -

Hello {{ name }}!

-

Thank you for trying out Checkmate! We developed it with great care to meet our own needs, and we're excited to share it with you.

-

Checkmate is an automated way of checking whether a service such as a website or an application is available or not.

-

We hope you find our service as valuable as we do.

-

Thank you.

-
-
- - - -

This email was sent by Checkmate.

-
-
-
-
-
\ No newline at end of file + + + + + + + + + + + + + Message from Checkmate Service + + + + + + +

Hello {{ name }}!

+

Thank you for trying out Checkmate! We developed it with great care to meet our own needs, and we're excited to share it with you.

+

Checkmate is an automated way of checking whether a service such as a website or an application is available or not.

+

We hope you find our service as valuable as we do.

+

Thank you.

+
+
+ + + +

This email was sent by Checkmate.

+
+
+
+
+ From 7236e8532131827e9e34acc44202aa473402b811 Mon Sep 17 00:00:00 2001 From: Br0wnHammer Date: Thu, 24 Jul 2025 01:56:05 +0530 Subject: [PATCH 5/6] Removal of old code --- client/src/Hooks/checkHooks.js | 43 ---------------------------- client/src/Pages/Incidents/index.jsx | 16 +---------- 2 files changed, 1 insertion(+), 58 deletions(-) diff --git a/client/src/Hooks/checkHooks.js b/client/src/Hooks/checkHooks.js index 6fd48e828..bdb1a73b7 100644 --- a/client/src/Hooks/checkHooks.js +++ b/client/src/Hooks/checkHooks.js @@ -185,47 +185,6 @@ const useResolveIncident = () => { return [resolveIncident, isLoading]; }; -const useAckMonitorChecks = () => { - const [isLoading, setIsLoading] = useState(false); - const { t } = useTranslation(); - - const ackMonitorChecks = async (monitorId, setUpdateTrigger) => { - try { - setIsLoading(true); - await networkService.updateMonitorChecksStatus({ - monitorId, - ack: true, - }); - setUpdateTrigger((prev) => !prev); - } catch (error) { - createToast({ body: t("checkHooks.failureResolveMonitor") }); - } finally { - setIsLoading(false); - } - }; - - return [ackMonitorChecks, isLoading]; -}; - -const useAckAllChecks = () => { - const [isLoading, setIsLoading] = useState(false); - const { t } = useTranslation(); - - const ackAllChecks = async (setUpdateTrigger) => { - try { - setIsLoading(true); - await networkService.updateAllChecksStatus({ ack: true }); - setUpdateTrigger((prev) => !prev); - } catch (error) { - createToast({ body: t("checkHooks.failureResolveAll") }); - } finally { - setIsLoading(false); - } - }; - - return [ackAllChecks, isLoading]; -}; - const useAcknowledgeChecks = () => { const [isLoading, setIsLoading] = useState(false); const { t } = useTranslation(); @@ -257,7 +216,5 @@ export { useFetchChecksTeam, useFetchChecksSummaryByTeamId, useResolveIncident, - useAckMonitorChecks, - useAckAllChecks, useAcknowledgeChecks, }; diff --git a/client/src/Pages/Incidents/index.jsx b/client/src/Pages/Incidents/index.jsx index d963db9e7..7696c453b 100644 --- a/client/src/Pages/Incidents/index.jsx +++ b/client/src/Pages/Incidents/index.jsx @@ -11,11 +11,7 @@ import { Box, Button } from "@mui/material"; import { useTheme } from "@emotion/react"; import { useFetchMonitorsByTeamId } from "../../Hooks/monitorHooks"; import { useFetchChecksSummaryByTeamId } from "../../Hooks/checkHooks"; -import { - useAckAllChecks, - useAckMonitorChecks, - useAcknowledgeChecks, -} from "../../Hooks/checkHooks"; +import { useAcknowledgeChecks } from "../../Hooks/checkHooks"; import { useState, useEffect } from "react"; import NetworkError from "../../Components/GenericFallback/NetworkError"; import { useTranslation } from "react-i18next"; @@ -38,8 +34,6 @@ const Incidents = () => { const [updateTrigger, setUpdateTrigger] = useState(false); //Hooks - const [ackAllChecks, ackAllLoading] = useAckAllChecks(); - const [ackMonitorChecks, ackMonitorLoading] = useAckMonitorChecks(); const { acknowledge, isLoadingAcknowledge } = useAcknowledgeChecks(); //Utils @@ -68,14 +62,6 @@ const Incidents = () => { setMonitorLookup(monitorLookup); }, [monitors]); - const handleAckAllChecks = () => { - if (selectedMonitor === "0") { - ackAllChecks(setUpdateTrigger); - } else { - ackMonitorChecks(selectedMonitor, setUpdateTrigger); - } - }; - const handleAcknowledge = () => { const monitorId = selectedMonitor === "0" ? null : selectedMonitor; acknowledge(setUpdateTrigger, monitorId); From c766dc9f004420bea8bbb6594c45c4a666a9a814 Mon Sep 17 00:00:00 2001 From: Br0wnHammer Date: Thu, 24 Jul 2025 02:06:55 +0530 Subject: [PATCH 6/6] JSDOC for both network calls --- client/src/Utils/NetworkService.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/client/src/Utils/NetworkService.js b/client/src/Utils/NetworkService.js index a711ceb21..3abd726da 100644 --- a/client/src/Utils/NetworkService.js +++ b/client/src/Utils/NetworkService.js @@ -631,12 +631,35 @@ class NetworkService { }); } + /** + * ************************************ + * Update the status of all checks for a given monitor + * ************************************ + * + * @async + * @param {Object} config - The configuration object. + * @param {string} config.monitorId - The ID of the monitor. + * @param {boolean} config.ack - The acknowledgment to update the checks to. + * @returns {Promise} The response from the axios PUT request. + * + */ async updateMonitorChecksStatus(config) { return this.axiosInstance.put(`/checks/monitor/${config.monitorId}`, { ack: config.ack, }); } + /** + * ************************************ + * Update the status of all checks for a given team + * ************************************ + * + * @async + * @param {Object} config - The configuration object. + * @param {boolean} config.ack - The acknowledgment to update the checks to. + * @returns {Promise} The response from the axios PUT request. + * + */ async updateAllChecksStatus(config) { return this.axiosInstance.put(`/checks/team/`, { ack: config.ack,