UNPKG

@keycloakify/keycloak-admin-ui

Version:
135 lines 7.46 kB
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime"; import { KeycloakSelect, SelectVariant, useFetch, } from "../../ui-shared"; import { Button, ButtonVariant, Chip, ChipGroup, SelectOption, } from "@patternfly/react-core"; import { useState } from "react"; import { Controller, useFormContext, } from "react-hook-form"; import { useTranslation } from "react-i18next"; import { Link, useNavigate } from "react-router-dom"; import { useAdminClient } from "../../admin-client"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useRealm } from "../../context/realm-context/RealmContext"; import useToggle from "../../utils/useToggle"; import { toCreatePolicy } from "../../clients/routes/NewPolicy"; import { toPolicyDetails } from "../../clients/routes/PolicyDetails"; import { toResourceDetails } from "../../clients/routes/Resource"; import { NewPolicyDialog } from "../../clients/authorization/NewPolicyDialog"; const typeMapping = { resources: { searchFunction: "listResources", fetchFunction: "getAssociatedResources", }, policies: { searchFunction: "listPolicies", fetchFunction: "getAssociatedPolicies", }, }; export const ResourcesPolicySelect = ({ name, clientId, permissionId, variant = SelectVariant.typeaheadMulti, preSelected, isRequired = false, }) => { const { adminClient } = useAdminClient(); const { realm } = useRealm(); const { t } = useTranslation(); const navigate = useNavigate(); const { control, formState: { errors, isDirty }, } = useFormContext(); const [items, setItems] = useState([]); const [search, setSearch] = useState(""); const [open, setOpen] = useState(false); const [createPolicyDialog, toggleCreatePolicyDialog] = useToggle(); const [policyProviders, setPolicyProviders] = useState(); const [onUnsavedChangesConfirm, setOnUnsavedChangesConfirm] = useState(); const functions = typeMapping[name]; const convert = (p) => ({ id: "_id" in p ? p._id : "id" in p ? p.id : undefined, name: p.name, type: p.type, }); useFetch(async () => { const params = Object.assign({ id: clientId, first: 0, max: 10, permission: "false" }, search === "" ? null : { name: search }); return await Promise.all([ adminClient.clients.listPolicyProviders({ id: clientId }), adminClient.clients[functions.searchFunction](params), permissionId ? adminClient.clients[functions.fetchFunction]({ id: clientId, permissionId, }) : Promise.resolve([]), ]); }, ([providers, ...policies]) => { setPolicyProviders(providers.filter((p) => p.type !== "resource" && p.type !== "scope")); setItems(policies .flat() .filter((r) => typeof r !== "string") .map(convert) .filter(({ id }, index, self) => index === self.findIndex(({ id: otherId }) => id === otherId))); }, [search]); const [toggleUnsavedChangesDialog, UnsavedChangesConfirm] = useConfirmDialog({ titleKey: t("unsavedChangesTitle"), messageKey: t("unsavedChangesConfirm"), continueButtonLabel: t("continue"), continueButtonVariant: ButtonVariant.danger, onConfirm: () => onUnsavedChangesConfirm === null || onUnsavedChangesConfirm === void 0 ? void 0 : onUnsavedChangesConfirm(), }); const to = (policy) => name === "policies" ? toPolicyDetails({ realm: realm, id: clientId, policyId: policy.id, policyType: policy.type, }) : toResourceDetails({ realm, id: clientId, resourceId: policy.id, }); const toSelectOptions = () => items.map((p) => (_jsx(SelectOption, { value: p.id, children: p.name }, p.id))); const toChipGroupItems = (field) => { var _a; return (_jsx(ChipGroup, { children: (_a = field.value) === null || _a === void 0 ? void 0 : _a.map((permissionId) => { const item = items.find((permission) => permission.id === permissionId); if (!item) return; const route = to(item); return (_jsx(Chip, { onClick: () => { var _a; field.onChange((_a = field.value) === null || _a === void 0 ? void 0 : _a.filter((id) => id !== item.id)); }, children: _jsx(Link, { to: route, onClick: (event) => { if (isDirty) { event.preventDefault(); setOnUnsavedChangesConfirm(() => () => navigate(route)); toggleUnsavedChangesDialog(); } }, children: item.name }) }, item.id)); }) })); }; return (_jsxs(_Fragment, { children: [_jsx(UnsavedChangesConfirm, {}), createPolicyDialog && (_jsx(NewPolicyDialog, { policyProviders: policyProviders, onSelect: (p) => { navigate(toCreatePolicy({ id: clientId, realm, policyType: p.type })); }, toggleDialog: toggleCreatePolicyDialog })), _jsx(Controller, { name: name, defaultValue: preSelected ? [preSelected] : [], control: control, rules: { validate: (value) => !isRequired || value.length > 0 }, render: ({ field }) => (_jsx(KeycloakSelect, { toggleId: name, variant: variant, onToggle: (val) => setOpen(val), onFilter: (filter) => { setSearch(filter); return toSelectOptions(); }, onClear: () => { field.onChange([]); setSearch(""); }, selections: field.value, onSelect: (selectedValue) => { var _a; const option = selectedValue.toString(); if (variant === SelectVariant.typeaheadMulti) { const changedValue = ((_a = field.value) === null || _a === void 0 ? void 0 : _a.find((p) => p === option)) ? field.value.filter((p) => p !== option) : [...field.value, option]; field.onChange(changedValue); } else { field.onChange([option]); } setSearch(""); }, isOpen: open, "aria-label": t(name), isDisabled: !!preSelected, validated: errors[name] ? "error" : "default", typeAheadAriaLabel: t(name), chipGroupComponent: toChipGroupItems(field), footer: name === "policies" ? (_jsx(Button, { variant: "link", isInline: true, onClick: () => { if (isDirty) { setOpen(false); setOnUnsavedChangesConfirm(() => toggleCreatePolicyDialog); toggleUnsavedChangesDialog(); } else { toggleCreatePolicyDialog(); } }, children: t("createPolicy") })) : undefined, children: toSelectOptions() })) })] })); }; //# sourceMappingURL=ResourcesPolicySelect.js.map