diff --git a/Client/src/Components/Dialog/genericDialog.jsx b/Client/src/Components/Dialog/genericDialog.jsx
new file mode 100644
index 000000000..eb1c287d3
--- /dev/null
+++ b/Client/src/Components/Dialog/genericDialog.jsx
@@ -0,0 +1,67 @@
+import { useId } from "react";
+import PropTypes from "prop-types";
+import { Modal, Stack, Typography } from "@mui/material";
+
+const GenericDialog = ({ title, description, open, onClose, theme, children }) => {
+ const titleId = useId();
+ const descriptionId = useId();
+ const ariaDescribedBy = description?.length > 0 ? descriptionId : "";
+ return (
+
+
+
+ {title}
+
+ {description && (
+
+ {description}
+
+ )}
+ {children}
+
+
+ );
+};
+
+GenericDialog.propTypes = {
+ title: PropTypes.string.isRequired,
+ description: PropTypes.string,
+ open: PropTypes.bool.isRequired,
+ onClose: PropTypes.func.isRequired,
+ theme: PropTypes.object.isRequired,
+ children: PropTypes.element.isRequired,
+};
+
+export { GenericDialog };
diff --git a/Client/src/Components/Dialog/index.jsx b/Client/src/Components/Dialog/index.jsx
index 55ec801d7..fdc34c0c1 100644
--- a/Client/src/Components/Dialog/index.jsx
+++ b/Client/src/Components/Dialog/index.jsx
@@ -1,103 +1,62 @@
-import LoadingButton from "@mui/lab/LoadingButton";
-import { Button, Modal, Stack, Typography } from "@mui/material";
import PropTypes from "prop-types";
+import LoadingButton from "@mui/lab/LoadingButton";
+import { Button, Stack } from "@mui/material";
+import { GenericDialog } from "./genericDialog";
+
const Dialog = ({
- modelTitle,
- modelDescription,
- open,
- onClose,
title,
- confirmationBtnLbl,
- confirmationBtnOnClick,
- cancelBtnLbl,
- cancelBtnOnClick,
- theme,
- isLoading,
description,
+ open,
+ theme,
+ onCancel,
+ confirmationButtonLabel,
+ onConfirm,
+ isLoading,
}) => {
return (
-
-
- {title}
-
- {description && (
-
- {description}
-
- )}
-
+
-
-
- {confirmationBtnLbl}
-
-
+ {confirmationButtonLabel}
+
-
+
);
};
Dialog.propTypes = {
- modelTitle: PropTypes.string.isRequired,
- modelDescription: PropTypes.string.isRequired,
+ title: PropTypes.string.isRequired,
+ description: PropTypes.string,
open: PropTypes.bool.isRequired,
onClose: PropTypes.func.isRequired,
- title: PropTypes.string.isRequired,
- confirmationBtnLbl: PropTypes.string.isRequired,
- confirmationBtnOnClick: PropTypes.func.isRequired,
- cancelBtnLbl: PropTypes.string.isRequired,
- cancelBtnOnClick: PropTypes.func.isRequired,
theme: PropTypes.object.isRequired,
+ onCancel: PropTypes.func.isRequired,
+ confirmationButtonLabel: PropTypes.string.isRequired,
+ onConfirm: PropTypes.func.isRequired,
isLoading: PropTypes.bool.isRequired,
- description: PropTypes.string,
};
export default Dialog;
diff --git a/Client/src/Components/TabPanels/Account/ProfilePanel.jsx b/Client/src/Components/TabPanels/Account/ProfilePanel.jsx
index 999e026c7..710d6a59f 100644
--- a/Client/src/Components/TabPanels/Account/ProfilePanel.jsx
+++ b/Client/src/Components/TabPanels/Account/ProfilePanel.jsx
@@ -1,7 +1,7 @@
import { useTheme } from "@emotion/react";
import { useRef, useState } from "react";
import TabPanel from "@mui/lab/TabPanel";
-import { Box, Button, Divider, Modal, Stack, Typography } from "@mui/material";
+import { Box, Button, Divider, Stack, Typography } from "@mui/material";
import Avatar from "../../Avatar";
import Field from "../../Inputs/Field";
import ImageField from "../../Inputs/Image";
@@ -15,6 +15,8 @@ import { clearUptimeMonitorState } from "../../../Features/UptimeMonitors/uptime
import { createToast } from "../../../Utils/toastUtils";
import { logger } from "../../../Utils/Logger";
import LoadingButton from "@mui/lab/LoadingButton";
+import { GenericDialog } from "../../Dialog/genericDialog";
+import Dialog from "../../Dialog";
/**
* ProfilePanel component displays a form for editing user profile information
@@ -369,158 +371,82 @@ const ProfilePanel = () => {
)}
{/* TODO - Update ModalPopup Component with @mui for reusability */}
- setIsOpen("")}
- disablePortal
- >
-
-
- Really delete this account?
-
-
- If you delete your account, you will no longer be able to sign in, and all of
- your data will be deleted. Deleting your account is permanent and
- non-recoverable action.
-
-
-
-
- Delete account
-
-
-
-
- setIsOpen("")}
+ confirmationButtonLabel={"Delete account"}
+ onConfirm={handleDeleteAccount}
+ isLoading={isLoading}
+ />
+
+
-
-
- Upload Image
-
-
+ {progress.isLoading || progress.value !== 0 || errors["picture"] ? (
+ }
+ label={file?.name}
+ size={file?.size}
+ progress={progress.value}
+ onClick={removePicture}
+ error={errors["picture"]}
/>
- {progress.isLoading || progress.value !== 0 || errors["picture"] ? (
- }
- label={file?.name}
- size={file?.size}
- progress={progress.value}
- onClick={removePicture}
- error={errors["picture"]}
- />
- ) : (
- ""
- )}
-
+
+ Remove
+
+
+ Update
+
-
+
);
};
diff --git a/Client/src/Components/TabPanels/Account/TeamPanel.jsx b/Client/src/Components/TabPanels/Account/TeamPanel.jsx
index 33218bcbb..7d9171384 100644
--- a/Client/src/Components/TabPanels/Account/TeamPanel.jsx
+++ b/Client/src/Components/TabPanels/Account/TeamPanel.jsx
@@ -1,6 +1,6 @@
import { useTheme } from "@emotion/react";
import TabPanel from "@mui/lab/TabPanel";
-import { Box, Button, ButtonGroup, Modal, Stack, Typography } from "@mui/material";
+import { Button, ButtonGroup, Stack, Typography } from "@mui/material";
import { useEffect, useState } from "react";
import Field from "../../Inputs/Field";
import { credentials } from "../../../Validation/validation";
@@ -10,6 +10,7 @@ import { useSelector } from "react-redux";
import BasicTable from "../../BasicTable";
import Select from "../../Inputs/Select";
import LoadingButton from "@mui/lab/LoadingButton";
+import { GenericDialog } from "../../Dialog/genericDialog";
/**
* TeamPanel component manages the organization and team members,
@@ -31,10 +32,10 @@ const TeamPanel = () => {
const { authToken, user } = useSelector((state) => state.auth);
//TODO
- const [orgStates, setOrgStates] = useState({
- name: "Bluewave Labs",
- isEdit: false,
- });
+ // const [orgStates, setOrgStates] = useState({
+ // name: "Bluewave Labs",
+ // isEdit: false,
+ // });
const [toInvite, setToInvite] = useState({
email: "",
role: ["0"],
@@ -134,10 +135,10 @@ const TeamPanel = () => {
}, [errors, toInvite.email]);
// RENAME ORGANIZATION
- const toggleEdit = () => {
- setOrgStates((prev) => ({ ...prev, isEdit: !prev.isEdit }));
- };
- const handleRename = () => {};
+ // const toggleEdit = () => {
+ // setOrgStates((prev) => ({ ...prev, isEdit: !prev.isEdit }));
+ // };
+ // const handleRename = () => {};
// INVITE MEMBER
const [isOpen, setIsOpen] = useState(false);
@@ -327,100 +328,65 @@ const TeamPanel = () => {
table={"team"}
/>
-
+
+
+
);
};
diff --git a/Client/src/Pages/Maintenance/MaintenanceTable/ActionsMenu/index.jsx b/Client/src/Pages/Maintenance/MaintenanceTable/ActionsMenu/index.jsx
index 088dae988..8928b1e05 100644
--- a/Client/src/Pages/Maintenance/MaintenanceTable/ActionsMenu/index.jsx
+++ b/Client/src/Pages/Maintenance/MaintenanceTable/ActionsMenu/index.jsx
@@ -2,23 +2,16 @@ import { useState } from "react";
import { useTheme } from "@emotion/react";
import { useNavigate } from "react-router-dom";
import { useSelector } from "react-redux";
-import {
- Button,
- IconButton,
- Menu,
- MenuItem,
- Modal,
- Stack,
- Typography,
-} from "@mui/material";
-import LoadingButton from "@mui/lab/LoadingButton";
+import { IconButton, Menu, MenuItem } from "@mui/material";
import { logger } from "../../../../Utils/Logger";
import Settings from "../../../../assets/icons/settings-bold.svg?react";
import PropTypes from "prop-types";
import { networkService } from "../../../../main";
import { createToast } from "../../../../Utils/toastUtils";
-const ActionsMenu = ({ isAdmin, maintenanceWindow, updateCallback }) => {
+import Dialog from "../../../../Components/Dialog";
+
+const ActionsMenu = ({ /* isAdmin, */ maintenanceWindow, updateCallback }) => {
maintenanceWindow;
const { authToken } = useSelector((state) => state.auth);
const [anchorEl, setAnchorEl] = useState(null);
@@ -155,71 +148,21 @@ const ActionsMenu = ({ isAdmin, maintenanceWindow, updateCallback }) => {
Remove
- {
+ theme={theme}
+ title={"Do you really want to remove this maintenance window?"}
+ onCancel={(e) => {
e.stopPropagation();
setIsOpen(false);
}}
- >
-
-
- Do you really want to remove this maintenance window?
-
-
- {
- e.stopPropagation();
- setIsOpen(false);
- }}
- >
- Cancel
-
- {
- e.stopPropagation(e);
- handleRemove(e);
- }}
- >
- Delete
-
-
-
-
+ confirmationButtonLabel={"Delete"}
+ onConfirm={(e) => {
+ e.stopPropagation(e);
+ handleRemove(e);
+ }}
+ isLoading={isLoading}
+ />
>
);
};
diff --git a/Client/src/Pages/Monitors/Configure/index.jsx b/Client/src/Pages/Monitors/Configure/index.jsx
index 9eb27c478..22cc8618e 100644
--- a/Client/src/Pages/Monitors/Configure/index.jsx
+++ b/Client/src/Pages/Monitors/Configure/index.jsx
@@ -453,20 +453,17 @@ const Configure = () => {
>
)}
+
+ onCancel={() => setIsOpen(false)}
+ confirmationButtonLabel="Delete"
+ onConfirm={handleRemove}
+ isLoading={isLoading}
+ />
);
};
diff --git a/Client/src/Pages/Monitors/Home/actionsMenu.jsx b/Client/src/Pages/Monitors/Home/actionsMenu.jsx
index fb3bd4b49..7efffa93c 100644
--- a/Client/src/Pages/Monitors/Home/actionsMenu.jsx
+++ b/Client/src/Pages/Monitors/Home/actionsMenu.jsx
@@ -188,25 +188,25 @@ const ActionsMenu = ({ monitor, isAdmin, updateCallback }) => {
)}
+ modelTitle="modal-delete-monitor"
+ modelDescription="delete-monitor-confirmation"
+ />
>
);
};
diff --git a/Client/src/Pages/PageSpeed/Configure/index.jsx b/Client/src/Pages/PageSpeed/Configure/index.jsx
index 71f3ff083..222fa733f 100644
--- a/Client/src/Pages/PageSpeed/Configure/index.jsx
+++ b/Client/src/Pages/PageSpeed/Configure/index.jsx
@@ -1,6 +1,6 @@
import { useEffect, useState } from "react";
import { useTheme } from "@emotion/react";
-import { Box, Button, Modal, Stack, Tooltip, Typography } from "@mui/material";
+import { Box, Stack, Tooltip, Typography } from "@mui/material";
import { useDispatch, useSelector } from "react-redux";
import { useNavigate, useParams } from "react-router";
import {
@@ -25,6 +25,7 @@ import PlayCircleOutlineRoundedIcon from "@mui/icons-material/PlayCircleOutlineR
import SkeletonLayout from "./skeleton";
import useUtils from "../../Monitors/utils";
import "./index.css";
+import Dialog from "../../../Components/Dialog";
const PageSpeedConfigure = () => {
const theme = useTheme();
@@ -37,6 +38,7 @@ const PageSpeedConfigure = () => {
const [monitor, setMonitor] = useState({});
const [errors, setErrors] = useState({});
const { statusColor, pagespeedStatusMsg, determineState } = useUtils();
+ const [buttonLoading, setButtonLoading] = useState(false);
const idMap = {
"monitor-url": "url",
"monitor-name": "name",
@@ -156,12 +158,14 @@ const PageSpeedConfigure = () => {
const [isOpen, setIsOpen] = useState(false);
const handleRemove = async (event) => {
event.preventDefault();
+ setButtonLoading(true);
const action = await dispatch(deletePageSpeed({ authToken, monitor }));
if (action.meta.requestStatus === "fulfilled") {
navigate("/pagespeed");
} else {
createToast({ body: "Failed to delete monitor." });
}
+ setButtonLoading(false);
};
return (
@@ -428,69 +432,16 @@ const PageSpeedConfigure = () => {
>
)}
- setIsOpen(false)}
- disablePortal
- >
-
-
- Do you really want to delete this monitor?
-
-
- Once deleted, this monitor cannot be retrieved.
-
-
- setIsOpen(false)}
- >
- Cancel
-
-
- Delete
-
-
-
-
+ theme={theme}
+ title={"Do you really want to delete this monitor?"}
+ description={"Once deleted, this monitor cannot be retrieved."}
+ onCancel={() => setIsOpen(false)}
+ confirmationButtonLabel={"Delete"}
+ onConfirm={handleRemove}
+ isLoading={buttonLoading}
+ />
);
};
diff --git a/Client/src/Pages/Settings/index.jsx b/Client/src/Pages/Settings/index.jsx
index ad4085ab6..9a8913c39 100644
--- a/Client/src/Pages/Settings/index.jsx
+++ b/Client/src/Pages/Settings/index.jsx
@@ -263,18 +263,15 @@ const Settings = ({ isAdmin }) => {
+ />
)}
{isAdmin && (
@@ -314,18 +311,14 @@ const Settings = ({ isAdmin }) => {
+ />
)}
{isAdmin && (