UNPKG

@keycloakify/keycloak-admin-ui

Version:
161 lines 15.3 kB
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import { FormErrorText, HelpItem, KeycloakSelect, SelectControl, SelectVariant, useFetch, } from "../../../ui-shared"; import { Alert, Button, Divider, FormGroup, Grid, GridItem, Radio, SelectOption, Switch, TextInput, } from "@patternfly/react-core"; import { GlobeRouteIcon } from "@patternfly/react-icons"; import { isEqual } from "lodash-es"; import { useEffect, useState } from "react"; import { Controller, FormProvider, useFormContext, useWatch, } from "react-hook-form"; import { useTranslation } from "react-i18next"; import { useAdminClient } from "../../../admin-client"; import { FormAccess } from "../../../components/form/FormAccess"; import { KeycloakSpinner } from "../../../ui-shared"; import { DefaultSwitchControl } from "../../../components/SwitchControl"; import { useRealm } from "../../../context/realm-context/RealmContext"; import { useParams } from "../../../utils/useParams"; import useToggle from "../../../utils/useToggle"; import { USERNAME_EMAIL } from "../../../realm-settings/NewAttributeSettings"; import { AddTranslationsDialog, } from "../../../realm-settings/user-profile/attribute/AddTranslationsDialog"; import "../../realm-settings-section.css"; const REQUIRED_FOR = [ { label: "requiredForLabel.both", value: ["admin", "user"] }, { label: "requiredForLabel.users", value: ["user"] }, { label: "requiredForLabel.admins", value: ["admin"] }, ]; export const AttributeGeneralSettings = ({ onHandlingTranslationData, onHandlingGeneratedDisplayName, }) => { var _a; const { adminClient } = useAdminClient(); const { t } = useTranslation(); const { realmRepresentation: realm } = useRealm(); const form = useFormContext(); const [clientScopes, setClientScopes] = useState(); const [config, setConfig] = useState(); const [selectEnabledWhenOpen, setSelectEnabledWhenOpen] = useState(false); const [selectRequiredForOpen, setSelectRequiredForOpen] = useState(false); const [addTranslationsModalOpen, toggleModal] = useToggle(); const { attributeName } = useParams(); const editMode = attributeName ? true : false; const [newAttributeName, setNewAttributeName] = useState(""); const [generatedDisplayName, setGeneratedDisplayName] = useState(""); const [type, setType] = useState(); const [translationsData, setTranslationsData] = useState({ key: "", translations: [], }); const displayNameRegex = /\$\{([^}]+)\}/; const handleAttributeNameChange = (_event, value) => { setNewAttributeName(value); const newDisplayName = value !== "" && (realm === null || realm === void 0 ? void 0 : realm.internationalizationEnabled) ? "${profile.attributes." + `${value}}` : ""; setGeneratedDisplayName(newDisplayName); }; const hasSelector = useWatch({ control: form.control, name: "hasSelector", }); const hasRequiredScopes = useWatch({ control: form.control, name: "hasRequiredScopes", }); const required = useWatch({ control: form.control, name: "isRequired", defaultValue: false, }); const attributeDisplayName = useWatch({ control: form.control, name: "displayName", }); const displayNamePatternMatch = displayNameRegex.test(attributeDisplayName); useFetch(() => adminClient.clientScopes.find(), setClientScopes, []); useFetch(() => adminClient.users.getProfile(), setConfig, []); const handleTranslationsData = (translationsData) => { onHandlingTranslationData(translationsData); }; const handleGeneratedDisplayName = (displayName) => { onHandlingGeneratedDisplayName(displayName); }; useEffect(() => { handleTranslationsData(translationsData); handleGeneratedDisplayName(generatedDisplayName); }, [translationsData, generatedDisplayName]); if (!clientScopes) { return _jsx(KeycloakSpinner, {}); } function setHasSelector(hasSelector) { form.setValue("hasSelector", hasSelector); } function setHasRequiredScopes(hasRequiredScopes) { form.setValue("hasRequiredScopes", hasRequiredScopes); } const handleTranslationsAdded = (translationsData) => { setTranslationsData(translationsData); }; const handleToggleDialog = () => { toggleModal(); handleTranslationsData(translationsData); handleGeneratedDisplayName(generatedDisplayName); }; const formattedAttributeDisplayName = attributeDisplayName === null || attributeDisplayName === void 0 ? void 0 : attributeDisplayName.substring(2, attributeDisplayName.length - 1); return (_jsxs(_Fragment, { children: [addTranslationsModalOpen && (_jsx(AddTranslationsDialog, { translationKey: editMode ? formattedAttributeDisplayName : `profile.attributes.${newAttributeName}`, translations: translationsData, type: type !== null && type !== void 0 ? type : "displayName", onTranslationsAdded: handleTranslationsAdded, toggleDialog: handleToggleDialog, onCancel: () => { toggleModal(); } })), _jsx(FormAccess, { role: "manage-realm", isHorizontal: true, children: _jsxs(FormProvider, { ...form, children: [_jsxs(FormGroup, { label: t("attributeName"), labelIcon: _jsx(HelpItem, { helpText: t("upAttributeNameHelp"), fieldLabelId: "attributeName" }), fieldId: "kc-attribute-name", isRequired: true, children: [_jsx(TextInput, { isRequired: true, id: "kc-attribute-name", defaultValue: "", "data-testid": "attribute-name", isDisabled: editMode, validated: form.formState.errors.name ? "error" : "default", ...form.register("name", { required: true }), onChange: handleAttributeNameChange }), form.formState.errors.name && (_jsx(FormErrorText, { message: t("validateAttributeName") }))] }), _jsx(FormGroup, { label: t("attributeDisplayName"), labelIcon: _jsx(HelpItem, { helpText: t("attributeDisplayNameHelp"), fieldLabelId: "attributeDisplayName" }), fieldId: "kc-attribute-display-name", children: _jsxs(Grid, { hasGutter: true, children: [_jsxs(GridItem, { span: (realm === null || realm === void 0 ? void 0 : realm.internationalizationEnabled) ? 11 : 12, children: [_jsx(TextInput, { id: "kc-attribute-display-name", "data-testid": "attribute-display-name", isDisabled: ((realm === null || realm === void 0 ? void 0 : realm.internationalizationEnabled) && newAttributeName !== "") || (editMode && displayNamePatternMatch), value: editMode ? attributeDisplayName : (realm === null || realm === void 0 ? void 0 : realm.internationalizationEnabled) ? generatedDisplayName : undefined, ...form.register("displayName") }), generatedDisplayName && (_jsx(Alert, { className: "pf-v5-u-mt-sm", variant: "info", isInline: true, isPlain: true, title: t("addAttributeTranslationInfo") }))] }), (realm === null || realm === void 0 ? void 0 : realm.internationalizationEnabled) && (_jsx(GridItem, { span: 1, children: _jsx(Button, { variant: "link", className: "pf-m-plain kc-attribute-display-name-iconBtn", "data-testid": "addAttributeTranslationBtn", "aria-label": t("addAttributeTranslationBtn"), isDisabled: !newAttributeName && !editMode, onClick: () => { setType("displayName"); toggleModal(); }, icon: _jsx(GlobeRouteIcon, {}) }) }))] }) }), _jsx(DefaultSwitchControl, { name: "multivalued", label: t("multivalued"), labelIcon: t("multivaluedHelp") }), _jsx(SelectControl, { name: "group", label: t("attributeGroup"), labelIcon: t("attributeGroupHelp"), controller: { defaultValue: "", }, options: [ { key: "", value: t("none") }, ...(((_a = config === null || config === void 0 ? void 0 : config.groups) === null || _a === void 0 ? void 0 : _a.map((g) => ({ key: g.name, value: g.name, }))) || []), ] }), !USERNAME_EMAIL.includes(attributeName) && (_jsxs(_Fragment, { children: [_jsx(Divider, {}), _jsxs(FormGroup, { label: t("enabledWhen"), labelIcon: _jsx(HelpItem, { helpText: t("enabledWhenTooltip"), fieldLabelId: "enabled-when" }), fieldId: "enabledWhen", hasNoPaddingTop: true, children: [_jsx(Radio, { id: "always", "data-testid": "always", isChecked: !hasSelector, name: "enabledWhen", label: t("always"), onChange: () => setHasSelector(false), className: "pf-v5-u-mb-md" }), _jsx(Radio, { id: "scopesAsRequested", "data-testid": "scopesAsRequested", isChecked: hasSelector, name: "enabledWhen", label: t("scopesAsRequested"), onChange: () => setHasSelector(true), className: "pf-v5-u-mb-md" })] }), hasSelector && (_jsx(FormGroup, { fieldId: "kc-scope-enabled-when", children: _jsx(Controller, { name: "selector.scopes", control: form.control, defaultValue: [], render: ({ field }) => (_jsx(KeycloakSelect, { "data-testid": "enabled-when-scope-field", variant: SelectVariant.typeaheadMulti, typeAheadAriaLabel: "Select", chipGroupProps: { numChips: 3, expandedText: t("hide"), collapsedText: t("showRemaining"), }, onToggle: (isOpen) => setSelectEnabledWhenOpen(isOpen), selections: field.value, onSelect: (selectedValue) => { const option = selectedValue.toString(); let changedValue = [""]; if (field.value) { changedValue = field.value.includes(option) ? field.value.filter((item) => item !== option) : [...field.value, option]; } else { changedValue = [option]; } field.onChange(changedValue); }, onClear: () => { field.onChange([]); }, isOpen: selectEnabledWhenOpen, "aria-labelledby": "scope", children: clientScopes.map((option) => (_jsx(SelectOption, { value: option.name, children: option.name }, option.name))) })) }) }))] })), attributeName !== "username" && (_jsxs(_Fragment, { children: [_jsx(Divider, {}), _jsx(FormGroup, { label: t("required"), labelIcon: _jsx(HelpItem, { helpText: t("requiredHelp"), fieldLabelId: "required" }), fieldId: "kc-required", hasNoPaddingTop: true, children: _jsx(Controller, { name: "isRequired", "data-testid": "required", defaultValue: false, control: form.control, render: ({ field }) => (_jsx(Switch, { id: "kc-required", onChange: field.onChange, isChecked: field.value, label: t("on"), labelOff: t("off"), "aria-label": t("required") })) }) }), required && (_jsxs(_Fragment, { children: [_jsx(FormGroup, { label: t("requiredFor"), fieldId: "requiredFor", hasNoPaddingTop: true, children: _jsx(Controller, { name: "required.roles", "data-testid": "requiredFor", defaultValue: REQUIRED_FOR[0].value, control: form.control, render: ({ field }) => (_jsx("div", { className: "kc-requiredFor", children: REQUIRED_FOR.map((option) => (_jsx(Radio, { id: option.label, "data-testid": option.label, isChecked: isEqual(field.value, option.value), name: "roles", onChange: () => { field.onChange(option.value); }, label: t(option.label), className: "kc-requiredFor-option" }, option.label))) })) }) }), _jsxs(FormGroup, { label: t("requiredWhen"), labelIcon: _jsx(HelpItem, { helpText: t("requiredWhenTooltip"), fieldLabelId: "required-when" }), fieldId: "requiredWhen", hasNoPaddingTop: true, children: [_jsx(Radio, { id: "requiredAlways", "data-testid": "requiredAlways", isChecked: !hasRequiredScopes, name: "requiredWhen", label: t("always"), onChange: () => setHasRequiredScopes(false), className: "pf-v5-u-mb-md" }), _jsx(Radio, { id: "requiredScopesAsRequested", "data-testid": "requiredScopesAsRequested", isChecked: hasRequiredScopes, name: "requiredWhen", label: t("scopesAsRequested"), onChange: () => setHasRequiredScopes(true), className: "pf-v5-u-mb-md" })] }), hasRequiredScopes && (_jsx(FormGroup, { fieldId: "kc-scope-required-when", children: _jsx(Controller, { name: "required.scopes", control: form.control, defaultValue: [], render: ({ field }) => (_jsx(KeycloakSelect, { "data-testid": "required-when-scope-field", variant: SelectVariant.typeaheadMulti, typeAheadAriaLabel: "Select", chipGroupProps: { numChips: 3, expandedText: t("hide"), collapsedText: t("showRemaining"), }, onToggle: (isOpen) => setSelectRequiredForOpen(isOpen), selections: field.value, onSelect: (selectedValue) => { const option = selectedValue.toString(); let changedValue = [""]; if (field.value) { changedValue = field.value.includes(option) ? field.value.filter((item) => item !== option) : [...field.value, option]; } else { changedValue = [option]; } field.onChange(changedValue); }, onClear: () => { field.onChange([]); }, isOpen: selectRequiredForOpen, "aria-labelledby": "scope", children: clientScopes.map((option) => (_jsx(SelectOption, { value: option.name, children: option.name }, option.name))) })) }) }))] }))] }))] }) })] })); }; //# sourceMappingURL=AttributeGeneralSettings.js.map