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 {
createInfrastructureMonitor,
checkInfrastructureEndpointResolution,
} from "../../../Features/InfrastructureMonitors/infrastructureMonitorsSlice";
import { useNavigate } from "react-router-dom";
import { useTheme } from "@emotion/react";
import { createToast } from "../../../Utils/toastUtils";
import { logger } from "../../../Utils/Logger";
import { ConfigBox } from "../../Monitors/styled";
import Field from "../../../Components/Inputs/Field";
import Select from "../../../Components/Inputs/Select";
import Checkbox from "../../../Components/Inputs/Checkbox";
import Breadcrumbs from "../../../Components/Breadcrumbs";
import { buildErrors, hasValidationErrors } from "../../../Validation/error";
const CreateInfrastructureMonitor = () => {
const [infrastructureMonitor, setInfrastructureMonitor] = useState({
url: "",
name: "",
notifications: [],
interval: 15,
cpu: false,
usage_cpu: "",
memory: false,
usage_memory: "",
disk: false,
usage_disk: "",
secret: "",
});
const MS_PER_MINUTE = 60000;
const THRESHOLD_FIELD_PREFIX = "usage_"
const { user, authToken } = useSelector((state) => state.auth);
const monitorState = useSelector((state) => state.infrastructureMonitor);
const dispatch = useDispatch();
const navigate = useNavigate();
const theme = useTheme();
const idMap = {
"notify-email-default": "notification-email",
};
const [errors, setErrors] = useState({});
const CustomAlertStack = ({
checkboxId,
checkboxLabel,
fieldId,
alertUnit,
onChange,
onBlur,
}) => (
{alertUnit}
);
const handleCustomAlertCheckChange = (event) => {
const { value, id } = event.target;
setInfrastructureMonitor((prev) => {
const newState = {
[id]: prev[id] == undefined && value == "on" ? true : !prev[id],
};
return {
...prev,
...newState,
[`${THRESHOLD_FIELD_PREFIX}${id}`]: newState[id]
? prev[`${THRESHOLD_FIELD_PREFIX}${id}`]
: "",
};
});
// Remove the error if unchecked
setErrors((prev) => {
return buildErrors(prev, [`${THRESHOLD_FIELD_PREFIX}${id}`]);
});
};
const handleBlur = (event, appenedID) => {
event.preventDefault();
const { value, id } = event.target;
if (id?.startsWith("notify-email-")) return;
const { error } = infrastractureMonitorValidation.validate(
{ [id ?? appenedID]: value },
{
abortEarly: false,
}
);
setErrors((prev) => {
return buildErrors(prev, id ?? appenedID, error);
});
};
const handleChange = (event, appendedId) => {
event.preventDefault();
const { value, id } = event.target;
let name = appendedId ?? idMap[id] ?? id;
if (name.includes("notification-")) {
name = name.replace("notification-", "");
let hasNotif = infrastructureMonitor.notifications.some(
(notification) => notification.type === name
);
setInfrastructureMonitor((prev) => {
const notifs = [...prev.notifications];
if (hasNotif) {
return {
...prev,
notifications: notifs.filter((notif) => notif.type !== name),
};
} else {
return {
...prev,
notifications: [
...notifs,
name === "email"
? { type: name, address: value }
: // TODO - phone number
{ type: name, phone: value },
],
};
}
});
} else {
setInfrastructureMonitor((prev) => ({
...prev,
[name]: value,
}));
}
};
const generatePayload = (form) => {
let thresholds = {};
Object.keys(form)
.filter((k) => k.startsWith(`${THRESHOLD_FIELD_PREFIX}`))
.map((k) => {
if (form[k]) thresholds[k] = form[k];
delete form[k];
delete form[k.substring(`${THRESHOLD_FIELD_PREFIX}`.length)];
});
form = {
...form,
description: form.name,
teamId: user.teamId,
userId: user._id,
type: "hardware",
notifications: infrastructureMonitor.notifications,
thresholds,
};
return form;
};
const handleCreateInfrastructureMonitor = async (event) => {
event.preventDefault();
let form = {
...infrastructureMonitor,
name:
infrastructureMonitor.name === ""
? infrastructureMonitor.url
: infrastructureMonitor.name,
interval: infrastructureMonitor.interval * MS_PER_MINUTE,
};
delete form.notifications;
if (hasValidationErrors(form, infrastractureMonitorValidation, setErrors)) {
return;
} else {
const checkEndpointAction = dispatch(
checkInfrastructureEndpointResolution({ authToken, monitorURL: form.url })
);
if (checkEndpointAction.meta.requestStatus === "rejected") {
createToast({
body: "The endpoint you entered doesn't resolve. Check the URL again.",
});
setErrors({ url: "The entered URL is not reachable." });
return;
}
const action = dispatch(
createInfrastructureMonitor({ authToken, monitor: generatePayload(form) })
);
if (action.meta.requestStatus === "fulfilled") {
createToast({ body: "Infrastructure monitor created successfully!" });
navigate("/infrastructure-monitors/create");
} else {
createToast({ body: "Failed to create monitor." });
}
}
};
//select values
const frequencies = [
{ _id: 15, name: "15 seconds" },
{ _id: 30, name: "30 seconds" },
{ _id: 60, name: "1 minute" },
{ _id: 120, name: "2 minutes" },
{ _id: 300, name: "5 minutes" },
{ _id: 600, name: "10 minutes" },
];
return (
Create your{" "}
infrastructure monitor
General settings
Here you can select the URL of the host, together with the type of monitor.
Incident notifications
When there is an incident, notify users.
When there is a new incident,
notification.type === "email"
)}
value={user?.email}
onChange={(e) => handleChange(e)}
onBlur={handleBlur}
/>
logger.warn("disabled")}
onBlur={handleBlur}
isDisabled={true}
/>
logger.warn("disabled")}
onBlur={handleBlur}
/>
You can separate multiple emails with a comma
Customize alerts
Send a notification to user(s) When the theresholds exceed a certain number
or percentage.
{/*
*/}
Logging retention
Configure how logs are stored. After this period, the Uptime Manager
will start deleting oldest data.
{/*
*/}
Advanced settings
Create infrastructure monitor
);
};
export default CreateInfrastructureMonitor;