diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md
index 3d9b31e2d..55d456545 100644
--- a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md
+++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md
@@ -1,6 +1,6 @@
## Describe your changes
-Provide a brief description of the changes you’ve made and their purpose.
+Briefly describe the changes you made and their purpose.
## Issue number
@@ -11,4 +11,11 @@ Mention the issue number(s) this PR addresses (e.g., #123).
- [ ] I have performed a self-review of my code.
- [ ] I have included the issue # in the PR.
- [ ] I have labelled the PR correctly.
-- [ ] My PR is granular and targeted to one specific feature only.
+- [ ] The issue I am working on is assigned to me.
+- [ ] I didn't use any hardcoded values (otherwise it will not scale, and will make it difficult to maintain consistency across the application).
+- [ ] I made sure font sizes, color choices etc are all referenced from the theme.
+- [ ] My PR is granular and targeted to one specific feature.
+- [ ] I took a screenshot or a video and attached to this PR if there is a UI change.
+
+
+
diff --git a/Client/src/App.jsx b/Client/src/App.jsx
index b27373071..3b28e285a 100644
--- a/Client/src/App.jsx
+++ b/Client/src/App.jsx
@@ -3,7 +3,6 @@ import { useSelector } from "react-redux";
import { useDispatch } from "react-redux";
import "react-toastify/dist/ReactToastify.css";
import { ToastContainer } from "react-toastify";
-
import { ThemeProvider } from "@emotion/react";
import lightTheme from "./Utils/Theme/lightTheme";
import darkTheme from "./Utils/Theme/darkTheme";
diff --git a/Client/src/Components/Inputs/Checkbox/index.jsx b/Client/src/Components/Inputs/Checkbox/index.jsx
index 2f89d86df..054f43b92 100644
--- a/Client/src/Components/Inputs/Checkbox/index.jsx
+++ b/Client/src/Components/Inputs/Checkbox/index.jsx
@@ -3,33 +3,50 @@ import { FormControlLabel, Checkbox as MuiCheckbox } from "@mui/material";
import { useTheme } from "@emotion/react";
import CheckboxOutline from "../../../assets/icons/checkbox-outline.svg?react";
import CheckboxFilled from "../../../assets/icons/checkbox-filled.svg?react";
-
import "./index.css";
/**
- * @param {Object} props
- * @param {string} props.id - The id attribute for the checkbox input.
- * @param {string} props.label - The label to display next to the checkbox.
- * @param {('small' | 'medium' | 'large')} - The size of the checkbox.
- * @param {boolean} props.isChecked - Whether the checkbox is checked or not.
- * @param {string} [props.value] - The value of the checkbox input.
- * @param {function} [props.onChange] - The function to call when the checkbox value changes.
- * @param {boolean} [props.isDisabled] - Whether the checkbox is disabled or not.
+ * Checkbox Component
*
- * @returns {JSX.Element}
+ * A customized checkbox component using Material-UI that supports custom sizing,
+ * disabled states, and custom icons.
+ *
+ * @component
+ * @param {Object} props - Component properties
+ * @param {string} props.id - Unique identifier for the checkbox input
+ * @param {string} [props.name] - Optional name attribute for the checkbox
+ * @param {(string|React.ReactNode)} props.label - Label text or node for the checkbox
+ * @param {('small'|'medium'|'large')} [props.size='medium'] - Size of the checkbox icon
+ * @param {boolean} props.isChecked - Current checked state of the checkbox
+ * @param {string} [props.value] - Optional value associated with the checkbox
+ * @param {Function} [props.onChange] - Callback function triggered when checkbox state changes
+ * @param {boolean} [props.isDisabled] - Determines if the checkbox is disabled
+ *
+ * @returns {React.ReactElement} Rendered Checkbox component
*
* @example
+ * // Basic usage
*
+ *
+ * @example
+ * // With custom size and disabled state
+ *
*/
-
const Checkbox = ({
id,
+ name,
label,
size = "medium",
isChecked,
@@ -46,6 +63,7 @@ const Checkbox = ({
control={
}
@@ -54,7 +72,7 @@ const Checkbox = ({
"aria-label": "controlled checkbox",
id: id,
}}
- sx={{
+ sx={{
"&:hover": { backgroundColor: "transparent" },
"& svg": { width: sizes[size], height: sizes[size] },
alignSelf: "flex-start",
@@ -89,6 +107,7 @@ const Checkbox = ({
Checkbox.propTypes = {
id: PropTypes.string.isRequired,
+ name: PropTypes.string,
label: PropTypes.oneOfType([PropTypes.string, PropTypes.node]).isRequired,
size: PropTypes.oneOf(["small", "medium", "large"]),
isChecked: PropTypes.bool.isRequired,
diff --git a/Client/src/Components/Sidebar/index.jsx b/Client/src/Components/Sidebar/index.jsx
index 00a32a8d3..95abe1d20 100644
--- a/Client/src/Components/Sidebar/index.jsx
+++ b/Client/src/Components/Sidebar/index.jsx
@@ -47,7 +47,7 @@ import Folder from "../../assets/icons/folder.svg?react";
import "./index.css";
const menu = [
- { name: "Monitors", path: "monitors", icon: },
+ { name: "Uptime", path: "uptime", icon: },
{ name: "Pagespeed", path: "pagespeed", icon: },
{ name: "Infrastructure", path: "infrastructure", icon: },
{ name: "Incidents", path: "incidents", icon: },
@@ -262,10 +262,10 @@ function Sidebar() {
Menu
}
- sx={{
+ sx={{
px: theme.spacing(6),
height: "100%",
- overflow: "hidden"
+ overflow: "hidden",
}}
>
{menu.map((item) =>
diff --git a/Client/src/Pages/Auth/Login.jsx b/Client/src/Pages/Auth/Login.jsx
index 6329835ef..a7554a7c1 100644
--- a/Client/src/Pages/Auth/Login.jsx
+++ b/Client/src/Pages/Auth/Login.jsx
@@ -388,7 +388,7 @@ const Login = () => {
useEffect(() => {
if (authToken) {
- navigate("/monitors");
+ navigate("/uptime");
return;
}
networkService
@@ -454,7 +454,7 @@ const Login = () => {
} else {
const action = await dispatch(login(form));
if (action.payload.success) {
- navigate("/monitors");
+ navigate("/uptime");
createToast({
body: "Welcome back! You're successfully logged in.",
});
diff --git a/Client/src/Pages/Auth/Register/Register.jsx b/Client/src/Pages/Auth/Register/Register.jsx
index 2f4c26040..65c20ca40 100644
--- a/Client/src/Pages/Auth/Register/Register.jsx
+++ b/Client/src/Pages/Auth/Register/Register.jsx
@@ -237,7 +237,7 @@ const Register = ({ isSuperAdmin }) => {
if (action.payload.success) {
const authToken = action.payload.data;
localStorage.setItem("token", authToken);
- navigate("/monitors");
+ navigate("/uptime");
createToast({
body: "Welcome! Your account was created successfully.",
});
diff --git a/Client/src/Pages/Infrastructure/CreateMonitor/CustomThreshold/index.jsx b/Client/src/Pages/Infrastructure/CreateMonitor/CustomThreshold/index.jsx
index c7b9f0c76..3220582a8 100644
--- a/Client/src/Pages/Infrastructure/CreateMonitor/CustomThreshold/index.jsx
+++ b/Client/src/Pages/Infrastructure/CreateMonitor/CustomThreshold/index.jsx
@@ -5,32 +5,58 @@ import { useTheme } from "@emotion/react";
import PropTypes from "prop-types";
/**
- * `CustomThreshold` is a functional React component that displays a
- * group of CheckBox with a label and its correspondant threshold input field.
+ * CustomThreshold Component
*
- * @param {{ checkboxId: any; checkboxLabel: any; onCheckboxChange: any; fieldId: any; onFieldChange: any; onFieldBlur: any; alertUnit: any; infrastructureMonitor: any; errors: any; }} param0
- * @param {string} param0.checkboxId - The text is the id of the checkbox.
- * @param {string} param0.checkboxLabel - The text to be displayed as the label next to the check icon.
- * @param {func} param0.onCheckboxChange - The function to invoke when checkbox is checked or unchecked.
- * @param {string} param0.fieldId - The text is the id of the input field.
- * @param {func} param0.onFieldChange - The function to invoke when input field is changed.
- * @param {func} param0.onFieldBlur - The function to invoke when input field is losing focus.
- * @param {string} param0.alertUnit the threshold unit such as usage percentage '%' etc
- * @param {object} param0.infrastructureMonitor the form object of the create infrastrcuture monitor page
- * @param {object} param0.errors the object that holds all the errors of the form page
- * @returns A compound React component that renders the custom threshold alert section
+ * A reusable component that renders a checkbox with an associated numeric input field
+ * and an optional unit label. The input field can be enabled/disabled based on checkbox state.
*
+ * @component
+ * @param {Object} props - Component properties
+ * @param {string} [props.checkboxId] - Optional unique identifier for the checkbox
+ * @param {string} [props.checkboxName] - Optional name attribute for the checkbox
+ * @param {string} props.checkboxLabel - Label text for the checkbox
+ * @param {boolean} props.isChecked - Current checked state of the checkbox
+ * @param {Function} props.onCheckboxChange - Callback function when checkbox is toggled
+ * @param {string} props.fieldId - Unique identifier for the input field
+ * @param {string} [props.fieldName] - Optional name attribute for the input field
+ * @param {string} props.fieldValue - Current value of the input field
+ * @param {Function} props.onFieldChange - Callback function when input field value changes
+ * @param {Function} props.onFieldBlur - Callback function when input field loses focus
+ * @param {string} props.alertUnit - Unit label displayed next to the input field
+ * @param {Object} props.errors - Object containing validation errors for the field
+ * @param {Object} props.infrastructureMonitor - Infrastructure monitor configuration object
+ *
+ * @returns {React.ReactElement} Rendered CustomThreshold component
+ *
+ * @example
+ *
*/
-
export const CustomThreshold = ({
checkboxId,
+ checkboxName,
checkboxLabel,
onCheckboxChange,
+ isChecked,
fieldId,
+ fieldName,
+ fieldValue,
onFieldChange,
onFieldBlur,
alertUnit,
- infrastructureMonitor,
errors,
}) => {
const theme = useTheme();
@@ -46,8 +72,9 @@ export const CustomThreshold = ({
@@ -61,11 +88,12 @@ export const CustomThreshold = ({
maxWidth="var(--env-var-width-4)"
type="number"
id={fieldId}
- value={infrastructureMonitor[fieldId]}
+ name={fieldName}
+ value={fieldValue}
onBlur={onFieldBlur}
onChange={onFieldChange}
error={errors[fieldId] ? true : false}
- disabled={!infrastructureMonitor[checkboxId]}
+ disabled={!isChecked}
/>
{
+ return Object.keys(errors).filter((k) => k.startsWith(METRIC_PREFIX)).length > 0;
+};
+
+const getAlertError = (errors) => {
+ return Object.keys(errors).find((key) => key.startsWith(METRIC_PREFIX))
+ ? errors[Object.keys(errors).find((key) => key.startsWith(METRIC_PREFIX))]
+ : null;
+};
const CreateInfrastructureMonitor = () => {
+ const theme = useTheme();
+ const { user, authToken } = useSelector((state) => state.auth);
+ const monitorState = useSelector((state) => state.infrastructureMonitor);
+ const dispatch = useDispatch();
+ const navigate = useNavigate();
+
+ // State
+ const [errors, setErrors] = useState({});
+ const [https, setHttps] = useState(false);
const [infrastructureMonitor, setInfrastructureMonitor] = useState({
url: "",
name: "",
@@ -38,118 +73,73 @@ const CreateInfrastructureMonitor = () => {
secret: "",
});
- const MS_PER_MINUTE = 60000;
- const THRESHOLD_FIELD_PREFIX = "usage_";
- const HARDWARE_MONITOR_TYPES = ["cpu", "memory", "disk", "temperature"];
- 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 alertErrKeyLen = Object.keys(errors).filter((k) =>
- k.startsWith(THRESHOLD_FIELD_PREFIX)
- ).length;
-
- 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, appendID) => {
+ // Handlers
+ const handleCreateInfrastructureMonitor = async (event) => {
event.preventDefault();
- const { value, id } = event.target;
- let name = idMap[id] ?? id;
- if (name === "url" && infrastructureMonitor.name === "") {
- setInfrastructureMonitor((prev) => ({
- ...prev,
- name: parseDomainName(value),
- }));
+ // Build the form
+ let form = {
+ url: `http${https ? "s" : ""}://` + infrastructureMonitor.url,
+ name:
+ infrastructureMonitor.name === ""
+ ? infrastructureMonitor.url
+ : infrastructureMonitor.name,
+ interval: infrastructureMonitor.interval * MS_PER_MINUTE,
+ cpu: infrastructureMonitor.cpu,
+ ...(infrastructureMonitor.cpu
+ ? { usage_cpu: infrastructureMonitor.usage_cpu }
+ : {}),
+ memory: infrastructureMonitor.memory,
+ ...(infrastructureMonitor.memory
+ ? { usage_memory: infrastructureMonitor.usage_memory }
+ : {}),
+ disk: infrastructureMonitor.disk,
+ ...(infrastructureMonitor.disk
+ ? { usage_disk: infrastructureMonitor.usage_disk }
+ : {}),
+ temperature: infrastructureMonitor.temperature,
+ ...(infrastructureMonitor.temperature
+ ? { usage_temperature: infrastructureMonitor.usage_temperature }
+ : {}),
+ secret: infrastructureMonitor.secret,
+ };
+
+ const { error } = infrastructureMonitorValidation.validate(form, {
+ abortEarly: false,
+ });
+
+ if (error) {
+ const newErrors = {};
+ error.details.forEach((err) => {
+ newErrors[err.path[0]] = err.message;
+ });
+ setErrors(newErrors);
+ createToast({ body: "Please check the form for errors." });
+ return;
}
- if (id?.startsWith("notify-email-")) return;
- const { error } = infrastructureMonitorValidation.validate(
- { [id ?? appendID]: value },
- {
- abortEarly: false,
- }
- );
- setErrors((prev) => {
- return buildErrors(prev, id ?? appendID, error);
- });
- };
+ // Build the thresholds for the form
+ const {
+ cpu,
+ usage_cpu,
+ memory,
+ usage_memory,
+ disk,
+ usage_disk,
+ temperature,
+ usage_temperature,
+ ...rest
+ } = form;
- 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] / 100;
- delete form[k];
- delete form[k.substring(THRESHOLD_FIELD_PREFIX.length)];
- });
+ const thresholds = {
+ ...(cpu ? { usage_cpu: usage_cpu / 100 } : {}),
+ ...(memory ? { usage_memory: usage_memory / 100 } : {}),
+ ...(disk ? { usage_disk: usage_disk / 100 } : {}),
+ ...(temperature ? { usage_temperature: usage_temperature / 100 } : {}),
+ };
form = {
- ...form,
+ ...rest,
description: form.name,
teamId: user.teamId,
userId: user._id,
@@ -157,54 +147,69 @@ const CreateInfrastructureMonitor = () => {
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, infrastructureMonitorValidation, setErrors)) {
- return;
+ const action = await dispatch(
+ createInfrastructureMonitor({ authToken, monitor: form })
+ );
+ if (action.meta.requestStatus === "fulfilled") {
+ createToast({ body: "Infrastructure monitor created successfully!" });
+ navigate("/infrastructure");
} else {
- const checkEndpointAction = await 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 = await dispatch(
- createInfrastructureMonitor({ authToken, monitor: generatePayload(form) })
- );
- if (action.meta.requestStatus === "fulfilled") {
- createToast({ body: "Infrastructure monitor created successfully!" });
- navigate("/infrastructure");
- } else {
- createToast({ body: "Failed to create monitor." });
- }
+ createToast({ body: "Failed to create monitor." });
}
};
- //select values
- const frequencies = [
- { _id: 0.25, name: "15 seconds" },
- { _id: 0.5, name: "30 seconds" },
- { _id: 1, name: "1 minute" },
- { _id: 2, name: "2 minutes" },
- { _id: 5, name: "5 minutes" },
- { _id: 10, name: "10 minutes" },
- ];
+ const handleChange = (event) => {
+ const { value, name } = event.target;
+ setInfrastructureMonitor({
+ ...infrastructureMonitor,
+ [name]: value,
+ });
+
+ const { error } = infrastructureMonitorValidation.validate(
+ { [name]: value },
+ { abortEarly: false }
+ );
+ setErrors((prev) => ({
+ ...prev,
+ ...(error ? { [name]: error.details[0].message } : { [name]: undefined }),
+ }));
+ };
+
+ const handleCheckboxChange = (event) => {
+ const { name } = event.target;
+ const { checked } = event.target;
+ setInfrastructureMonitor({
+ ...infrastructureMonitor,
+ [name]: checked,
+ });
+ };
+
+ const handleNotifications = (event, type) => {
+ const { value } = event.target;
+ let notifications = [...infrastructureMonitor.notifications];
+ const notificationExists = notifications.some((notification) => {
+ if (notification.type === type && notification.address === value) {
+ return true;
+ }
+ return false;
+ });
+ if (notificationExists) {
+ notifications = notifications.filter((notification) => {
+ if (notification.type === type && notification.address === value) {
+ return false;
+ }
+ return true;
+ });
+ } else {
+ notifications.push({ type, address: value });
+ }
+
+ setInfrastructureMonitor((prev) => ({
+ ...prev,
+ notifications,
+ }));
+ };
return (
@@ -239,56 +244,75 @@ const CreateInfrastructureMonitor = () => {
fontSize="inherit"
fontWeight="inherit"
>
- infrastructure monitor
+ monitor
-
-
- General settings
-
- Here you can select the URL of the host, together with the friendly name
- and authorization secret to connect to the server agent.
-
-
- The server you are monitoring must be running the{" "}
-
-
-
-
+
+ General settings
+
+ Here you can select the URL of the host, together with the friendly name and
+ authorization secret to connect to the server agent.
+
+
+ The server you are monitoring must be running the{" "}
+
+
+
}
+ placeholder={"localhost:59232/api/v1/metrics"}
label="Server URL"
- placeholder="https://"
+ https={https}
value={infrastructureMonitor.url}
- onBlur={handleBlur}
onChange={handleChange}
error={errors["url"] ? true : false}
helperText={errors["url"]}
/>
+
+ Protocol
+
+
+
+
+
{
(notification) => notification.type === "email"
)}
value={user?.email}
- onChange={(e) => handleChange(e)}
- onBlur={handleBlur}
+ onChange={(event) => handleNotifications(event, "email")}
/>
-
Customize alerts
@@ -325,25 +347,31 @@ const CreateInfrastructureMonitor = () => {
- {HARDWARE_MONITOR_TYPES.map((type, idx) => (
-
- ))}
- {alertErrKeyLen > 0 && (
+ {METRICS.map((metric) => {
+ return (
+
+ );
+ })}
+ {/* Error text */}
+ {hasAlertError(errors) && (
{
opacity: 0.8,
}}
>
- {
- errors[
- THRESHOLD_FIELD_PREFIX +
- HARDWARE_MONITOR_TYPES.filter(
- (type) => errors[THRESHOLD_FIELD_PREFIX + type]
- )[0]
- ]
- }
+ {getAlertError(errors)}
)}
@@ -372,11 +393,12 @@ const CreateInfrastructureMonitor = () => {
diff --git a/Client/src/Pages/Infrastructure/Details/index.jsx b/Client/src/Pages/Infrastructure/Details/index.jsx
index 06fb1296a..346fe9c5e 100644
--- a/Client/src/Pages/Infrastructure/Details/index.jsx
+++ b/Client/src/Pages/Infrastructure/Details/index.jsx
@@ -8,7 +8,7 @@ import AreaChart from "../../../Components/Charts/AreaChart";
import { useSelector } from "react-redux";
import { networkService } from "../../../main";
import PulseDot from "../../../Components/Animated/PulseDot";
-import useUtils from "../../Monitors/utils";
+import useUtils from "../../Uptime/utils";
import { useNavigate } from "react-router-dom";
import Empty from "./empty";
import { logger } from "../../../Utils/Logger";
@@ -283,7 +283,7 @@ const InfrastructureDetails = () => {
{
type: "memory",
value: decimalToPercentage(memoryUsagePercent),
- heading: "Memory Usage",
+ heading: "Memory usage",
metricOne: "Used",
valueOne: formatBytes(memoryUsedBytes),
metricTwo: "Total",
@@ -292,7 +292,7 @@ const InfrastructureDetails = () => {
{
type: "cpu",
value: decimalToPercentage(cpuUsagePercent),
- heading: "CPU Usage",
+ heading: "CPU usage",
metricOne: "Cores",
valueOne: cpuPhysicalCores ?? 0,
metricTwo: "Frequency",
@@ -364,7 +364,7 @@ const InfrastructureDetails = () => {
heading: "Memory usage",
strokeColor: theme.palette.primary.main,
gradientStartColor: theme.palette.primary.main,
- yLabel: "Memory Usage",
+ yLabel: "Memory usage",
yDomain: [0, 1],
yTick: ,
xTick: ,
@@ -372,7 +372,7 @@ const InfrastructureDetails = () => {
),
},
@@ -383,7 +383,7 @@ const InfrastructureDetails = () => {
heading: "CPU usage",
strokeColor: theme.palette.success.main,
gradientStartColor: theme.palette.success.main,
- yLabel: "CPU Usage",
+ yLabel: "CPU usage",
yDomain: [0, 1],
yTick: ,
xTick: ,
@@ -391,7 +391,7 @@ const InfrastructureDetails = () => {
),
},
diff --git a/Client/src/Pages/Infrastructure/components/Menu/index.jsx b/Client/src/Pages/Infrastructure/components/Menu/index.jsx
index 9794a34d9..98b3f9878 100644
--- a/Client/src/Pages/Infrastructure/components/Menu/index.jsx
+++ b/Client/src/Pages/Infrastructure/components/Menu/index.jsx
@@ -109,88 +109,6 @@ const InfrastructureMenu = ({ monitor, isAdmin, updateCallback }) => {
},
}}
>
- {/*
- Open site action. Not necessary for infrastructure?
-
- {actions.url !== null ? (
-
- ) : (
- ""
- )}
- */}
-
- {/*
- Incidents. Necessary?
- */}
- {/*
- Configure. Necessary?
- {isAdmin && (
-
- )} */}
- {/*
- Clone. Necessary?
- {isAdmin && (
-
- )} */}
- {/*
- Pause. Necessary?
- const handlePause = async () => {
- try {
- const action = await dispatch(
- pauseUptimeMonitor({ authToken, monitorId: monitor._id })
- );
- if (pauseUptimeMonitor.fulfilled.match(action)) {
- updateCallback();
- const state = action?.payload?.data.isActive === false ? "paused" : "resumed";
- createToast({ body: `Monitor ${state} successfully.` });
- } else {
- throw new Error(action?.error?.message ?? "Failed to pause monitor.");
- }
- } catch (error) {
- logger.error("Error pausing monitor:", monitor._id, error);
- createToast({ body: "Failed to pause monitor." });
- }
- };
- {isAdmin && (
-
- )} */}
{isAdmin && }