@keycloakify/keycloak-admin-ui
Version:
Repackaged Keycloak Admin UI
161 lines • 15.3 kB
JavaScript
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