keycloak-scim/src/groups/GroupsSection.tsx

190 lines
5.8 KiB
TypeScript
Raw Normal View History

import React, { useState } from "react";
2020-09-15 19:54:52 +00:00
import { useTranslation } from "react-i18next";
import {
Button,
Dropdown,
DropdownItem,
KebabToggle,
PageSection,
PageSectionVariants,
ToolbarItem,
AlertVariant,
} from "@patternfly/react-core";
import { UsersIcon } from "@patternfly/react-icons";
import GroupRepresentation from "keycloak-admin/lib/defs/groupRepresentation";
import { GroupsCreateModal } from "./GroupsCreateModal";
import { ViewHeader } from "../components/view-header/ViewHeader";
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";
import { useAdminClient } from "../context/auth/AdminClient";
import { useAlerts } from "../components/alert/Alerts";
import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable";
import "./GroupsSection.css";
import { Link, useRouteMatch } from "react-router-dom";
type GroupTableData = GroupRepresentation & {
membersLength?: number;
};
export const GroupsSection = () => {
2020-09-15 19:54:52 +00:00
const { t } = useTranslation("groups");
const adminClient = useAdminClient();
const [isKebabOpen, setIsKebabOpen] = useState(false);
2020-09-30 13:55:18 +00:00
const [createGroupName, setCreateGroupName] = useState("");
2020-10-13 20:52:23 +00:00
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
const [selectedRows, setSelectedRows] = useState<GroupRepresentation[]>([]);
const { addAlert } = useAlerts();
const { url } = useRouteMatch();
const [key, setKey] = useState("");
const refresh = () => setKey(`${new Date().getTime()}`);
const getMembers = async (id: string) => {
const response = await adminClient.groups.listMembers({ id });
return response ? response.length : 0;
};
2020-09-15 19:54:52 +00:00
const loader = async () => {
const groupsData = await adminClient.groups.find();
const memberPromises = groupsData.map((group) => getMembers(group.id!));
const memberData = await Promise.all(memberPromises);
const updatedObject = groupsData.map((group: GroupTableData, i) => {
group.membersLength = memberData[i];
return group;
});
return updatedObject;
2020-09-15 19:54:52 +00:00
};
2020-10-01 18:52:18 +00:00
const handleModalToggle = () => {
2020-10-01 19:15:23 +00:00
setIsCreateModalOpen(!isCreateModalOpen);
2020-10-01 18:52:18 +00:00
};
const deleteGroup = (group: GroupRepresentation) => {
try {
return adminClient.groups.del({
id: group.id!,
});
} catch (error) {
addAlert(t("groupDeleteError", { error }), AlertVariant.danger);
}
};
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();
}
};
const GroupNameCell = (group: GroupTableData) => (
<>
<Link key={group.id} to={`${url}/${group.id}`}>
{group.name}
</Link>
</>
);
const GroupMemberCell = (group: GroupTableData) => (
<div className="keycloak-admin--groups__member-count">
<UsersIcon key={`user-icon-${group.id}`} />
{group.membersLength}
</div>
);
2020-09-15 19:54:52 +00:00
return (
2020-10-14 20:47:29 +00:00
<>
2020-10-01 19:15:23 +00:00
<ViewHeader titleKey="groups:groups" subKey="groups:groupsDescription" />
<PageSection variant={PageSectionVariants.light}>
<KeycloakDataTable
key={key}
onSelect={(rows) => setSelectedRows([...rows])}
canSelectAll={false}
loader={loader}
ariaLabelKey="client-scopes:clientScopeList"
searchPlaceholderKey="client-scopes:searchFor"
toolbarItem={
<>
<ToolbarItem>
<Button variant="primary" onClick={handleModalToggle}>
{t("createGroup")}
</Button>
</ToolbarItem>
<ToolbarItem>
<Dropdown
toggle={
<KebabToggle
onToggle={() => setIsKebabOpen(!isKebabOpen)}
2020-10-13 21:06:58 +00:00
/>
}
isOpen={isKebabOpen}
isPlain
dropdownItems={[
<DropdownItem
key="action"
component="button"
onClick={() => {
multiDelete();
setIsKebabOpen(false);
}}
>
{t("common:delete")}
</DropdownItem>,
]}
2020-10-14 20:53:32 +00:00
/>
</ToolbarItem>
</>
}
actions={[
{
title: t("moveTo"),
onRowClick: () => console.log("TO DO: Add move to functionality"),
},
{
title: t("common:delete"),
onRowClick: async (group: GroupRepresentation) => {
await deleteGroup(group);
return true;
},
},
]}
columns={[
{
name: "name",
displayKey: "groups:groupName",
cellRenderer: GroupNameCell,
},
{
name: "members",
displayKey: "groups:members",
cellRenderer: GroupMemberCell,
},
]}
emptyState={
<ListEmptyState
hasIcon={true}
message={t("noGroupsInThisRealm")}
instructions={t("noGroupsInThisRealmInstructions")}
primaryActionText={t("createGroup")}
onPrimaryAction={() => handleModalToggle()}
/>
}
/>
<GroupsCreateModal
isCreateModalOpen={isCreateModalOpen}
handleModalToggle={handleModalToggle}
setIsCreateModalOpen={setIsCreateModalOpen}
createGroupName={createGroupName}
setCreateGroupName={setCreateGroupName}
refresh={refresh}
/>
</PageSection>
2020-10-14 20:47:29 +00:00
</>
2020-09-15 19:54:52 +00:00
);
};