@keycloakify/keycloak-admin-ui
Version:
Repackaged Keycloak Admin UI
148 lines • 8.26 kB
JavaScript
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { useHelp } from "../ui-shared";
import { AlertVariant, Button, ButtonVariant, Checkbox, Popover, } from "@patternfly/react-core";
import { QuestionCircleIcon } from "@patternfly/react-icons";
import { cellWidth } from "@patternfly/react-table";
import { intersectionBy, sortBy, uniqBy } from "lodash-es";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { useAdminClient } from "../admin-client";
import { useAlerts } from "../ui-shared";
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
import { GroupPath } from "../components/group/GroupPath";
import { GroupPickerDialog } from "../components/group/GroupPickerDialog";
import { ListEmptyState } from "../ui-shared";
import { KeycloakDataTable } from "../ui-shared";
import { useAccess } from "../context/access/Access";
export const UserGroups = ({ user }) => {
var _a, _b, _c;
const { adminClient } = useAdminClient();
const { t } = useTranslation();
const { addAlert, addError } = useAlerts();
const [key, setKey] = useState(0);
const refresh = () => setKey(key + 1);
const [selectedGroups, setSelectedGroups] = useState([]);
const [isDirectMembership, setDirectMembership] = useState(true);
const [directMembershipList, setDirectMembershipList] = useState([]);
const [open, setOpen] = useState(false);
const { enabled } = useHelp();
const { hasAccess } = useAccess();
const isManager = hasAccess("manage-users");
const alphabetize = (groupsList) => {
return sortBy(groupsList, (group) => { var _a; return (_a = group.path) === null || _a === void 0 ? void 0 : _a.toUpperCase(); });
};
const loader = async (first, max, search) => {
const params = {
first: first,
max: max,
};
const searchParam = search || "";
if (searchParam) {
params.search = searchParam;
}
const joinedUserGroups = await adminClient.users.listGroups({
...params,
id: user.id,
});
setDirectMembershipList([...joinedUserGroups]);
const indirect = [];
if (!isDirectMembership)
joinedUserGroups.forEach((g) => {
var _a;
const paths = (((_a = g.path) === null || _a === void 0 ? void 0 : _a.substring(1).match(/((~\/)|[^/])+/g)) || []).slice(0, -1);
indirect.push(...paths.map((p) => {
var _a;
return ({
name: p,
path: (_a = g.path) === null || _a === void 0 ? void 0 : _a.substring(0, g.path.indexOf(p) + p.length),
});
}));
});
return alphabetize(uniqBy([...joinedUserGroups, ...indirect], "path"));
};
const toggleModal = () => {
setOpen(!open);
};
const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({
titleKey: t("leaveGroup", {
count: selectedGroups.length,
name: (_a = selectedGroups[0]) === null || _a === void 0 ? void 0 : _a.name,
}),
messageKey: t("leaveGroupConfirmDialog", {
count: selectedGroups.length,
groupname: (_b = selectedGroups[0]) === null || _b === void 0 ? void 0 : _b.name,
username: user.username,
}),
continueButtonLabel: "leave",
continueButtonVariant: ButtonVariant.danger,
onConfirm: async () => {
try {
await Promise.all(selectedGroups.map((group) => adminClient.users.delFromGroup({
id: user.id,
groupId: group.id,
})));
setSelectedGroups([]);
addAlert(t("removedGroupMembership"), AlertVariant.success);
}
catch (error) {
addError("removedGroupMembershipError", error);
}
refresh();
},
});
const leave = (group) => {
setSelectedGroups(group);
toggleDeleteDialog();
};
const addGroups = async (groups) => {
try {
await Promise.all(groups.map((group) => adminClient.users.addToGroup({
id: user.id,
groupId: group.id,
})));
addAlert(t("addedGroupMembership"), AlertVariant.success);
}
catch (error) {
addError("addedGroupMembershipError", error);
}
refresh();
};
return (_jsxs(_Fragment, { children: [_jsx(DeleteConfirm, {}), open && (_jsx(GroupPickerDialog, { id: user.id, type: "selectMany", text: {
title: t("joinGroupsFor", { username: user.username }),
ok: "join",
}, canBrowse: isManager, onClose: () => setOpen(false), onConfirm: async (groups = []) => {
await addGroups(groups);
setOpen(false);
} })), _jsx(KeycloakDataTable, { loader: loader, className: "keycloak_user-section_groups-table", isPaginated: true, ariaLabelKey: "roleList", searchPlaceholderKey: "searchGroup", canSelectAll: true, onSelect: (groups) => isDirectMembership
? setSelectedGroups(groups)
: setSelectedGroups(intersectionBy(groups, directMembershipList, "id")), isRowDisabled: (group) => !isDirectMembership &&
directMembershipList.every((item) => item.id !== group.id), toolbarItem: _jsxs(_Fragment, { children: [_jsx(Button, { className: "kc-join-group-button", onClick: toggleModal, "data-testid": "add-group-button", isDisabled: !((_c = user.access) === null || _c === void 0 ? void 0 : _c.manageGroupMembership), children: t("joinGroup") }), _jsx(Checkbox, { label: t("directMembership"), id: "kc-direct-membership-checkbox", onChange: () => {
setDirectMembership(!isDirectMembership);
refresh();
}, isChecked: isDirectMembership, className: "direct-membership-check" }, "direct-membership-check"), _jsx(Button, { onClick: () => leave(selectedGroups), "data-testid": "leave-group-button", variant: "link", isDisabled: selectedGroups.length === 0, children: t("leave") }), enabled && (_jsx(Popover, { "aria-label": "Basic popover", position: "bottom", bodyContent: _jsx("div", { children: t("whoWillAppearPopoverTextUsers") }), children: _jsx(Button, { variant: "link", className: "kc-who-will-appear-button", icon: _jsx(QuestionCircleIcon, {}), children: t("whoWillAppearLinkTextUsers") }, "who-will-appear-button") }))] }), columns: [
{
name: "groupMembership",
displayKey: "groupMembership",
cellRenderer: (group) => group.name || "-",
transforms: [cellWidth(40)],
},
{
name: "path",
displayKey: "path",
cellRenderer: (group) => (_jsx(GroupPath, { group: group })),
transforms: [cellWidth(45)],
},
{
name: "",
cellRenderer: (group) => {
var _a;
const canLeaveGroup = directMembershipList.some((item) => item.id === group.id) ||
directMembershipList.length === 0 ||
isDirectMembership;
return canLeaveGroup ? (_jsx(Button, { "data-testid": `leave-${group.name}`, onClick: () => leave([group]), variant: "link", isDisabled: !((_a = user.access) === null || _a === void 0 ? void 0 : _a.manageGroupMembership), children: t("leave") })) : ("-");
},
transforms: [cellWidth(20)],
},
], emptyState: _jsx(ListEmptyState, { hasIcon: true, message: t("noGroups"), instructions: t("noGroupsText"), primaryActionText: t("joinGroup"), onPrimaryAction: toggleModal }) }, key)] }));
};
//# sourceMappingURL=UserGroups.js.map