- Add basic joi validation to match what's available in BE
- Extract/ refactor the custom alert section to its own function - WIP UI added custom alert section, retain log section and maxreties in advaced setting section - Extend Field component to accomodate for custom alert narrower text field
This commit is contained in:
1 parent
4452cb90e6
commit
63cb4e7f1d
5 files changed
+170
-175
No files matched your search
@@ -1,6 +1,15 @@
|
||||
.field {
|
||||
min-width: 250px;
|
||||
}
|
||||
|
||||
.field-infrastructure-alert {
|
||||
max-width: 100px;
|
||||
}
|
||||
|
||||
.field-infrastructure-alert .MuiInputBase-root:has(input) {
|
||||
height: 34px;
|
||||
}
|
||||
|
||||
.field h3.MuiTypography-root,
|
||||
.field h5.MuiTypography-root,
|
||||
.field input,
|
||||
|
||||
@@ -46,6 +46,7 @@ const Field = forwardRef(
|
||||
error,
|
||||
disabled,
|
||||
hidden,
|
||||
className
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
@@ -56,7 +57,7 @@ const Field = forwardRef(
|
||||
return (
|
||||
<Stack
|
||||
gap={theme.spacing(2)}
|
||||
className={`field field-${type}`}
|
||||
className={`${className ?? `field field-${type}`}`}
|
||||
sx={{
|
||||
"& fieldset": {
|
||||
borderColor: theme.palette.border.dark,
|
||||
@@ -223,6 +224,7 @@ Field.propTypes = {
|
||||
error: PropTypes.string,
|
||||
disabled: PropTypes.bool,
|
||||
hidden: PropTypes.bool,
|
||||
className: PropTypes.string
|
||||
};
|
||||
|
||||
export default Field;
|
||||
@@ -86,7 +86,7 @@ export const getInfrastructureMonitorsByTeamId = createAsyncThunk(
|
||||
const res = await networkService.getMonitorsAndSummaryByTeamId({
|
||||
authToken: token,
|
||||
teamId: user.teamId,
|
||||
types: ["http", "ping"],
|
||||
types: ["hardware"],
|
||||
});
|
||||
return res.data;
|
||||
} catch (error) {
|
||||
@@ -112,6 +112,7 @@ export const updateInfrastructureMonitor = createAsyncThunk(
|
||||
description: monitor.description,
|
||||
interval: monitor.interval,
|
||||
notifications: monitor.notifications,
|
||||
threshold: monitor.threshold
|
||||
};
|
||||
const res = await networkService.updateMonitor({
|
||||
authToken: authToken,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useState } from "react";
|
||||
import { Box, Button, ButtonGroup, Stack, Typography } from "@mui/material";
|
||||
import { Box, Stack, Typography } from "@mui/material";
|
||||
import LoadingButton from "@mui/lab/LoadingButton";
|
||||
import { useSelector, useDispatch } from "react-redux";
|
||||
import { monitorValidation } from "../../../Validation/validation";
|
||||
import { infrastractureMonitorValidation } from "../../../Validation/validation";
|
||||
import {
|
||||
createInfrastructureMonitor,
|
||||
checkInfrastructureEndpointResolution,
|
||||
@@ -12,13 +12,63 @@ import { useTheme } from "@emotion/react";
|
||||
import { createToast } from "../../../Utils/toastUtils";
|
||||
import { logger } from "../../../Utils/Logger";
|
||||
import { ConfigBox } from "../../Monitors/styled";
|
||||
import Radio from "../../../Components/Inputs/Radio";
|
||||
import Field from "../../../Components/Inputs/Field";
|
||||
import Select from "../../../Components/Inputs/Select";
|
||||
import Checkbox from "../../../Components/Inputs/Checkbox";
|
||||
import Breadcrumbs from "../../../Components/Breadcrumbs";
|
||||
|
||||
const CreateInfrastructureMonitor = () => {
|
||||
const CustomAlertStack = ({
|
||||
checkboxId,
|
||||
checkboxLabel,
|
||||
checkboxValue,
|
||||
isChecked,
|
||||
onChange,
|
||||
fieldId,
|
||||
fieldValue,
|
||||
alertUnit,
|
||||
}) => {
|
||||
console.log("fieldValue")
|
||||
console.log(fieldValue)
|
||||
return (
|
||||
<Stack
|
||||
direction={"row"}
|
||||
sx={{
|
||||
width: "50%",
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
>
|
||||
<Box>
|
||||
<Checkbox
|
||||
id={checkboxId}
|
||||
label={checkboxLabel}
|
||||
value={checkboxValue??""}
|
||||
isChecked= {isChecked??false}
|
||||
onChange={onChange}
|
||||
/>
|
||||
</Box>
|
||||
<Stack
|
||||
direction={"row"}
|
||||
sx={{
|
||||
justifyContent: "flex-end",
|
||||
}}
|
||||
>
|
||||
<Field
|
||||
type="number"
|
||||
className="field-infrastructure-alert"
|
||||
id={fieldId}
|
||||
value={fieldValue}
|
||||
></Field>
|
||||
<Typography
|
||||
component="p"
|
||||
m={theme.spacing(3)}
|
||||
>
|
||||
{alertUnit}
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Stack>
|
||||
);}
|
||||
|
||||
const MS_PER_MINUTE = 60000;
|
||||
const { user, authToken } = useSelector((state) => state.auth);
|
||||
const monitorState = useSelector((state) => state.infrastructureMonitor);
|
||||
@@ -30,19 +80,16 @@ const CreateInfrastructureMonitor = () => {
|
||||
"monitor-url": "url",
|
||||
"monitor-name": "name",
|
||||
"monitor-secret": "secret",
|
||||
"monitor-checks-http": "type",
|
||||
"monitor-checks-ping": "type",
|
||||
"notify-email-default": "notification-email",
|
||||
};
|
||||
|
||||
const [infrastructureMonitor, setInfrastructureMonitor] = useState({
|
||||
url: "",
|
||||
name: "",
|
||||
type: "http",
|
||||
notifications: [],
|
||||
interval: 1,
|
||||
threshold: {cpu: "", disk: "", memory: ""}
|
||||
});
|
||||
const [https, setHttps] = useState(true);
|
||||
const [errors, setErrors] = useState({});
|
||||
|
||||
const handleChange = (event, name) => {
|
||||
@@ -80,7 +127,7 @@ const CreateInfrastructureMonitor = () => {
|
||||
[name]: value,
|
||||
}));
|
||||
|
||||
const { error } = monitorValidation.validate(
|
||||
const { error } = infrastractureMonitorValidation.validate(
|
||||
{ [name]: value },
|
||||
{ abortEarly: false }
|
||||
);
|
||||
@@ -98,20 +145,15 @@ const CreateInfrastructureMonitor = () => {
|
||||
event.preventDefault();
|
||||
//obj to submit
|
||||
let form = {
|
||||
url:
|
||||
//preprending protocol for url
|
||||
infrastructureMonitor.type === "http"
|
||||
? `http${https ? "s" : ""}://` + infrastructureMonitor.url
|
||||
: infrastructureMonitor.url,
|
||||
url:infrastructureMonitor.url,
|
||||
name:
|
||||
infrastructureMonitor.name === ""
|
||||
? infrastructureMonitor.url
|
||||
: infrastructureMonitor.name,
|
||||
type: infrastructureMonitor.type,
|
||||
interval: infrastructureMonitor.interval * MS_PER_MINUTE,
|
||||
};
|
||||
|
||||
const { error } = monitorValidation.validate(form, {
|
||||
const { error } =infrastractureMonitorValidation.validate(form, {
|
||||
abortEarly: false,
|
||||
});
|
||||
|
||||
@@ -287,166 +329,75 @@ const CreateInfrastructureMonitor = () => {
|
||||
</Typography>
|
||||
</Box>
|
||||
<Stack gap={theme.spacing(6)}>
|
||||
<Stack
|
||||
direction={"row"}
|
||||
sx={{
|
||||
justifyContent: "space-between",
|
||||
width: "75%",
|
||||
}}
|
||||
>
|
||||
<Box>
|
||||
<Checkbox
|
||||
id="customize-cpu"
|
||||
label={`CPU`}
|
||||
value={true}
|
||||
onChange={(event) => handleChange(event)}
|
||||
/>
|
||||
</Box>
|
||||
<Stack
|
||||
direction={"row"}
|
||||
sx={{
|
||||
justifyContent: "flex-end",
|
||||
}}
|
||||
>
|
||||
<Box>
|
||||
<Field type="text"></Field>
|
||||
</Box>
|
||||
<Box>
|
||||
<Typography
|
||||
component="p"
|
||||
m={theme.spacing(3)}
|
||||
>
|
||||
%
|
||||
</Typography>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Stack>
|
||||
<Stack
|
||||
direction={"row"}
|
||||
sx={{
|
||||
width: "75%",
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
>
|
||||
<Box>
|
||||
<Checkbox
|
||||
id="customize-memory"
|
||||
label={`Memory`}
|
||||
value={true}
|
||||
onChange={(event) => handleChange(event)}
|
||||
/>
|
||||
</Box>
|
||||
<Stack
|
||||
direction={"row"}
|
||||
sx={{
|
||||
justifyContent: "flex-end",
|
||||
}}
|
||||
>
|
||||
<Field type="text"></Field>
|
||||
<Typography
|
||||
component="p"
|
||||
m={theme.spacing(3)}
|
||||
>
|
||||
%
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
<Stack
|
||||
direction={"row"}
|
||||
sx={{
|
||||
width: "75%",
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
>
|
||||
<Box>
|
||||
<Checkbox
|
||||
id="customize-disk"
|
||||
label={`Disk`}
|
||||
value={user?.email}
|
||||
onChange={(event) => handleChange(event)}
|
||||
/>
|
||||
</Box>
|
||||
<Stack
|
||||
direction={"row"}
|
||||
sx={{
|
||||
justifyContent: "flex-end",
|
||||
}}
|
||||
>
|
||||
<Field type="text"></Field>
|
||||
<Typography
|
||||
component="p"
|
||||
m={theme.spacing(3)}
|
||||
>
|
||||
%
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
<Stack
|
||||
direction={"row"}
|
||||
sx={{
|
||||
width: "75%",
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
>
|
||||
<Box>
|
||||
<Checkbox
|
||||
id="customize-temparature"
|
||||
label={`Temparature`}
|
||||
value={user?.email}
|
||||
onChange={(event) => handleChange(event)}
|
||||
/>
|
||||
</Box>
|
||||
<Stack
|
||||
direction={"row"}
|
||||
sx={{
|
||||
justifyContent: "flex-end",
|
||||
}}
|
||||
>
|
||||
<Field type="text"></Field>
|
||||
<Typography
|
||||
component="p"
|
||||
m={theme.spacing(3)}
|
||||
>
|
||||
°C
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
<Stack
|
||||
direction={"row"}
|
||||
sx={{
|
||||
width: "75%",
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
>
|
||||
<Box>
|
||||
<Checkbox
|
||||
id="customize-systemload"
|
||||
label={`System load`}
|
||||
value={user?.email}
|
||||
onChange={(event) => handleChange(event)}
|
||||
/>
|
||||
</Box>
|
||||
<Stack
|
||||
direction={"row"}
|
||||
sx={{
|
||||
justifyContent: "flex-end",
|
||||
}}
|
||||
>
|
||||
<Field type="text"></Field>
|
||||
<Typography
|
||||
component="p"
|
||||
m={theme.spacing(3)}
|
||||
>
|
||||
%
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Stack>
|
||||
<CustomAlertStack
|
||||
checkboxId="customize-cpu"
|
||||
checkboxLabel="CPU"
|
||||
checkboxValue={""}
|
||||
fieldId={"usage_cpu"}
|
||||
fieldValue={infrastructureMonitor.threshold['cpu']??""}
|
||||
onChange={(event) => handleChange(event)}
|
||||
alertUnit="%"
|
||||
/>
|
||||
<CustomAlertStack
|
||||
checkboxId="customize-memory"
|
||||
checkboxLabel="Memory"
|
||||
checkboxValue={""}
|
||||
fieldId={"usage_memory"}
|
||||
fieldValue={infrastructureMonitor.threshold['memory']??""}
|
||||
onChange={(event) => handleChange(event)}
|
||||
alertUnit="%"
|
||||
/>
|
||||
<CustomAlertStack
|
||||
checkboxId="customize-disk"
|
||||
checkboxLabel="Disk"
|
||||
checkboxValue={""}
|
||||
fieldId={"usage_disk"}
|
||||
fieldValue={infrastructureMonitor.threshold['disk']??""}
|
||||
onChange={(event) => handleChange(event)}
|
||||
alertUnit="%"
|
||||
/>
|
||||
{/* <CustomAlertStack
|
||||
checkboxId="customize-temperature"
|
||||
checkboxLabel="Temperature"
|
||||
checkboxValue={true}
|
||||
onChange={(event) => handleChange(event)}
|
||||
alertUnit="°C"
|
||||
/>
|
||||
<CustomAlertStack
|
||||
checkboxId="customize-systemload"
|
||||
checkboxLabel="System load"
|
||||
checkboxValue={true}
|
||||
onChange={(event) => handleChange(event)}
|
||||
alertUnit="%"
|
||||
/>
|
||||
<CustomAlertStack
|
||||
checkboxId="customize-swap"
|
||||
checkboxLabel="Swap used"
|
||||
checkboxValue={""}
|
||||
onChange={(event) => handleChange(event)}
|
||||
alertUnit="%"
|
||||
/> */}
|
||||
</Stack>
|
||||
</ConfigBox>
|
||||
|
||||
<ConfigBox>
|
||||
<Box>
|
||||
<Typography component="h2">Logging retention</Typography>
|
||||
<Typography component="p">
|
||||
Configure how logn logs are stored. After this period, the Uptime Manager
|
||||
will start deleting oldest data.
|
||||
</Typography>
|
||||
</Box>
|
||||
{/* <Stack gap={theme.spacing(6)}>
|
||||
<CustomAlertStack
|
||||
checkboxId="retain-log"
|
||||
checkboxLabel="Retain data for"
|
||||
checkboxValue={""}
|
||||
fieldId={"retries_max"}
|
||||
onChange={(event) => handleChange(event)}
|
||||
alertUnit="days"
|
||||
/>
|
||||
</Stack> */}
|
||||
</ConfigBox>
|
||||
<ConfigBox>
|
||||
<Box>
|
||||
<Typography component="h2">Advanced settings</Typography>
|
||||
@@ -459,6 +410,14 @@ const CreateInfrastructureMonitor = () => {
|
||||
onChange={(event) => handleChange(event, "interval")}
|
||||
items={frequencies}
|
||||
/>
|
||||
<Field
|
||||
type={"text"}
|
||||
id="monitor-retries"
|
||||
label="Maximum retries before the service is marked as down"
|
||||
value={infrastructureMonitor.url}
|
||||
onChange={handleChange}
|
||||
error={errors["url"]}
|
||||
/>
|
||||
</Stack>
|
||||
</ConfigBox>
|
||||
<Stack
|
||||
|
||||
@@ -173,6 +173,29 @@ const advancedSettingsValidation = joi.object({
|
||||
pagespeedApiKey: joi.string().allow(""),
|
||||
});
|
||||
|
||||
const infrastractureMonitorValidation = 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.",
|
||||
}),
|
||||
name: joi.string().trim().max(50).allow("").messages({
|
||||
"string.max": "This field should not exceed the 50 characters limit.",
|
||||
}),
|
||||
type: joi.string().trim().messages({ "string.empty": "This field is required." }),
|
||||
usage_cpu: joi.number(),
|
||||
usage_memory: joi.number(),
|
||||
usage_disk: joi.number(),
|
||||
// usage_temperature: joi.number().messages({
|
||||
// "number.base": "Temperature must be a number.",
|
||||
// }),
|
||||
// usage_system: joi.number().messages({
|
||||
// "number.base": "System load must be a number.",
|
||||
// }),
|
||||
// usage_swap: joi.number().messages({
|
||||
// "number.base": "Swap used must be a number.",
|
||||
// }),
|
||||
});
|
||||
|
||||
export {
|
||||
credentials,
|
||||
imageValidation,
|
||||
@@ -180,4 +203,5 @@ export {
|
||||
settingsValidation,
|
||||
maintenanceWindowValidation,
|
||||
advancedSettingsValidation,
|
||||
infrastractureMonitorValidation
|
||||
};
|
||||
Reference in new issue
Block a user