diff --git a/Client/src/Components/Inputs/Field/index.jsx b/Client/src/Components/Inputs/Field/index.jsx
index 1d9034c66..6fb8ea612 100644
--- a/Client/src/Components/Inputs/Field/index.jsx
+++ b/Client/src/Components/Inputs/Field/index.jsx
@@ -177,7 +177,7 @@ Field.propTypes = {
autoComplete: PropTypes.string,
placeholder: PropTypes.string,
value: PropTypes.string.isRequired,
- onChange: PropTypes.func.isRequired,
+ onChange: PropTypes.func,
error: PropTypes.string,
disabled: PropTypes.bool,
};
diff --git a/Client/src/Features/UptimeMonitors/uptimeMonitorsSlice.js b/Client/src/Features/UptimeMonitors/uptimeMonitorsSlice.js
index 8302aa1e5..4ffa31054 100644
--- a/Client/src/Features/UptimeMonitors/uptimeMonitorsSlice.js
+++ b/Client/src/Features/UptimeMonitors/uptimeMonitorsSlice.js
@@ -68,6 +68,31 @@ export const getUptimeMonitorsByUserId = createAsyncThunk(
}
);
+export const updateUptimeMonitor = createAsyncThunk(
+ "monitors/updateMonitor",
+ async (data, thunkApi) => {
+ try {
+ const { authToken, monitor } = data;
+ const res = await axiosInstance.post(
+ `/monitors/edit/${monitor._id}`,
+ monitor,
+ {
+ headers: {
+ Authorization: `Bearer ${authToken}`,
+ "Content-Type": "application/json",
+ },
+ }
+ );
+ return res.data;
+ } catch (error) {
+ if (error.response && error.response.data) {
+ return thunkApi.rejectWithValue(error.response.data);
+ }
+ return thunkApi.rejectWithValue(error.message);
+ }
+ }
+);
+
const uptimeMonitorsSlice = createSlice({
name: "uptimeMonitors",
initialState,
@@ -137,6 +162,25 @@ const uptimeMonitorsSlice = createSlice({
state.msg = action.payload
? action.payload.msg
: "Failed to create uptime monitor";
+ })
+
+ // *****************************************************
+ // update Monitor
+ // *****************************************************
+ .addCase(updateUptimeMonitor.pending, (state) => {
+ state.isLoading = true;
+ })
+ .addCase(updateUptimeMonitor.fulfilled, (state, action) => {
+ state.isLoading = false;
+ state.success = action.payload.success;
+ state.msg = action.payload.msg;
+ })
+ .addCase(updateUptimeMonitor.rejected, (state, action) => {
+ state.isLoading = false;
+ state.success = false;
+ state.msg = action.payload
+ ? action.payload.msg
+ : "Failed to update uptime monitor";
});
},
});
diff --git a/Client/src/Pages/Monitors/Configure/index.jsx b/Client/src/Pages/Monitors/Configure/index.jsx
index 2f694c07c..0aed07500 100644
--- a/Client/src/Pages/Monitors/Configure/index.jsx
+++ b/Client/src/Pages/Monitors/Configure/index.jsx
@@ -4,8 +4,7 @@ import { useDispatch, useSelector } from "react-redux";
import { useEffect, useState } from "react";
import Button from "../../../Components/Button";
import Field from "../../../Components/Inputs/Field";
-import RadioButton from "../../../Components/RadioButton";
-import { Box, MenuItem, Stack, Typography } from "@mui/material";
+import { Box, Stack, Typography } from "@mui/material";
import WestRoundedIcon from "@mui/icons-material/WestRounded";
import GreenCheck from "../../../assets/icons/checkbox-green.svg?react";
import RedCheck from "../../../assets/icons/checkbox-red.svg?react";
@@ -15,6 +14,20 @@ import "./index.css";
import { monitorValidation } from "../../../Validation/validation";
import Select from "../../../Components/Inputs/Select";
import { formatDurationRounded } from "../../../Utils/timeUtils";
+import { updateUptimeMonitor } from "../../../Features/UptimeMonitors/uptimeMonitorsSlice";
+/**
+ * Parses a URL string and returns a URL object.
+ *
+ * @param {string} url - The URL string to parse.
+ * @returns {URL} - The parsed URL object if valid, otherwise an empty string.
+ */
+const parseUrl = (url) => {
+ try {
+ return new URL(url);
+ } catch (error) {
+ return null;
+ }
+};
/**
* Helper function to get duration since last check
@@ -39,6 +52,9 @@ const Configure = () => {
const dispatch = useDispatch();
const { authToken } = useSelector((state) => state.auth);
const { monitors } = useSelector((state) => state.uptimeMonitors);
+ const [monitor, setMonitor] = useState();
+ const [duration, setDuration] = useState(0);
+ const [errors, setErrors] = useState({});
const { monitorId } = useParams();
const idMap = {
@@ -48,26 +64,20 @@ const Configure = () => {
"monitor-checks-ping": "type",
};
- const [config, setConfig] = useState();
- const [monitor, setMonitor] = useState();
- const [errors, setErrors] = useState({});
useEffect(() => {
- const fetchMonitor = () => {
- const data = monitors.find((monitor) => monitor._id === monitorId);
- setConfig(data);
- setMonitor({
- name: data.name,
- url: data.url.replace(/^https?:\/\//, ""),
- type: data.type,
- interval: data.interval / MS_PER_MINUTE,
- });
- };
- fetchMonitor();
- }, [monitorId, authToken]);
+ const data = monitors.find((monitor) => monitor._id === monitorId);
+ setMonitor({
+ ...data,
+ });
+ setDuration(formatDurationRounded(data?.interval));
+ }, [monitorId, authToken, monitors]);
const handleChange = (event, name) => {
- const { value, id } = event.target;
+ let { value, id } = event.target;
if (!name) name = idMap[id];
+ if (name === "interval") {
+ value = value * MS_PER_MINUTE;
+ }
setMonitor((prev) => ({
...prev,
[name]: value,
@@ -90,7 +100,9 @@ const Configure = () => {
const handleSubmit = (event) => {
event.preventDefault();
- // TODO
+ const updatedMonitor = { ...monitor };
+ delete updatedMonitor.checks;
+ dispatch(updateUptimeMonitor({ authToken, monitor: updatedMonitor }));
};
const frequencies = [
@@ -101,6 +113,10 @@ const Configure = () => {
{ _id: 5, name: "5 minutes" },
];
+ // Parse the URL
+ const parsedUrl = parseUrl(monitor?.url);
+ const protocol = parsedUrl?.protocol?.replace(":", "") || "";
+
return (
{
/>
-
-
- Checks to perform
-
- You can always add or remove checks after adding your site.
-
-
-
-
-
-
- {errors["type"] ? (
-
- {errors["type"]}
-
- ) : (
- ""
- )}
-
-
-
{
-
+