diff --git a/cypress/integration/group_test.spec.ts b/cypress/integration/group_test.spec.ts index b5453b840c..764826eaf1 100644 --- a/cypress/integration/group_test.spec.ts +++ b/cypress/integration/group_test.spec.ts @@ -9,6 +9,7 @@ import LoginPage from "../support/pages/LoginPage"; import ViewHeaderPage from "../support/pages/ViewHeaderPage"; import AdminClient from "../support/util/AdminClient"; import { keycloakBefore } from "../support/util/keycloak_before"; +import ModalUtils from "../support/util/ModalUtils"; describe("Group test", () => { const loginPage = new LoginPage(); @@ -19,6 +20,7 @@ describe("Group test", () => { const groupModal = new GroupModal(); const searchGroupPage = new SearchGroupPage(); const moveGroupModal = new MoveGroupModal(); + const modalUtils = new ModalUtils(); let groupName = "group"; @@ -53,6 +55,7 @@ describe("Group test", () => { // Delete listingPage.deleteItem(groupName); + modalUtils.checkModalTitle("Delete group?").confirmModal(); masthead.checkNotificationMessage("Group deleted"); }); @@ -71,6 +74,7 @@ describe("Group test", () => { sidebarPage.goToGroups(); listingPage.searchItem(newName, false).itemExist(newName); listingPage.deleteItem(newName); + modalUtils.checkModalTitle("Delete group?").confirmModal(); masthead.checkNotificationMessage("Group deleted"); }); @@ -95,6 +99,7 @@ describe("Group test", () => { listingPage.itemExist(groupName); sidebarPage.goToGroups(); listingPage.deleteItem(targetGroupName); + modalUtils.checkModalTitle("Delete group?").confirmModal(); masthead.checkNotificationMessage("Group deleted"); }); @@ -112,7 +117,9 @@ describe("Group test", () => { new GroupDetailPage().checkListSubGroup(groups); listingPage.deleteItem(groups[0]); + modalUtils.checkModalTitle("Delete group?").confirmModal(); listingPage.deleteItem(groups[1]); + modalUtils.checkModalTitle("Delete group?").confirmModal(); }); it("Group search", () => { diff --git a/cypress/integration/user_fed_ldap_mapper_test.spec.ts b/cypress/integration/user_fed_ldap_mapper_test.spec.ts index 4ddc1da21e..dc83ae6d78 100644 --- a/cypress/integration/user_fed_ldap_mapper_test.spec.ts +++ b/cypress/integration/user_fed_ldap_mapper_test.spec.ts @@ -265,6 +265,7 @@ describe("User Fed LDAP mapper tests", () => { it("Cleanup - delete group", () => { sidebarPage.goToGroups(); listingPage.deleteItem(groupName); + modalUtils.confirmModal(); masthead.checkNotificationMessage("Group deleted"); }); diff --git a/src/components/bread-crumb/GroupBreadCrumbs.tsx b/src/components/bread-crumb/GroupBreadCrumbs.tsx index be34e7d86d..e26bf1b7be 100644 --- a/src/components/bread-crumb/GroupBreadCrumbs.tsx +++ b/src/components/bread-crumb/GroupBreadCrumbs.tsx @@ -42,7 +42,7 @@ export const GroupBreadCrumbs = () => { {group.name} )} - {subGroups.length - 1 === i && <>{group.name}} + {subGroups.length - 1 === i && <>{t("groups:groupDetails")}} ))} diff --git a/src/components/bread-crumb/__tests__/__snapshots__/GroupBreadCrumbs.test.tsx.snap b/src/components/bread-crumb/__tests__/__snapshots__/GroupBreadCrumbs.test.tsx.snap index 573bed9925..1504384ea0 100644 --- a/src/components/bread-crumb/__tests__/__snapshots__/GroupBreadCrumbs.test.tsx.snap +++ b/src/components/bread-crumb/__tests__/__snapshots__/GroupBreadCrumbs.test.tsx.snap @@ -129,7 +129,7 @@ exports[`Group BreadCrumbs tests couple of crumbs 1`] = ` - active group + Group details diff --git a/src/groups/GroupTable.tsx b/src/groups/GroupTable.tsx index 2437e15cd8..da02948ebf 100644 --- a/src/groups/GroupTable.tsx +++ b/src/groups/GroupTable.tsx @@ -5,11 +5,13 @@ import _ from "lodash"; import { AlertVariant, Button, + ButtonVariant, Dropdown, DropdownItem, KebabToggle, ToolbarItem, } from "@patternfly/react-core"; +import { cellWidth } from "@patternfly/react-table"; import { UsersIcon } from "@patternfly/react-icons"; import type GroupRepresentation from "keycloak-admin/lib/defs/groupRepresentation"; @@ -22,6 +24,7 @@ import { GroupsModal } from "./GroupsModal"; import { getLastId } from "./groupIdUtils"; import { MoveGroupDialog } from "./MoveGroupDialog"; import { useSubGroups } from "./SubGroupsContext"; +import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog"; type GroupTableData = GroupRepresentation & { membersLength?: number; @@ -71,27 +74,22 @@ export const GroupTable = () => { return []; }; - const deleteGroup = async (group: GroupRepresentation) => { + const multiDelete = async () => { try { - await adminClient.groups.del({ - id: group.id!, - }); - addAlert(t("groupDelete"), AlertVariant.success); + for (const group of selectedRows) { + await adminClient.groups.del({ + id: group.id!, + }); + } + addAlert( + t("groupDeleted", { count: selectedRows.length }), + AlertVariant.success + ); + setSelectedRows([]); } catch (error) { addAlert(t("groupDeleteError", { error }), AlertVariant.danger); } - return true; - }; - - const multiDelete = async () => { - if (selectedRows!.length !== 0) { - const chainedPromises = selectedRows!.map((group) => deleteGroup(group)); - - await Promise.all(chainedPromises); - addAlert(t("groupsDeleted"), AlertVariant.success); - setSelectedRows([]); - refresh(); - } + refresh(); }; const GroupNameCell = (group: GroupTableData) => ( @@ -120,8 +118,17 @@ export const GroupTable = () => { setIsCreateModalOpen(!isCreateModalOpen); }; + const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({ + titleKey: t("deleteConfirmTitle", { count: selectedRows.length }), + messageKey: t("deleteConfirm", { count: selectedRows.length }), + continueButtonLabel: "common:delete", + continueButtonVariant: ButtonVariant.danger, + onConfirm: multiDelete, + }); + return ( <> + setSelectedRows([...rows])} @@ -143,7 +150,10 @@ export const GroupTable = () => { setIsKebabOpen(!isKebabOpen)} /> + setIsKebabOpen(!isKebabOpen)} + isDisabled={selectedRows!.length === 0} + /> } isOpen={isKebabOpen} isPlain @@ -152,7 +162,7 @@ export const GroupTable = () => { key="action" component="button" onClick={() => { - multiDelete(); + toggleDeleteDialog(); setIsKebabOpen(false); }} > @@ -174,8 +184,8 @@ export const GroupTable = () => { { title: t("common:delete"), onRowClick: async (group: GroupRepresentation) => { - await deleteGroup(group); - refresh(); + setSelectedRows([group]); + toggleDeleteDialog(); return true; }, }, @@ -185,6 +195,7 @@ export const GroupTable = () => { name: "name", displayKey: "groups:groupName", cellRenderer: GroupNameCell, + transforms: [cellWidth(15)], }, { name: "members", diff --git a/src/groups/GroupsSection.tsx b/src/groups/GroupsSection.tsx index 2ecead6123..6d68f34e0c 100644 --- a/src/groups/GroupsSection.tsx +++ b/src/groups/GroupsSection.tsx @@ -97,7 +97,7 @@ export const GroupsSection = () => { /> )}