Merge remote-tracking branch 'upstream/develop' into fix/incident-pagination

This commit is contained in:
Alex Holliday committed 2024-08-09 10:02:27 -07:00
commit 3924099e3e
14 files changed
+632 -75

No files matched your search

+5
View File
@@ -26,6 +26,7 @@ import PageSpeed from "./Pages/PageSpeed";
import CreatePageSpeed from "./Pages/PageSpeed/CreatePageSpeed";
import CreateNewMaintenanceWindow from "./Pages/Maintenance/CreateMaintenanceWindow";
import PageSpeedDetails from "./Pages/PageSpeed/Details";
import PageSpeedConfigure from "./Pages/PageSpeed/Configure";
function App() {
const AdminCheckedRegister = withAdminCheck(Register);
@@ -103,6 +104,10 @@ function App() {
path="pagespeed/:monitorId"
element={<ProtectedRoute Component={PageSpeedDetails} />}
/>
<Route
path="pagespeed/configure/:monitorId"
element={<ProtectedRoute Component={PageSpeedConfigure} />}
/>
</Route>
<Route exact path="/login" element={<Login />} />
@@ -352,7 +352,7 @@ const ProfilePanel = () => {
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
width: 400,
width: 500,
bgcolor: "white",
border: "solid 1px #f2f2f2",
borderRadius: `${theme.shape.borderRadius}px`,
@@ -68,6 +68,58 @@ export const getPageSpeedByUserId = createAsyncThunk(
}
);
export const updatePageSpeed = createAsyncThunk(
"pageSpeedMonitors/updatePageSpeed",
async (data, thunkApi) => {
try {
const { authToken, monitor } = data;
const updatedFields = {
name: monitor.name,
description: monitor.description,
interval: monitor.interval,
// notifications: monitor.notifications,
};
const res = await axiosInstance.put(
`/monitors/${monitor._id}`,
updatedFields,
{
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);
}
}
);
export const deletePageSpeed = createAsyncThunk(
"pageSpeedMonitors/deletePageSpeed",
async (data, thunkApi) => {
try {
const { authToken, monitor } = data;
const res = await axiosInstance.delete(`/monitors/${monitor._id}`, {
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 pageSpeedMonitorSlice = createSlice({
name: "pageSpeedMonitor",
initialState,
@@ -137,6 +189,44 @@ const pageSpeedMonitorSlice = createSlice({
state.msg = action.payload
? action.payload.msg
: "Failed to create page speed monitor";
})
// *****************************************************
// Create Monitor
// *****************************************************
.addCase(updatePageSpeed.pending, (state) => {
state.isLoading = true;
})
.addCase(updatePageSpeed.fulfilled, (state, action) => {
state.isLoading = false;
state.success = action.payload.success;
state.msg = action.payload.msg;
})
.addCase(updatePageSpeed.rejected, (state, action) => {
state.isLoading = false;
state.success = false;
state.msg = action.payload
? action.payload.msg
: "Failed to update page speed monitor";
})
// *****************************************************
// Delete Monitor
// *****************************************************
.addCase(deletePageSpeed.pending, (state) => {
state.isLoading = true;
})
.addCase(deletePageSpeed.fulfilled, (state, action) => {
state.isLoading = false;
state.success = action.payload.success;
state.msg = action.payload.msg;
})
.addCase(deletePageSpeed.rejected, (state, action) => {
state.isLoading = false;
state.success = false;
state.msg = action.payload
? action.payload.msg
: "Failed to delete page speed monitor";
});
},
});
@@ -80,7 +80,7 @@ export const updateUptimeMonitor = createAsyncThunk(
notifications: monitor.notifications,
};
const res = await axiosInstance.put(
`/monitors/edit/${monitor._id}`,
`/monitors/${monitor._id}`,
updatedFields,
{
headers: {
@@ -460,10 +460,10 @@ const Configure = () => {
}}
>
<Typography id="modal-delete-monitor" component="h2">
Really delete this monitor?
Do you really want to delete this monitor?
</Typography>
<Typography id="delete-monitor-confirmation">
Once deleted, this monitor cannot be retrieved back.
Once deleted, this monitor cannot be retrieved.
</Typography>
<Stack
direction="row"
@@ -8,12 +8,17 @@ import {
TableBody,
TableFooter,
TablePagination,
PaginationItem,
Pagination,
Paper,
} from "@mui/material";
import { useState, useEffect } from "react";
import { useSelector } from "react-redux";
import axiosInstance from "../../../../Utils/axiosConfig";
import { StatusLabel } from "../../../../Components/Label";
import ArrowBackRoundedIcon from "@mui/icons-material/ArrowBackRounded";
import ArrowForwardRoundedIcon from "@mui/icons-material/ArrowForwardRounded";
const PaginationTable = ({ monitorId, dateRange }) => {
const { authToken } = useSelector((state) => state.auth);
@@ -53,63 +58,76 @@ const PaginationTable = ({ monitorId, dateRange }) => {
const handlePageChange = (_, newPage) => {
setPaginationController({
...paginationController,
page: newPage,
});
};
const handleChangeRowsPerPage = (event) => {
setPaginationController({
...paginationController,
rowsPerPage: parseInt(event.target.value, 10),
page: 0,
page: newPage - 1,
});
};
let paginationComponent = <></>;
if (checksCount > paginationController.rowsPerPage) {
paginationComponent = (
<Pagination
count={Math.ceil(checksCount / paginationController.rowsPerPage)}
page={paginationController.page + 1}
onChange={handlePageChange}
shape="rounded"
renderItem={(item) => (
<PaginationItem
slots={{
previous: ArrowBackRoundedIcon,
next: ArrowForwardRoundedIcon,
}}
{...item}
sx={{
"&:focus": {
outline: "none",
},
"& .MuiTouchRipple-root": {
pointerEvents: "none",
display: "none",
},
}}
/>
)}
/>
);
}
return (
<TableContainer>
<Table>
<TableHead>
<TableRow>
<TableCell>Status</TableCell>
<TableCell>Date & Time</TableCell>
<TableCell>Message</TableCell>
</TableRow>
</TableHead>
<TableBody>
{checks.map((check) => {
const status = check.status === true ? "up" : "down";
<>
<TableContainer component={Paper}>
<Table>
<TableHead>
<TableRow>
<TableCell>Status</TableCell>
<TableCell>Date & Time</TableCell>
<TableCell>Message</TableCell>
</TableRow>
</TableHead>
<TableBody>
{checks.map((check) => {
const status = check.status === true ? "up" : "down";
return (
<TableRow key={check._id}>
<TableCell>
<StatusLabel
status={status}
text={status}
customStyles={{ textTransform: "capitalize" }}
/>
</TableCell>
<TableCell>
{new Date(check.createdAt).toLocaleString()}
</TableCell>
<TableCell>{check.statusCode}</TableCell>
</TableRow>
);
})}
</TableBody>
<TableFooter>
<TableRow>
<TablePagination
rowsPerPageOptions={[5, 10, 25]}
onPageChange={handlePageChange}
page={paginationController.page}
count={checksCount}
rowsPerPage={paginationController.rowsPerPage}
onRowsPerPageChange={handleChangeRowsPerPage}
/>
</TableRow>
</TableFooter>
</Table>
</TableContainer>
return (
<TableRow key={check._id}>
<TableCell>
<StatusLabel
status={status}
text={status}
customStyles={{ textTransform: "capitalize" }}
/>
</TableCell>
<TableCell>
{new Date(check.createdAt).toLocaleString()}
</TableCell>
<TableCell>{check.statusCode}</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
{paginationComponent}
</>
);
};
-1
View File
@@ -12,7 +12,6 @@
.monitors p.MuiTypography-root {
font-size: var(--env-var-font-size-medium);
}
.monitors h2:has(+ p),
.monitors p.MuiTypography-root {
color: var(--env-var-color-5);
}
@@ -0,0 +1,68 @@
.configure-pagespeed form > .MuiStack-root:nth-child(2) {
background-color: var(--env-var-color-8);
border: solid 1px var(--env-var-color-6);
border-radius: var(--env-var-radius-1);
padding: var(--env-var-default-2);
}
.configure-pagespeed h1.MuiTypography-root {
font-size: var(--env-var-font-size-large-plus);
}
.configure-pagespeed h1.MuiTypography-root,
.configure-pagespeed h2.MuiTypography-root {
color: var(--env-var-color-1);
}
.configure-pagespeed span.MuiTypography-root {
font-size: var(--env-var-font-size-small-plus);
}
.configure-pagespeed p.MuiTypography-root,
.configure-pagespeed h3.MuiTypography-root {
color: var(--env-var-color-5);
}
.configure-pagespeed h1.MuiTypography-root,
.configure-pagespeed h3.MuiTypography-root,
.configure-pagespeed h2.MuiTypography-root {
font-weight: 600;
}
.configure-pagespeed p.MuiTypography-root,
.configure-pagespeed h3.MuiTypography-root,
.configure-pagespeed h3.MuiTypography-root > span.MuiTypography-root {
font-size: var(--env-var-font-size-medium);
}
.configure-pagespeed .MuiBox-root > .field + p.MuiTypography-root {
font-size: var(--env-var-font-size-small-plus);
}
.configure-pagespeed .MuiBox-root > .field + p.MuiTypography-root,
.configure-pagespeed h3.MuiTypography-root > span.MuiTypography-root {
opacity: 0.6;
}
.configure-pagespeed .checkbox-wrapper {
margin-bottom: 1px;
}
.configure-pagespeed .MuiInputBase-root:has(> .Mui-disabled) {
background-color: var(--env-var-color-13);
}
/* to be removed */
.configure-pagespeed .section-disabled {
opacity: 0.4;
background-color: #f1f1f2;
padding: 10px;
border-radius: 8px;
user-select: none;
pointer-events: none;
}
.configure-pagespeed button {
height: var(--env-var-height-2);
}
body:has(.configure-pagespeed) .select-dropdown .MuiMenuItem-root,
.configure-pagespeed .select-wrapper .select-component > .MuiSelect-select {
text-transform: lowercase;
}
.configure-pagespeed .field,
.configure-pagespeed .section-disabled,
.configure-pagespeed .select-wrapper,
.configure-pagespeed h3.MuiTypography-root {
flex: 1;
}
@@ -0,0 +1,365 @@
import { useEffect, useState } from "react";
import { useTheme } from "@emotion/react";
import { Box, Modal, Skeleton, Stack, Typography } from "@mui/material";
import { useDispatch, useSelector } from "react-redux";
import { useNavigate, useParams } from "react-router";
import {
deletePageSpeed,
getPageSpeedByUserId,
updatePageSpeed,
} from "../../../Features/PageSpeedMonitor/pageSpeedMonitorSlice";
import { monitorValidation } from "../../../Validation/validation";
import { createToast } from "../../../Utils/toastUtils";
import Button from "../../../Components/Button";
import Field from "../../../Components/Inputs/Field";
import Select from "../../../Components/Inputs/Select";
import Checkbox from "../../../Components/Inputs/Checkbox";
import PauseCircleOutlineIcon from "@mui/icons-material/PauseCircleOutline";
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";
import "./index.css";
/**
* Renders a skeleton layout.
*
* @returns {JSX.Element}
*/
const SkeletonLayout = () => {
const theme = useTheme();
return (
<>
<Skeleton variant="rounded" width="15%" height={34} />
<Stack gap={theme.gap.xl} mt={theme.gap.medium} maxWidth="1000px">
<Stack direction="row" gap={theme.gap.small} mt={theme.gap.small}>
<Skeleton
variant="circular"
style={{ minWidth: 24, minHeight: 24 }}
/>
<Box width="80%">
<Skeleton
variant="rounded"
width="50%"
height={24}
sx={{ mb: theme.gap.small }}
/>
<Skeleton variant="rounded" width="50%" height={18} />
</Box>
<Stack
direction="row"
gap={theme.gap.medium}
sx={{
ml: "auto",
alignSelf: "flex-end",
}}
>
<Skeleton variant="rounded" width={100} height={34} />
<Skeleton variant="rounded" width={100} height={34} />
</Stack>
</Stack>
<Skeleton variant="rounded" width="100%" height={500} />
<Stack direction="row" justifyContent="flex-end">
<Skeleton variant="rounded" width="15%" height={34} />
</Stack>
</Stack>
</>
);
};
const PageSpeedConfigure = () => {
const theme = useTheme();
const navigate = useNavigate();
const dispatch = useDispatch();
const MS_PER_MINUTE = 60000;
const { authToken } = useSelector((state) => state.auth);
const { monitors } = useSelector((state) => state.pageSpeedMonitors);
const { monitorId } = useParams();
const [monitor, setMonitor] = useState({});
const [errors, setErrors] = useState({});
const frequencies = [
{ _id: 3, name: "3 minutes" },
{ _id: 5, name: "5 minutes" },
{ _id: 10, name: "10 minutes" },
{ _id: 20, name: "20 minutes" },
{ _id: 60, name: "1 hour" },
{ _id: 1440, name: "1 day" },
{ _id: 10080, name: "1 week" },
];
useEffect(() => {
const data = monitors.find((monitor) => monitor._id === monitorId);
if (!data) {
console.error("Error fetching pagespeed monitor of id: " + monitorId);
navigate("/not-found");
}
setMonitor({
...data,
});
}, [monitorId]);
const handleChange = (event, id) => {
let { value } = event.target;
if (id === "interval") {
value = value * MS_PER_MINUTE;
}
setMonitor((prev) => ({ ...prev, [id]: value }));
const { error } = monitorValidation.validate(
{ [id]: value },
{ abortEarly: false }
);
setErrors((prev) => {
const newErrors = { ...prev };
if (error) newErrors[id] = error.details[0].message;
else delete newErrors[id];
return newErrors;
});
};
const handleSave = async (event) => {
event.preventDefault();
const action = await dispatch(
updatePageSpeed({ authToken, monitor: monitor })
);
if (action.meta.requestStatus === "fulfilled") {
createToast({ body: "Monitor updated successfully!" });
dispatch(getPageSpeedByUserId(authToken));
} else {
createToast({ body: "Failed to update monitor." });
}
};
const [isOpen, setIsOpen] = useState(false);
const handleRemove = async (event) => {
event.preventDefault();
const action = await dispatch(deletePageSpeed({ authToken, monitor }));
if (action.meta.requestStatus === "fulfilled") {
navigate("/pagespeed");
} else {
createToast({ body: "Failed to delete monitor." });
}
};
let loading = Object.keys(monitor).length === 0;
return (
<Box className="configure-pagespeed">
{loading ? (
<SkeletonLayout />
) : (
<>
<Button
level="tertiary"
label="Back"
animate="slideLeft"
img={<WestRoundedIcon />}
onClick={() => navigate(-1)}
sx={{
backgroundColor: theme.palette.otherColors.fillGray,
mb: theme.gap.large,
px: theme.gap.ml,
"& svg.MuiSvgIcon-root": {
mr: theme.gap.small,
fill: theme.palette.otherColors.slateGray,
},
}}
/>
<form
noValidate
spellCheck="false"
onSubmit={handleSave}
style={{
display: "flex",
flexDirection: "column",
gap: theme.gap.large,
maxWidth: "1000px",
}}
>
<Stack direction="row" gap={theme.gap.small}>
{monitor?.status ? <GreenCheck /> : <RedCheck />}
<Box>
<Typography
component="h1"
mb={theme.gap.xs}
sx={{ lineHeight: 1 }}
>
{monitor?.url}
</Typography>
<Typography
component="span"
sx={{
color: monitor?.status
? "var(--env-var-color-17)"
: "var(--env-var-color-24)",
}}
>
Your pagespeed monitor is {monitor?.status ? "live" : "down"}.
</Typography>
</Box>
<Box alignSelf="flex-end" ml="auto">
<Button
level="tertiary"
label="Pause"
animate="rotate180"
img={<PauseCircleOutlineIcon />}
sx={{
backgroundColor: theme.palette.otherColors.fillGray,
pl: theme.gap.small,
pr: theme.gap.medium,
"& svg": {
mr: theme.gap.xs,
},
}}
/>
<Button
level="error"
label="Remove"
sx={{
boxShadow: "none",
px: theme.gap.ml,
ml: theme.gap.medium,
}}
onClick={() => setIsOpen(true)}
/>
</Box>
</Stack>
<Stack gap={theme.gap.xl}>
<Stack direction="row">
<Typography component="h3">Monitor friendly name</Typography>
<Field
type="text"
id="monitor-name"
placeholder="Example monitor"
value={monitor?.name || ""}
onChange={(event) => handleChange(event, "name")}
error={errors.name}
/>
</Stack>
<Stack direction="row">
<Typography component="h3">URL</Typography>
<Field
type="url"
id="monitor-url"
placeholder="random.website.com"
value={monitor?.url?.replace("http://", "") || ""}
onChange={(event) => handleChange(event, "url")}
error={errors.url}
disabled={true}
/>
</Stack>
<Stack direction="row">
<Typography component="h3">Check frequency</Typography>
<Select
id="monitor-frequency"
items={frequencies}
value={monitor?.interval / MS_PER_MINUTE || 3}
onChange={(event) => handleChange(event, "interval")}
/>
</Stack>
<Stack direction="row">
<Typography component="h3">
Incidents notifications{" "}
<Typography component="span">(coming soon)</Typography>
</Typography>
<Stack className="section-disabled">
<Typography mb={theme.gap.small}>
When there is a new incident,
</Typography>
<Checkbox
id="notify-sms"
label="Notify via SMS (coming soon)"
isChecked={false}
isDisabled={true}
/>
<Checkbox
id="notify-email"
label="Notify via email (to gorkem.cetin@bluewavelabs.ca)"
isChecked={false}
/>
<Checkbox
id="notify-emails"
label="Notify via email to following emails"
isChecked={false}
/>
<Box mx={`calc(${theme.gap.ml} * 2)`}>
<Field
id="notify-emails-list"
placeholder="notifications@gmail.com"
value=""
onChange={() => console.log("disabled")}
error=""
/>
<Typography mt={theme.gap.small}>
You can separate multiple emails with a comma
</Typography>
</Box>
</Stack>
</Stack>
</Stack>
<Stack direction="row" justifyContent="flex-end">
<Button
type="submit"
level="primary"
label="Save"
onClick={handleSave}
sx={{ px: theme.gap.large, mt: theme.gap.large }}
/>
</Stack>
</form>
</>
)}
<Modal
aria-labelledby="modal-delete-pagespeed-monitor"
aria-describedby="delete-pagespeed-monitor-confirmation"
open={isOpen}
onClose={() => setIsOpen(false)}
disablePortal
>
<Stack
gap={theme.gap.xs}
sx={{
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
width: 400,
bgcolor: "white",
border: "solid 1px #f2f2f2",
borderRadius: `${theme.shape.borderRadius}px`,
boxShadow: 24,
p: "30px",
"&:focus": {
outline: "none",
},
}}
>
<Typography id="modal-delete-pagespeed-monitor" component="h2">
Do you really want to delete this monitor?
</Typography>
<Typography id="delete-pagespeed-monitor-confirmation">
Once deleted, this monitor cannot be retrieved.
</Typography>
<Stack
direction="row"
gap={theme.gap.small}
mt={theme.gap.large}
justifyContent="flex-end"
>
<Button
level="tertiary"
label="Cancel"
onClick={() => setIsOpen(false)}
/>
<Button level="error" label="Delete" onClick={handleRemove} />
</Stack>
</Stack>
</Modal>
</Box>
);
};
export default PageSpeedConfigure;
+3 -3
View File
@@ -139,7 +139,7 @@ const SkeletonLayout = () => {
<Skeleton variant="rounded" width="15%" height={34} />
<Stack direction="row" gap={theme.gap.small}>
<Skeleton variant="circular" style={{ minWidth: 24, minHeight: 24 }} />
<Box width="80%">
<Box width="85%">
<Skeleton variant="rounded" width="50%" height={24} />
<Skeleton
variant="rounded"
@@ -289,7 +289,7 @@ const PageSpeedDetails = () => {
return props;
};
const pieSize = { width: 200, height: 200 };
const pieSize = { width: 210, height: 200 };
const pieData = getPieData(audits);
const colorMap = getColors(performance);
@@ -321,7 +321,7 @@ const PageSpeedDetails = () => {
}}
/>
<Stack direction="row" gap={theme.gap.small}>
<GreenCheck />
{monitor?.status ? <GreenCheck /> : <RedCheck />}
<Box>
<Typography
component="h1"
+19 -7
View File
@@ -76,29 +76,41 @@ Made with [contrib.rocks](https://contrib.rocks).
###### Auth
- <code>POST</code> [/api/v1/auth/register](#post-register)
- <code>POST</code> [/api/v1/auth/login](#post-login)
- <code>POST</code> [/api/v1/auth/user/{userId}](#post-auth-user-edit-id)
- <code>PUT</code> [/api/v1/auth/user/{userId}](#post-auth-user-edit-id)
- <code>GET</code> [/api/v1/auth/users](#get-all-users-id)
- <code>GET</code> [/api/v1/auth/users/admin](#get-all-admin-users-id)
- <code>POST</code> [/api/v1/auth/invite](#post-auth-invite-id)
- <code>POST</code> [/api/v1/auth/invite/verify/](#post-auth-invite-verify-id)
- <code>POST</code> [/api/v1/auth/recovery/request](#post-auth-recovery-request-id)
- <code>POST</code> [/api/v1/auth/recovery/validate](#post-auth-recovery-validate-id)
- <code>POST</code> [/api/v1/auth/recovery/reset](#post-auth-recovery-reset-id)
###### Monitors
- <code>GET</code> [/api/v1/monitors](#get-monitors)
- <code>GET</code> [/api/v1/monitor/{id}](#get-monitor-id)
- <code>GET</code> [/api/v1/monitors/{monitorId}](#get-monitor-id)
- <code>GET</code> [/api/v1/monitors/user/{userId}?limit](#get-monitors-user-userid)
- <code>POST</code> [/api/v1/monitors](#post-monitors)
- <code>POST</code> [/api/v1/monitors/delete/{monitorId}](#post-monitors-del-id)
- <code>POST</code> [/api/v1/monitors/edit/{monitorId}](#post-monitors-edit-id)
- <code>PUT</code> [/api/v1/monitors/{monitorId}](#put-monitors-id)
- <code>DELETE</code> [/api/v1/monitors/{monitorId}](#delete-monitors-id)
- <code>DELETE</code> [/api/v1/monitors/all](#delete-all-monitors)
###### Checks
- <code>POST</code> [/api/v1/checks/{monitorId}](#post-checks)
- <code>GET</code> [/api/v1/checks/{monitorId}](#get-checks)
- <code>POST</code> [/api/v1/checks/delete/{monitorId}](#delete-checks)
- <code>DELETE</code> [/api/v1/checks/{monitorId}](#delete-checks)
###### Alerts
- <code>POST</code> [/api/v1/alerts/{monitorId}](#create-alert)
- <code>GET</code> [/api/v1/alerts/user/{userId}](#get-alerts-user-id)
- <code>GET</code> [/api/v1/alerts/monitor/{monitorId}](#get-alerts-monitor-id)
- <code>GET</code> [/api/v1/alerts/{alertId}](#get-alert-alert-id)
- <code>POST</code> [/api/v1/alerts/edit/{alertId}](#edit-alert)
- <code>POST</code> [/api/v1/alerts/delete/{alertId}](#delete-alert)
- <code>PUT</code> [/api/v1/alerts/{alertId}](#edit-alert)
- <code>DELETE</code> [/api/v1/alerts/{alertId}](#delete-alert)
###### Page Speed
- <code>POST</code> [/api/v1/pagespeed/:monitorId](#post-pagespeed)
- <code>GET</code> [/api/v1/pagespeed/:monitorId](#get-pagespeed)
- <code>DELETE</code> [/api/v1/pagespeed/:monitorId](#delete-pagespeed)
###### Maintenance Window
- <code>POST</code> [/api/v1/maintenance-window/:monitorId](#post-maintenance-window)
- <code>GET</code> [/api/v1/maintenance-window/user/:userId](#get-maintenance-window-by-userid)
- <code>GET</code> [/api/v1/maintenance-window/monitor/:monitorId](#get-maintenance-window-by-monitor-id)
1. [Error Handling](#error-handling)
1. [Contributors](#contributors)
+4 -4
View File
@@ -29,14 +29,14 @@ router.get(
alertController.getAlertById
);
// Edit
router.post(
"/edit/:alertId",
router.put(
"/:alertId",
verifyOwnership(Monitor, "monitorId"),
alertController.editAlert
);
//Delete
router.post(
"/delete/:alertId",
router.delete(
"/:alertId",
verifyOwnership(Monitor, "monitorId"),
alertController.deleteAlert
);
+2 -2
View File
@@ -15,8 +15,8 @@ router.get(
checkController.getChecks
);
router.post(
"/delete/:monitorId",
router.delete(
"/:monitorId",
verifyOwnership(Monitor, "monitorId"),
checkController.deleteChecks
);
+2 -2
View File
@@ -14,10 +14,10 @@ router.delete(
monitorController.deleteMonitor
);
router.put(
"/edit/:monitorId",
"/:monitorId",
verifyOwnership(Monitor, "monitorId"),
monitorController.editMonitor
);
router.delete("/delete/all", monitorController.deleteAllMonitors);
router.delete("/all", monitorController.deleteAllMonitors);
module.exports = router;