mirror of
https://github.com/bluewave-labs/Checkmate.git
synced 2026-05-07 17:20:06 -05:00
Implement setting TTL on FE
This commit is contained in:
@@ -67,7 +67,7 @@ export const update = createAsyncThunk(
|
||||
fd.append("deleteProfileImage", form.deleteProfileImage);
|
||||
|
||||
const res = await networkService.updateUser(token, user._id, fd);
|
||||
|
||||
console.log(res);
|
||||
return res.data;
|
||||
} catch (error) {
|
||||
if (error.response && error.response.data) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { Box, Stack, styled, Typography } from "@mui/material";
|
||||
import { Box, Stack, Typography } from "@mui/material";
|
||||
import Field from "../../Components/Inputs/Field";
|
||||
import Link from "../../Components/Link";
|
||||
import Select from "../../Components/Inputs/Select";
|
||||
@@ -12,20 +12,92 @@ import {
|
||||
addDemoMonitors,
|
||||
deleteAllMonitors,
|
||||
} from "../../Features/UptimeMonitors/uptimeMonitorsSlice";
|
||||
import { update } from "../../Features/Auth/authSlice";
|
||||
import PropTypes from "prop-types";
|
||||
import LoadingButton from "@mui/lab/LoadingButton";
|
||||
import { setTimezone } from "../../Features/UI/uiSlice";
|
||||
import timezones from "../../Utils/timezones.json";
|
||||
import { useState } from "react";
|
||||
import { ConfigBox } from "./styled";
|
||||
import { networkService } from "../../main";
|
||||
import { settingsValidation } from "../../Validation/validation";
|
||||
|
||||
const SECONDS_PER_DAY = 86400;
|
||||
|
||||
const Settings = ({ isAdmin }) => {
|
||||
const theme = useTheme();
|
||||
const { user, authToken } = useSelector((state) => state.auth);
|
||||
const { checkTTL } = user;
|
||||
const { isLoading } = useSelector((state) => state.uptimeMonitors);
|
||||
const { isLoading: authIsLoading } = useSelector((state) => state.auth);
|
||||
const { timezone } = useSelector((state) => state.ui);
|
||||
|
||||
const [checksIsLoading, setChecksIsLoading] = useState(false);
|
||||
const [form, setForm] = useState({
|
||||
ttl: (checkTTL / SECONDS_PER_DAY).toString(),
|
||||
});
|
||||
const [errors, setErrors] = useState({});
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const handleChange = (event) => {
|
||||
const { value, id } = event.target;
|
||||
const { error } = settingsValidation.validate(
|
||||
{ [id]: value },
|
||||
{
|
||||
abortEarly: false,
|
||||
}
|
||||
);
|
||||
if (!error || error.details.length === 0) {
|
||||
setErrors({});
|
||||
} else {
|
||||
const newErrors = {};
|
||||
error.details.forEach((err) => {
|
||||
newErrors[err.path[0]] = err.message;
|
||||
});
|
||||
setErrors(newErrors);
|
||||
console.log(newErrors);
|
||||
logger.error("Validation errors:", error.details);
|
||||
}
|
||||
let inputValue = value;
|
||||
id === "ttl" && (inputValue = value.replace(/[^0-9]/g, ""));
|
||||
setForm((prev) => ({
|
||||
...prev,
|
||||
[id]: inputValue,
|
||||
}));
|
||||
};
|
||||
|
||||
// TODO Handle saving
|
||||
const handleSave = async () => {};
|
||||
const handleSave = async () => {
|
||||
try {
|
||||
setChecksIsLoading(true);
|
||||
await networkService.updateChecksTTL(authToken, form.ttl);
|
||||
const updatedUser = { ...user, checkTTL: form.ttl };
|
||||
const action = await dispatch(
|
||||
update({ authToken, localData: updatedUser })
|
||||
);
|
||||
if (action.payload.success) {
|
||||
createToast({
|
||||
body: "Settings saved successfully",
|
||||
});
|
||||
} else {
|
||||
if (action.payload) {
|
||||
// dispatch errors
|
||||
createToast({
|
||||
body: action.payload.msg,
|
||||
});
|
||||
} else {
|
||||
// unknown errors
|
||||
createToast({
|
||||
body: "Unknown error.",
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
createToast({ body: "Failed to save settings" });
|
||||
} finally {
|
||||
setChecksIsLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleClearStats = async () => {
|
||||
try {
|
||||
@@ -72,33 +144,6 @@ const Settings = ({ isAdmin }) => {
|
||||
}
|
||||
};
|
||||
|
||||
const ConfigBox = styled("div")({
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
gap: theme.spacing(20),
|
||||
paddingTop: theme.spacing(12),
|
||||
paddingInline: theme.spacing(15),
|
||||
paddingBottom: theme.spacing(25),
|
||||
backgroundColor: theme.palette.background.main,
|
||||
border: 1,
|
||||
borderStyle: "solid",
|
||||
borderColor: theme.palette.border.light,
|
||||
borderRadius: theme.spacing(2),
|
||||
"& > div:first-of-type": {
|
||||
flex: 0.7,
|
||||
},
|
||||
"& > div:last-of-type": {
|
||||
flex: 1,
|
||||
},
|
||||
"& h1, & h2": {
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
"& p": {
|
||||
color: theme.palette.text.tertiary,
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<Box
|
||||
className="settings"
|
||||
@@ -132,7 +177,7 @@ const Settings = ({ isAdmin }) => {
|
||||
/>
|
||||
</Stack>
|
||||
</ConfigBox>
|
||||
{isAdmin && (
|
||||
{true && (
|
||||
<ConfigBox>
|
||||
<Box>
|
||||
<Typography component="h1">History and monitoring</Typography>
|
||||
@@ -143,21 +188,19 @@ const Settings = ({ isAdmin }) => {
|
||||
</Box>
|
||||
<Stack gap={theme.spacing(20)}>
|
||||
<Field
|
||||
type="text"
|
||||
id="history-monitoring"
|
||||
id="ttl"
|
||||
label="The days you want to keep monitoring history."
|
||||
isOptional={true}
|
||||
optionalLabel="0 for infinite"
|
||||
placeholder="90"
|
||||
value=""
|
||||
onChange={() => logger.warn("Disabled")}
|
||||
value={form.ttl}
|
||||
onChange={handleChange}
|
||||
error={errors.ttl}
|
||||
/>
|
||||
<Box>
|
||||
<Typography>Clear all stats. This is irreversible.</Typography>
|
||||
<LoadingButton
|
||||
variant="contained"
|
||||
color="error"
|
||||
loading={isLoading}
|
||||
loading={isLoading || authIsLoading || checksIsLoading}
|
||||
onClick={handleClearStats}
|
||||
sx={{ mt: theme.spacing(4) }}
|
||||
>
|
||||
@@ -181,7 +224,7 @@ const Settings = ({ isAdmin }) => {
|
||||
<LoadingButton
|
||||
variant="contained"
|
||||
color="primary"
|
||||
loading={isLoading}
|
||||
loading={isLoading || authIsLoading || checksIsLoading}
|
||||
onClick={handleInsertDemoMonitors}
|
||||
sx={{ mt: theme.spacing(4) }}
|
||||
>
|
||||
@@ -193,7 +236,7 @@ const Settings = ({ isAdmin }) => {
|
||||
<LoadingButton
|
||||
variant="contained"
|
||||
color="error"
|
||||
loading={isLoading}
|
||||
loading={isLoading || authIsLoading || checksIsLoading}
|
||||
onClick={handleDeleteAllMonitors}
|
||||
sx={{ mt: theme.spacing(4) }}
|
||||
>
|
||||
@@ -223,7 +266,8 @@ const Settings = ({ isAdmin }) => {
|
||||
</ConfigBox>
|
||||
<Stack direction="row" justifyContent="flex-end">
|
||||
<LoadingButton
|
||||
loading={false}
|
||||
loading={isLoading || authIsLoading || checksIsLoading}
|
||||
disabled={Object.keys(errors).length > 0}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
sx={{ px: theme.spacing(12), mt: theme.spacing(20) }}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
import { Stack, styled } from "@mui/material";
|
||||
|
||||
export const ConfigBox = styled(Stack)(({ theme }) => ({
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
gap: theme.spacing(20),
|
||||
paddingTop: theme.spacing(12),
|
||||
paddingInline: theme.spacing(15),
|
||||
paddingBottom: theme.spacing(25),
|
||||
backgroundColor: theme.palette.background.main,
|
||||
border: 1,
|
||||
borderStyle: "solid",
|
||||
borderColor: theme.palette.border.light,
|
||||
borderRadius: theme.spacing(2),
|
||||
"& > div:first-of-type": {
|
||||
flex: 0.7,
|
||||
},
|
||||
"& > div:last-of-type": {
|
||||
flex: 1,
|
||||
},
|
||||
"& h1, & h2": {
|
||||
color: theme.palette.text.secondary,
|
||||
},
|
||||
"& p": {
|
||||
color: theme.palette.text.tertiary,
|
||||
},
|
||||
}));
|
||||
@@ -582,6 +582,19 @@ class NetworkService {
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
async updateChecksTTL(authToken, ttl) {
|
||||
return this.axiosInstance.put(
|
||||
`/checks/ttl`,
|
||||
{ ttl },
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${authToken}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default NetworkService;
|
||||
|
||||
@@ -146,9 +146,16 @@ const maintenanceWindowValidation = joi.object({
|
||||
}),
|
||||
});
|
||||
|
||||
const settingsValidation = joi.object({
|
||||
ttl: joi.number().required().messages({
|
||||
"string.empty": "TTL is required",
|
||||
}),
|
||||
});
|
||||
|
||||
export {
|
||||
credentials,
|
||||
imageValidation,
|
||||
monitorValidation,
|
||||
maintenanceWindowValidation,
|
||||
settingsValidation,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user