Files
Checkmate/Client/src/Pages/CreateNewMonitor/index.jsx
T

454 lines
15 KiB
React
Raw Normal View History

2024-06-25 13:22:28 +03:30
import "./index.css";
2024-06-18 22:39:58 +03:30
import ConfigBox from "../../Components/ConfigBox";
import FlexibileTextField from "../../Components/TextFields/Flexibile/FlexibileTextField";
2024-06-25 13:22:28 +03:30
import React, { useState } from "react";
2024-06-20 19:53:08 +03:30
import RadioButton from "../../Components/RadioButton";
2024-06-25 13:22:28 +03:30
import CustomizableCheckBox from "../../Components/Checkbox/CustomizableCheckbox";
import Button from "../../Components/Button";
import { Box, MenuItem, Select, Stack, Typography } from "@mui/material";
import { useSelector, useDispatch } from "react-redux";
2024-06-27 17:26:00 -04:00
import { createMonitorValidation } from "../../Validation/validation";
import { createMonitor } from "../../Features/Monitors/monitorsSlice";
import { useNavigate } from "react-router-dom";
import { useTheme } from "@emotion/react";
2024-07-07 18:25:03 -04:00
import WestRoundedIcon from "@mui/icons-material/WestRounded";
2024-06-18 22:39:58 +03:30
const CreateNewMonitor = () => {
const MS_PER_MINUTE = 60000;
const { user, authToken } = useSelector((state) => state.auth);
const dispatch = useDispatch();
const navigate = useNavigate();
const theme = useTheme();
2024-06-27 17:26:00 -04:00
const [errors, setErrors] = useState({});
2024-06-27 16:29:50 -04:00
//General Settings Form
const [generalSettings, setGeneralSettings] = useState({ url: "", name: "" });
//Checks Form
2024-06-27 17:26:00 -04:00
const [checks, setChecks] = useState({
type: "",
// port: ""
2024-06-27 16:29:50 -04:00
});
2024-06-27 17:26:00 -04:00
//Incidents Form
// const [notifications, setNotifications] = useState({
// viaSms: false,
// viaEmail: false,
// viaOther: false,
// email: "",
// });
2024-06-27 16:29:50 -04:00
//Advanced Settings Form
const [advancedSettings, setAdvancedSettings] = useState({
frequency: 1,
2024-06-27 17:26:00 -04:00
// retries: "",
// codes: "",
// redirects: "",
2024-06-27 16:29:50 -04:00
});
//Proxy Settings Form
2024-06-27 17:26:00 -04:00
// const [proxy, setProxy] = useState({
// enabled: false,
// protocol: "",
// address: "",
// proxy_port: "",
// });
2024-06-26 21:56:56 +03:30
2024-06-27 16:29:50 -04:00
const handleChange = (event, id, setState, checkbox) => {
const { value } = event.target;
setState((prev) => ({
...prev,
[id]: checkbox ? true : value,
}));
2024-06-27 17:26:00 -04:00
const validation = createMonitorValidation.validate(
{ [id]: value },
{ abortEarly: false }
);
setErrors((prev) => {
const updatedErrors = { ...prev };
if (validation.error) {
updatedErrors[id] = validation.error.details[0].message;
} else {
delete updatedErrors[id];
}
return updatedErrors;
});
2024-06-26 21:56:56 +03:30
};
2024-06-27 17:26:00 -04:00
// const handleCheck = (id, setState) => {
// setState((prev) => ({
// ...prev,
// [id]: !prev[id],
// }));
// };
2024-06-26 21:56:56 +03:30
const handleCreateNewMonitor = async (event) => {
2024-06-27 17:26:00 -04:00
event.preventDefault();
//obj to submit
let monitor = {
2024-06-27 17:26:00 -04:00
...generalSettings,
...checks,
};
const { error } = createMonitorValidation.validate(monitor, {
abortEarly: false,
});
if (error) {
const newErrors = {};
error.details.forEach((err) => {
newErrors[err.path[0]] = err.message;
});
setErrors(newErrors);
} else {
monitor = {
...monitor,
description: monitor.name,
userId: user._id,
// ...advancedSettings, // TODO frequency should be interval, then we can use spread
interval: advancedSettings.frequency * MS_PER_MINUTE,
};
try {
const action = await dispatch(createMonitor({ authToken, monitor }));
if (action.meta.requestStatus === "fulfilled") {
navigate("/monitors");
}
} catch (error) {
alert(error);
}
2024-06-27 17:26:00 -04:00
}
};
2024-06-27 16:44:56 -04:00
2024-06-27 17:26:00 -04:00
//select values
// const ports = ["Port 1", "Port 2", "Port 3"];
2024-06-27 16:29:50 -04:00
const frequencies = [1, 2, 3, 4, 5];
2024-06-25 13:22:28 +03:30
2024-06-18 22:39:58 +03:30
return (
<form
className="create-monitor-form"
onSubmit={handleCreateNewMonitor}
noValidate
spellCheck="false"
style={{
maxWidth: "1200px",
flex: 1,
padding: `${theme.content.pY} ${theme.content.pX}`,
}}
>
2024-07-07 18:25:03 -04:00
<Button
level="tertiary"
label="Back"
img={<WestRoundedIcon />}
onClick={() => navigate("/monitors")}
sx={{
backgroundColor: "#f4f4f4",
mb: theme.gap.medium,
px: theme.gap.ml,
"& svg.MuiSvgIcon-root": {
pr: theme.gap.small,
},
}}
/>
<Typography component="h1">Create new monitor</Typography>
2024-06-18 22:39:58 +03:30
<div className="monitors-gaps-medium"></div>
<ConfigBox
leftLayout={
<Stack gap={theme.gap.small}>
<Typography component="h2">General settings</Typography>
<Typography component="p">
2024-06-18 22:39:58 +03:30
Here you can select the URL of the host, together with the type of
monitor.
</Typography>
</Stack>
2024-06-18 22:39:58 +03:30
}
rightLayout={
<Stack gap={theme.gap.xl}>
2024-06-18 22:39:58 +03:30
<FlexibileTextField
2024-06-27 16:29:50 -04:00
id="monitor-url"
2024-06-18 22:39:58 +03:30
title="URL to monitor"
type="url"
placeholder="https://google.com"
2024-06-27 16:29:50 -04:00
value={generalSettings.url}
onChange={(event) =>
handleChange(event, "url", setGeneralSettings)
}
error={errors["url"]}
2024-06-18 22:39:58 +03:30
/>
<FlexibileTextField
2024-06-27 16:29:50 -04:00
id="monitor-name"
title={
<>
Friendly name <span>(optional)</span>
</>
}
2024-06-18 22:39:58 +03:30
type="text"
placeholder="Google"
2024-06-27 16:29:50 -04:00
value={generalSettings.name}
onChange={(event) =>
handleChange(event, "name", setGeneralSettings)
}
error={errors["name"]}
2024-06-18 22:39:58 +03:30
/>
</Stack>
2024-06-18 22:39:58 +03:30
}
/>
<div className="monitors-gaps-medium"></div>
<div className="monitors-gaps-medium"></div>
<ConfigBox
leftLayout={
<Stack gap={theme.gap.small}>
<Typography component="h2">Checks to perform</Typography>
<Typography component="p">
2024-06-18 22:39:58 +03:30
You can always add or remove checks after adding your site.
</Typography>
</Stack>
2024-06-18 22:39:58 +03:30
}
2024-06-20 19:53:08 +03:30
rightLayout={
<Stack gap={theme.gap.large}>
2024-06-20 19:53:08 +03:30
<RadioButton
2024-06-27 16:29:50 -04:00
id="monitor-checks-http"
2024-06-20 19:53:08 +03:30
title="HTTP/website monitoring"
desc="Use HTTP(s) to monitor your website or API endpoint."
size="small"
2024-06-25 13:22:28 +03:30
value="http"
2024-06-27 17:26:00 -04:00
checked={checks.type === "http"}
onChange={(event) => handleChange(event, "type", setChecks)}
2024-06-20 19:53:08 +03:30
/>
<RadioButton
2024-06-27 16:29:50 -04:00
id="monitor-checks-ping"
2024-06-20 19:53:08 +03:30
title="Ping monitoring"
desc="Check whether your server is available or not."
size="small"
2024-06-25 13:22:28 +03:30
value="ping"
2024-06-27 17:26:00 -04:00
checked={checks.type === "ping"}
onChange={(event) => handleChange(event, "type", setChecks)}
2024-06-20 19:53:08 +03:30
/>
2024-06-27 16:44:56 -04:00
{/* TODO */}
{/* <RadioButton
2024-06-27 16:29:50 -04:00
id="monitor-checks-port"
2024-06-20 19:53:08 +03:30
title="Port monitoring"
desc="Monitor a specific service on your server."
2024-06-25 13:22:28 +03:30
value="port"
2024-06-27 17:26:00 -04:00
checked={checks.type === "port"}
onChange={(event) => handleChange(event, "type", setChecks)}
2024-06-20 19:53:08 +03:30
/>
2024-06-26 21:56:56 +03:30
<div className="monitors-gaps-small-plus"></div>
2024-06-25 13:22:28 +03:30
<div className="monitors-dropdown-holder">
2024-06-27 16:29:50 -04:00
<Select
id="monitor-ports"
value={checks.port || "placeholder"}
inputProps={{ id: "monitor-ports-select" }}
onChange={(event) => handleChange(event, "port", setChecks)}
>
<MenuItem id="port-placeholder" value="placeholder">
Select a port to check
</MenuItem>
{ports.map((port, index) => (
<MenuItem key={`port-${index}`} value={port}>
{port}
</MenuItem>
))}
</Select>
2024-06-27 16:44:56 -04:00
</div> */}
<Box className="error-container">
{errors["type"] ? (
<Typography component="p" className="input-error">
{errors["type"]}
</Typography>
) : (
""
)}
</Box>
</Stack>
2024-06-20 19:53:08 +03:30
}
2024-06-18 22:39:58 +03:30
/>
2024-06-27 16:44:56 -04:00
{/* TODO */}
{/* <div className="monitors-gaps-medium"></div>
2024-06-18 22:39:58 +03:30
<div className="monitors-gaps-medium"></div>
<ConfigBox
leftLayout={
<div className="config-box-desc">
<div className="config-box-desc-title">Incident notifications</div>
<div className="config-box-desc-text">
When there is an incident, notify users.
</div>
</div>
}
2024-06-25 13:22:28 +03:30
rightLayout={
<div className="incident-notif-config">
<div className="incident-notif-config-title">
When there is a new incident,
</div>
<div className="monitors-gaps-medium"></div>
<div className="incident-notif-config-checks">
<CustomizableCheckBox
2024-06-27 16:29:50 -04:00
id="monitor-notify-sms"
2024-06-25 13:22:28 +03:30
title="Notify via SMS (to be implemented)"
2024-06-27 16:29:50 -04:00
isChecked={notifications.viaSms}
handleChange={() => handleCheck("viaSms", setNotifications)}
2024-06-25 13:22:28 +03:30
/>
<div className="monitors-gaps-medium"></div>
<CustomizableCheckBox
2024-06-27 16:29:50 -04:00
id="monitor-notify-email"
2024-06-25 13:22:28 +03:30
title="Notify via email (to current email address)"
2024-06-27 16:29:50 -04:00
isChecked={notifications.viaEmail}
handleChange={() => handleCheck("viaEmail", setNotifications)}
2024-06-25 13:22:28 +03:30
/>
<div className="monitors-gaps-medium"></div>
<CustomizableCheckBox
2024-06-27 16:29:50 -04:00
id="monitor-notify-other"
2024-06-25 13:22:28 +03:30
title="Notify via email (to another email address below)"
2024-06-27 16:29:50 -04:00
isChecked={notifications.viaOther}
handleChange={() => handleCheck("viaOther", setNotifications)}
2024-06-25 13:22:28 +03:30
/>
<div className="monitors-gaps-small-plus"></div>
<div className="monitors-dropdown-holder">
<FlexibileTextField
2024-06-27 16:29:50 -04:00
id="monitor-notify-other-email"
2024-06-25 13:22:28 +03:30
placeholder="notifications@gmail.com"
type="email"
2024-06-27 16:29:50 -04:00
value={notifications.email}
onChange={(event) =>
handleChange(event, "email", setNotifications)
}
2024-06-25 13:22:28 +03:30
/>
</div>
</div>
</div>
}
2024-06-27 16:44:56 -04:00
/> */}
2024-06-18 22:39:58 +03:30
<div className="monitors-gaps-medium"></div>
<div className="monitors-gaps-medium"></div>
<ConfigBox
leftLayout={
<Stack gap={theme.gap.small}>
<Typography component="h2">Advanced settings</Typography>
</Stack>
2024-06-18 22:39:58 +03:30
}
2024-06-25 13:22:28 +03:30
rightLayout={
<Stack gap={theme.gap.large}>
{/* TODO - refactor select component */}
<Box>
<Typography component="p" mb={theme.gap.small}>
Check frequency
</Typography>
<Select
id="monitor-frequencies"
value={advancedSettings.frequency || 1}
inputProps={{ id: "monitor-frequencies-select" }}
onChange={(event) =>
handleChange(event, "frequency", setAdvancedSettings)
}
MenuProps={{
PaperProps: {
style: {
2024-07-07 18:25:03 -04:00
marginTop: "10px",
},
},
}}
>
{frequencies.map((freq) => (
<MenuItem
key={`port-${freq}`}
value={freq}
sx={{
fontSize: "13px",
borderRadius: `${theme.shape.borderRadius}px`,
margin: "5px",
}}
>
{freq} {freq === 1 ? "minute" : "minutes"}
</MenuItem>
))}
</Select>
</Box>
2024-06-27 16:44:56 -04:00
{/* TODO */}
{/* <FlexibileTextField
2024-06-27 16:29:50 -04:00
id="monitor-settings-retries"
title="Maximum retries before the service is marked as down"
2024-06-25 13:22:28 +03:30
type="number"
2024-06-27 16:29:50 -04:00
value={advancedSettings.retries}
onChange={(event) =>
handleChange(event, "retries", setAdvancedSettings)
}
2024-06-25 13:22:28 +03:30
/>
<div className="monitors-gaps-medium"></div>
<FlexibileTextField
2024-06-27 16:29:50 -04:00
id="monitor-settings-codes"
title="Accepted status codes"
2024-06-25 13:22:28 +03:30
type="number"
2024-06-27 16:29:50 -04:00
value={advancedSettings.codes}
onChange={(event) =>
handleChange(event, "codes", setAdvancedSettings)
}
2024-06-25 13:22:28 +03:30
/>
<div className="monitors-gaps-medium"></div>
<FlexibileTextField
2024-06-27 16:29:50 -04:00
id="monitor-settings-redirects"
title="Maximum redirects"
2024-06-25 13:22:28 +03:30
type="number"
2024-06-27 16:29:50 -04:00
value={advancedSettings.redirects}
onChange={(event) =>
handleChange(event, "redirects", setAdvancedSettings)
}
2024-06-27 16:44:56 -04:00
/> */}
</Stack>
2024-06-25 13:22:28 +03:30
}
2024-06-18 22:39:58 +03:30
/>
2024-06-27 16:44:56 -04:00
{/* TODO */}
{/* <div className="monitors-gaps-medium"></div>
2024-06-18 22:39:58 +03:30
<div className="monitors-gaps-medium"></div>
<ConfigBox
leftLayout={
<div className="config-box-desc">
<div className="config-box-desc-title">Proxy settings</div>
</div>
}
2024-06-25 13:22:28 +03:30
rightLayout={
<div className="proxy-setting-config">
<CustomizableCheckBox
2024-06-27 16:29:50 -04:00
id="monitor-proxy-enable"
2024-06-25 13:22:28 +03:30
title="Enable proxy"
2024-06-27 16:29:50 -04:00
isChecked={proxy.enabled}
handleChange={() => handleCheck("enabled", setProxy)}
2024-06-25 13:22:28 +03:30
/>
<div className="monitors-gaps-medium"></div>
2024-06-27 16:29:50 -04:00
<FlexibileTextField
id="monitor-proxy-protocol"
title="Proxy protocol"
value={proxy.protocol}
onChange={(event) => handleChange(event, "protocol", setProxy)}
/>
2024-06-25 13:22:28 +03:30
<div className="monitors-gaps-medium"></div>
2024-06-27 16:29:50 -04:00
<FlexibileTextField
id="monitor-proxy-address"
title="Proxy address"
value={proxy.address}
onChange={(event) => handleChange(event, "address", setProxy)}
/>
2024-06-25 13:22:28 +03:30
<div className="monitors-gaps-medium"></div>
2024-06-27 16:29:50 -04:00
<FlexibileTextField
id="monitor-proxy-port"
title="Proxy port"
value={proxy.proxy_port}
onChange={(event) => handleChange(event, "proxy_port", setProxy)}
/>
2024-06-25 13:22:28 +03:30
</div>
}
2024-06-27 16:44:56 -04:00
/> */}
2024-06-25 13:22:28 +03:30
<div className="monitors-gaps-medium"></div>
<div className="monitors-gaps-small"></div>
<div className="monitors-create-button-holder">
<Button
2024-06-26 21:56:56 +03:30
id="create-new-monitor-btn"
2024-06-25 13:22:28 +03:30
level="primary"
label="Create new monitor"
sx={{ width: "210px", fontSize: "var(--env-var-font-size-medium)" }}
2024-06-27 17:26:00 -04:00
onClick={handleCreateNewMonitor}
disabled={Object.keys(errors).length !== 0 && true}
2024-06-25 13:22:28 +03:30
/>
</div>
2024-06-27 16:44:56 -04:00
</form>
2024-06-18 22:39:58 +03:30
);
};
export default CreateNewMonitor;