Skip to content

Commit

Permalink
feat: bulk delete
Browse files Browse the repository at this point in the history
  • Loading branch information
sdisalvo-crd committed Mar 5, 2025
1 parent 4e4e85e commit 617b418
Show file tree
Hide file tree
Showing 14 changed files with 217 additions and 118 deletions.
27 changes: 14 additions & 13 deletions services/credential-server-ui/eslint.config.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import tseslint from 'typescript-eslint'
import js from "@eslint/js";
import globals from "globals";
import reactHooks from "eslint-plugin-react-hooks";
import reactRefresh from "eslint-plugin-react-refresh";
import tseslint from "typescript-eslint";

export default tseslint.config(
{ ignores: ['dist'] },
{ ignores: ["dist"] },
{
extends: [js.configs.recommended, ...tseslint.configs.recommended],
files: ['**/*.{ts,tsx}'],
files: ["**/*.{ts,tsx}"],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
plugins: {
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
"react-hooks": reactHooks,
"react-refresh": reactRefresh,
},
rules: {
...reactHooks.configs.recommended.rules,
'react-refresh/only-export-components': [
'warn',
"react-refresh/only-export-components": [
"warn",
{ allowConstantExport: true },
],
"@typescript-eslint/no-unused-vars": "off",
},
},
)
}
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
.popup-modal.MuiModal-root {
display: flex;
align-items: center;
justify-content: center;

.popup-modal-container {
display: flex;
flex-direction: column;
justify-content: space-between;
width: 29.25rem;
min-height: 13.25rem;
padding: 1.5rem;
background-color: var(--color-neutral-100);
border-radius: 1.5rem;
box-shadow: 0.25rem 0.25rem 1.25rem 0rem rgba(var(--text-color-rgb), 0.16);

.popup-modal-header {
display: flex;
flex-direction: row;
justify-content: space-between;
margin-bottom: 0.5rem;

h2 {
margin: 0;
}

button {
width: 1.5rem;
height: 1.5rem;
padding: 0.25rem;
color: var(--text-color);

&:hover,
&:active {
background-color: var(--color-neutral-300);
}

svg {
width: 1.25rem;
height: 1.25rem;
}
}
}

.popup-modal-body {
font-weight: 500;
text-align: left;
margin-bottom: 1.5rem;
}

.popup-modal-footer {
display: flex;
justify-content: space-between;

button {
text-transform: none;
padding: 0.75rem 1.25rem;
border-radius: 1rem;
box-shadow: none;
width: 12.75rem;

&:first-of-type {
color: var(--text-color);
background-color: var(--color-neutral-100);
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React from "react";
import { Modal, Fade, Box, IconButton, Typography } from "@mui/material";
import { Close } from "@mui/icons-material";
import "./PopupModal.scss";

interface PopupModalProps {
open: boolean;
onClose: () => void;
title: string;
body: React.ReactNode;
footer: React.ReactNode;
}

const PopupModal: React.FC<PopupModalProps> = ({
open,
onClose,
title,
body,
footer,
}) => {
return (
<Modal
open={open}
onClose={onClose}
aria-labelledby="popup-modal-title"
aria-describedby="popup-modal-description"
className="popup-modal"
>
<Fade in={open}>
<Box
color="text.primary"
bgcolor="background.default"
className="popup-modal-container"
>
<div className="popup-modal-header">
<h2>{title}</h2>
<IconButton
size="large"
aria-label="close modal"
disableRipple
onClick={onClose}
>
<Close />
</IconButton>
</div>
<Typography className="popup-modal-body">{body}</Typography>
<div className="popup-modal-footer">{footer}</div>
</Box>
</Fade>
</Modal>
);
};

export { PopupModal };
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./PopupModal";
8 changes: 7 additions & 1 deletion services/credential-server-ui/src/locales/en/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@
"issueCredential": "Issue credential",
"connectionName": "Connection Name",
"connectionDate": "Connection Date",
"issuedCredentials": "Issued Credentials"
"issuedCredentials": "Issued Credentials",
"deleteConnections": {
"title": "Delete Connection(s)",
"body": "Are you sure you want to delete this connection? This action cannot be undone.",
"cancel": "Cancel",
"delete": "Delete"
}
},
"credentials": {
"title": "Credentials"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
fetchContactCredentials,
} from "../../../../store/reducers/connectionsSlice";
import { RootState, AppDispatch } from "../../../../store";
import { Contact, Data } from "../../../../types";
import { Contact, Data } from "../ConnectionsTable/ConnectionsTable.types";
import { menuItems } from "./menuItems";
import { generateRows } from "./helpers";

Expand All @@ -40,9 +40,9 @@ const ConnectionsTable: React.FC = () => {
);
const [filteredContacts, setFilteredContacts] = useState<Contact[]>([]);
// TODO: implement search filter
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [connectionsFilterBySearch, setConnectionsFilterBySearch] =
useState<string>("");
const [numSelected, setNumSelected] = useState<number>(0);

useEffect(() => {
dispatch(fetchContacts());
Expand Down Expand Up @@ -73,6 +73,7 @@ const ConnectionsTable: React.FC = () => {
order,
orderBy,
selected,
setSelected,
page,
rowsPerPage,
handleRequestSort,
Expand All @@ -82,7 +83,7 @@ const ConnectionsTable: React.FC = () => {
handleChangeRowsPerPage,
emptyRows,
visibleRows,
} = useTable(rows);
} = useTable(rows, setNumSelected);

const ActionButton = (
<Tooltip
Expand All @@ -98,7 +99,12 @@ const ConnectionsTable: React.FC = () => {
return (
<Box sx={{ width: "100%" }}>
<Paper className="connections-table">
<EnhancedTableToolbar numSelected={selected.length} />
<EnhancedTableToolbar
numSelected={numSelected}
setNumSelected={setNumSelected}
selected={selected}
setSelected={setSelected}
/>
<TableContainer>
<Table
sx={{ minWidth: 750 }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,34 @@ import * as React from "react";
import { Toolbar, Typography, IconButton, Button } from "@mui/material";
import { DeleteOutline, FilterList } from "@mui/icons-material";
import { i18n } from "../../../../i18n";
import { useState } from "react";
import { PopupModal } from "../../../../components/PopupModal";
import { handleDeleteContact } from "./helpers";
import { AppDispatch } from "../../../../store";
import { useDispatch } from "react-redux";

interface EnhancedTableToolbarProps {
numSelected: number;
setNumSelected: (num: number) => void;
selected: string[];
setSelected: (selected: string[]) => void;
}

const EnhancedTableToolbar: React.FC<EnhancedTableToolbarProps> = (props) => {
const { numSelected } = props;
const handleOpenModal = () =>
setState((prevState) => ({ ...prevState, openModal: true }));
const { numSelected, setNumSelected, selected, setSelected } = props;
const [openModal, setOpenModal] = useState(false);
const dispatch = useDispatch<AppDispatch>();

const handleDelete = async () => {
console.log("delete connections");
for (const id of selected) {
await handleDeleteContact(id, dispatch);
}
setNumSelected(0);
setSelected([]);
setOpenModal(false);
};

return (
<>
<Toolbar className="connection-table-toolbar">
Expand Down Expand Up @@ -41,20 +60,38 @@ const EnhancedTableToolbar: React.FC<EnhancedTableToolbarProps> = (props) => {
aria-label="delete connections"
startIcon={<DeleteOutline />}
className="delete-connections-button"
onClick={handleOpenModal}
onClick={() => setOpenModal(true)}
>
{i18n.t("pages.connections.delete")}
</Button>
</>
)}
</div>
</Toolbar>
{/* <DeleteConnectionModal
openModal={state.openModal}
setOpenModal={(open) =>
setState((prevState) => ({ ...prevState, openModal: open }))
<PopupModal
open={openModal}
onClose={() => setOpenModal(false)}
title={i18n.t("pages.connections.deleteConnections.title")}
body={i18n.t("pages.connections.deleteConnections.body")}
footer={
<>
<Button
variant="contained"
aria-label="cancel delete connections"
onClick={() => setOpenModal(false)}
>
{i18n.t("pages.connections.deleteConnections.cancel")}
</Button>
<Button
variant="contained"
aria-label="confirm delete connections"
onClick={handleDelete}
>
{i18n.t("pages.connections.deleteConnections.delete")}
</Button>
</>
}
/> */}
/>
</>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Contact, Credential, Data } from "../../../../types";
import { Contact, Credential, Data } from "./ConnectionsTable.types";
import axios from "axios";
import { config } from "../../../../config";
import { fetchContacts } from "../../../../store/reducers/connectionsSlice";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useState } from "react";
import { Data } from "../../components/ConnectionsTable/ConnectionsTable.types";
import { useState, useEffect } from "react";
import { Data } from "../ConnectionsTable/ConnectionsTable.types";

type Order = "asc" | "desc";

Expand All @@ -16,10 +16,7 @@ const descendingComparator = <T>(a: T, b: T, orderBy: keyof T) => {
const getComparator = <Key extends keyof Data>(
order: Order,
orderBy: Key
): ((
a: { [key in Key]: number | string },
b: { [key in Key]: number | string }
) => number) => {
): ((a: Data, b: Data) => number) => {
return order === "desc"
? (a, b) => descendingComparator(a, b, orderBy)
: (a, b) => -descendingComparator(a, b, orderBy);
Expand All @@ -35,13 +32,20 @@ const stableSort = <T>(array: T[], comparator: (a: T, b: T) => number) => {
return stabilizedThis.map((el) => el[0]);
};

export const useTable = (rows: Data[]) => {
export const useTable = (
rows: Data[],
setNumSelected: (num: number) => void
) => {
const [order, setOrder] = useState<Order>("asc");
const [orderBy, setOrderBy] = useState<keyof Data>("name");
const [selected, setSelected] = useState<string[]>([]);
const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(5);

useEffect(() => {
setNumSelected(selected.length);
}, [selected, setNumSelected]);

const handleRequestSort = (
event: React.MouseEvent<unknown>,
property: keyof Data
Expand Down Expand Up @@ -103,6 +107,7 @@ export const useTable = (rows: Data[]) => {
order,
orderBy,
selected,
setSelected,
page,
rowsPerPage,
handleRequestSort,
Expand Down

This file was deleted.

Loading

0 comments on commit 617b418

Please sign in to comment.