diff --git a/cypress/e2e/memberships/deleteItemMembership.cy.ts b/cypress/e2e/memberships/deleteItemMembership.cy.ts
index d8c975674..9023501aa 100644
--- a/cypress/e2e/memberships/deleteItemMembership.cy.ts
+++ b/cypress/e2e/memberships/deleteItemMembership.cy.ts
@@ -1,5 +1,6 @@
import { buildItemPath } from '../../../src/config/paths';
import {
+ CONFIRM_MEMBERSHIP_DELETE_BUTTON_ID,
buildItemMembershipRowDeleteButtonId,
buildShareButtonId,
} from '../../../src/config/selectors';
@@ -16,6 +17,7 @@ const deleteItemMembership = ({
cy.get(`#${buildShareButtonId(itemId)}`).click();
cy.wait(TABLE_MEMBERSHIP_RENDER_TIME);
cy.get(`#${buildItemMembershipRowDeleteButtonId(id)}`).click();
+ cy.get(`#${CONFIRM_MEMBERSHIP_DELETE_BUTTON_ID}`).click();
};
describe('Delete Membership', () => {
diff --git a/src/components/item/sharing/ConfirmMembership.tsx b/src/components/item/sharing/ConfirmMembership.tsx
new file mode 100644
index 000000000..ba61a8a87
--- /dev/null
+++ b/src/components/item/sharing/ConfirmMembership.tsx
@@ -0,0 +1,110 @@
+import {
+ Alert,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogContentText,
+ DialogTitle,
+} from '@mui/material';
+
+import { ItemMembership, PermissionLevel } from '@graasp/sdk';
+import { ItemRecord } from '@graasp/sdk/frontend';
+import { Button } from '@graasp/ui';
+
+import { useCurrentUserContext } from '@/components/context/CurrentUserContext';
+
+import { useBuilderTranslation } from '../../../config/i18n';
+import { mutations } from '../../../config/queryClient';
+import { CONFIRM_MEMBERSHIP_DELETE_BUTTON_ID } from '../../../config/selectors';
+import { BUILDER } from '../../../langs/constants';
+import CancelButton from '../../common/CancelButton';
+
+const labelId = 'alert-dialog-title';
+const descriptionId = 'alert-dialog-description';
+
+type Props = {
+ open?: boolean;
+ handleClose: () => void;
+ item: ItemRecord;
+ membershipToDelete: ItemMembership | null;
+ hasOnlyOneAdmin: boolean;
+};
+
+const DeleteItemDialog = ({
+ item,
+ open = false,
+ handleClose,
+ membershipToDelete,
+ hasOnlyOneAdmin = false,
+}: Props): JSX.Element => {
+ const { t: translateBuilder } = useBuilderTranslation();
+ const { data: member } = useCurrentUserContext();
+
+ const { mutate: deleteItemMembership } = mutations.useDeleteItemMembership();
+
+ const onDelete = () => {
+ if (membershipToDelete?.id) {
+ deleteItemMembership({ id: membershipToDelete.id, itemId: item.id });
+ handleClose();
+ }
+ };
+
+ let dialogText = '';
+ const isDeletingLastAdmin =
+ hasOnlyOneAdmin && membershipToDelete?.permission === PermissionLevel.Admin;
+ // incase of deleting the only admin
+ if (isDeletingLastAdmin) {
+ dialogText = translateBuilder(BUILDER.DELETE_LAST_ADMIN_ALERT_MESSAGE);
+ } else if (member?.id === membershipToDelete?.member?.id) {
+ // deleting yourself
+ dialogText = translateBuilder(BUILDER.DELETE_OWN_MEMBERSHIP_MESSAGE);
+ } else {
+ // delete other members
+ dialogText = translateBuilder(BUILDER.DELETE_MEMBERSHIP_MESSAGE, {
+ name: membershipToDelete?.member.name,
+ permissionLevel: membershipToDelete?.permission,
+ });
+ }
+ return (
+
+ );
+};
+
+export default DeleteItemDialog;
diff --git a/src/components/item/sharing/ItemMembershipsTable.tsx b/src/components/item/sharing/ItemMembershipsTable.tsx
index da5777d29..eb636f027 100644
--- a/src/components/item/sharing/ItemMembershipsTable.tsx
+++ b/src/components/item/sharing/ItemMembershipsTable.tsx
@@ -1,4 +1,4 @@
-import { useMemo } from 'react';
+import { useMemo, useState } from 'react';
import { Typography } from '@mui/material';
@@ -19,6 +19,7 @@ import {
buildItemMembershipRowId,
} from '../../../config/selectors';
import { BUILDER } from '../../../langs/constants';
+import DeleteItemDialog from './ConfirmMembership';
import TableRowDeleteButtonRenderer from './TableRowDeleteButtonRenderer';
import TableRowPermissionRenderer from './TableRowPermissionRenderer';
@@ -69,12 +70,23 @@ const ItemMembershipsTable = ({
}: Props): JSX.Element => {
const { t: translateBuilder } = useBuilderTranslation();
- const { mutate: deleteItemMembership } = mutations.useDeleteItemMembership();
const { mutate: editItemMembership } = mutations.useEditItemMembership();
const { mutate: shareItem } = mutations.usePostItemMembership();
+ const [open, setOpen] = useState(false);
+ const [membershipToDelete, setMembershipToDelete] =
+ useState(null);
+
+ const handleClickOpen = () => {
+ setOpen(true);
+ };
+
+ const handleClose = () => {
+ setOpen(false);
+ };
const onDelete = ({ instance }: { instance: ItemMembership }) => {
- deleteItemMembership({ id: instance.id, itemId: item.id });
+ setMembershipToDelete(instance);
+ handleClickOpen();
};
// never changes, so we can use useMemo
@@ -196,16 +208,31 @@ const ItemMembershipsTable = ({
});
return (
-
+ <>
+
+ {open && (
+ per.permission === PermissionLevel.Admin,
+ ).length === 1
+ }
+ />
+ )}
+ >
);
};
diff --git a/src/config/selectors.ts b/src/config/selectors.ts
index ea9f5a675..8266cbeea 100644
--- a/src/config/selectors.ts
+++ b/src/config/selectors.ts
@@ -312,6 +312,8 @@ export const EDIT_MODAL_ID = 'editModal';
export const EDIT_ITEM_MODAL_CANCEL_BUTTON_ID = 'editModalCancelButton';
export const FILE_SETTING_MAX_WIDTH_ID = 'fileSettingMaxWidth';
+export const CONFIRM_MEMBERSHIP_DELETE_BUTTON_ID =
+ 'confirmDeleteMembershipButton';
export const buildDownloadButtonId = (itemId: string): string =>
`download-button-id-${itemId}`;
export const CUSTOM_APP_URL_ID = 'customAppURLId';
diff --git a/src/langs/ar.json b/src/langs/ar.json
index e1189a164..f0a880c64 100644
--- a/src/langs/ar.json
+++ b/src/langs/ar.json
@@ -242,6 +242,12 @@
"USER_SWITCH_SIGN_OUT_BUTTON": "خروج",
"USER_SWITCH_SIGNED_OUT_TOOLTIP": "أنت غير مسجل الدخول.",
"USER_SWITCH_SWITCH_USER_TEXT": "تسجيل الدخول بحساب آخر",
+ "DELETE_MEMBERSHIP": "حذف العضوية",
+ "DELETE_MEMBERSHIP_MODAL_CONFIRM_BUTTON": "تأكيد",
+ "DELETE_OWN_MEMBERSHIP_MESSAGE": "هل أنت متأكد من إلغاء عضويتك على هذا العنصر؟",
+ "DELETE_MEMBERSHIP_MESSAGE": "هل أنت متأكد من إزالة عضوية {{name}}ك {{permissionLevel}} على هذا العنصر؟",
+ "DELETE_LAST_ADMIN_ALERT_MESSAGE": "لا يمكنك إلغاء عضوية هذا الأدمن حيث أنه الأدمن الوحيد",
+ "APPROVE_BUTTON_TEXT": "موافق",
"STATUS_TOOLTIP_IS_PINNED": "مُثبت",
"STATUS_TOOLTIP_IS_HIDDEN": "مخفي",
"STATUS_TOOLTIP_IS_PUBLIC": "عام",
diff --git a/src/langs/constants.ts b/src/langs/constants.ts
index 4118097be..3d7e571ac 100644
--- a/src/langs/constants.ts
+++ b/src/langs/constants.ts
@@ -307,6 +307,13 @@ export const BUILDER = {
STATUS_TOOLTIP_IS_COLLAPSIBLE: 'STATUS_TOOLTIP_IS_COLLAPSIBLE',
STATUS_TOOLTIP_SHOW_CHATBOX: 'STATUS_TOOLTIP_SHOW_CHATBOX',
SETTINGS_FILE_SETTINGS_TITLE: 'SETTINGS_FILE_SETTINGS_TITLE',
+ DELETE_MEMBERSHIP: 'DELETE_MEMBERSHIP',
+ DELETE_MEMBERSHIP_MODAL_CONFIRM_BUTTON:
+ 'DELETE_MEMBERSHIP_MODAL_CONFIRM_BUTTON',
+ DELETE_MEMBERSHIP_MESSAGE: 'DELETE_MEMBERSHIP_MESSAGE',
+ DELETE_OWN_MEMBERSHIP_MESSAGE: 'DELETE_OWN_MEMBERSHIP_MESSAGE',
+ DELETE_LAST_ADMIN_ALERT_MESSAGE: 'DELETE_LAST_ADMIN_ALERT_MESSAGE',
+ APPROVE_BUTTON_TEXT: 'APPROVE_BUTTON_TEXT',
APP_URL: 'APP_URL',
CREATE_CUSTOM_APP: 'CREATE_CUSTOM_APP',
};
diff --git a/src/langs/de.json b/src/langs/de.json
index 81b1cd218..a6382dcdd 100644
--- a/src/langs/de.json
+++ b/src/langs/de.json
@@ -227,5 +227,10 @@
"USER_SWITCH_PROFILE_BUTTON": "Siehe Profil",
"USER_SWITCH_SIGN_OUT_BUTTON": "Abmelden",
"USER_SWITCH_SIGNED_OUT_TOOLTIP": "Sie sind nicht angemeldet.",
- "USER_SWITCH_SWITCH_USER_TEXT": "Melden Sie sich mit einem anderen Konto an"
+ "USER_SWITCH_SWITCH_USER_TEXT": "Melden Sie sich mit einem anderen Konto an",
+ "DELETE_MEMBERSHIP": "Mitgliedschaft löschen",
+ "DELETE_MEMBERSHIP_MODAL_CONFIRM_BUTTON": "Bestätigen",
+ "DELETE_OWN_MEMBERSHIP_MESSAGE": "Sind Sie sicher, dass Sie Ihre eigene Berechtigung für dieses Element entfernen möchten? Sie verlieren den Zugriff auf dieses Element, diese Aktion ist irreversibel.",
+ "DELETE_MEMBERSHIP_MESSAGE": "Sind Sie sicher, dass Sie {{permissionLevel}} Zugang für diesen Artikel für {{name}} entfernen möchten?",
+ "DELETE_LAST_ADMIN_ALERT_MESSAGE": "Sie dürfen diesen Administrator nicht löschen, da dies der einzige Administrator ist"
}
diff --git a/src/langs/en.json b/src/langs/en.json
index 9d79a21b6..c54a9ebc8 100644
--- a/src/langs/en.json
+++ b/src/langs/en.json
@@ -249,6 +249,12 @@
"STATUS_TOOLTIP_IS_COLLAPSIBLE": "Collapsible",
"STATUS_TOOLTIP_SHOW_CHATBOX": "Chatbox visible",
"SETTINGS_FILE_SETTINGS_TITLE": "File Settings",
+ "DELETE_MEMBERSHIP": "Delete Membership",
+ "DELETE_MEMBERSHIP_MODAL_CONFIRM_BUTTON": "Confirm",
+ "DELETE_OWN_MEMBERSHIP_MESSAGE": "Are you sure you want to delete your own permission on this item? You will loose access to this item, this action can not be undone.",
+ "DELETE_MEMBERSHIP_MESSAGE": "Are you sure you want to remove {{permissionLevel}} access on this item for {{name}}? They will loose access to this item.",
+ "DELETE_LAST_ADMIN_ALERT_MESSAGE": "You are not allowed to delete this admin as this is the only admin",
+ "APPROVE_BUTTON_TEXT": "OK",
"APP_URL": "App Url",
"CREATE_CUSTOM_APP": "Add Your Custom App"
}
diff --git a/src/langs/fr.json b/src/langs/fr.json
index ae8b87a49..8dd10cdd1 100644
--- a/src/langs/fr.json
+++ b/src/langs/fr.json
@@ -247,5 +247,10 @@
"STATUS_TOOLTIP_IS_PUBLISHED": "Publié",
"STATUS_TOOLTIP_IS_COLLAPSIBLE": "Minifié",
"STATUS_TOOLTIP_SHOW_CHATBOX": "Chatbox visible",
- "SETTINGS_FILE_SETTINGS_TITLE": "Paramètres du fichier"
+ "SETTINGS_FILE_SETTINGS_TITLE": "Paramètres du fichier",
+ "DELETE_MEMBERSHIP": "Supprimer l'autorisation",
+ "DELETE_MEMBERSHIP_MODAL_CONFIRM_BUTTON": "Confirmer",
+ "DELETE_OWN_MEMBERSHIP_MESSAGE": "Êtes-vous sûr de vouloir supprimer votre propre autorisation sur cet élément ? Vous perdrez l'accès à cet élément, cette action est irréversible.",
+ "DELETE_MEMBERSHIP_MESSAGE": "Êtes-vous sûr de vouloir supprimer l'accès en {{permissionLevel}} sur cet élément à {{name}} ? Il leur sera impossible d'accéder à cet élément.",
+ "DELETE_LAST_ADMIN_ALERT_MESSAGE": "Vous n'êtes pas autorisé à supprimer le dernier administrateur de cet élément."
}