Users(groups): functionality for adding multiple users to groups (#534)

* add user to groups modal wip

* add logic for selecting multiple groups, API does not support this yet

* cfixcheckbox select bug

* add functionality to select and add multiple groups

* function name

* update cypress test
This commit is contained in:
Eugenia 2021-04-19 15:53:28 -04:00 committed by GitHub
parent ba4e576a2d
commit 820af6abca
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 87 additions and 28 deletions

View file

@ -10,6 +10,7 @@ import GroupModal from "../support/pages/admin_console/manage/groups/GroupModal"
import UserGroupsPage from "../support/pages/admin_console/manage/users/UserGroupsPage";
let groupName = "group";
let groupsList: string[] = [];
describe("Group creation", () => {
const loginPage = new LoginPage();
@ -24,7 +25,7 @@ describe("Group creation", () => {
sidebarPage.goToGroups();
});
it("Add group to be joined", () => {
it("Add groups to be joined", () => {
groupName += "_" + (Math.random() + 1).toString(36).substring(7);
groupModal
@ -32,6 +33,21 @@ describe("Group creation", () => {
.fillGroupForm(groupName)
.clickCreate();
groupsList = [...groupsList, groupName];
masthead.checkNotificationMessage("Group created");
sidebarPage.goToGroups();
listingPage.searchItem(groupName, false).itemExist(groupName);
groupName = "group";
groupName += "_" + (Math.random() + 1).toString(36).substring(7);
groupModal
.open("openCreateGroupModal")
.fillGroupForm(groupName)
.clickCreate();
groupsList = [...groupsList, groupName];
masthead.checkNotificationMessage("Group created");
sidebarPage.goToGroups();
@ -101,7 +117,7 @@ describe("Users test", () => {
listingPage.searchItem(itemId).itemExist(itemId);
});
it("Add user to group test", function () {
it("Add user to groups test", function () {
// Go to user groups
listingPage.searchItem(itemId).itemExist(itemId);
@ -109,7 +125,11 @@ describe("Users test", () => {
userGroupsPage.goToGroupsTab();
userGroupsPage.toggleAddGroupModal();
cy.getId(`${groupName}`).click();
groupsList.forEach((element) => {
cy.getId(`${element}-check`).click();
});
userGroupsPage.joinGroup();
cy.wait(1000);

View file

@ -7,6 +7,7 @@ import {
DataList,
DataListAction,
DataListCell,
DataListCheck,
DataListItem,
DataListItemCells,
DataListItemRow,
@ -23,14 +24,19 @@ import { asyncStateFetch, useAdminClient } from "../context/auth/AdminClient";
import { AngleRightIcon, SearchIcon } from "@patternfly/react-icons";
import GroupRepresentation from "keycloak-admin/lib/defs/groupRepresentation";
import { useErrorHandler } from "react-error-boundary";
import { useParams } from "react-router-dom";
import _ from "lodash";
import { useParams } from "react-router-dom";
export type JoinGroupDialogProps = {
open: boolean;
toggleDialog: () => void;
onClose: () => void;
onConfirm: (newGroup: GroupRepresentation) => void;
username: string;
onConfirm: (newGroups: Group[]) => void;
};
type Group = GroupRepresentation & {
checked?: boolean;
};
export const JoinGroupDialog = ({
@ -42,11 +48,12 @@ export const JoinGroupDialog = ({
}: JoinGroupDialogProps) => {
const { t } = useTranslation("roles");
const adminClient = useAdminClient();
const [selectedRows, setSelectedRows] = useState<Group[]>([]);
const errorHandler = useErrorHandler();
const [navigation, setNavigation] = useState<GroupRepresentation[]>([]);
const [groups, setGroups] = useState<GroupRepresentation[]>([]);
const [navigation, setNavigation] = useState<Group[]>([]);
const [groups, setGroups] = useState<Group[]>([]);
const [filtered, setFiltered] = useState<GroupRepresentation[]>();
const [filter, setFilter] = useState("");
@ -75,6 +82,9 @@ export const JoinGroupDialog = ({
setNavigation([...navigation, selectedGroup]);
}
groups.forEach((group: Group) => {
group.checked = !!selectedRows.find((r) => r.id === group.id);
});
setGroups(groups);
},
errorHandler
@ -96,8 +106,9 @@ export const JoinGroupDialog = ({
form="group-form"
onClick={() => {
toggleDialog();
onConfirm(navigation[navigation.length - 1]);
onConfirm(selectedRows);
}}
isDisabled={selectedRows.length === 0}
>
{t("users:Join")}
</Button>,
@ -166,17 +177,43 @@ export const JoinGroupDialog = ({
</ToolbarContent>
</Toolbar>
<DataList
onSelectDataListItem={(value) => setGroupId(value)}
onSelectDataListItem={(value) => {
setGroupId(value);
}}
aria-label={t("groups")}
isCompact
>
{(filtered || groups).map((group) => (
{(filtered || groups).map((group: Group) => (
<DataListItem
aria-labelledby={group.name}
key={group.id}
id={group.id}
onClick={(e) => {
if ((e.target as HTMLInputElement).type !== "checkbox") {
setGroupId(group.id);
}
}}
>
<DataListItemRow data-testid={group.name}>
<DataListCheck
data-testid={`${group.name}-check`}
isChecked={group.checked}
onChange={(checked, e) => {
group.checked = (e.target as HTMLInputElement).checked;
let newSelectedRows: Group[];
if (!group.checked) {
newSelectedRows = selectedRows.filter(
(r) => r.id !== group.id
);
} else if (group.checked) {
newSelectedRows = [...selectedRows, group];
}
setSelectedRows(newSelectedRows!);
}}
aria-labelledby="data-list-check"
/>
<DataListItemCells
dataListCells={[
<DataListCell key={`name-${group.id}`}>

View file

@ -265,13 +265,14 @@ export const UserGroups = () => {
}
};
const addGroup = async (group: GroupRepresentation): Promise<void> => {
const newGroup = group;
const addGroups = async (groups: GroupRepresentation[]): Promise<void> => {
const newGroups = groups;
newGroups.forEach(async (group) => {
try {
await adminClient.users.addToGroup({
id: id,
groupId: newGroup.id!,
groupId: group.id!,
});
setList(true);
refresh();
@ -282,6 +283,7 @@ export const UserGroups = () => {
AlertVariant.danger
);
}
});
};
return (
@ -292,7 +294,7 @@ export const UserGroups = () => {
<JoinGroupDialog
open={open}
onClose={() => setOpen(!open)}
onConfirm={addGroup}
onConfirm={addGroups}
toggleDialog={() => toggleModal()}
username={username}
/>