feat: adding delete and detail actions
This commit is contained in:
1 parent
55e3c674b6
commit
91f608a62a
3 files changed
+274
-10
No files matched your search
@@ -0,0 +1,11 @@
|
||||
import { useSelector } from "react-redux";
|
||||
|
||||
const useIsAdmin = () => {
|
||||
const { user } = useSelector((state) => state.auth);
|
||||
const isAdmin =
|
||||
(user?.role?.includes("admin") ?? false) ||
|
||||
(user?.role?.includes("superadmin") ?? false);
|
||||
return isAdmin;
|
||||
};
|
||||
|
||||
export { useIsAdmin };
|
||||
@@ -0,0 +1,235 @@
|
||||
/* TODO I basically copied and pasted this component from the actionsMenu. Check how we can make it reusable */
|
||||
|
||||
import { useRef, useState } from "react";
|
||||
import { useSelector, useDispatch } from "react-redux";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { createToast } from "../../../../Utils/toastUtils";
|
||||
/* import { logger } from "../../../Utils/Logger"; */
|
||||
import { IconButton, Menu, MenuItem } from "@mui/material";
|
||||
import {
|
||||
deleteUptimeMonitor,
|
||||
/* pauseUptimeMonitor, */
|
||||
getUptimeMonitorsByTeamId,
|
||||
} from "../../../../Features/UptimeMonitors/uptimeMonitorsSlice";
|
||||
import Settings from "../../../../assets/icons/settings-bold.svg?react";
|
||||
import PropTypes from "prop-types";
|
||||
import Dialog from "../../../../Components/Dialog";
|
||||
import { networkService } from "../../../../Utils/NetworkService.js";
|
||||
|
||||
const InfrastructureMenu = ({ monitor, isAdmin, updateCallback }) => {
|
||||
/* const [anchorEl, setAnchorEl] = useState(null);
|
||||
const [actions, setActions] = useState({}); */
|
||||
const actions = { id: monitor.id, url: monitor.url };
|
||||
const anchor = useRef(null);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
||||
const dispatch = useDispatch();
|
||||
const theme = useTheme();
|
||||
const authState = useSelector((state) => state.auth);
|
||||
const authToken = authState.authToken;
|
||||
const { isLoading } = useSelector((state) => state.uptimeMonitors);
|
||||
|
||||
/* 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." });
|
||||
}
|
||||
}; */
|
||||
|
||||
/* TODO
|
||||
1) Clean component
|
||||
2) Rerender after removing
|
||||
3) Add padding to inputs (I took of their height)
|
||||
*/
|
||||
|
||||
const openMenu = (e) => {
|
||||
e.stopPropagation();
|
||||
setIsOpen(true);
|
||||
};
|
||||
|
||||
const closeMenu = (e) => {
|
||||
e.stopPropagation();
|
||||
setIsOpen(false);
|
||||
};
|
||||
|
||||
const openRemove = (e) => {
|
||||
closeMenu(e);
|
||||
setIsDialogOpen(true);
|
||||
};
|
||||
const cancelRemove = () => {
|
||||
setIsDialogOpen(false);
|
||||
};
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
function openDetails(id) {
|
||||
navigate(`/infrastructure/${id}`);
|
||||
}
|
||||
|
||||
const handleRemove = async () => {
|
||||
try {
|
||||
/* TODO not working, dont know why */
|
||||
const result = await networkService.deleteMonitorById({
|
||||
authToken,
|
||||
monitorId: actions.id,
|
||||
});
|
||||
console.log(result);
|
||||
/* Toast success */
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
/* Toast error */
|
||||
} finally {
|
||||
setIsDialogOpen(false);
|
||||
updateCallback();
|
||||
}
|
||||
/* let monitor = { _id: actions.id };
|
||||
const action = await dispatch(
|
||||
deleteUptimeMonitor({ authToken: authState.authToken, monitor })
|
||||
);
|
||||
if (action.meta.requestStatus === "fulfilled") {
|
||||
setIsOpen(false); // close modal
|
||||
dispatch(getUptimeMonitorsByTeamId(authState.authToken));
|
||||
updateCallback();
|
||||
createToast({ body: "Monitor deleted successfully." });
|
||||
} else {
|
||||
createToast({ body: "Failed to delete monitor." });
|
||||
} */
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<IconButton
|
||||
aria-label="monitor actions"
|
||||
onClick={openMenu}
|
||||
sx={{
|
||||
"&:focus": {
|
||||
outline: "none",
|
||||
},
|
||||
"& svg path": {
|
||||
stroke: theme.palette.other.icon,
|
||||
},
|
||||
}}
|
||||
ref={anchor}
|
||||
>
|
||||
<Settings />
|
||||
</IconButton>
|
||||
|
||||
<Menu
|
||||
className="actions-menu"
|
||||
anchorEl={anchor.current}
|
||||
open={isOpen}
|
||||
onClose={closeMenu}
|
||||
disableScrollLock
|
||||
slotProps={{
|
||||
paper: {
|
||||
sx: {
|
||||
"& ul": { p: theme.spacing(2.5) },
|
||||
"& li": { m: 0 },
|
||||
"& li:last-of-type": {
|
||||
color: theme.palette.error.contrastText,
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
{/*
|
||||
Open sit action. Not necessary for infrastructure?
|
||||
|
||||
{actions.url !== null ? (
|
||||
<MenuItem
|
||||
onClick={(e) => {
|
||||
closeMenu(e);
|
||||
e.stopPropagation();
|
||||
window.open(actions.url, "_blank", "noreferrer");
|
||||
}}
|
||||
>
|
||||
Open site
|
||||
</MenuItem>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
*/}
|
||||
<MenuItem onClick={() => openDetails(actions.id)}>Details</MenuItem>
|
||||
{/* TODO - pass monitor id to Incidents page */}
|
||||
{/* <MenuItem
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
navigate(`/incidents/${actions.id}`);
|
||||
}}
|
||||
>
|
||||
Incidents
|
||||
</MenuItem> */}
|
||||
{/* {isAdmin && (
|
||||
<MenuItem
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
|
||||
navigate(`/monitors/configure/${actions.id}`);
|
||||
}}
|
||||
>
|
||||
Configure
|
||||
</MenuItem>
|
||||
)} */}
|
||||
{/* {isAdmin && (
|
||||
<MenuItem
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
navigate(`/monitors/create/${actions.id}`);
|
||||
}}
|
||||
>
|
||||
Clone
|
||||
</MenuItem>
|
||||
)} */}
|
||||
{/* {isAdmin && (
|
||||
<MenuItem
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handlePause(e);
|
||||
}}
|
||||
>
|
||||
{monitor?.isActive === true ? "Pause" : "Resume"}
|
||||
</MenuItem>
|
||||
)} */}
|
||||
{isAdmin && <MenuItem onClick={openRemove}>Remove</MenuItem>}
|
||||
</Menu>
|
||||
<Dialog
|
||||
open={isDialogOpen}
|
||||
theme={theme}
|
||||
title="Do you really want to delete this monitor?"
|
||||
description="Once deleted, this monitor cannot be retrieved."
|
||||
onCancel={cancelRemove}
|
||||
confirmationButtonLabel="Delete"
|
||||
/* Do we need stop propagation? */
|
||||
onConfirm={handleRemove}
|
||||
isLoading={isLoading}
|
||||
modelTitle="modal-delete-monitor"
|
||||
modelDescription="delete-monitor-confirmation"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
InfrastructureMenu.propTypes = {
|
||||
monitor: PropTypes.shape({
|
||||
_id: PropTypes.string,
|
||||
url: PropTypes.string,
|
||||
type: PropTypes.string,
|
||||
isActive: PropTypes.bool,
|
||||
}).isRequired,
|
||||
isAdmin: PropTypes.bool,
|
||||
updateCallback: PropTypes.func,
|
||||
};
|
||||
|
||||
export { InfrastructureMenu };
|
||||
@@ -4,7 +4,7 @@ import { /* useDispatch, */ useSelector } from "react-redux";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import useUtils from "../Monitors/utils";
|
||||
import { jwtDecode } from "jwt-decode";
|
||||
import GearIcon from "../../Assets/icons/settings-bold.svg?react";
|
||||
// import GearIcon from "../../Assets/icons/settings-bold.svg?react";
|
||||
import CPUChipIcon from "../../Assets/icons/cpu-chip.svg?react";
|
||||
import {
|
||||
Box,
|
||||
@@ -27,6 +27,9 @@ import { Pagination } from "./components/TablePagination";
|
||||
import { networkService } from "../../Utils/NetworkService.js";
|
||||
import CustomGauge from "../../Components/Charts/CustomGauge/index.jsx";
|
||||
import Host from "../Monitors/Home/host.jsx";
|
||||
import ActionsMenu from "../Monitors/Home/actionsMenu.jsx";
|
||||
import { useIsAdmin } from "../../Hooks/useIsAdmin.js";
|
||||
import { InfrastructureMenu } from "./components/Menu";
|
||||
|
||||
const columns = [
|
||||
{ label: "Host" },
|
||||
@@ -71,7 +74,9 @@ Analyze existing BasicTable
|
||||
* @returns {JSX.Element} The infrastructure monitoring page.
|
||||
*/
|
||||
|
||||
function Infrastructure(/* {isAdmin} */) {
|
||||
function Infrastructure() {
|
||||
/* Adding this custom hook so we can avoid using the HOC approach that can lower performance (we are calling the admin logic N times on initializing the project. using a custom hook will cal it ass needed ) */
|
||||
const isAdmin = useIsAdmin();
|
||||
const theme = useTheme();
|
||||
|
||||
const navigate = useNavigate();
|
||||
@@ -93,7 +98,7 @@ function Infrastructure(/* {isAdmin} */) {
|
||||
const { authToken } = useSelector((state) => state.auth);
|
||||
const user = jwtDecode(authToken);
|
||||
|
||||
const fetchMonitors = useCallback(async () => {
|
||||
const fetchMonitors = async () => {
|
||||
try {
|
||||
const response = await networkService.getMonitorsByTeamId({
|
||||
authToken,
|
||||
@@ -106,6 +111,7 @@ function Infrastructure(/* {isAdmin} */) {
|
||||
page: page,
|
||||
rowsPerPage: rowsPerPage,
|
||||
});
|
||||
console.log({ response });
|
||||
setMonitorState({
|
||||
monitors: response?.data?.data?.monitors ?? [],
|
||||
total: response?.data?.data?.monitorCount ?? 0,
|
||||
@@ -113,7 +119,7 @@ function Infrastructure(/* {isAdmin} */) {
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}, [page, rowsPerPage, authToken]);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchMonitors();
|
||||
@@ -121,8 +127,6 @@ function Infrastructure(/* {isAdmin} */) {
|
||||
|
||||
const { determineState } = useUtils();
|
||||
const { monitors, total: totalMonitors } = monitorState;
|
||||
console.log({ monitors });
|
||||
console.log(monitors[0]?.checks[0]?.memory.usage_percent);
|
||||
const monitorsAsRows = monitors.map((monitor) => ({
|
||||
id: monitor._id,
|
||||
url: monitor.url,
|
||||
@@ -133,12 +137,21 @@ function Infrastructure(/* {isAdmin} */) {
|
||||
mem: monitor?.checks[0]?.memory.usage_percent * 100,
|
||||
disk: monitor?.checks[0]?.disk[0]?.usage_percent * 100,
|
||||
}));
|
||||
/* Adding click on row action */
|
||||
/* Adding actions to the table */
|
||||
|
||||
/*
|
||||
TODO
|
||||
Clean component (actions component)
|
||||
Add padding to inputs (I took of their height)
|
||||
Add toast
|
||||
|
||||
*/
|
||||
|
||||
function openDetails(id) {
|
||||
navigate(`/infrastructure/${id}`);
|
||||
}
|
||||
function handleActionMenuDelete() {
|
||||
fetchMonitors();
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack
|
||||
@@ -273,10 +286,15 @@ function Infrastructure(/* {isAdmin} */) {
|
||||
},
|
||||
}}
|
||||
>
|
||||
<GearIcon
|
||||
<InfrastructureMenu
|
||||
monitor={row}
|
||||
isAdmin={isAdmin}
|
||||
updateCallback={handleActionMenuDelete}
|
||||
/>
|
||||
{/* <GearIcon
|
||||
width={20}
|
||||
height={20}
|
||||
/>
|
||||
/> */}
|
||||
</IconButton>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
|
||||
Reference in new issue
Block a user