From 2f8638cf047baac42c99d0dcec7ed534e54e554c Mon Sep 17 00:00:00 2001 From: Shemy Gan Date: Fri, 15 Nov 2024 14:49:27 -0500 Subject: [PATCH] - update safe checking for string util - remove required for threshold in joi - refine if logic and update no error checking with values due to the change to set null instead of delete error entry - move customthreshold component to under create infrastructure folder - correct interval setting and threshold default value and fix typo --- .../CreateMonitor}/CustomThreshold/index.jsx | 4 ++-- .../CreateMonitor/index.jsx | 18 +++++++++--------- Client/src/Utils/stringUtils.js | 15 ++++++++++++--- Client/src/Validation/error.js | 8 ++++---- Client/src/Validation/validation.js | 8 ++------ 5 files changed, 29 insertions(+), 24 deletions(-) rename Client/src/{Components => Pages/InfrastructureMonitors/CreateMonitor}/CustomThreshold/index.jsx (96%) diff --git a/Client/src/Components/CustomThreshold/index.jsx b/Client/src/Pages/InfrastructureMonitors/CreateMonitor/CustomThreshold/index.jsx similarity index 96% rename from Client/src/Components/CustomThreshold/index.jsx rename to Client/src/Pages/InfrastructureMonitors/CreateMonitor/CustomThreshold/index.jsx index 73bacba57..9bbd57baa 100644 --- a/Client/src/Components/CustomThreshold/index.jsx +++ b/Client/src/Pages/InfrastructureMonitors/CreateMonitor/CustomThreshold/index.jsx @@ -1,6 +1,6 @@ import { Box, Stack, Typography } from "@mui/material"; -import Field from "../Inputs/Field"; -import Checkbox from "../Inputs/Checkbox"; +import Field from "../../../../Components/Inputs/Field"; +import Checkbox from "../../../../Components/Inputs/Checkbox"; import { useTheme } from "@emotion/react"; import PropTypes from "prop-types"; diff --git a/Client/src/Pages/InfrastructureMonitors/CreateMonitor/index.jsx b/Client/src/Pages/InfrastructureMonitors/CreateMonitor/index.jsx index 9a6e2cfeb..4707b9155 100644 --- a/Client/src/Pages/InfrastructureMonitors/CreateMonitor/index.jsx +++ b/Client/src/Pages/InfrastructureMonitors/CreateMonitor/index.jsx @@ -2,7 +2,7 @@ import { useState } from "react"; import { Box, Stack, Typography } from "@mui/material"; import LoadingButton from "@mui/lab/LoadingButton"; import { useSelector, useDispatch } from "react-redux"; -import { infrastractureMonitorValidation } from "../../../Validation/validation"; +import { infrastructureMonitorValidation } from "../../../Validation/validation"; import { createInfrastructureMonitor, checkInfrastructureEndpointResolution, @@ -18,7 +18,7 @@ import Checkbox from "../../../Components/Inputs/Checkbox"; import Breadcrumbs from "../../../Components/Breadcrumbs"; import { buildErrors, hasValidationErrors } from "../../../Validation/error"; import { capitalizeFirstLetter } from "../../../Utils/stringUtils"; -import { CustomThreshold } from "../../../Components/CustomThreshold"; +import { CustomThreshold } from "../CreateMonitor/CustomThreshold"; const CreateInfrastructureMonitor = () => { const [infrastructureMonitor, setInfrastructureMonitor] = useState({ @@ -27,15 +27,15 @@ const CreateInfrastructureMonitor = () => { notifications: [], interval: 15, cpu: false, - usage_cpu: "", + usage_cpu: 0, memory: false, - usage_memory: "", + usage_memory: 0, disk: false, - usage_disk: "", + usage_disk: 0, secret: "", }); - const MS_PER_MINUTE = 60000; + const MS_PER_SECOND = 1000; const THRESHOLD_FIELD_PREFIX = "usage_"; const HARDWARE_MONITOR_TYPES = ["cpu", "memory", "disk"]; const { user, authToken } = useSelector((state) => state.auth); @@ -78,7 +78,7 @@ const CreateInfrastructureMonitor = () => { event.preventDefault(); const { value, id } = event.target; if (id?.startsWith("notify-email-")) return; - const { error } = infrastractureMonitorValidation.validate( + const { error } = infrastructureMonitorValidation.validate( { [id ?? appenedID]: value }, { abortEarly: false, @@ -156,10 +156,10 @@ const CreateInfrastructureMonitor = () => { infrastructureMonitor.name === "" ? infrastructureMonitor.url : infrastructureMonitor.name, - interval: infrastructureMonitor.interval * MS_PER_MINUTE, + interval: infrastructureMonitor.interval * MS_PER_SECOND, }; delete form.notifications; - if (hasValidationErrors(form, infrastractureMonitorValidation, setErrors)) { + if (hasValidationErrors(form, infrastructureMonitorValidation, setErrors)) { return; } else { const checkEndpointAction = await dispatch( diff --git a/Client/src/Utils/stringUtils.js b/Client/src/Utils/stringUtils.js index 693051f17..43ae5ed54 100644 --- a/Client/src/Utils/stringUtils.js +++ b/Client/src/Utils/stringUtils.js @@ -3,6 +3,15 @@ * @param {string} str String whose first letter is to be capitalized * @returns A string with first letter capitalized */ -export const capitalizeFirstLetter = (str) =>{ - return str?.charAt(0).toUpperCase() + str.slice(1); -} +export const capitalizeFirstLetter = (str) => { + if (str === null || str === undefined) { + return ""; + } + if (typeof str !== "string") { + throw new TypeError("Input must be a string"); + } + if (str.length === 0) { + return ""; + } + return str.charAt(0).toUpperCase() + str.slice(1); +}; diff --git a/Client/src/Validation/error.js b/Client/src/Validation/error.js index d017cfd2d..a941e2509 100644 --- a/Client/src/Validation/error.js +++ b/Client/src/Validation/error.js @@ -28,17 +28,17 @@ const hasValidationErrors = (form, validation, setErrors) => { newErrors[err.path[0]] = err.message ?? "Validation error"; } // Handle conditionally usage number required cases - if (!form.cpu || (form.cpu && form.usage_cpu)) { + if (!form.cpu || form.usage_cpu) { newErrors["usage_cpu"] = null; } - if (!form.memory || (form.memory && form.usage_memory)) { + if (!form.memory || form.usage_memory) { newErrors["usage_memory"] = null; } - if (!form.disk || (form.disk && form.usage_disk)) { + if (!form.disk || form.usage_disk) { newErrors["usage_disk"] = null; } }); - if (Object.keys(newErrors).length > 0) { + if (Object.values(newErrors).some(v=> v)) { setErrors(newErrors); return true; } else { diff --git a/Client/src/Validation/validation.js b/Client/src/Validation/validation.js index d542c221e..7dfbeb246 100644 --- a/Client/src/Validation/validation.js +++ b/Client/src/Validation/validation.js @@ -1,7 +1,6 @@ import joi from "joi"; import dayjs from "dayjs"; -const THRESHOLD_COMMON_MSG = "Threshold is required."; const THRESHOLD_COMMON_BASE_MSG = "Threshold must be a number."; const nameSchema = joi @@ -176,7 +175,7 @@ const advancedSettingsValidation = joi.object({ pagespeedApiKey: joi.string().allow(""), }); -const infrastractureMonitorValidation = joi.object({ +const infrastructureMonitorValidation = joi.object({ url: joi.string().uri({ allowRelative: true }).trim().messages({ "string.empty": "This field is required.", "string.uri": "The URL you provided is not valid.", @@ -187,18 +186,15 @@ const infrastractureMonitorValidation = joi.object({ secret: joi.string().trim().messages({ "string.empty": "This field is required." }), usage_cpu: joi.number().messages({ "number.base": THRESHOLD_COMMON_BASE_MSG, - "any.required": THRESHOLD_COMMON_MSG, }), cpu: joi.boolean(), memory: joi.boolean(), disk: joi.boolean(), usage_memory: joi.number().messages({ "number.base": THRESHOLD_COMMON_BASE_MSG, - "any.required": THRESHOLD_COMMON_MSG, }), usage_disk: joi.number().messages({ "number.base": THRESHOLD_COMMON_BASE_MSG, - "any.required": THRESHOLD_COMMON_MSG, }), // usage_temperature: joi.number().messages({ // "number.base": "Temperature must be a number.", @@ -222,5 +218,5 @@ export { settingsValidation, maintenanceWindowValidation, advancedSettingsValidation, - infrastractureMonitorValidation, + infrastructureMonitorValidation, };