diff --git a/client/src/App.jsx b/client/src/App.jsx
index da83f9061..194a5bf5b 100644
--- a/client/src/App.jsx
+++ b/client/src/App.jsx
@@ -7,7 +7,6 @@ import lightTheme from "./Utils/Theme/lightTheme";
import darkTheme from "./Utils/Theme/darkTheme";
import { CssBaseline, GlobalStyles } from "@mui/material";
import { logger } from "./Utils/Logger"; // Import the logger
-import { networkService } from "./main";
import { Routes } from "./Routes";
import AppLayout from "@/Components/v1/Layouts/AppLayout";
@@ -18,7 +17,6 @@ function App() {
useEffect(() => {
return () => {
logger.cleanup();
- networkService.cleanup();
};
}, []);
diff --git a/client/src/Hooks/useSendTestEmail.js b/client/src/Hooks/useSendTestEmail.js
deleted file mode 100644
index 7223a489a..000000000
--- a/client/src/Hooks/useSendTestEmail.js
+++ /dev/null
@@ -1,60 +0,0 @@
-import { useState } from "react";
-import { networkService } from "../main.jsx";
-import { useSelector } from "react-redux";
-import { createToast } from "../Utils/toastUtils.jsx";
-import { useTranslation } from "react-i18next";
-
-const useSendTestEmail = () => {
- const [isSending, setIsSending] = useState(false);
- const [error, setError] = useState(null);
- const user = useSelector((state) => state.auth.user);
- const { t } = useTranslation();
-
- /**
- * Send a test email with optional email configuration
- * @param {Object} emailConfig - Optional email configuration parameters
- */
- const sendTestEmail = async (emailConfig = null) => {
- try {
- setIsSending(true);
- setError(null);
-
- // Send the test email with or without configuration
- const response = await networkService.sendTestEmail({
- to: user.email,
- emailConfig,
- });
-
- if (typeof response?.data?.data?.messageId !== "undefined") {
- createToast({
- body: t("settingsTestEmailSuccess", "Test email sent successfully"),
- });
- } else {
- throw new Error(
- response?.data?.error ||
- t("settingsTestEmailFailed", "Failed to send test email")
- );
- }
- } catch (error) {
- createToast({
- body: t("failedToSendEmail"),
- });
- setError(error);
- createToast({
- body: t(
- "settingsTestEmailFailedWithReason",
- "Failed to send test email: {{reason}}",
- {
- reason: error.message || t("settingsTestEmailUnknownError", "Unknown error"),
- }
- ),
- variant: "error",
- });
- } finally {
- setIsSending(false);
- }
- };
- return [isSending, error, sendTestEmail];
-};
-
-export { useSendTestEmail };
diff --git a/client/src/Pages/ServerUnreachable.jsx b/client/src/Pages/ServerUnreachable.jsx
index bfbbfa90a..5051ee95f 100644
--- a/client/src/Pages/ServerUnreachable.jsx
+++ b/client/src/Pages/ServerUnreachable.jsx
@@ -2,7 +2,7 @@ import React, { useState } from "react";
import { Box, Typography, Button, Stack } from "@mui/material";
import { useTheme } from "@emotion/react";
import { useNavigate } from "react-router-dom";
-import { networkService } from "@/Utils/NetworkService.js";
+import { get } from "@/Utils/ApiClient";
import Alert from "@/Components/v1/Alert/index.jsx";
import { createToast } from "@/Utils/toastUtils.jsx";
import { useTranslation } from "react-i18next";
@@ -24,7 +24,7 @@ const ServerUnreachable = () => {
try {
// Try to connect to the backend with a simple API call
// We'll use any lightweight endpoint that doesn't require authentication
- await networkService.axiosInstance.get("/health", { timeout: 5000 });
+ await get("/health", { timeout: 5000 });
// If successful, show toast and navigate to login page
createToast({
diff --git a/client/src/Pages/Settings/SettingsEmail.jsx b/client/src/Pages/Settings/SettingsEmail.jsx
index 6f0b02137..859ff604c 100644
--- a/client/src/Pages/Settings/SettingsEmail.jsx
+++ b/client/src/Pages/Settings/SettingsEmail.jsx
@@ -12,7 +12,8 @@ import { PropTypes } from "prop-types";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { PasswordEndAdornment } from "@/Components/v1/Inputs/TextInput/Adornments/index.jsx";
-import { useSendTestEmail } from "@/Hooks/useSendTestEmail.js";
+import { usePost } from "@/Hooks/UseApi";
+import { useSelector } from "react-redux";
import { createToast } from "@/Utils/toastUtils.jsx";
const SettingsEmail = ({
@@ -48,7 +49,8 @@ const SettingsEmail = ({
const [password, setPassword] = useState("");
// Network
- const [isSending, , sendTestEmail] = useSendTestEmail(); // Using empty placeholder for unused error variable
+ const { post: sendTestEmailFn, loading: isSending } = usePost();
+ const user = useSelector((state) => state.auth.user);
// Handlers
const handlePasswordChange = (e) => {
@@ -94,7 +96,10 @@ const SettingsEmail = ({
}
// Send test email with current form values
- sendTestEmail(emailConfig);
+ sendTestEmailFn("/settings/test-email", {
+ to: user.email,
+ ...emailConfig,
+ });
};
if (!isAdmin) {
@@ -297,6 +302,14 @@ const SettingsEmail = ({
+
+ {JSON.stringify({
+ systemEmailHost,
+ systemEmailAddress,
+ systemEmailPassword,
+ })}
+
+
{systemEmailHost &&
systemEmailPort &&
diff --git a/client/src/Utils/NetworkService.js b/client/src/Utils/NetworkService.js
deleted file mode 100644
index 7f6a8e455..000000000
--- a/client/src/Utils/NetworkService.js
+++ /dev/null
@@ -1,1187 +0,0 @@
-import axios from "axios";
-import i18next from "i18next";
-const BASE_URL = import.meta.env.VITE_APP_API_BASE_URL;
-const FALLBACK_BASE_URL = "http://localhost:5000/api/v1";
-import { clearAuthState } from "../Features/Auth/authSlice";
-class NetworkService {
- constructor(store, dispatch, navigate) {
- this.store = store;
- this.dispatch = dispatch;
- this.navigate = navigate;
- let baseURL = BASE_URL;
- this.axiosInstance = axios.create();
- this.setBaseUrl(baseURL);
- this.unsubscribe = store.subscribe(() => {
- const state = store.getState();
- if (BASE_URL !== undefined) {
- baseURL = BASE_URL;
- } else if (state?.settings?.apiBaseUrl ?? null) {
- baseURL = state.settings.apiBaseUrl;
- } else {
- baseURL = FALLBACK_BASE_URL;
- }
- this.setBaseUrl(baseURL);
- });
- this.axiosInstance.interceptors.request.use(
- (config) => {
- const currentLanguage = i18next.language || "en";
-
- const { authToken } = store.getState().auth;
-
- config.headers = {
- Authorization: `Bearer ${authToken}`,
- "Accept-Language": currentLanguage === "gb" ? "en" : currentLanguage,
- ...config.headers,
- };
-
- return config;
- },
- (error) => {
- return Promise.reject(error);
- }
- );
- this.axiosInstance.interceptors.response.use(
- (response) => response,
- (error) => {
- // Handle network errors (server unreachable)
- if (error.code === "ERR_NETWORK") {
- // Navigate to server unreachable page
- navigate("/server-unreachable");
- // Return an empty resolved promise to stop the error propagation
- return Promise.reject(error);
- }
-
- // Handle authentication errors
-
- if (error.response && error.response.status === 401) {
- dispatch(clearAuthState());
- navigate("/login");
- } else if (error.request && !error.response) {
- return Promise.reject(error);
- }
- return Promise.reject(error);
- }
- );
- }
-
- setBaseUrl = (url) => {
- this.axiosInstance.defaults.baseURL = url;
- };
-
- cleanup() {
- if (this.unsubscribe) {
- this.unsubscribe();
- }
- }
-
- /**
- * Fetch the games associated with a monitor
- *
- * @async
- * @returns {Promise} The response from the axios GET request.
- */
- async getMonitorGames() {
- return this.axiosInstance.get(`/monitors/games`, {
- headers: {
- "Content-Type": "application/json",
- },
- });
- }
-
- /**
- *
- * ************************************
- * Create a new monitor
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @param {string} config.monitorId - The monitor ID to be sent in the param.
- * @returns {Promise} The response from the axios GET request.
- */
-
- async getMonitorById(config) {
- return this.axiosInstance.get(`/monitors/${config.monitorId}`, {
- headers: {
- "Content-Type": "application/json",
- },
- });
- }
-
- /**
- *
- * ************************************
- * Create a new monitor
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @param {Object} config.monitor - The monitor object to be sent in the request body.
- * @returns {Promise} The response from the axios POST request.
- */
- async createMonitor(config) {
- const { monitor } = config;
-
- return this.axiosInstance.post(`/monitors`, monitor);
- }
-
- /**
- * ************************************
- * Get all uptime monitors for a Team
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @param {string} config.teamId - The ID of the team whose monitors are to be retrieved.
- * @param {number} [config.limit] - The maximum number of checks to retrieve. 0 for all, -1 for none
- * @param {Array} [config.types] - The types of monitors to retrieve.
- * @param {number} [config.page] - The page number for pagination.
- * @param {number} [config.rowsPerPage] - The number of rows per page for pagination.
- * @param {string} [config.filter] - The filter to apply to the monitors.
- * @param {string} [config.field] - The field to sort by.
- * @param {string} [config.order] - The order in which to sort the field.
- * @returns {Promise} The response from the axios GET request.
- */
-
- async getMonitorsByTeamId(config) {
- const { types, filter } = config ?? {};
- const params = new URLSearchParams();
-
- if (types) {
- types.forEach((type) => {
- params.append("type", type);
- });
- }
- if (filter !== undefined && filter !== null && filter !== "")
- params.append("filter", filter);
-
- return this.axiosInstance.get(`/monitors/team?${params.toString()}`, {
- headers: {
- "Content-Type": "application/json",
- },
- });
- }
-
- /**
- * ************************************
- * Get stats for a monitor
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @param {string} config.monitorId - The ID of the monitor whose statistics are to be retrieved.
- * @param {string} config.sortOrder - The order in which to sort the retrieved statistics.
- * @param {number} config.limit - The maximum number of statistics to retrieve.
- * @param {string} config.dateRange - The date range for which to retrieve statistics.
- * @param {number} config.numToDisplay - The number of checks to display.
- * @param {boolean} config.normalize - Whether to normalize the retrieved statistics.
- * @returns {Promise} The response from the axios GET request.
- */
- async getStatsByMonitorId(config) {
- const params = new URLSearchParams();
- if (config.sortOrder) params.append("sortOrder", config.sortOrder);
- if (config.limit) params.append("limit", config.limit);
- if (config.dateRange) params.append("dateRange", config.dateRange);
- if (config.numToDisplay) params.append("numToDisplay", config.numToDisplay);
- if (config.normalize) params.append("normalize", config.normalize);
-
- return this.axiosInstance.get(
- `/monitors/stats/${config.monitorId}?${params.toString()}`
- );
- }
-
- async getHardwareDetailsByMonitorId(config) {
- const params = new URLSearchParams();
- if (config.dateRange) params.append("dateRange", config.dateRange);
-
- return this.axiosInstance.get(
- `/monitors/hardware/details/${config.monitorId}?${params.toString()}`
- );
- }
- async getPageSpeedDetailsByMonitorId(config) {
- const params = new URLSearchParams();
- if (config.dateRange) params.append("dateRange", config.dateRange);
-
- return this.axiosInstance.get(
- `/monitors/pagespeed/details/${config.monitorId}?${params.toString()}`
- );
- }
- async getUptimeDetailsById(config) {
- const params = new URLSearchParams();
- if (config.dateRange) params.append("dateRange", config.dateRange);
- if (config.normalize) params.append("normalize", config.normalize);
-
- return this.axiosInstance.get(
- `/monitors/uptime/details/${config.monitorId}?${params.toString()}`
- );
- }
-
- /**
- * ************************************
- * Updates a single monitor
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @param {string} config.monitorId - The ID of the monitor to be updated.
- * @param {Object} config.updatedFields - The fields to be updated for the monitor.
- * @returns {Promise} The response from the axios PUT request.
- */
- async updateMonitor(config) {
- const { monitorId, updatedFields } = config;
- const payload = updatedFields;
- return this.axiosInstance.patch(`/monitors/${monitorId}`, payload, {
- headers: {
- "Content-Type": "application/json",
- },
- });
- }
-
- /**
- * ************************************
- * Deletes a single monitor by its ID
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @param {string} config.monitorId - The ID of the monitor to be deleted.
- * @returns {Promise} The response from the axios DELETE request.
- */
- async deleteMonitorById(config) {
- return this.axiosInstance.delete(`/monitors/${config.monitorId}`, {
- headers: {
- "Content-Type": "application/json",
- },
- });
- }
-
- /**
- * ************************************
- * Deletes all checks for all monitor by teamID
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @param {string} config.teamId - The team ID of the monitors to be deleted.
- * @returns {Promise} The response from the axios DELETE request.
- */
- async deleteChecksByTeamId(config) {
- return this.axiosInstance.delete(`/checks/team`, {
- headers: {
- "Content-Type": "application/json",
- },
- });
- }
- /**
- * ************************************
- * Pauses a single monitor by its ID
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @param {string} config.monitorId - The ID of the monitor to be paused.
- * @returns {Promise} The response from the axios POST request.
- */
- async pauseMonitorById(config) {
- return this.axiosInstance.post(
- `/monitors/pause/${config.monitorId}`,
- {},
- {
- headers: {
- "Content-Type": "application/json",
- },
- }
- );
- }
-
- /**
- * ************************************
- * Adds demo monitors
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @returns {Promise} The response from the axios POST request.
- */
- async addDemoMonitors(config) {
- return this.axiosInstance.post(
- `/monitors/demo`,
- {},
- {
- headers: {
- "Content-Type": "application/json",
- },
- }
- );
- }
-
- /**
- * ************************************
- * Deletes all monitors for a team by team ID
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @returns {Promise} The response from the axios DELETE request.
- */
- async deleteAllMonitors(config) {
- return this.axiosInstance.delete(`/monitors/`, {
- headers: {
- "Content-Type": "application/json",
- },
- });
- }
-
- /**
- * ************************************
- * Gets the certificate expiry for a monitor
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @param {string} config.monitorId - The ID of the monitor whose certificate expiry is to be retrieved.
- * @returns {Promise} The response from the axios GET request.
- *
- */
- async getCertificateExpiry(config) {
- return this.axiosInstance.get(`/monitors/certificate/${config.monitorId}`);
- }
-
- async registerUser(user, token) {
- return this.axiosInstance.post(`/auth/register`, { user, token });
- }
-
- /**
- * ************************************
- * Logs in a user
- * ************************************
- *
- * @async
- * @param {Object} form - The form data for the user to be logged in.
- * @returns {Promise} The response from the axios POST request.
- *
- */
- async loginUser(form) {
- return this.axiosInstance.post(`/auth/login`, form);
- }
-
- /**
- * ************************************
- * Updates a user
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @param {string} config.userId - The ID of the user to be updated.
- * @param {Object} config.form - The form data for the user to be updated.
- * @returns {Promise} The response from the axios PATCH request.
- *
- */
- async updateUser(config) {
- return this.axiosInstance.patch(`/auth/user`, config.form);
- }
-
- /**
- * ************************************
- * Deletes a user
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @param {string} config.userId - The ID of the user to be deleted.
- *
- **/
- async deleteUser() {
- return this.axiosInstance.delete(`/auth/user`);
- }
-
- /**
- * ************************************
- * Forgot password request
- * ************************************
- *
- * @async
- * @param {Object} form - The form data for the password recovery request.
- * @returns {Promise} The response from the axios POST request.
- *
- */
- async forgotPassword(form) {
- return this.axiosInstance.post(`/auth/recovery/request`, form);
- }
-
- /**
- * ************************************
- * Validates a recovery token
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @param {string} config.recoveryToken - The recovery token to be validated.
- * @returns {Promise} The response from the axios POST request.
- *
- */
- async validateRecoveryToken(config) {
- return this.axiosInstance.post("/auth/recovery/validate", {
- recoveryToken: config.recoveryToken,
- });
- }
-
- /**
- * ************************************
- * Requests password recovery
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @param {string} config.recoveryToken - The token for recovery request.
- * @param {Object} config.form - The form data for the password recovery request.
- * @returns {Promise} The response from the axios POST request.
- *
- */
- async setNewPassword(config) {
- return this.axiosInstance.post("/auth/recovery/reset", {
- ...config.form,
- recoveryToken: config.recoveryToken,
- });
- }
-
- /**
- * ************************************
- * Checks if an admin user exists
- * ************************************
- *
- * @async
- * @returns {Promise} The response from the axios GET request.
- *
- */
- async doesSuperAdminExist() {
- return this.axiosInstance.get("/auth/users/superadmin");
- }
-
- /**
- * ************************************
- * Get all users
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @returns {Promise} The response from the axios GET request.
- *
- */
- async getAllUsers(config) {
- return this.axiosInstance.get("/auth/users");
- }
-
- /**
- * ************************************
- * Requests an invitation token
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @param {string} config.email - The email of the user to be invited.
- * @param {string} config.role - The role of the user to be invited.
- * @returns {Promise} The response from the axios POST request.
- *
- */
- async requestInvitationToken(config) {
- return this.axiosInstance.post(`/invite`, { email: config.email, role: config.role });
- }
- /**
- * ************************************
- * Sends an invitation token
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @param {string} config.email - The email of the user to be invited.
- * @param {string} config.role - The role of the user to be invited.
- * @returns {Promise} The response from the axios POST request.
- *
- */
- async sendInvitationToken(config) {
- return this.axiosInstance.post(`/invite/send`, {
- email: config.email,
- role: config.role,
- });
- }
-
- /**
- * ************************************
- * Verifies an invitation token
- * ************************************
- *
- * @async
- * @param {string} token - The invitation token to be verified.
- * @returns {Promise} The response from the axios POST request.
- *
- */
- async verifyInvitationToken(token) {
- return this.axiosInstance.post(`/invite/verify`, {
- token,
- });
- }
-
- /**
- * ************************************
- * Get all checks for a given monitor
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @param {string} config.monitorId - The ID of the monitor.
- * @param {string} config.sortOrder - The order in which to sort the checks.
- * @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.
- *
- */
-
- getChecksByMonitor = async (config) => {
- const params = new URLSearchParams();
- if (config.type) params.append("type", config.type);
- if (config.sortOrder) params.append("sortOrder", config.sortOrder);
- 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);
-
- return this.axiosInstance.get(`/checks/${config.monitorId}?${params.toString()}`);
- };
-
- /**
- * ************************************
- * Get all checks for a given user
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @param {string} config.userId - The ID of the user.
- * @param {string} config.sortOrder - The order in which to sort the checks.
- * @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.
- *
- */
- getChecksByTeam = async (config) => {
- const params = new URLSearchParams();
- if (config.sortOrder) params.append("sortOrder", config.sortOrder);
- 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);
- return this.axiosInstance.get(`/checks/team?${params.toString()}`);
- };
-
- /**
- * ************************************
- * Get summary of checks by team ID
- * ************************************
- *
- * @async
- * @returns {Promise} The response from the axios GET request.
- */
- getChecksAndSummaryByTeamId = async ({ dateRange }) => {
- return this.axiosInstance.get(`/checks/team/summary?dateRange=${dateRange}`);
- };
-
- /**
- * ************************************
- * 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.ack - The acknowledgment to update the check to.
- * @returns {Promise} The response from the axios PUT request.
- *
- */
- async updateCheckStatus(config) {
- return this.axiosInstance.patch(`/checks/check/${config.checkId}`, {
- ack: config.ack,
- });
- }
-
- /**
- * ************************************
- * 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.patch(`/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.patch(`/checks/team/`, {
- ack: config.ack,
- });
- }
-
- /**
- * ************************************
- * Get all checks for a given user
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @param {number} config.ttl - TTL for checks
- * @returns {Promise} The response from the axios GET request.
- *
- */
- async updateChecksTTL(config) {
- return this.axiosInstance.patch(
- `/checks/team/ttl`,
- { ttl: config.ttl },
- {
- headers: {
- "Content-Type": "application/json",
- },
- }
- );
- }
-
- /**
- * ************************************
- * Get app settings
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @returns {Promise} The response from the axios GET request.
- *
- */
-
- async getAppSettings(config) {
- return this.axiosInstance.get("/settings", {
- headers: {
- "Content-Type": "application/json",
- },
- });
- }
-
- /**
- *
- * ************************************
- * Create a new monitor
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @param {Object} config.settings - The monitor object to be sent in the request body.
- * @returns {Promise} The response from the axios POST request.
- */
- async updateAppSettings(config) {
- return this.axiosInstance.patch(`/settings`, config.settings, {
- headers: {
- "Content-Type": "application/json",
- },
- });
- }
-
- /**
- * ************************************
- * Test a notification integration
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @param {string} config.platform - The notification platform (slack, discord, telegram, webhook).
- * @param {Object} config.payload - The payload with configuration for the notification.
- * @returns {Promise} The response from the axios POST request.
- */
- async testNotification(config) {
- return this.axiosInstance.post("/notifications/test", config.notification, {
- headers: {
- "Content-Type": "application/json",
- },
- });
- }
-
- async testAllNotifications(config) {
- const { monitorId } = config;
- return this.axiosInstance.post("/notifications/test/all", {
- monitorId,
- headers: {
- "Content-Type": "application/json",
- },
- });
- }
-
- /**
- * ************************************
- * Creates a maintenance window
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @param {Object} config.maintenanceWindow - The maintenance window object to be sent in the request body.
- * @returns {Promise} The response from the axios POST request.
- *
- */
-
- async createMaintenanceWindow(config) {
- return this.axiosInstance.post(`/maintenance-window`, config.maintenanceWindow, {
- headers: {
- "Content-Type": "application/json",
- },
- });
- }
-
- /**
- * ************************************
- * Edits a maintenance window
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @param {Object} config.maintenanceWindowId - The maintenance window id.
- * @param {Object} config.maintenanceWindow - The maintenance window object to be sent in the request body.
- * @returns {Promise} The response from the axios POST request.
- *
- */
-
- async editMaintenanceWindow(config) {
- return this.axiosInstance.patch(
- `/maintenance-window/${config.maintenanceWindowId}`,
- config.maintenanceWindow,
- {
- headers: {
- "Content-Type": "application/json",
- },
- }
- );
- }
-
- /**
- * ************************************
- * Get maintenance window by id
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @param {string} [config.maintenanceWindowId] - The id of the maintenance window to delete.
- * @returns {Promise} The response from the axios POST request.
- *
- */
-
- async getMaintenanceWindowById(config) {
- const { maintenanceWindowId } = config;
- return this.axiosInstance.get(`/maintenance-window/${maintenanceWindowId}`, {
- headers: {
- "Content-Type": "application/json",
- },
- });
- }
-
- /**
- * ************************************
- * Get maintenance windows by teamId
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @param {string} [config.active] - The status of the maintenance windows to retrieve.
- * @param {number} [config.page] - The page number for pagination.
- * @param {number} [config.rowsPerPage] - The number of rows per page for pagination.
- * @param {string} [config.field] - The field to sort by.
- * @param {string} [config.order] - The order in which to sort the field.
- * @returns {Promise} The response from the axios POST request.
- *
- */
-
- async getMaintenanceWindowsByTeamId(config) {
- const { active, page, rowsPerPage, field, order } = config;
- const params = new URLSearchParams();
-
- if (active) params.append("status", active);
- if (page) params.append("page", page);
- if (rowsPerPage) params.append("rowsPerPage", rowsPerPage);
- if (field) params.append("field", field);
- if (order) params.append("order", order);
-
- return this.axiosInstance.get(`/maintenance-window/team?${params.toString()}`, {
- headers: {
- "Content-Type": "application/json",
- },
- });
- }
- /**
- * ************************************
- * Delete maintenance window by id
- * ************************************
- *
- * @async
- * @param {Object} config - The configuration object.
- * @param {string} [config.maintenanceWindowId] - The id of the maintenance window to delete.
- * @returns {Promise} The response from the axios POST request.
- *
- */
-
- async deleteMaintenanceWindow(config) {
- const { maintenanceWindowId } = config;
- return this.axiosInstance.delete(`/maintenance-window/${maintenanceWindowId}`, {
- headers: {
- "Content-Type": "application/json",
- },
- });
- }
-
- /**
- * ************************************
- * Fetcher github latest release version
- * ************************************
- *
- * @async
- * @returns {Promise} The response from the axios GET request.
- *
- */
- async fetchGithubLatestRelease() {
- return this.axiosInstance.get(
- "https://api.github.com/repos/bluewave-labs/checkmate/releases/latest",
- {
- headers: {
- Authorization: null, // No authorization header for this request
- },
- }
- );
- }
-
- async getStatusPage() {
- return this.axiosInstance.get(`/status-page`, {
- headers: {
- "Content-Type": "application/json",
- },
- });
- }
-
- async getStatusPageByUrl(config) {
- const { url, type } = config;
- const params = new URLSearchParams();
- params.append("type", type);
-
- return this.axiosInstance.get(`/status-page/${url}?${params.toString()}`, {
- headers: {
- "Content-Type": "application/json",
- },
- });
- }
-
- async getStatusPagesByTeamId(config) {
- return this.axiosInstance.get(`/status-page/team`, {
- headers: {
- "Content-Type": "application/json",
- },
- });
- }
-
- async createStatusPage(config) {
- const { form, isCreate, id } = config;
-
- const fd = new FormData();
- fd.append("type", form.type);
- form.isPublished !== undefined && fd.append("isPublished", form.isPublished);
- form.companyName && fd.append("companyName", form.companyName);
- form.url && fd.append("url", form.url);
- form.timezone && fd.append("timezone", form.timezone);
- form.color && fd.append("color", form.color);
- if (form.showCharts !== undefined) {
- fd.append("showCharts", String(form.showCharts));
- }
- if (form.showUptimePercentage !== undefined) {
- fd.append("showUptimePercentage", String(form.showUptimePercentage));
- }
- if (form.showAdminLoginLink !== undefined) {
- fd.append("showAdminLoginLink", String(form.showAdminLoginLink));
- }
- form.monitors &&
- form.monitors.forEach((monitorId) => {
- fd.append("monitors[]", monitorId);
- });
- // Handle subMonitors, even if it's an empty array
- if (form.subMonitors && form.subMonitors.length > 0) {
- form.subMonitors.forEach((monitorId) => {
- fd.append("subMonitors[]", monitorId);
- });
- } else {
- fd.append("deleteSubmonitors", true);
- }
-
- if (form?.logo?.src && form?.logo?.src !== "") {
- const imageResult = await axios.get(form.logo.src, {
- responseType: "blob",
- });
- fd.append("logo", imageResult.data);
- // Cleanup blob
- if (form.logo.src.startsWith("blob:")) {
- URL.revokeObjectURL(form.logo.src);
- }
- }
-
- if (isCreate) {
- return this.axiosInstance.post(`/status-page`, fd, {});
- }
-
- return this.axiosInstance.patch(`/status-page/${id}`, fd, {});
- }
-
- async deleteStatusPage(config) {
- const { url } = config;
- const encodedUrl = encodeURIComponent(url);
-
- return this.axiosInstance.delete(`/status-page/${encodedUrl}`, {});
- }
-
- // ************************************
- // Create bulk monitors
- // ************************************
-
- async createBulkMonitors(formData) {
- const response = await this.axiosInstance.post(`/monitors/bulk`, formData, {
- headers: {
- "Content-Type": "multipart/form-data",
- },
- });
- return response.data;
- }
-
- // ************************************
- // Fetch monitors with summary by TeamID
- // ************************************
- async getMonitorsWithSummaryByTeamId(config) {
- const { types } = config;
- const params = new URLSearchParams();
-
- if (types) {
- types.forEach((type) => {
- params.append("type", type);
- });
- }
-
- return this.axiosInstance.get(`/monitors/team/summary?${params.toString()}`, {
- headers: {
- "Content-Type": "application/json",
- },
- });
- }
-
- // ************************************
- // Fetch monitors with checks by TeamID
- // ************************************
- async getMonitorsWithChecksByTeamId(config) {
- const { limit, types, page, rowsPerPage, filter, field, order } = config;
- const params = new URLSearchParams();
-
- if (limit) params.append("limit", limit);
- if (types) {
- types.forEach((type) => {
- params.append("type", type);
- });
- }
- if (page) params.append("page", page);
- if (rowsPerPage) params.append("rowsPerPage", rowsPerPage);
- if (filter) params.append("filter", filter);
- if (field) params.append("field", field);
- if (order) params.append("order", order);
-
- return this.axiosInstance.get(`/monitors/team/with-checks?${params.toString()}`, {
- headers: {
- "Content-Type": "application/json",
- },
- });
- }
-
- // ************************************
- // Send test email
- // ************************************
- async sendTestEmail(config) {
- // Extract recipient and email configuration
- const { to, emailConfig } = config;
-
- // If emailConfig is provided, use the new endpoint with direct parameters
- if (emailConfig) {
- return this.axiosInstance.post(`/settings/test-email`, {
- to,
- systemEmailHost: emailConfig.systemEmailHost,
- systemEmailPort: emailConfig.systemEmailPort,
- systemEmailAddress: emailConfig.systemEmailAddress,
- systemEmailPassword: emailConfig.systemEmailPassword,
- systemEmailSecure: emailConfig.systemEmailSecure,
- systemEmailPool: emailConfig.systemEmailPool,
- systemEmailIgnoreTLS: emailConfig.systemEmailIgnoreTLS,
- systemEmailRequireTLS: emailConfig.systemEmailRequireTLS,
- systemEmailRejectUnauthorized: emailConfig.systemEmailRejectUnauthorized,
- systemEmailTLSServername: emailConfig.systemEmailTLSServername,
- ...(emailConfig.systemEmailUser && {
- systemEmailUser: emailConfig.systemEmailUser,
- }),
- });
- }
-
- // Fallback to original behavior for backward compatibility
- return this.axiosInstance.post(`/settings/test-email`, { to });
- }
-
- async createNotification(config) {
- const { notification } = config;
- return this.axiosInstance.post(`/notifications`, notification);
- }
-
- async getNotificationsByTeamId(config) {
- return this.axiosInstance.get(`/notifications/team`);
- }
-
- async deleteNotificationById(config) {
- const { id } = config;
- return this.axiosInstance.delete(`/notifications/${id}`);
- }
-
- async getNotificationById(config) {
- const { id } = config;
- return this.axiosInstance.get(`/notifications/${id}`);
- }
-
- async editNotification(config) {
- const { id, notification } = config;
- return this.axiosInstance.patch(`/notifications/${id}`, notification);
- }
-
- async getQueueData() {
- return this.axiosInstance.get(`/queue/all-metrics`, {
- headers: {
- "Content-Type": "application/json",
- },
- });
- }
-
- async flushQueue() {
- return this.axiosInstance.post(`/queue/flush`);
- }
-
- async exportMonitors() {
- const response = await this.axiosInstance.get("/monitors/export", {
- responseType: "blob",
- });
- return response;
- }
-
- async getLogs() {
- return this.axiosInstance.get(`/logs`, {
- headers: {
- "Content-Type": "application/json",
- },
- });
- }
-
- async getDiagnostics() {
- return this.axiosInstance.get(`/diagnostic/system`, {
- headers: {
- "Content-Type": "application/json",
- },
- });
- }
-
- async getUserById(config) {
- const userId = config?.userId;
- return this.axiosInstance.get(`auth/users/${userId}`, {
- headers: {
- "Content-Type": "application/json",
- },
- });
- }
-
- async editUser(config) {
- const { userId, user } = config;
- return this.axiosInstance.patch(`auth/users/${userId}`, user, {
- headers: {
- "Content-Type": "application/json",
- },
- });
- }
-
- async changePasswordByAdmin(config) {
- const { userId, passwordForm } = config;
- return this.axiosInstance.patch(`auth/users/${userId}/password`, passwordForm, {
- headers: {
- "Content-Type": "application/json",
- },
- });
- }
-
- async fetchJson() {
- return this.axiosInstance.get("/monitors/export/json");
- }
-
- getIncidentsByTeam = async (config) => {
- const params = new URLSearchParams();
- if (config.monitorId) params.append("monitorId", config.monitorId);
- if (config.status !== undefined) params.append("status", config.status);
- if (config.resolutionType) params.append("resolutionType", config.resolutionType);
- if (config.sortOrder) params.append("sortOrder", config.sortOrder);
- if (config.dateRange) params.append("dateRange", config.dateRange);
- if (config.page) params.append("page", config.page);
- if (config.rowsPerPage) params.append("rowsPerPage", config.rowsPerPage);
- return this.axiosInstance.get(`/incidents/team?${params.toString()}`);
- };
-
- getIncidentById = async (incidentId) => {
- return this.axiosInstance.get(`/incidents/${incidentId}`);
- };
-
- resolveIncidentManually = async (incidentId, options = {}) => {
- const body = {};
- if (options.comment) body.comment = options.comment;
- return this.axiosInstance.patch(`/incidents/${incidentId}/resolve`, body);
- };
-
- getIncidentSummary = async (config = {}) => {
- const params = new URLSearchParams();
- if (config.limit) params.append("limit", config.limit);
- const queryString = params.toString();
- return this.axiosInstance.get(
- `/incidents/team/summary${queryString ? `?${queryString}` : ""}`
- );
- };
-}
-
-export default NetworkService;
-
-let networkService;
-
-export const setNetworkService = (service) => {
- networkService = service;
-};
-export { networkService };
diff --git a/client/src/Utils/NetworkServiceProvider.jsx b/client/src/Utils/NetworkServiceProvider.jsx
deleted file mode 100644
index 73c3a2f94..000000000
--- a/client/src/Utils/NetworkServiceProvider.jsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import { useDispatch } from "react-redux";
-import { useNavigate } from "react-router-dom";
-import { setNetworkService } from "./NetworkService";
-import NetworkService, { networkService } from "./NetworkService";
-import { store } from "../store";
-
-const NetworkServiceProvider = ({ children }) => {
- const dispatch = useDispatch();
- const navigate = useNavigate();
- if (!networkService) {
- setNetworkService(new NetworkService(store, dispatch, navigate));
- }
- return children;
-};
-
-export default NetworkServiceProvider;
diff --git a/client/src/main.jsx b/client/src/main.jsx
index 5cfbe6f33..ad35d0303 100644
--- a/client/src/main.jsx
+++ b/client/src/main.jsx
@@ -5,9 +5,6 @@ import { BrowserRouter as Router } from "react-router-dom";
import { Provider } from "react-redux";
import { persistor, store } from "./store";
import { PersistGate } from "redux-persist/integration/react";
-import NetworkServiceProvider from "./Utils/NetworkServiceProvider.jsx";
-import { networkService } from "./Utils/NetworkService";
-export { networkService };
import I18nLoader from "./Components/v1/I18nLoader";
import { initApiClient } from "./Utils/ApiClient";
@@ -21,9 +18,7 @@ ReactDOM.createRoot(document.getElementById("root")).render(
>
-
-
-
+