UNPKG

@keycloakify/keycloak-admin-ui

Version:
174 lines 10.8 kB
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; import { useAlerts } from "../../ui-shared"; import { AlertVariant, Button, ButtonVariant, Dropdown, DropdownItem, DropdownList, MenuToggle, ToolbarItem, } from "@patternfly/react-core"; import { EllipsisVIcon } from "@patternfly/react-icons"; import { useState } from "react"; import { useTranslation } from "react-i18next"; import { Link } from "react-router-dom"; import { useAdminClient } from "../../admin-client"; import { ChangeTypeDropdown } from "../../client-scopes/ChangeTypeDropdown"; import { SearchDropdown, SearchToolbar, nameFilter, typeFilter, } from "../../client-scopes/details/SearchFilter"; import { AllClientScopes, CellDropdown, ClientScope, addClientScope, changeClientScope, removeClientScope, } from "../../components/client-scope/ClientScopeTypes"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { ListEmptyState } from "../../ui-shared"; import { KeycloakDataTable } from "../../ui-shared"; import { useAccess } from "../../context/access/Access"; import { useRealm } from "../../context/realm-context/RealmContext"; import { translationFormatter } from "../../utils/translationFormatter"; import useLocaleSort, { mapByKey } from "../../utils/useLocaleSort"; import { toDedicatedScope } from "../../clients/routes/DedicatedScopeDetails"; import { AddScopeDialog } from "../../clients/scopes/AddScopeDialog"; import "./client-scopes.css"; const DEDICATED_ROW = "dedicated"; const TypeSelector = ({ clientId, refresh, fineGrainedAccess, ...scope }) => { const { adminClient } = useAdminClient(); const { t } = useTranslation(); const { addAlert, addError } = useAlerts(); const { hasAccess } = useAccess(); const isDedicatedRow = (value) => value.id === DEDICATED_ROW; const isManager = hasAccess("manage-clients") || fineGrainedAccess; return (_jsx(CellDropdown, { isDisabled: isDedicatedRow(scope) || !isManager, clientScope: scope, type: scope.type, onSelect: async (value) => { try { await changeClientScope(adminClient, clientId, scope, scope.type, value); addAlert(t("clientScopeSuccess"), AlertVariant.success); refresh(); } catch (error) { addError("clientScopeError", error); } } })); }; export const ClientScopes = ({ clientId, protocol, clientName, fineGrainedAccess, }) => { var _a; const { adminClient } = useAdminClient(); const { t } = useTranslation(); const { addAlert, addError } = useAlerts(); const { realm } = useRealm(); const localeSort = useLocaleSort(); const [searchType, setSearchType] = useState("name"); const [searchTypeType, setSearchTypeType] = useState(AllClientScopes.none); const [addDialogOpen, setAddDialogOpen] = useState(false); const [rest, setRest] = useState(); const [selectedRows, setSelectedRowState] = useState([]); const setSelectedRows = (rows) => setSelectedRowState(rows.filter(({ id }) => id !== DEDICATED_ROW)); const [kebabOpen, setKebabOpen] = useState(false); const [key, setKey] = useState(0); const refresh = () => setKey(key + 1); const isDedicatedRow = (value) => value.id === DEDICATED_ROW; const { hasAccess } = useAccess(); const isManager = hasAccess("manage-clients") || fineGrainedAccess; const isViewer = hasAccess("view-clients") || fineGrainedAccess; const loader = async (first, max, search) => { const defaultClientScopes = await adminClient.clients.listDefaultClientScopes({ id: clientId }); const optionalClientScopes = await adminClient.clients.listOptionalClientScopes({ id: clientId }); const clientScopes = await adminClient.clientScopes.find(); const find = (id) => clientScopes.find((clientScope) => id === clientScope.id); const optional = optionalClientScopes.map((c) => { const scope = find(c.id); const row = { ...c, type: ClientScope.optional, description: scope === null || scope === void 0 ? void 0 : scope.description, }; return row; }); const defaultScopes = defaultClientScopes.map((c) => { const scope = find(c.id); const row = { ...c, type: ClientScope.default, description: scope === null || scope === void 0 ? void 0 : scope.description, }; return row; }); let rows = [...optional, ...defaultScopes]; const names = rows.map((row) => row.name); setRest(clientScopes .filter((scope) => !names.includes(scope.name)) .filter((scope) => scope.protocol === protocol)); rows = localeSort(rows, mapByKey("name")); if (isViewer) { rows.unshift({ id: DEDICATED_ROW, name: t("dedicatedScopeName", { clientName }), type: AllClientScopes.none, description: t("dedicatedScopeDescription"), }); } const filter = searchType === "name" ? nameFilter(search) : typeFilter(searchTypeType); const firstNum = Number(first); return rows.filter(filter).slice(firstNum, firstNum + Number(max)); }; const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({ titleKey: t("deleteClientScope", { count: selectedRows.length, name: (_a = selectedRows[0]) === null || _a === void 0 ? void 0 : _a.name, }), messageKey: "deleteConfirmClientScopes", continueButtonLabel: "delete", continueButtonVariant: ButtonVariant.danger, onConfirm: async () => { try { await removeClientScope(adminClient, clientId, selectedRows[0], selectedRows[0].type); addAlert(t("clientScopeRemoveSuccess"), AlertVariant.success); refresh(); } catch (error) { addError("clientScopeRemoveError", error); } }, }); return (_jsxs(_Fragment, { children: [rest && (_jsx(AddScopeDialog, { clientScopes: rest, clientName: clientName, open: addDialogOpen, toggleDialog: () => setAddDialogOpen(!addDialogOpen), onAdd: async (scopes) => { try { await Promise.all(scopes.map(async (scope) => await addClientScope(adminClient, clientId, scope.scope, scope.type))); addAlert(t("clientScopeSuccess"), AlertVariant.success); refresh(); } catch (error) { addError("clientScopeError", error); } } })), _jsx(KeycloakDataTable, { loader: loader, ariaLabelKey: `clientScopeList-${key}`, searchPlaceholderKey: searchType === "name" ? "searchByName" : undefined, canSelectAll: true, isPaginated: true, isSearching: searchType === "type", onSelect: (rows) => setSelectedRows([...rows]), searchTypeComponent: _jsx(SearchDropdown, { searchType: searchType, onSelect: (searchType) => setSearchType(searchType) }), toolbarItem: _jsxs(_Fragment, { children: [_jsx(SearchToolbar, { searchType: searchType, type: searchTypeType, onSelect: (searchType) => setSearchType(searchType), onType: (value) => { setSearchTypeType(value); refresh(); } }), isManager && (_jsxs(_Fragment, { children: [_jsx(DeleteConfirm, {}), _jsx(ToolbarItem, { children: _jsx(Button, { onClick: () => setAddDialogOpen(true), children: t("addClientScope") }) }), _jsx(ToolbarItem, { children: _jsx(ChangeTypeDropdown, { clientId: clientId, selectedRows: selectedRows, refresh: refresh }) }), _jsx(ToolbarItem, { children: _jsx(Dropdown, { onOpenChange: (isOpen) => setKebabOpen(isOpen), toggle: (ref) => (_jsx(MenuToggle, { "data-testid": "kebab", "aria-label": "Kebab toggle", ref: ref, variant: "plain", onClick: () => setKebabOpen(!kebabOpen), isExpanded: kebabOpen, children: _jsx(EllipsisVIcon, {}) })), isOpen: kebabOpen, children: _jsx(DropdownList, { children: _jsx(DropdownItem, { isDisabled: selectedRows.length === 0, onClick: async () => { try { await Promise.all(selectedRows.map((row) => removeClientScope(adminClient, clientId, { ...row }, row.type))); setKebabOpen(false); setSelectedRows([]); addAlert(t("clientScopeRemoveSuccess")); refresh(); } catch (error) { addError("clientScopeRemoveError", error); } }, children: t("remove") }, "deleteAll") }) }) })] }))] }), columns: [ { name: "name", displayKey: "assignedClientScope", cellRenderer: (row) => { if (isDedicatedRow(row)) { return (_jsx(Link, { to: toDedicatedScope({ realm, clientId }), children: row.name })); } return row.name; }, }, { name: "type", displayKey: "assignedType", cellRenderer: (row) => (_jsx(TypeSelector, { clientId: clientId, refresh: refresh, ...row })), }, { name: "description", cellFormatters: [translationFormatter(t)] }, ], actions: isManager ? [ { title: t("remove"), onRowClick: async (row) => { setSelectedRows([row]); toggleDeleteDialog(); return true; }, }, ] : [], emptyState: _jsx(ListEmptyState, { message: t("emptyClientScopes"), instructions: t("emptyClientScopesInstructions"), primaryActionText: t("emptyClientScopesPrimaryAction"), onPrimaryAction: () => setAddDialogOpen(true) }) }, key)] })); }; //# sourceMappingURL=ClientScopes.js.map