diff --git a/Client/src/Pages/Monitors/Configure/index.css b/Client/src/Pages/Monitors/Configure/index.css index b1808b237..3a879bcd2 100644 --- a/Client/src/Pages/Monitors/Configure/index.css +++ b/Client/src/Pages/Monitors/Configure/index.css @@ -43,6 +43,14 @@ .configure-monitor .config-box .MuiStack-root { flex: 1; } +.configure-monitor .MuiStack-root:has(span.MuiTypography-root.input-error) { + position: relative; +} +.configure-monitor span.MuiTypography-root.input-error { + position: absolute; + top: 100%; +} + .MuiInputBase-root:has(#monitor-interval) { height: 34px; } diff --git a/Client/src/Pages/Monitors/Configure/index.jsx b/Client/src/Pages/Monitors/Configure/index.jsx index 0784399cc..f74eeae58 100644 --- a/Client/src/Pages/Monitors/Configure/index.jsx +++ b/Client/src/Pages/Monitors/Configure/index.jsx @@ -14,6 +14,7 @@ import PauseCircleOutlineIcon from "@mui/icons-material/PauseCircleOutline"; import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown"; import "./index.css"; +import { monitorValidation } from "../../../Validation/validation"; const formatDurationRounded = (ms) => { const seconds = Math.floor(ms / 1000); @@ -66,6 +67,14 @@ const Configure = () => { const { authToken } = useSelector((state) => state.auth); const { monitorId } = useParams(); + const idMap = { + "monitor-url": "url", + "monitor-name": "name", + "monitor-type": "type", + "monitor-interval": "interval", + }; + + const [config, setConfig] = useState(); const [monitor, setMonitor] = useState(); const [errors, setErrors] = useState({}); useEffect(() => { @@ -76,17 +85,45 @@ const Configure = () => { }, }); let data = res.data.data; + setConfig(data); setMonitor({ name: data.name, url: data.url.replace(/^https?:\/\//, ""), type: data.type, interval: data.interval / MS_PER_MINUTE, - status: data.status, }); }; fetchMonitor(); }, [monitorId, authToken]); + const handleChange = (event) => { + const { value, id } = event.target; + const name = idMap[id]; + setMonitor((prev) => ({ + ...prev, + [name]: value, + })); + + const validation = monitorValidation.validate( + { [name]: value }, + { abortEarly: false } + ); + + setErrors((prev) => { + const updatedErrors = { ...prev }; + + if (validation.error) + updatedErrors[name] = validation.error.details[0].message; + else delete updatedErrors[name]; + return updatedErrors; + }); + }; + + const handleSubmit = (event) => { + event.preventDefault(); + // TODO + }; + const frequencies = [1, 2, 3, 4, 5]; return ( @@ -114,25 +151,25 @@ const Configure = () => {
- {monitor?.status ? : } + {config?.status ? : } - {monitor?.url.replace(/^https?:\/\//, "") || "..."} + {config?.url.replace(/^https?:\/\//, "") || "..."} - Your site is {monitor?.status ? "up" : "down"}. + Your site is {config?.status ? "up" : "down"}. {" "} - Checking every {formatDurationRounded(monitor?.interval)}. Last + Checking every {formatDurationRounded(config?.interval)}. Last time checked{" "} - {formatDurationRounded(getLastChecked(monitor?.checks))} ago. + {formatDurationRounded(getLastChecked(config?.checks))} ago. { id="monitor-url" label="URL to monitor" placeholder="google.com" - value={monitor?.url} + value={monitor?.url || ""} + onChange={handleChange} + error={errors["url"]} /> { label="Friendly name" isOptional={true} placeholder="Google" - value={monitor?.name} + value={monitor?.name || ""} + onChange={handleChange} + error={errors["name"]} /> diff --git a/Client/src/Pages/Monitors/CreateMonitor/index.jsx b/Client/src/Pages/Monitors/CreateMonitor/index.jsx index e460ccaa2..04cae3fb6 100644 --- a/Client/src/Pages/Monitors/CreateMonitor/index.jsx +++ b/Client/src/Pages/Monitors/CreateMonitor/index.jsx @@ -5,7 +5,7 @@ import RadioButton from "../../../Components/RadioButton"; import Button from "../../../Components/Button"; import { Box, MenuItem, Select, Stack, Typography } from "@mui/material"; import { useSelector, useDispatch } from "react-redux"; -import { createMonitorValidation } from "../../../Validation/validation"; +import { monitorValidation } from "../../../Validation/validation"; import { createMonitor } from "../../../Features/Monitors/monitorsSlice"; import { useNavigate } from "react-router-dom"; import { useTheme } from "@emotion/react"; @@ -37,7 +37,7 @@ const CreateMonitor = () => { // }); //Advanced Settings Form const [advancedSettings, setAdvancedSettings] = useState({ - frequency: 1, + interval: 1, // retries: "", // codes: "", // redirects: "", @@ -57,7 +57,7 @@ const CreateMonitor = () => { [id]: checkbox ? true : value, })); - const validation = createMonitorValidation.validate( + const validation = monitorValidation.validate( { [id]: value }, { abortEarly: false } ); @@ -92,7 +92,7 @@ const CreateMonitor = () => { ...checks, }; - const { error } = createMonitorValidation.validate(monitor, { + const { error } = monitorValidation.validate(monitor, { abortEarly: false, }); @@ -107,8 +107,8 @@ const CreateMonitor = () => { ...monitor, description: monitor.name, userId: user._id, - // ...advancedSettings, // TODO frequency should be interval, then we can use spread - interval: advancedSettings.frequency * MS_PER_MINUTE, + // ...advancedSettings + interval: advancedSettings.interval * MS_PER_MINUTE, }; try { const action = await dispatch(createMonitor({ authToken, monitor })); @@ -333,10 +333,10 @@ const CreateMonitor = () => {