diff --git a/client/src/Hooks/useFetchSettings.js b/client/src/Hooks/useFetchSettings.js
index 15859795f..f7651e789 100644
--- a/client/src/Hooks/useFetchSettings.js
+++ b/client/src/Hooks/useFetchSettings.js
@@ -3,7 +3,7 @@ import { networkService } from "../main";
import { createToast } from "../Utils/toastUtils";
import { useTranslation } from "react-i18next";
-const useFetchSettings = ({ setSettings }) => {
+const useFetchSettings = ({ setSettingsData }) => {
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(undefined);
useEffect(() => {
@@ -11,7 +11,7 @@ const useFetchSettings = ({ setSettings }) => {
setIsLoading(true);
try {
const response = await networkService.getAppSettings();
- setSettings(response?.data?.data);
+ setSettingsData(response?.data?.data);
} catch (error) {
createToast({ body: "Failed to fetch settings" });
setError(error);
diff --git a/client/src/Pages/Settings/SettingsDemoMonitors.jsx b/client/src/Pages/Settings/SettingsDemoMonitors.jsx
index 6722e97ac..1a592e776 100644
--- a/client/src/Pages/Settings/SettingsDemoMonitors.jsx
+++ b/client/src/Pages/Settings/SettingsDemoMonitors.jsx
@@ -8,12 +8,8 @@ import { PropTypes } from "prop-types";
import { useTranslation } from "react-i18next";
import Dialog from "../../Components/Dialog";
import { useState } from "react";
-const SettingsDemoMonitors = ({
- isLoading,
- authIsLoading,
- checksIsLoading,
- handleChange,
-}) => {
+
+const SettingsDemoMonitors = ({ HEADER_SX, handleChange, isLoading }) => {
const { t } = useTranslation();
const theme = useTheme();
// Local state
@@ -23,16 +19,14 @@ const SettingsDemoMonitors = ({
{t("settingsDemoMonitors")}
-
- {t("settingsDemoMonitorsDescription")}
-
+ {t("settingsDemoMonitorsDescription")}
{t("settingsAddDemoMonitors")}
>
@@ -89,10 +83,8 @@ const SettingsDemoMonitors = ({
};
SettingsDemoMonitors.propTypes = {
- isLoading: PropTypes.bool,
- authIsLoading: PropTypes.bool,
- checksIsLoading: PropTypes.bool,
handleChange: PropTypes.func,
+ HEADER_SX: PropTypes.object,
};
export default SettingsDemoMonitors;
diff --git a/client/src/Pages/Settings/SettingsEmail.jsx b/client/src/Pages/Settings/SettingsEmail.jsx
new file mode 100644
index 000000000..ecc2a51f2
--- /dev/null
+++ b/client/src/Pages/Settings/SettingsEmail.jsx
@@ -0,0 +1,126 @@
+import Box from "@mui/material/Box";
+import Typography from "@mui/material/Typography";
+import ConfigBox from "../../Components/ConfigBox";
+import TextInput from "../../Components/Inputs/TextInput";
+import Button from "@mui/material/Button";
+import Stack from "@mui/material/Stack";
+// Utils
+import { useTheme } from "@emotion/react";
+import { PropTypes } from "prop-types";
+import { useState } from "react";
+import { useTranslation } from "react-i18next";
+import { PasswordEndAdornment } from "../../Components/Inputs/TextInput/Adornments";
+const SettingsEmail = ({
+ HEADER_SX,
+ handleChange,
+ settingsData,
+ setSettingsData,
+ isPasswordSet,
+}) => {
+ const { t } = useTranslation();
+ const theme = useTheme();
+
+ const [password, setPassword] = useState("");
+ const [hasBeenReset, setHasBeenReset] = useState(false);
+
+ const handlePasswordChange = (e) => {
+ setPassword(e.target.value);
+ setSettingsData({
+ ...settingsData,
+ settings: { ...settingsData.settings, systemEmailPassword: e.target.value },
+ });
+ };
+
+ return (
+
+
+ {t("settingsEmail")}
+ {t("settingsEmailDescription")}
+
+
+
+
+ {t("settingsEmailHost")}
+
+
+
+ {t("settingsEmailPort")}
+
+
+
+ {t("settingsEmailUser")}
+
+
+
+ {t("settingsEmailAddress")}
+
+
+ {(isPasswordSet === false || hasBeenReset === true) && (
+
+ {t("settingsEmailPassword")}
+ }
+ />
+
+ )}
+ {isPasswordSet === true && hasBeenReset === false && (
+
+ {t("settingsEmailFieldResetLabel")}
+ {
+ setPassword("");
+ setSettingsData({
+ ...settingsData,
+ settings: { ...settingsData.settings, systemEmailPassword: "" },
+ });
+ setHasBeenReset(true);
+ }}
+ variant="contained"
+ color="error"
+ sx={{ mt: theme.spacing(4) }}
+ >
+ {t("reset")}
+
+
+ )}
+
+
+
+ );
+};
+
+SettingsEmail.propTypes = {
+ settingsData: PropTypes.object,
+ setSettingsData: PropTypes.func,
+ handleChange: PropTypes.func,
+ HEADER_SX: PropTypes.object,
+ isPasswordSet: PropTypes.bool,
+};
+
+export default SettingsEmail;
diff --git a/client/src/Pages/Settings/SettingsPagespeed.jsx b/client/src/Pages/Settings/SettingsPagespeed.jsx
index 87f558f32..95b159fa5 100644
--- a/client/src/Pages/Settings/SettingsPagespeed.jsx
+++ b/client/src/Pages/Settings/SettingsPagespeed.jsx
@@ -11,26 +11,28 @@ import { PropTypes } from "prop-types";
import { useState, useEffect } from "react";
import { useTranslation } from "react-i18next";
-const SettingsPagespeed = ({ HEADING_SX, settings, setSettings }) => {
+const SettingsPagespeed = ({
+ HEADING_SX,
+ settingsData,
+ setSettingsData,
+ isApiKeySet,
+}) => {
const { t } = useTranslation();
const theme = useTheme();
// Local state
const [apiKey, setApiKey] = useState("");
- const [isApiKeySet, setIsApiKeySet] = useState(false);
const [hasBeenReset, setHasBeenReset] = useState(false);
// Handler
const handleChange = (e) => {
setApiKey(e.target.value);
- setSettings({ ...settings, pagespeedApiKey: e.target.value });
+ setSettingsData({
+ ...settingsData,
+ settings: { ...settingsData.settings, pagespeedApiKey: e.target.value },
+ });
};
- useEffect(() => {
- console.log(settings);
- setIsApiKeySet(Boolean(settings.pagespeedApiKey) && apiKey === "");
- }, [settings, apiKey]);
-
return (
@@ -56,7 +58,10 @@ const SettingsPagespeed = ({ HEADING_SX, settings, setSettings }) => {
{
setApiKey("");
- setSettings({ ...settings, pagespeedApiKey: "" });
+ setSettingsData({
+ ...settingsData,
+ settings: { ...settingsData.settings, pagespeedApiKey: "" },
+ });
setHasBeenReset(true);
}}
variant="contained"
@@ -74,8 +79,9 @@ const SettingsPagespeed = ({ HEADING_SX, settings, setSettings }) => {
SettingsPagespeed.propTypes = {
HEADING_SX: PropTypes.object,
- settings: PropTypes.object,
- setSettings: PropTypes.func,
+ settingsData: PropTypes.object,
+ setSettingsData: PropTypes.func,
+ isApiKeySet: PropTypes.bool,
};
export default SettingsPagespeed;
diff --git a/client/src/Pages/Settings/SettingsStats.jsx b/client/src/Pages/Settings/SettingsStats.jsx
index c9178b1da..961f13665 100644
--- a/client/src/Pages/Settings/SettingsStats.jsx
+++ b/client/src/Pages/Settings/SettingsStats.jsx
@@ -12,7 +12,7 @@ import { PropTypes } from "prop-types";
import { useTranslation } from "react-i18next";
import { useState } from "react";
-const SettingsStats = ({ HEADING_SX, handleChange, settings, errors }) => {
+const SettingsStats = ({ HEADING_SX, handleChange, settingsData, errors }) => {
const theme = useTheme();
const { t } = useTranslation();
const [isOpen, setIsOpen] = useState(false);
@@ -34,7 +34,7 @@ const SettingsStats = ({ HEADING_SX, handleChange, settings, errors }) => {
name="checkTTL"
label={t("settingsTTLLabel")}
optionalLabel={t("settingsTTLOptionalLabel")}
- value={settings?.checkTTL ?? ""}
+ value={settingsData?.settings?.checkTTL ?? ""}
onChange={handleChange}
type="number"
error={errors.checkTTL ? true : false}
@@ -77,7 +77,7 @@ const SettingsStats = ({ HEADING_SX, handleChange, settings, errors }) => {
SettingsStats.propTypes = {
HEADING_SX: PropTypes.object,
handleChange: PropTypes.func,
- settings: PropTypes.object,
+ settingsData: PropTypes.object,
errors: PropTypes.object,
};
diff --git a/client/src/Pages/Settings/index.jsx b/client/src/Pages/Settings/index.jsx
index e1e8c3859..eb516ba01 100644
--- a/client/src/Pages/Settings/index.jsx
+++ b/client/src/Pages/Settings/index.jsx
@@ -6,6 +6,7 @@ import SettingsUI from "./SettingsUI";
import SettingsPagespeed from "./SettingsPagespeed";
import SettingsDemoMonitors from "./SettingsDemoMonitors";
import SettingsAbout from "./SettingsAbout";
+import SettingsEmail from "./SettingsEmail";
import Button from "@mui/material/Button";
// Utils
import { settingsValidation } from "../../Validation/validation";
@@ -15,7 +16,6 @@ import { useTheme } from "@emotion/react";
import { useTranslation } from "react-i18next";
import { useSelector, useDispatch } from "react-redux";
import { setTimezone, setMode, setLanguage } from "../../Features/UI/uiSlice";
-import { getAppSettings } from "../../Features/Settings/settingsSlice";
import SettingsStats from "./SettingsStats";
import {
deleteMonitorChecksByTeamId,
@@ -34,17 +34,14 @@ const Settings = () => {
const { user } = useSelector((state) => state.auth);
// Local state
- const [settings, setSettings] = useState({});
+ const [settingsData, setSettingsData] = useState({});
const [errors, setErrors] = useState({});
-
// Network
const [isSettingsLoading, settingsError] = useFetchSettings({
- settings,
- setSettings,
+ setSettingsData,
});
const [isSaving, saveError, saveSettings] = useSaveSettings();
-
const [deleteMonitorStats, isDeletingMonitorStats] = UseDeleteMonitorStats();
// Setup
@@ -58,10 +55,15 @@ const Settings = () => {
const { name, value } = e.target;
// Build next state early
- const newSettings = { ...settings, [name]: value };
+ const newSettingsData = {
+ ...settingsData,
+ settings: { ...settingsData.settings, [name]: value },
+ };
// Validate
- const { error } = settingsValidation.validate(newSettings, { abortEarly: false });
+ const { error } = settingsValidation.validate(newSettingsData.settings, {
+ abortEarly: false,
+ });
if (!error || error.details.length === 0) {
setErrors({});
} else {
@@ -118,11 +120,13 @@ const Settings = () => {
return;
}
- setSettings(newSettings);
+ setSettingsData(newSettingsData);
};
const handleSave = () => {
- const { error } = settingsValidation.validate(settings, { abortEarly: false });
+ const { error } = settingsValidation.validate(settingsData.settings, {
+ abortEarly: false,
+ });
if (!error || error.details.length === 0) {
setErrors({});
} else {
@@ -132,7 +136,7 @@ const Settings = () => {
});
setErrors(newErrors);
}
- saveSettings(settings);
+ saveSettings(settingsData?.settings);
};
return (
@@ -152,21 +156,27 @@ const Settings = () => {
/>
+
{
diff --git a/client/src/locales/gb.json b/client/src/locales/gb.json
index 49993eb89..428cfbd3c 100644
--- a/client/src/locales/gb.json
+++ b/client/src/locales/gb.json
@@ -1,444 +1,451 @@
{
- "dontHaveAccount": "Don't have account",
- "doNotHaveAccount": "Do not have an account?",
- "registerHere": "Register here",
- "email": "E-mail",
- "forgotPassword": "Forgot Password",
- "password": "Password",
- "signUp": "Sign Up",
- "submit": "Submit",
- "title": "Title",
- "continue": "Continue",
- "enterEmail": "Enter your email",
- "authLoginTitle": "Log In",
- "authLoginEnterPassword": "Enter your password",
- "commonPassword": "Password",
- "commonBack": "Back",
- "authForgotPasswordTitle": "Forgot password?",
- "authForgotPasswordResetPassword": "Reset password",
- "createPassword": "Create your password",
- "createAPassword": "Password",
- "authRegisterAlreadyHaveAccount": "Already have an account?",
- "authRegisterLoginLink": "Log In",
- "commonAppName": "Checkmate",
- "welcomeBack": "Welcome back! You're successfully logged in.",
- "authLoginEnterEmail": "Enter your email",
- "authRegisterTitle": "Create an account",
- "authRegisterStepOneTitle": "Create your account",
- "authRegisterStepOneDescription": "Enter your details to get started",
- "authRegisterStepTwoTitle": "Set up your profile",
- "authRegisterStepTwoDescription": "Tell us more about yourself",
- "authRegisterStepThreeTitle": "Almost done!",
- "authRegisterStepThreeDescription": "Review your information",
- "authForgotPasswordDescription": "No worries, we'll send you reset instructions.",
- "authForgotPasswordSendInstructions": "Send instructions",
- "authForgotPasswordBackTo": "Back to",
- "authCheckEmailTitle": "Check your email",
- "authCheckEmailDescription": "We sent a password reset link to",
- "authCheckEmailResendEmail": "Resend email",
- "authCheckEmailBackTo": "Back to",
- "goBackTo": "Go back to",
- "authCheckEmailDidntReceiveEmail": "Didn't receive the email?",
- "authCheckEmailClickToResend": "Click to resend",
- "authSetNewPasswordTitle": "Set new password",
- "authSetNewPasswordDescription": "Your new password must be different from previously used passwords.",
- "authSetNewPasswordNewPassword": "New password",
- "authSetNewPasswordConfirmPassword": "Confirm password",
- "confirmPassword": "Re-enter password to confirm",
- "authSetNewPasswordResetPassword": "Reset password",
- "authSetNewPasswordBackTo": "Back to",
- "authPasswordMustBeAtLeast": "Must be at least",
- "authPasswordCharactersLong": "8 characters long",
- "authPasswordMustContainAtLeast": "Must contain at least",
- "authPasswordSpecialCharacter": "one special character",
- "authPasswordOneNumber": "one number",
- "authPasswordUpperCharacter": "one upper character",
- "authPasswordLowerCharacter": "one lower character",
- "authPasswordConfirmAndPassword": "Confirm password and password",
- "authPasswordMustMatch": "Passwords must match",
- "validationNameRequired": "Please enter your name",
- "validationNameTooLong": "Name should be less than 50 characters",
- "validationNameInvalidCharacters": "Please use only letters, spaces, apostrophes, or hyphens",
- "authRegisterCreateAccount": "Create your account to get started",
- "authRegisterCreateSuperAdminAccount": "Create your super admin account to get started",
- "authRegisterSignUpWithEmail": "Create super admin account",
- "authRegisterBySigningUp": "By creating an account, you agree to our Terms of Service and Privacy Policy.",
- "distributedStatusHeaderText": "Real-time, real-device coverage",
- "distributedStatusSubHeaderText": "Powered by millions devices worldwide, view a system performance by global region, country or city",
- "settingsGeneralSettings": "General settings",
- "settingsDisplayTimezone": "Display timezone",
- "settingsDisplayTimezoneDescription": "Select the timezone used to display dates and times throughout the application.",
- "settingsAppearance": "Appearance",
- "settingsAppearanceDescription": "Switch between light and dark mode, or change user interface language",
- "settingsThemeMode": "Theme Mode",
- "settingsLanguage": "Language",
- "settingsDistributedUptime": "Distributed uptime",
- "settingsDistributedUptimeDescription": "Enable/disable distributed uptime monitoring.",
- "settingsEnabled": "Enabled",
- "settingsDisabled": "Disabled",
- "settingsHistoryAndMonitoring": "History of monitoring",
- "settingsHistoryAndMonitoringDescription": "Define how long you want to retain historical data. You can also clear all existing data.",
- "settingsTTLLabel": "The days you want to keep monitoring history.",
- "settingsTTLOptionalLabel": "0 for infinite",
- "settingsClearAllStats": "Clear all stats. This is irreversible.",
- "settingsClearAllStatsButton": "Clear all stats",
- "settingsClearAllStatsDialogTitle": "Do you want to clear all stats?",
- "settingsClearAllStatsDialogDescription": "Once removed, the monitoring history and stats cannot be retrieved.",
- "settingsClearAllStatsDialogConfirm": "Yes, clear all stats",
- "settingsDemoMonitors": "Demo monitors",
- "settingsDemoMonitorsDescription": "Add sample monitors for demonstration purposes.",
- "settingsAddDemoMonitors": "Adding demo monitors",
- "settingsAddDemoMonitorsButton": "Add demo monitors",
- "settingsSystemReset": "System reset",
- "settingsSystemResetDescription": "Remove all monitors from your system.",
- "settingsRemoveAllMonitors": "Removing all monitors",
- "settingsRemoveAllMonitorsButton": "Remove all monitors",
- "settingsRemoveAllMonitorsDialogTitle": "Do you want to remove all monitors?",
- "settingsRemoveAllMonitorsDialogConfirm": "Yes, remove all monitors",
- "settingsWallet": "Wallet",
- "settingsWalletDescription": "Connect your wallet here. This is required for the Distributed Uptime monitor to connect to multiple nodes globally.",
- "settingsAbout": "About",
- "settingsDevelopedBy": "Developed by Bluewave Labs.",
- "settingsSave": "Save",
- "settingsSuccessSaved": "Settings saved successfully",
- "settingsFailedToSave": "Failed to save settings",
- "settingsStatsCleared": "Stats cleared successfully",
- "settingsFailedToClearStats": "Failed to clear stats",
- "settingsDemoMonitorsAdded": "Successfully added demo monitors",
- "settingsFailedToAddDemoMonitors": "Failed to add demo monitors",
- "settingsMonitorsDeleted": "Successfully deleted all monitors",
- "settingsFailedToDeleteMonitors": "Failed to delete all monitors",
- "backendUnreachable": "Server Connection Error",
- "backendUnreachableMessage": "We're unable to connect to the server. Please check your internet connection or verify your deployment configuration if the problem persists.",
- "backendUnreachableError": "Cannot connect to the server. Please try again later.",
- "retryConnection": "Retry connection",
- "retryingConnection": "Connecting...",
- "backendReconnected": "Successfully reconnected to the server.",
- "backendStillUnreachable": "Server is still unreachable. Please try again later.",
- "backendConnectionError": "Error connecting to the server. Please check your network connection.",
- "starPromptTitle": "Star Checkmate",
- "starPromptDescription": "See the latest releases and help grow the community on GitHub",
- "https": "HTTPS",
- "http": "HTTP",
- "monitor": "monitor",
- "aboutus": "About Us",
+ "dontHaveAccount": "Don't have account",
+ "doNotHaveAccount": "Do not have an account?",
+ "registerHere": "Register here",
+ "email": "E-mail",
+ "forgotPassword": "Forgot Password",
+ "password": "Password",
+ "signUp": "Sign Up",
+ "submit": "Submit",
+ "title": "Title",
+ "continue": "Continue",
+ "enterEmail": "Enter your email",
+ "authLoginTitle": "Log In",
+ "authLoginEnterPassword": "Enter your password",
+ "commonPassword": "Password",
+ "commonBack": "Back",
+ "authForgotPasswordTitle": "Forgot password?",
+ "authForgotPasswordResetPassword": "Reset password",
+ "createPassword": "Create your password",
+ "createAPassword": "Password",
+ "authRegisterAlreadyHaveAccount": "Already have an account?",
+ "authRegisterLoginLink": "Log In",
+ "commonAppName": "Checkmate",
+ "welcomeBack": "Welcome back! You're successfully logged in.",
+ "authLoginEnterEmail": "Enter your email",
+ "authRegisterTitle": "Create an account",
+ "authRegisterStepOneTitle": "Create your account",
+ "authRegisterStepOneDescription": "Enter your details to get started",
+ "authRegisterStepTwoTitle": "Set up your profile",
+ "authRegisterStepTwoDescription": "Tell us more about yourself",
+ "authRegisterStepThreeTitle": "Almost done!",
+ "authRegisterStepThreeDescription": "Review your information",
+ "authForgotPasswordDescription": "No worries, we'll send you reset instructions.",
+ "authForgotPasswordSendInstructions": "Send instructions",
+ "authForgotPasswordBackTo": "Back to",
+ "authCheckEmailTitle": "Check your email",
+ "authCheckEmailDescription": "We sent a password reset link to",
+ "authCheckEmailResendEmail": "Resend email",
+ "authCheckEmailBackTo": "Back to",
+ "goBackTo": "Go back to",
+ "authCheckEmailDidntReceiveEmail": "Didn't receive the email?",
+ "authCheckEmailClickToResend": "Click to resend",
+ "authSetNewPasswordTitle": "Set new password",
+ "authSetNewPasswordDescription": "Your new password must be different from previously used passwords.",
+ "authSetNewPasswordNewPassword": "New password",
+ "authSetNewPasswordConfirmPassword": "Confirm password",
+ "confirmPassword": "Re-enter password to confirm",
+ "authSetNewPasswordResetPassword": "Reset password",
+ "authSetNewPasswordBackTo": "Back to",
+ "authPasswordMustBeAtLeast": "Must be at least",
+ "authPasswordCharactersLong": "8 characters long",
+ "authPasswordMustContainAtLeast": "Must contain at least",
+ "authPasswordSpecialCharacter": "one special character",
+ "authPasswordOneNumber": "one number",
+ "authPasswordUpperCharacter": "one upper character",
+ "authPasswordLowerCharacter": "one lower character",
+ "authPasswordConfirmAndPassword": "Confirm password and password",
+ "authPasswordMustMatch": "Passwords must match",
+ "validationNameRequired": "Please enter your name",
+ "validationNameTooLong": "Name should be less than 50 characters",
+ "validationNameInvalidCharacters": "Please use only letters, spaces, apostrophes, or hyphens",
+ "authRegisterCreateAccount": "Create your account to get started",
+ "authRegisterCreateSuperAdminAccount": "Create your super admin account to get started",
+ "authRegisterSignUpWithEmail": "Create super admin account",
+ "authRegisterBySigningUp": "By creating an account, you agree to our Terms of Service and Privacy Policy.",
+ "distributedStatusHeaderText": "Real-time, real-device coverage",
+ "distributedStatusSubHeaderText": "Powered by millions devices worldwide, view a system performance by global region, country or city",
+ "settingsGeneralSettings": "General settings",
+ "settingsDisplayTimezone": "Display timezone",
+ "settingsDisplayTimezoneDescription": "Select the timezone used to display dates and times throughout the application.",
+ "settingsAppearance": "Appearance",
+ "settingsAppearanceDescription": "Switch between light and dark mode, or change user interface language",
+ "settingsThemeMode": "Theme Mode",
+ "settingsLanguage": "Language",
+ "settingsDistributedUptime": "Distributed uptime",
+ "settingsDistributedUptimeDescription": "Enable/disable distributed uptime monitoring.",
+ "settingsEnabled": "Enabled",
+ "settingsDisabled": "Disabled",
+ "settingsHistoryAndMonitoring": "History of monitoring",
+ "settingsHistoryAndMonitoringDescription": "Define how long you want to retain historical data. You can also clear all existing data.",
+ "settingsTTLLabel": "The days you want to keep monitoring history.",
+ "settingsTTLOptionalLabel": "0 for infinite",
+ "settingsClearAllStats": "Clear all stats. This is irreversible.",
+ "settingsClearAllStatsButton": "Clear all stats",
+ "settingsClearAllStatsDialogTitle": "Do you want to clear all stats?",
+ "settingsClearAllStatsDialogDescription": "Once removed, the monitoring history and stats cannot be retrieved.",
+ "settingsClearAllStatsDialogConfirm": "Yes, clear all stats",
+ "settingsDemoMonitors": "Demo monitors",
+ "settingsDemoMonitorsDescription": "Add sample monitors for demonstration purposes.",
+ "settingsAddDemoMonitors": "Adding demo monitors",
+ "settingsAddDemoMonitorsButton": "Add demo monitors",
+ "settingsSystemReset": "System reset",
+ "settingsSystemResetDescription": "Remove all monitors from your system.",
+ "settingsRemoveAllMonitors": "Removing all monitors",
+ "settingsRemoveAllMonitorsButton": "Remove all monitors",
+ "settingsRemoveAllMonitorsDialogTitle": "Do you want to remove all monitors?",
+ "settingsRemoveAllMonitorsDialogConfirm": "Yes, remove all monitors",
+ "settingsWallet": "Wallet",
+ "settingsWalletDescription": "Connect your wallet here. This is required for the Distributed Uptime monitor to connect to multiple nodes globally.",
+ "settingsAbout": "About",
+ "settingsDevelopedBy": "Developed by Bluewave Labs.",
+ "settingsSave": "Save",
+ "settingsSuccessSaved": "Settings saved successfully",
+ "settingsFailedToSave": "Failed to save settings",
+ "settingsStatsCleared": "Stats cleared successfully",
+ "settingsFailedToClearStats": "Failed to clear stats",
+ "settingsDemoMonitorsAdded": "Successfully added demo monitors",
+ "settingsFailedToAddDemoMonitors": "Failed to add demo monitors",
+ "settingsMonitorsDeleted": "Successfully deleted all monitors",
+ "settingsFailedToDeleteMonitors": "Failed to delete all monitors",
+ "settingsEmail": "Email settings",
+ "settingsEmailDescription": "Configure email settings",
+ "settingsEmailHost": "Email host",
+ "settingsEmailPort": "Email port",
+ "settingsEmailAddress": "Email address",
+ "settingsEmailPassword": "Email password",
+ "settingsEmailUser": "Email user",
+ "settingsEmailFieldResetLabel": "Password is set. Click Reset to change it.",
+ "backendUnreachable": "Server Connection Error",
+ "backendUnreachableMessage": "We're unable to connect to the server. Please check your internet connection or verify your deployment configuration if the problem persists.",
+ "backendUnreachableError": "Cannot connect to the server. Please try again later.",
+ "retryConnection": "Retry connection",
+ "retryingConnection": "Connecting...",
+ "backendReconnected": "Successfully reconnected to the server.",
+ "backendStillUnreachable": "Server is still unreachable. Please try again later.",
+ "backendConnectionError": "Error connecting to the server. Please check your network connection.",
+ "starPromptTitle": "Star Checkmate",
+ "starPromptDescription": "See the latest releases and help grow the community on GitHub",
+ "https": "HTTPS",
+ "http": "HTTP",
+ "monitor": "monitor",
+ "aboutus": "About Us",
- "now": "Now",
- "delete": "Delete",
- "configure": "Configure",
- "networkError": "Network error",
- "responseTime": "Response time",
- "ms": "ms",
- "bar": "Bar",
- "area": "Area",
- "country": "COUNTRY",
- "city": "CITY",
- "response": "RESPONSE",
- "checkConnection": "Please check your connection",
- "passwordreset": "Password Reset",
- "authRegisterStepOnePersonalDetails": "Enter your personal details",
- "authCheckEmailOpenEmailButton": "Open email app",
- "authNewPasswordConfirmed": "Your password has been successfully reset. Click below to log in magically.",
- "monitorStatusUp": "Monitor {name} ({url}) is now UP and responding",
- "monitorStatusDown": "Monitor {name} ({url}) is DOWN and not responding",
- "webhookSendSuccess": "Webhook notification sent successfully",
- "webhookSendError": "Error sending webhook notification to {platform}",
- "webhookUnsupportedPlatform": "Unsupported platform: {platform}",
- "distributedRightCategoryTitle": "Monitor",
- "distributedStatusServerMonitors": "Server Monitors",
- "distributedStatusServerMonitorsDescription": "Monitor status of related servers",
- "distributedUptimeCreateSelectURL": "Here you can select the URL of the host, together with the type of monitor.",
- "distributedUptimeCreateChecks": "Checks to perform",
- "distributedUptimeCreateChecksDescription": "You can always add or remove checks after adding your site.",
- "distributedUptimeCreateIncidentNotification": "Incident notifications",
- "distributedUptimeCreateIncidentDescription": "When there is an incident, notify users.",
- "distributedUptimeCreateAdvancedSettings": "Advanced settings",
- "distributedUptimeDetailsNoMonitorHistory": "There is no check history for this monitor yet.",
- "distributedUptimeDetailsFooterHeading": "Made with ❤️ by UpRock & Bluewave Labs",
- "distributedUptimeDetailsFooterBuilt": "Built on",
- "distributedUptimeDetailsFooterSolana": "Solana",
- "distributedUptimeDetailsMonitorHeader": "Distributed Uptime Monitoring powered by DePIN",
- "distributedUptimeDetailsStatusHeaderUptime": "Uptime:",
- "distributedUptimeDetailsStatusHeaderLastUpdate": "Last updated",
- "notifications": {
- "enableNotifications": "Enable {{platform}} notifications",
- "testNotification": "Test notification",
- "addOrEditNotifications": "Add or edit notifications",
- "slack": {
- "label": "Slack",
- "description": "To enable Slack notifications, create a Slack app and enable incoming webhooks. After that, simply provide the webhook URL here.",
- "webhookLabel": "Webhook URL",
- "webhookPlaceholder": "https://hooks.slack.com/services/...",
- "webhookRequired": "Slack webhook URL is required"
- },
- "discord": {
- "label": "Discord",
- "description": "To send data to a Discord channel from Checkmate via Discord notifications using webhooks, you can use Discord's incoming Webhooks feature.",
- "webhookLabel": "Discord Webhook URL",
- "webhookPlaceholder": "https://discord.com/api/webhooks/...",
- "webhookRequired": "Discord webhook URL is required"
- },
- "telegram": {
- "label": "Telegram",
- "description": "To enable Telegram notifications, create a Telegram bot using BotFather, an official bot for creating and managing Telegram bots. Then, get the API token and chat ID and write them down here.",
- "tokenLabel": "Your bot token",
- "tokenPlaceholder": "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11",
- "chatIdLabel": "Your Chat ID",
- "chatIdPlaceholder": "-1001234567890",
- "fieldsRequired": "Telegram token and chat ID are required"
- },
- "webhook": {
- "label": "Webhooks",
- "description": "You can set up a custom webhook to receive notifications when incidents occur.",
- "urlLabel": "Webhook URL",
- "urlPlaceholder": "https://your-server.com/webhook",
- "urlRequired": "Webhook URL is required"
- },
- "testNotificationDevelop": "Test notification 2",
- "integrationButton": "Notification Integration",
- "testSuccess": "Test notification sent successfully!",
- "testFailed": "Failed to send test notification",
- "unsupportedType": "Unsupported notification type",
- "networkError": "Network error occurred"
- },
- "testLocale": "testLocale",
- "add": "Add",
- "monitors": "monitors",
- "distributedUptimeStatusCreateStatusPage": "status page",
- "distributedUptimeStatusCreateStatusPageAccess": "Access",
- "distributedUptimeStatusCreateStatusPageReady": "If your status page is ready, you can mark it as published.",
- "distributedUptimeStatusBasicInfoHeader": "Basic Information",
- "distributedUptimeStatusBasicInfoDescription": "Define company name and the subdomain that your status page points to.",
- "distributedUptimeStatusLogoHeader": "Logo",
- "distributedUptimeStatusLogoDescription": "Upload a logo for your status page",
- "distributedUptimeStatusLogoUploadButton": "Upload logo",
- "distributedUptimeStatusStandardMonitorsHeader": "Standard Monitors",
- "distributedUptimeStatusStandardMonitorsDescription": "Attach standard monitors to your status page.",
- "distributedUptimeStatusCreateYour": "Create your",
- "distributedUptimeStatusEditYour": "Edit your",
- "distributedUptimeStatusPublishedLabel": "Published and visible to the public",
- "distributedUptimeStatusCompanyNameLabel": "Company name",
- "distributedUptimeStatusPageAddressLabel": "Your status page address",
- "distributedUptimeStatus30Days": "30 days",
- "distributedUptimeStatus60Days": "60 days",
- "distributedUptimeStatus90Days": "90 days",
- "distributedUptimeStatusPageNotSetUp": "A status page is not set up.",
- "distributedUptimeStatusContactAdmin": "Please contact your administrator",
- "distributedUptimeStatusPageNotPublic": "This status page is not public.",
- "distributedUptimeStatusPageDeleteDialog": "Do you want to delete this status page?",
- "distributedUptimeStatusPageDeleteConfirm": "Yes, delete status page",
- "distributedUptimeStatusPageDeleteDescription": "Once deleted, your status page cannot be retrieved.",
- "distributedUptimeStatusDevices": "Devices",
- "distributedUptimeStatusUpt": "UPT",
- "distributedUptimeStatusUptBurned": "UPT Burned",
- "distributedUptimeStatusUptLogo": "Upt Logo",
- "incidentsTableNoIncidents": "No incidents recorded",
- "incidentsTablePaginationLabel": "incidents",
- "incidentsTableMonitorName": "Monitor Name",
- "incidentsTableStatus": "Status",
- "incidentsTableDateTime": "Date & Time",
- "incidentsTableStatusCode": "Status Code",
- "incidentsTableMessage": "Message",
- "incidentsOptionsHeader": "Incidents for:",
- "incidentsOptionsHeaderFilterBy": "Filter by:",
- "incidentsOptionsHeaderFilterAll": "All",
- "incidentsOptionsHeaderFilterDown": "Down",
- "incidentsOptionsHeaderFilterCannotResolve": "Cannot resolve",
- "incidentsOptionsHeaderShow": "Show:",
- "incidentsOptionsHeaderLastHour": "Last hour",
- "incidentsOptionsHeaderLastDay": "Last day",
- "incidentsOptionsHeaderLastWeek": "Last week",
- "incidentsOptionsPlaceholderAllServers": "All servers",
- "infrastructureCreateYour": "Create your",
- "infrastructureCreateGeneralSettingsDescription": "Here you can select the URL of the host, together with the friendly name and authorization secret to connect to the server agent.",
- "infrastructureServerRequirement": "The server you are monitoring must be running the",
- "infrastructureCustomizeAlerts": "Customize alerts",
- "infrastructureAlertNotificationDescription": "Send a notification to user(s) when thresholds exceed a specified percentage.",
- "infrastructureCreateMonitor": "Create Infrastructure Monitor",
- "infrastructureProtocol": "Protocol",
- "infrastructureServerUrlLabel": "Server URL",
- "infrastructureDisplayNameLabel": "Display name",
- "infrastructureAuthorizationSecretLabel": "Authorization secret",
- "gb": "GB",
- "mb": "MB",
- "mem": "Mem",
- "memoryUsage": "Memory usage",
- "cpu": "CPU",
- "cpuUsage": "CPU usage",
- "cpuTemperature": "CPU Temperature",
- "diskUsage": "Disk Usage",
- "used": "Used",
- "total": "Total",
- "cores": "Cores",
- "frequency": "Frequency",
- "status": "Status",
- "cpuPhysical": "CPU (Physical)",
- "cpuLogical": "CPU (Logical)",
- "cpuFrequency": "CPU Frequency",
- "avgCpuTemperature": "Average CPU Temperature",
- "memory": "Memory",
- "disk": "Disk",
- "uptime": "Uptime",
- "os": "OS",
- "host": "Host",
- "actions": "Actions",
- "integrations": "Integrations",
- "integrationsPrism": "Connect Prism to your favorite service.",
- "integrationsSlack": "Slack",
- "integrationsSlackInfo": "Connect with Slack and see incidents in a channel",
- "integrationsDiscord": "Discord",
- "integrationsDiscordInfo": "Connect with Discord and view incidents directly in a channel",
- "integrationsZapier": "Zapier",
- "integrationsZapierInfo": "Send all incidents to Zapier, and then see them everywhere",
- "commonSave": "Save",
- "createYour": "Create your",
- "createMonitor": "Create monitor",
- "pause": "Pause",
- "resume": "Resume",
- "editing": "Editing...",
- "url": "URL",
- "access": "Access",
- "timezone": "Timezone",
- "features": "Features",
- "administrator": "Administrator?",
- "loginHere": "Login here",
- "displayName": "Display name",
- "urlMonitor": "URL to monitor",
- "portToMonitor": "Port to monitor",
- "websiteMonitoring": "Website monitoring",
- "websiteMonitoringDescription": "Use HTTP(s) to monitor your website or API endpoint.",
- "pingMonitoring": "Ping monitoring",
- "pingMonitoringDescription": "Check whether your server is available or not.",
- "dockerContainerMonitoring": "Docker container monitoring",
- "dockerContainerMonitoringDescription": "Check whether your Docker container is running or not.",
- "portMonitoring": "Port monitoring",
- "portMonitoringDescription": "Check whether your port is open or not.",
- "createMaintenanceWindow": "Create maintenance window",
- "createMaintenance": "Create maintenance",
- "editMaintenance": "Edit maintenance",
- "maintenanceWindowName": "Maintenance Window Name",
- "friendlyNameInput": "Friendly name",
- "friendlyNamePlaceholder": "Maintenance at __ : __ for ___ minutes",
- "maintenanceRepeat": "Maintenance Repeat",
- "maintenance": "maintenance",
- "duration": "Duration",
- "addMonitors": "Add monitors",
- "window": "window",
- "cancel": "Cancel",
- "message": "Message",
- "low": "low",
- "high": "high",
- "statusCode": "Status code",
- "date&Time": "Date & Time",
- "type": "Type",
- "statusPageName": "Status page name",
- "publicURL": "Public URL",
- "repeat": "Repeat",
- "edit": "Edit",
- "createA": "Create a",
- "remove": "Remove",
- "maintenanceWindowDescription": "Your pings won't be sent during this time frame",
- "startTime": "Start time",
- "timeZoneInfo": "All dates and times are in GMT+0 time zone.",
- "monitorsToApply": "Monitors to apply maintenance window to",
- "nextWindow": "Next window",
- "notFoundButton": "Go to the main dashboard",
- "pageSpeedConfigureSettingsDescription": "Here you can select the URL of the host, together with the type of monitor.",
- "monitorDisplayName": "Monitor display name",
- "whenNewIncident": "When there is a new incident,",
- "notifySMS": "Notify via SMS (coming soon)",
- "notifyEmails": "Also notify via email to multiple addresses (coming soon)",
- "seperateEmails": "You can separate multiple emails with a comma",
- "checkFrequency": "Check frequency",
- "matchMethod": "Match Method",
- "expectedValue": "Expected value",
- "deleteDialogTitle": "Do you really want to delete this monitor?",
- "deleteDialogDescription": "Once deleted, this monitor cannot be retrieved.",
- "pageSpeedMonitor": "PageSpeed monitor",
- "shown": "Shown",
- "ago": "ago",
- "companyName": "Company name",
- "pageSpeedDetailsPerformanceReport": "Values are estimated and may vary.",
- "pageSpeedDetailsPerformanceReportCalculator": "See calculator",
- "checkingEvery": "Checking every",
- "statusPageCreateSettings": "If your status page is ready, you can mark it as published.",
- "basicInformation": "Basic Information",
- "statusPageCreateBasicInfoDescription": "Define company name and the subdomain that your status page points to.",
- "statusPageCreateSelectTimeZoneDescription": "Select the timezone that your status page will be displayed in.",
- "statusPageCreateAppearanceDescription": "Define the default look and feel of your public status page.",
- "statusPageCreateSettingsCheckboxLabel": "Published and visible to the public",
- "statusPageCreateBasicInfoStatusPageAddress": "Your status page address",
- "statusPageCreateTabsContent": "Status page servers",
- "statusPageCreateTabsContentDescription": "You can add any number of servers that you monitor to your status page. You can also reorder them for the best viewing experience.",
- "statusPageCreateTabsContentFeaturesDescription": "Show more details on the status page",
- "showCharts": "Show charts",
- "showUptimePercentage": "Show uptime percentage",
- "removeLogo": "Remove Logo",
- "statusPageStatus": "A public status page is not set up.",
- "statusPageStatusContactAdmin": "Please contact to your administrator",
- "statusPageStatusNotPublic": "This status page is not public.",
- "statusPageStatusNoPage": "There's no status page here.",
- "statusPageStatusServiceStatus": "Service status",
- "deleteStatusPage": "Do you want to delete this status page?",
- "deleteStatusPageConfirm": "Yes, delete status page",
- "deleteStatusPageDescription": "Once deleted, your status page cannot be retrieved.",
- "uptimeCreate": "The expected value is used to match against response result, and the match determines the status.",
- "uptimeCreateJsonPath": "This expression will be evaluated against the reponse JSON data and the result will be used to match against the expected value. See",
- "uptimeCreateJsonPathQuery": "for query language documentation.",
- "maintenanceTableActionMenuDialogTitle": "Do you really want to remove this maintenance window?",
- "infrastructureEditYour": "Edit your",
- "infrastructureEditMonitor": "Save Infrastructure Monitor",
- "infrastructureMonitorCreated": "Infrastructure monitor created successfully!",
- "infrastructureMonitorUpdated": "Infrastructure monitor updated successfully!",
- "errorInvalidTypeId": "Invalid notification type provided",
- "errorInvalidFieldId": "Invalid field ID provided",
- "inviteNoTokenFound": "No invite token found",
- "pageSpeedWarning": "Warning: You haven't added a Google PageSpeed API key yet. Without it, the PageSpeed monitor won't function.",
- "pageSpeedLearnMoreLink": "Click here",
- "pageSpeedAddApiKey": "to add your API key.",
- "update": "Update",
- "invalidFileFormat": "Unsupported file format!",
- "invalidFileSize": "File size is too large!",
- "ClickUpload": "Click to upload",
- "DragandDrop": "drag and drop",
- "MaxSize": "Maximum Size",
- "SupportedFormats": "Supported formats",
- "FirstName": "First name",
- "LastName": "Last name",
- "EmailDescriptionText": "This is your current email address — it cannot be changed.",
- "ignoreTLSError": "Ignore TLS/SSL error",
- "tlsErrorIgnored": "TLS/SSL errors ignored",
- "ignoreTLSErrorDescription": "Ignore TLS/SSL errors and continue checking the website's availability",
- "YourPhoto": "Profile photo",
- "PhotoDescriptionText": "This photo will be displayed in your profile page.",
- "save": "Save",
- "DeleteAccountTitle": "Remove account",
- "DeleteAccountButton": "Remove account",
- "DeleteDescriptionText": "This will remove the account and all associated data from the server. This isn't reversible.",
- "DeleteAccountWarning": "Removing your account means you won't be able to sign in again and all your data will be removed. This isn't reversible.",
- "DeleteWarningTitle": "Really remove this account?",
- "authRegisterFirstName": "Name",
- "authRegisterLastName": "Surname",
- "authRegisterEmail": "Email",
- "authRegisterEmailRequired": "To continue, please enter your email address",
- "authRegisterEmailInvalid": "Please enter a valid email address",
- "bulkImport": {
- "title": "Bulk Import",
- "selectFileTips": "Select CSV file to upload",
- "selectFileDescription": "You can download our template or sample",
- "selectFile": "Select File",
- "parsingFailed": "Parsing failed",
- "uploadSuccess": "Monitors created successfully!",
- "validationFailed": "Validation failed",
- "noFileSelected": "No file selected",
- "fallbackPage": "Import a file to upload a list of servers in bulk"
- },
- "publicLink": "Public link",
- "maskedPageSpeedKeyPlaceholder": "*************************************",
- "pageSpeedApiKeyFieldTitle": "Google PageSpeed API key",
- "pageSpeedApiKeyFieldLabel": "PageSpeed API key",
- "pageSpeedApiKeyFieldDescription": "Enter your Google PageSpeed API key to enable pagespeed monitoring. Click Reset to update the key.",
- "pageSpeedApiKeyFieldResetLabel": "API key is set. Click Reset to change it.",
- "reset": "Reset"
+ "now": "Now",
+ "delete": "Delete",
+ "configure": "Configure",
+ "networkError": "Network error",
+ "responseTime": "Response time",
+ "ms": "ms",
+ "bar": "Bar",
+ "area": "Area",
+ "country": "COUNTRY",
+ "city": "CITY",
+ "response": "RESPONSE",
+ "checkConnection": "Please check your connection",
+ "passwordreset": "Password Reset",
+ "authRegisterStepOnePersonalDetails": "Enter your personal details",
+ "authCheckEmailOpenEmailButton": "Open email app",
+ "authNewPasswordConfirmed": "Your password has been successfully reset. Click below to log in magically.",
+ "monitorStatusUp": "Monitor {name} ({url}) is now UP and responding",
+ "monitorStatusDown": "Monitor {name} ({url}) is DOWN and not responding",
+ "webhookSendSuccess": "Webhook notification sent successfully",
+ "webhookSendError": "Error sending webhook notification to {platform}",
+ "webhookUnsupportedPlatform": "Unsupported platform: {platform}",
+ "distributedRightCategoryTitle": "Monitor",
+ "distributedStatusServerMonitors": "Server Monitors",
+ "distributedStatusServerMonitorsDescription": "Monitor status of related servers",
+ "distributedUptimeCreateSelectURL": "Here you can select the URL of the host, together with the type of monitor.",
+ "distributedUptimeCreateChecks": "Checks to perform",
+ "distributedUptimeCreateChecksDescription": "You can always add or remove checks after adding your site.",
+ "distributedUptimeCreateIncidentNotification": "Incident notifications",
+ "distributedUptimeCreateIncidentDescription": "When there is an incident, notify users.",
+ "distributedUptimeCreateAdvancedSettings": "Advanced settings",
+ "distributedUptimeDetailsNoMonitorHistory": "There is no check history for this monitor yet.",
+ "distributedUptimeDetailsFooterHeading": "Made with ❤️ by UpRock & Bluewave Labs",
+ "distributedUptimeDetailsFooterBuilt": "Built on",
+ "distributedUptimeDetailsFooterSolana": "Solana",
+ "distributedUptimeDetailsMonitorHeader": "Distributed Uptime Monitoring powered by DePIN",
+ "distributedUptimeDetailsStatusHeaderUptime": "Uptime:",
+ "distributedUptimeDetailsStatusHeaderLastUpdate": "Last updated",
+ "notifications": {
+ "enableNotifications": "Enable {{platform}} notifications",
+ "testNotification": "Test notification",
+ "addOrEditNotifications": "Add or edit notifications",
+ "slack": {
+ "label": "Slack",
+ "description": "To enable Slack notifications, create a Slack app and enable incoming webhooks. After that, simply provide the webhook URL here.",
+ "webhookLabel": "Webhook URL",
+ "webhookPlaceholder": "https://hooks.slack.com/services/...",
+ "webhookRequired": "Slack webhook URL is required"
+ },
+ "discord": {
+ "label": "Discord",
+ "description": "To send data to a Discord channel from Checkmate via Discord notifications using webhooks, you can use Discord's incoming Webhooks feature.",
+ "webhookLabel": "Discord Webhook URL",
+ "webhookPlaceholder": "https://discord.com/api/webhooks/...",
+ "webhookRequired": "Discord webhook URL is required"
+ },
+ "telegram": {
+ "label": "Telegram",
+ "description": "To enable Telegram notifications, create a Telegram bot using BotFather, an official bot for creating and managing Telegram bots. Then, get the API token and chat ID and write them down here.",
+ "tokenLabel": "Your bot token",
+ "tokenPlaceholder": "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11",
+ "chatIdLabel": "Your Chat ID",
+ "chatIdPlaceholder": "-1001234567890",
+ "fieldsRequired": "Telegram token and chat ID are required"
+ },
+ "webhook": {
+ "label": "Webhooks",
+ "description": "You can set up a custom webhook to receive notifications when incidents occur.",
+ "urlLabel": "Webhook URL",
+ "urlPlaceholder": "https://your-server.com/webhook",
+ "urlRequired": "Webhook URL is required"
+ },
+ "testNotificationDevelop": "Test notification 2",
+ "integrationButton": "Notification Integration",
+ "testSuccess": "Test notification sent successfully!",
+ "testFailed": "Failed to send test notification",
+ "unsupportedType": "Unsupported notification type",
+ "networkError": "Network error occurred"
+ },
+ "testLocale": "testLocale",
+ "add": "Add",
+ "monitors": "monitors",
+ "distributedUptimeStatusCreateStatusPage": "status page",
+ "distributedUptimeStatusCreateStatusPageAccess": "Access",
+ "distributedUptimeStatusCreateStatusPageReady": "If your status page is ready, you can mark it as published.",
+ "distributedUptimeStatusBasicInfoHeader": "Basic Information",
+ "distributedUptimeStatusBasicInfoDescription": "Define company name and the subdomain that your status page points to.",
+ "distributedUptimeStatusLogoHeader": "Logo",
+ "distributedUptimeStatusLogoDescription": "Upload a logo for your status page",
+ "distributedUptimeStatusLogoUploadButton": "Upload logo",
+ "distributedUptimeStatusStandardMonitorsHeader": "Standard Monitors",
+ "distributedUptimeStatusStandardMonitorsDescription": "Attach standard monitors to your status page.",
+ "distributedUptimeStatusCreateYour": "Create your",
+ "distributedUptimeStatusEditYour": "Edit your",
+ "distributedUptimeStatusPublishedLabel": "Published and visible to the public",
+ "distributedUptimeStatusCompanyNameLabel": "Company name",
+ "distributedUptimeStatusPageAddressLabel": "Your status page address",
+ "distributedUptimeStatus30Days": "30 days",
+ "distributedUptimeStatus60Days": "60 days",
+ "distributedUptimeStatus90Days": "90 days",
+ "distributedUptimeStatusPageNotSetUp": "A status page is not set up.",
+ "distributedUptimeStatusContactAdmin": "Please contact your administrator",
+ "distributedUptimeStatusPageNotPublic": "This status page is not public.",
+ "distributedUptimeStatusPageDeleteDialog": "Do you want to delete this status page?",
+ "distributedUptimeStatusPageDeleteConfirm": "Yes, delete status page",
+ "distributedUptimeStatusPageDeleteDescription": "Once deleted, your status page cannot be retrieved.",
+ "distributedUptimeStatusDevices": "Devices",
+ "distributedUptimeStatusUpt": "UPT",
+ "distributedUptimeStatusUptBurned": "UPT Burned",
+ "distributedUptimeStatusUptLogo": "Upt Logo",
+ "incidentsTableNoIncidents": "No incidents recorded",
+ "incidentsTablePaginationLabel": "incidents",
+ "incidentsTableMonitorName": "Monitor Name",
+ "incidentsTableStatus": "Status",
+ "incidentsTableDateTime": "Date & Time",
+ "incidentsTableStatusCode": "Status Code",
+ "incidentsTableMessage": "Message",
+ "incidentsOptionsHeader": "Incidents for:",
+ "incidentsOptionsHeaderFilterBy": "Filter by:",
+ "incidentsOptionsHeaderFilterAll": "All",
+ "incidentsOptionsHeaderFilterDown": "Down",
+ "incidentsOptionsHeaderFilterCannotResolve": "Cannot resolve",
+ "incidentsOptionsHeaderShow": "Show:",
+ "incidentsOptionsHeaderLastHour": "Last hour",
+ "incidentsOptionsHeaderLastDay": "Last day",
+ "incidentsOptionsHeaderLastWeek": "Last week",
+ "incidentsOptionsPlaceholderAllServers": "All servers",
+ "infrastructureCreateYour": "Create your",
+ "infrastructureCreateGeneralSettingsDescription": "Here you can select the URL of the host, together with the friendly name and authorization secret to connect to the server agent.",
+ "infrastructureServerRequirement": "The server you are monitoring must be running the",
+ "infrastructureCustomizeAlerts": "Customize alerts",
+ "infrastructureAlertNotificationDescription": "Send a notification to user(s) when thresholds exceed a specified percentage.",
+ "infrastructureCreateMonitor": "Create Infrastructure Monitor",
+ "infrastructureProtocol": "Protocol",
+ "infrastructureServerUrlLabel": "Server URL",
+ "infrastructureDisplayNameLabel": "Display name",
+ "infrastructureAuthorizationSecretLabel": "Authorization secret",
+ "gb": "GB",
+ "mb": "MB",
+ "mem": "Mem",
+ "memoryUsage": "Memory usage",
+ "cpu": "CPU",
+ "cpuUsage": "CPU usage",
+ "cpuTemperature": "CPU Temperature",
+ "diskUsage": "Disk Usage",
+ "used": "Used",
+ "total": "Total",
+ "cores": "Cores",
+ "frequency": "Frequency",
+ "status": "Status",
+ "cpuPhysical": "CPU (Physical)",
+ "cpuLogical": "CPU (Logical)",
+ "cpuFrequency": "CPU Frequency",
+ "avgCpuTemperature": "Average CPU Temperature",
+ "memory": "Memory",
+ "disk": "Disk",
+ "uptime": "Uptime",
+ "os": "OS",
+ "host": "Host",
+ "actions": "Actions",
+ "integrations": "Integrations",
+ "integrationsPrism": "Connect Prism to your favorite service.",
+ "integrationsSlack": "Slack",
+ "integrationsSlackInfo": "Connect with Slack and see incidents in a channel",
+ "integrationsDiscord": "Discord",
+ "integrationsDiscordInfo": "Connect with Discord and view incidents directly in a channel",
+ "integrationsZapier": "Zapier",
+ "integrationsZapierInfo": "Send all incidents to Zapier, and then see them everywhere",
+ "commonSave": "Save",
+ "createYour": "Create your",
+ "createMonitor": "Create monitor",
+ "pause": "Pause",
+ "resume": "Resume",
+ "editing": "Editing...",
+ "url": "URL",
+ "access": "Access",
+ "timezone": "Timezone",
+ "features": "Features",
+ "administrator": "Administrator?",
+ "loginHere": "Login here",
+ "displayName": "Display name",
+ "urlMonitor": "URL to monitor",
+ "portToMonitor": "Port to monitor",
+ "websiteMonitoring": "Website monitoring",
+ "websiteMonitoringDescription": "Use HTTP(s) to monitor your website or API endpoint.",
+ "pingMonitoring": "Ping monitoring",
+ "pingMonitoringDescription": "Check whether your server is available or not.",
+ "dockerContainerMonitoring": "Docker container monitoring",
+ "dockerContainerMonitoringDescription": "Check whether your Docker container is running or not.",
+ "portMonitoring": "Port monitoring",
+ "portMonitoringDescription": "Check whether your port is open or not.",
+ "createMaintenanceWindow": "Create maintenance window",
+ "createMaintenance": "Create maintenance",
+ "editMaintenance": "Edit maintenance",
+ "maintenanceWindowName": "Maintenance Window Name",
+ "friendlyNameInput": "Friendly name",
+ "friendlyNamePlaceholder": "Maintenance at __ : __ for ___ minutes",
+ "maintenanceRepeat": "Maintenance Repeat",
+ "maintenance": "maintenance",
+ "duration": "Duration",
+ "addMonitors": "Add monitors",
+ "window": "window",
+ "cancel": "Cancel",
+ "message": "Message",
+ "low": "low",
+ "high": "high",
+ "statusCode": "Status code",
+ "date&Time": "Date & Time",
+ "type": "Type",
+ "statusPageName": "Status page name",
+ "publicURL": "Public URL",
+ "repeat": "Repeat",
+ "edit": "Edit",
+ "createA": "Create a",
+ "remove": "Remove",
+ "maintenanceWindowDescription": "Your pings won't be sent during this time frame",
+ "startTime": "Start time",
+ "timeZoneInfo": "All dates and times are in GMT+0 time zone.",
+ "monitorsToApply": "Monitors to apply maintenance window to",
+ "nextWindow": "Next window",
+ "notFoundButton": "Go to the main dashboard",
+ "pageSpeedConfigureSettingsDescription": "Here you can select the URL of the host, together with the type of monitor.",
+ "monitorDisplayName": "Monitor display name",
+ "whenNewIncident": "When there is a new incident,",
+ "notifySMS": "Notify via SMS (coming soon)",
+ "notifyEmails": "Also notify via email to multiple addresses (coming soon)",
+ "seperateEmails": "You can separate multiple emails with a comma",
+ "checkFrequency": "Check frequency",
+ "matchMethod": "Match Method",
+ "expectedValue": "Expected value",
+ "deleteDialogTitle": "Do you really want to delete this monitor?",
+ "deleteDialogDescription": "Once deleted, this monitor cannot be retrieved.",
+ "pageSpeedMonitor": "PageSpeed monitor",
+ "shown": "Shown",
+ "ago": "ago",
+ "companyName": "Company name",
+ "pageSpeedDetailsPerformanceReport": "Values are estimated and may vary.",
+ "pageSpeedDetailsPerformanceReportCalculator": "See calculator",
+ "checkingEvery": "Checking every",
+ "statusPageCreateSettings": "If your status page is ready, you can mark it as published.",
+ "basicInformation": "Basic Information",
+ "statusPageCreateBasicInfoDescription": "Define company name and the subdomain that your status page points to.",
+ "statusPageCreateSelectTimeZoneDescription": "Select the timezone that your status page will be displayed in.",
+ "statusPageCreateAppearanceDescription": "Define the default look and feel of your public status page.",
+ "statusPageCreateSettingsCheckboxLabel": "Published and visible to the public",
+ "statusPageCreateBasicInfoStatusPageAddress": "Your status page address",
+ "statusPageCreateTabsContent": "Status page servers",
+ "statusPageCreateTabsContentDescription": "You can add any number of servers that you monitor to your status page. You can also reorder them for the best viewing experience.",
+ "statusPageCreateTabsContentFeaturesDescription": "Show more details on the status page",
+ "showCharts": "Show charts",
+ "showUptimePercentage": "Show uptime percentage",
+ "removeLogo": "Remove Logo",
+ "statusPageStatus": "A public status page is not set up.",
+ "statusPageStatusContactAdmin": "Please contact to your administrator",
+ "statusPageStatusNotPublic": "This status page is not public.",
+ "statusPageStatusNoPage": "There's no status page here.",
+ "statusPageStatusServiceStatus": "Service status",
+ "deleteStatusPage": "Do you want to delete this status page?",
+ "deleteStatusPageConfirm": "Yes, delete status page",
+ "deleteStatusPageDescription": "Once deleted, your status page cannot be retrieved.",
+ "uptimeCreate": "The expected value is used to match against response result, and the match determines the status.",
+ "uptimeCreateJsonPath": "This expression will be evaluated against the reponse JSON data and the result will be used to match against the expected value. See",
+ "uptimeCreateJsonPathQuery": "for query language documentation.",
+ "maintenanceTableActionMenuDialogTitle": "Do you really want to remove this maintenance window?",
+ "infrastructureEditYour": "Edit your",
+ "infrastructureEditMonitor": "Save Infrastructure Monitor",
+ "infrastructureMonitorCreated": "Infrastructure monitor created successfully!",
+ "infrastructureMonitorUpdated": "Infrastructure monitor updated successfully!",
+ "errorInvalidTypeId": "Invalid notification type provided",
+ "errorInvalidFieldId": "Invalid field ID provided",
+ "inviteNoTokenFound": "No invite token found",
+ "pageSpeedWarning": "Warning: You haven't added a Google PageSpeed API key yet. Without it, the PageSpeed monitor won't function.",
+ "pageSpeedLearnMoreLink": "Click here",
+ "pageSpeedAddApiKey": "to add your API key.",
+ "update": "Update",
+ "invalidFileFormat": "Unsupported file format!",
+ "invalidFileSize": "File size is too large!",
+ "ClickUpload": "Click to upload",
+ "DragandDrop": "drag and drop",
+ "MaxSize": "Maximum Size",
+ "SupportedFormats": "Supported formats",
+ "FirstName": "First name",
+ "LastName": "Last name",
+ "EmailDescriptionText": "This is your current email address — it cannot be changed.",
+ "ignoreTLSError": "Ignore TLS/SSL error",
+ "tlsErrorIgnored": "TLS/SSL errors ignored",
+ "ignoreTLSErrorDescription": "Ignore TLS/SSL errors and continue checking the website's availability",
+ "YourPhoto": "Profile photo",
+ "PhotoDescriptionText": "This photo will be displayed in your profile page.",
+ "save": "Save",
+ "DeleteAccountTitle": "Remove account",
+ "DeleteAccountButton": "Remove account",
+ "DeleteDescriptionText": "This will remove the account and all associated data from the server. This isn't reversible.",
+ "DeleteAccountWarning": "Removing your account means you won't be able to sign in again and all your data will be removed. This isn't reversible.",
+ "DeleteWarningTitle": "Really remove this account?",
+ "authRegisterFirstName": "Name",
+ "authRegisterLastName": "Surname",
+ "authRegisterEmail": "Email",
+ "authRegisterEmailRequired": "To continue, please enter your email address",
+ "authRegisterEmailInvalid": "Please enter a valid email address",
+ "bulkImport": {
+ "title": "Bulk Import",
+ "selectFileTips": "Select CSV file to upload",
+ "selectFileDescription": "You can download our template or sample",
+ "selectFile": "Select File",
+ "parsingFailed": "Parsing failed",
+ "uploadSuccess": "Monitors created successfully!",
+ "validationFailed": "Validation failed",
+ "noFileSelected": "No file selected",
+ "fallbackPage": "Import a file to upload a list of servers in bulk"
+ },
+ "publicLink": "Public link",
+ "maskedPageSpeedKeyPlaceholder": "*************************************",
+ "pageSpeedApiKeyFieldTitle": "Google PageSpeed API key",
+ "pageSpeedApiKeyFieldLabel": "PageSpeed API key",
+ "pageSpeedApiKeyFieldDescription": "Enter your Google PageSpeed API key to enable pagespeed monitoring. Click Reset to update the key.",
+ "pageSpeedApiKeyFieldResetLabel": "API key is set. Click Reset to change it.",
+ "reset": "Reset"
}
-
diff --git a/server/controllers/monitorController.js b/server/controllers/monitorController.js
index 5ab654375..9a42ea4e5 100755
--- a/server/controllers/monitorController.js
+++ b/server/controllers/monitorController.js
@@ -649,9 +649,8 @@ class MonitorController {
sendTestEmail = async (req, res, next) => {
try {
const { to } = req.body;
-
if (!to || typeof to !== "string") {
- return res.error({ msg: this.stringService.errorForValidEmailAddress });
+ throw new Error(this.stringService.errorForValidEmailAddress);
}
const subject = this.stringService.testEmailSubject;
diff --git a/server/controllers/settingsController.js b/server/controllers/settingsController.js
index 4d561216e..b557e8dd6 100755
--- a/server/controllers/settingsController.js
+++ b/server/controllers/settingsController.js
@@ -13,12 +13,25 @@ class SettingsController {
getAppSettings = async (req, res, next) => {
const dbSettings = await this.settingsService.getDBSettings();
const sanitizedSettings = { ...dbSettings };
+
+ const returnSettings = {
+ pagespeedKeySet: false,
+ emailPasswordSet: false,
+ };
+
if (typeof sanitizedSettings.pagespeedApiKey !== "undefined") {
- sanitizedSettings.pagespeedApiKey = "********";
+ returnSettings.pagespeedKeySet = true;
+ delete sanitizedSettings.pagespeedApiKey;
}
+ if (typeof sanitizedSettings.systemEmailPassword !== "undefined") {
+ returnSettings.emailPasswordSet = true;
+ delete sanitizedSettings.systemEmailPassword;
+ }
+
+ returnSettings.settings = sanitizedSettings;
return res.success({
msg: this.stringService.getAppSettings,
- data: sanitizedSettings,
+ data: returnSettings,
});
};
diff --git a/server/db/models/AppSettings.js b/server/db/models/AppSettings.js
index 1113bbe46..06ba8c1df 100755
--- a/server/db/models/AppSettings.js
+++ b/server/db/models/AppSettings.js
@@ -25,6 +25,9 @@ const AppSettingsSchema = mongoose.Schema(
systemEmailPassword: {
type: String,
},
+ systemEmailUser: {
+ type: String,
+ },
singleton: {
type: Boolean,
required: true,
diff --git a/server/db/mongo/modules/settingsModule.js b/server/db/mongo/modules/settingsModule.js
index 2c1b402c3..d3568ad32 100755
--- a/server/db/mongo/modules/settingsModule.js
+++ b/server/db/mongo/modules/settingsModule.js
@@ -21,6 +21,11 @@ const updateAppSettings = async (newSettings) => {
delete update.$set.pagespeedApiKey;
}
+ if (newSettings.systemEmailPassword === "") {
+ update.$unset = { systemEmailPassword: "" };
+ delete update.$set.systemEmailPassword;
+ }
+
const settings = await AppSettings.findOneAndUpdate({}, update, {
new: true,
upsert: true,
diff --git a/server/service/emailService.js b/server/service/emailService.js
index c9e34eeda..57f8c78e6 100755
--- a/server/service/emailService.js
+++ b/server/service/emailService.js
@@ -29,7 +29,10 @@ class EmailService {
this.mjml2html = mjml2html;
this.nodemailer = nodemailer;
this.logger = logger;
+ this.init();
+ }
+ init = async () => {
/**
* Loads an email template from the filesystem.
*
@@ -67,34 +70,14 @@ class EmailService {
serverIsUpTemplate: this.loadTemplate("serverIsUp"),
passwordResetTemplate: this.loadTemplate("passwordReset"),
hardwareIncidentTemplate: this.loadTemplate("hardwareIncident"),
- testEmailTemplate: this.loadTemplate("testEmailTemplate")
+ testEmailTemplate: this.loadTemplate("testEmailTemplate"),
};
/**
* The email transporter used to send emails.
* @type {Object}
*/
-
- const {
- systemEmailHost,
- systemEmailPort,
- systemEmailUser,
- systemEmailAddress,
- systemEmailPassword,
- } = this.settingsService.getSettings();
-
- const emailConfig = {
- host: systemEmailHost,
- port: systemEmailPort,
- secure: true,
- auth: {
- user: systemEmailUser || systemEmailAddress,
- pass: systemEmailPassword,
- },
- };
-
- this.transporter = this.nodemailer.createTransport(emailConfig);
- }
+ };
/**
* Asynchronously builds and sends an email using a specified template and context.
@@ -106,6 +89,28 @@ class EmailService {
* @returns {Promise} A promise that resolves to the messageId of the sent email.
*/
buildAndSendEmail = async (template, context, to, subject) => {
+ // TODO - Consider an update transporter method so this only needs to be recreated when smtp settings change
+ const {
+ systemEmailHost,
+ systemEmailPort,
+ systemEmailUser,
+ systemEmailAddress,
+ systemEmailPassword,
+ } = await this.settingsService.getDBSettings();
+
+ const emailConfig = {
+ host: systemEmailHost,
+ port: systemEmailPort,
+ secure: true,
+ auth: {
+ user: systemEmailUser || systemEmailAddress,
+ pass: systemEmailPassword,
+ },
+ connectionTimeout: 5000,
+ };
+
+ this.transporter = this.nodemailer.createTransport(emailConfig);
+
const buildHtml = async (template, context) => {
try {
const mjml = this.templateLookup[template](context);
diff --git a/server/validation/joi.js b/server/validation/joi.js
index b28ed3850..997d35d65 100755
--- a/server/validation/joi.js
+++ b/server/validation/joi.js
@@ -431,6 +431,7 @@ const updateAppSettingsBodyValidation = joi.object({
systemEmailPort: joi.number().allow(""),
systemEmailAddress: joi.string().allow(""),
systemEmailPassword: joi.string().allow(""),
+ systemEmailUser: joi.string().allow(""),
});
//****************************************