Revert "feat(ui): add bulk edit notifications modal and checkmark selection for uptime monitors"

This reverts commit 27dd565bc6.
This commit is contained in:
ashu130698 committed 2026-03-07 10:40:38 +05:30
1 parent 2a1645baf2
commit 5578fdf17f
5 files changed
-243

No files matched your search

-31
View File
@@ -18,7 +18,6 @@
"@mui/x-date-pickers": "7.29.4",
"@reduxjs/toolkit": "2.7.0",
"@types/maplibre-gl": "^1.13.2",
"@types/react-map-gl": "^6.1.8",
"axios": "^1.7.4",
"dayjs": "1.11.13",
"flag-icons": "7.3.2",
@@ -2291,15 +2290,6 @@
"integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==",
"license": "MIT"
},
"node_modules/@types/mapbox-gl": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/@types/mapbox-gl/-/mapbox-gl-3.4.1.tgz",
"integrity": "sha512-NsGKKtgW93B+UaLPti6B7NwlxYlES5DpV5Gzj9F75rK5ALKsqSk15CiEHbOnTr09RGbr6ZYiCdI+59NNNcAImg==",
"license": "MIT",
"dependencies": {
"@types/geojson": "*"
}
},
"node_modules/@types/maplibre-gl": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/@types/maplibre-gl/-/maplibre-gl-1.13.2.tgz",
@@ -2341,18 +2331,6 @@
"@types/react": "^18.0.0"
}
},
"node_modules/@types/react-map-gl": {
"version": "6.1.8",
"resolved": "https://registry.npmjs.org/@types/react-map-gl/-/react-map-gl-6.1.8.tgz",
"integrity": "sha512-M0WLRx7Q7m47aFoNRu7NxwaboY/K12J+zgSesJnwisIq5EgqkGUdl9AUb/yRd0cJtx6oOTeOMVPb7emEdlXpQg==",
"license": "MIT",
"dependencies": {
"@types/geojson": "*",
"@types/mapbox-gl": "<3.5",
"@types/react": "*",
"@types/viewport-mercator-project": "*"
}
},
"node_modules/@types/react-transition-group": {
"version": "4.4.12",
"license": "MIT",
@@ -2373,15 +2351,6 @@
"version": "0.0.6",
"license": "MIT"
},
"node_modules/@types/viewport-mercator-project": {
"version": "6.1.6",
"resolved": "https://registry.npmjs.org/@types/viewport-mercator-project/-/viewport-mercator-project-6.1.6.tgz",
"integrity": "sha512-uWrbqhRXFeiT6CAvRjf0BkQKRkKED+ofrPhglKpUktQML3463dEPiA4iwe7cZQs6m49Zo/g03rL7ChMLiE5Z8w==",
"license": "MIT",
"dependencies": {
"gl-matrix": "^3.2.0"
}
},
"node_modules/@ungap/structured-clone": {
"version": "1.3.0",
"dev": true,
-1
View File
@@ -26,7 +26,6 @@
"@mui/x-date-pickers": "7.29.4",
"@reduxjs/toolkit": "2.7.0",
"@types/maplibre-gl": "^1.13.2",
"@types/react-map-gl": "^6.1.8",
"axios": "^1.7.4",
"dayjs": "1.11.13",
"flag-icons": "7.3.2",
@@ -1,134 +0,0 @@
import { Dialog, Select, Autocomplete } from "@/Components/inputs";
import { useState, useMemo } from "react";
import { useTranslation } from "react-i18next";
import { useGet, usePatch } from "@/Hooks/UseApi";
import type { Notification } from "@/Types/Notification";
import Stack from "@mui/material/Stack";
import MenuItem from "@mui/material/MenuItem";
import Typography from "@mui/material/Typography";
import Divider from "@mui/material/Divider";
import IconButton from "@mui/material/IconButton";
import { Trash2 } from "lucide-react";
import { useTheme } from "@mui/material/styles";
import { LAYOUT } from "@/Utils/Theme/constants";
type ActionType = "add" | "remove" | "set";
export const BulkEditNotificationsModal = ({
open,
monitorIds,
onClose,
onSuccess,
}: {
open: boolean;
monitorIds: string[];
onClose: () => void;
onSuccess: () => void;
}) => {
const { t } = useTranslation();
const theme = useTheme();
const [action, setAction] = useState<ActionType>("add");
const [selectedNotificationIds, setSelectedNotificationIds] = useState<string[]>([]);
const { data: notifications } = useGet<Notification[]>("/notifications/team");
const { patch, loading } = usePatch();
const handleConfirm = async () => {
if (selectedNotificationIds.length === 0 && action !== "set") return;
const result = await patch("/notifications", {
monitorIds,
notificationIds: selectedNotificationIds,
action,
});
if (result?.success) {
onSuccess();
onClose();
}
};
const notificationOptions = useMemo(() => {
return (notifications ?? []).map((n) => ({
...n,
name: n.notificationName,
}));
}, [notifications]);
const selectedItems = useMemo(() => {
return notificationOptions.filter((n) => selectedNotificationIds.includes(n.id));
}, [notificationOptions, selectedNotificationIds]);
return (
<Dialog
open={open}
title={t("pages.uptime.bulkEdit.title", { defaultValue: "Bulk Edit Notifications" })}
content={t("pages.uptime.bulkEdit.description", {
defaultValue: `Apply notification changes to ${monitorIds.length} selected monitors.`,
})}
onConfirm={handleConfirm}
onCancel={onClose}
loading={loading}
confirmText={t("common.buttons.save")}
>
<Stack spacing={theme.spacing(LAYOUT.MD)} sx={{ mt: 2 }}>
<Select
value={action}
onChange={(e) => setAction(e.target.value as ActionType)}
fieldLabel={t("pages.uptime.bulkEdit.actionLabel", { defaultValue: "Action" })}
>
<MenuItem value="add">
{t("pages.uptime.bulkEdit.actionAdd", { defaultValue: "Add Notifications" })}
</MenuItem>
<MenuItem value="remove">
{t("pages.uptime.bulkEdit.actionRemove", { defaultValue: "Remove Notifications" })}
</MenuItem>
<MenuItem value="set">
{t("pages.uptime.bulkEdit.actionSet", { defaultValue: "Set Notifications (Replace All)" })}
</MenuItem>
</Select>
<Autocomplete
multiple
options={notificationOptions}
value={selectedItems}
getOptionLabel={(option) => option.name}
onChange={(_: unknown, newValue: typeof notificationOptions) => {
setSelectedNotificationIds(newValue.map((n) => n.id));
}}
isOptionEqualToValue={(option, value) => option.id === value.id}
fieldLabel={t("pages.uptime.bulkEdit.notificationsLabel", {
defaultValue: "Notifications",
})}
/>
{selectedItems.length > 0 && (
<Stack flex={1} width="100%">
{selectedItems.map((notification, index) => (
<Stack
direction="row"
alignItems="center"
key={notification.id}
width="100%"
>
<Typography flexGrow={1}>{notification.notificationName}</Typography>
<IconButton
size="small"
onClick={() => {
setSelectedNotificationIds((prev) =>
prev.filter((id) => id !== notification.id)
);
}}
aria-label="Remove notification"
>
<Trash2 size={16} />
</IconButton>
{index < selectedItems.length - 1 && <Divider />}
</Stack>
))}
</Stack>
)}
</Stack>
</Dialog>
);
};
@@ -16,7 +16,6 @@ import { useTheme } from "@mui/material/styles";
import { useNavigate } from "react-router-dom";
import { usePost } from "@/Hooks/UseApi";
import { useSelector } from "react-redux";
import { Checkbox } from "@/Components/inputs";
import type { Monitor } from "@/Types/Monitor";
import type { ActionMenuItem } from "@/Components/actions-menu";
@@ -35,8 +34,6 @@ export const MonitorTable = ({
setPage,
rowsPerPage,
setRowsPerPage,
selectedMonitors,
setSelectedMonitors,
}: {
monitors: Monitor[];
refetch: Function;
@@ -50,8 +47,6 @@ export const MonitorTable = ({
setPage: (page: number) => void;
rowsPerPage: number;
setRowsPerPage: (rowsPerPage: number) => void;
selectedMonitors: string[];
setSelectedMonitors: React.Dispatch<React.SetStateAction<string[]>>;
}) => {
const { t } = useTranslation();
const theme = useTheme();
@@ -156,37 +151,6 @@ export const MonitorTable = ({
</Box>
);
const headers: Header<Monitor>[] = [
{
id: "select",
content: (
<Checkbox
checked={monitors.length > 0 && selectedMonitors.length === monitors.length}
indeterminate={selectedMonitors.length > 0 && selectedMonitors.length < monitors.length}
onChange={(e) => {
e.stopPropagation();
if (e.target.checked) {
setSelectedMonitors(monitors.map((m) => m.id));
} else {
setSelectedMonitors([]);
}
}}
/>
),
onClick: (e) => e.stopPropagation(),
render: (row) => (
<Checkbox
checked={selectedMonitors.includes(row.id)}
onChange={(e) => {
e.stopPropagation();
if (e.target.checked) {
setSelectedMonitors((prev) => [...prev, row.id]);
} else {
setSelectedMonitors((prev) => prev.filter((id) => id !== row.id));
}
}}
/>
),
},
{
id: "name",
content: (
@@ -2,11 +2,8 @@ import { ControlsFilter, HeaderMonitorsSummary } from "@/Components/monitors";
import { MonitorBasePageWithStates } from "@/Components/design-elements";
import { TextField, Dialog } from "@/Components/inputs";
import Stack from "@mui/material/Stack";
import Typography from "@mui/material/Typography";
import { MonitorTable } from "@/Pages/Uptime/Monitors/Components/UptimeMonitorsTable";
import { HeaderCreate } from "@/Components/common";
import { Button } from "@/Components/inputs";
import { BulkEditNotificationsModal } from "./Components/BulkEditNotificationsModal";
import { useTranslation } from "react-i18next";
import useMediaQuery from "@mui/material/useMediaQuery";
@@ -42,9 +39,6 @@ const UptimeMonitorsPage = () => {
const [selectedMonitor, setSelectedMonitor] = useState<Monitor | null>(null);
const isDialogOpen = Boolean(selectedMonitor);
const [selectedMonitors, setSelectedMonitors] = useState<string[]>([]);
const [isBulkEditOpen, setIsBulkEditOpen] = useState(false);
const debouncedSearch = useDebounce<string>(search, 300);
// Convert filter selections to API filter values
@@ -165,28 +159,6 @@ const UptimeMonitorsPage = () => {
justifyContent={isSmall ? "flex-start" : "space-between"}
gap={theme.spacing(4)}
>
{selectedMonitors.length > 0 ? (
<Stack direction="row" alignItems="center" spacing={2} width="100%">
<Typography variant="body1" fontWeight="medium">
{selectedMonitors.length} monitor(s) selected
</Typography>
<Button
variant="contained"
color="primary"
onClick={() => setIsBulkEditOpen(true)}
>
Bulk Edit Notifications
</Button>
<Button
variant="text"
color="inherit"
onClick={() => setSelectedMonitors([])}
>
Cancel Selection
</Button>
</Stack>
) : (
<>
<ControlsFilter
selectedTypes={selectedTypes}
setSelectedTypes={setSelectedTypes}
@@ -203,8 +175,6 @@ const UptimeMonitorsPage = () => {
setSearch(event.target.value);
}}
/>
</>
)}
</Stack>
<MonitorTable
monitors={monitorsWithChecks || []}
@@ -218,8 +188,6 @@ const UptimeMonitorsPage = () => {
setSortField={setSortField}
sortOrder={sortOrder}
setSortOrder={setSortOrder}
selectedMonitors={selectedMonitors}
setSelectedMonitors={setSelectedMonitors}
setRowsPerPage={(rowsPerPage: number) => {
dispatch(
setRowsPerPage({
@@ -238,15 +206,6 @@ const UptimeMonitorsPage = () => {
onCancel={handleCancel}
loading={isDeleting}
/>
<BulkEditNotificationsModal
open={isBulkEditOpen}
monitorIds={selectedMonitors}
onClose={() => setIsBulkEditOpen(false)}
onSuccess={() => {
setSelectedMonitors([]);
refetch();
}}
/>
</MonitorBasePageWithStates>
);
};