Do not show enabled and required for email and username (#3766)
This commit is contained in:
parent
edf79d41af
commit
e6c415628f
6 changed files with 312 additions and 252 deletions
|
@ -92,7 +92,7 @@ describe("User profile tabs", () => {
|
|||
|
||||
userProfileTab.cancelRemovingValidator();
|
||||
userProfileTab.removeValidator();
|
||||
cy.get('tbody [class="kc-emptyValidators"]').contains("No validators.");
|
||||
cy.get(".kc-emptyValidators").contains("No validators.");
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ export default class UserProfile {
|
|||
private newAttributeCheckboxes = 'input[type="checkbox"]';
|
||||
private newAttributeRequiredFor = 'input[name="roles"]';
|
||||
private newAttributeRequiredWhen = 'input[name="requiredWhen"]';
|
||||
private newAttributeEmptyValidators = 'tbody [class="kc-emptyValidators"]';
|
||||
private newAttributeEmptyValidators = ".kc-emptyValidators";
|
||||
private newAttributeAnnotationKey = 'input[name="annotations[0].key"]';
|
||||
private newAttributeAnnotationValue = 'input[name="annotations[0].value"]';
|
||||
private validatorRolesList = 'tbody [data-label="Role name"]';
|
||||
|
|
|
@ -23,13 +23,30 @@ import { useAlerts } from "../components/alert/Alerts";
|
|||
import { UserProfileProvider } from "./user-profile/UserProfileContext";
|
||||
import type { UserProfileAttribute } from "@keycloak/keycloak-admin-client/lib/defs/userProfileConfig";
|
||||
import type { AttributeParams } from "./routes/Attribute";
|
||||
import type { KeyValueType } from "../components/key-value-form/key-value-convert";
|
||||
import { convertToFormValues } from "../util";
|
||||
import { flatten } from "flat";
|
||||
|
||||
import "./realm-settings-section.css";
|
||||
|
||||
type UserProfileAttributeType = UserProfileAttribute & Attribute & Permission;
|
||||
type IndexedAnnotations = {
|
||||
key: string;
|
||||
value: unknown;
|
||||
};
|
||||
|
||||
export type IndexedValidations = {
|
||||
key: string;
|
||||
value?: Record<string, unknown>[];
|
||||
};
|
||||
|
||||
type UserProfileAttributeType = Omit<
|
||||
UserProfileAttribute,
|
||||
"validations" | "annotations"
|
||||
> &
|
||||
Attribute &
|
||||
Permission & {
|
||||
validations: IndexedValidations[];
|
||||
annotations: IndexedAnnotations[];
|
||||
};
|
||||
|
||||
type Attribute = {
|
||||
roles: string[];
|
||||
|
@ -56,6 +73,8 @@ type PermissionEdit = [
|
|||
}
|
||||
];
|
||||
|
||||
export const USERNAME_EMAIL = ["username", "email"];
|
||||
|
||||
const CreateAttributeFormContent = ({
|
||||
save,
|
||||
}: {
|
||||
|
@ -108,12 +127,6 @@ export default function NewAttributeSettings() {
|
|||
const [config, setConfig] = useState<UserProfileConfig | null>(null);
|
||||
const editMode = attributeName ? true : false;
|
||||
|
||||
const convert = (obj: Record<string, unknown>[] | undefined) =>
|
||||
Object.entries(obj || []).map(([key, value]) => ({
|
||||
key,
|
||||
value,
|
||||
}));
|
||||
|
||||
useFetch(
|
||||
() => adminClient.users.getProfile(),
|
||||
(config) => {
|
||||
|
@ -133,15 +146,38 @@ export default function NewAttributeSettings() {
|
|||
Object.entries(
|
||||
flatten<any, any>({ permissions, selector, required }, { safe: true })
|
||||
).map(([key, value]) => form.setValue(key, value));
|
||||
form.setValue("annotations", convert(annotations));
|
||||
form.setValue("validations", validations);
|
||||
form.setValue(
|
||||
"annotations",
|
||||
Object.entries(annotations || {}).map(([key, value]) => ({
|
||||
key,
|
||||
value,
|
||||
}))
|
||||
);
|
||||
form.setValue(
|
||||
"validations",
|
||||
Object.entries(validations || {}).map(([key, value]) => ({
|
||||
key,
|
||||
value,
|
||||
}))
|
||||
);
|
||||
form.setValue("isRequired", required !== undefined);
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const save = async (profileConfig: UserProfileAttributeType) => {
|
||||
const annotations = (profileConfig.annotations! as KeyValueType[]).reduce(
|
||||
const validations = profileConfig.validations.reduce(
|
||||
(prevValidations, currentValidations) => {
|
||||
prevValidations[currentValidations.key] =
|
||||
currentValidations.value?.length === 0
|
||||
? {}
|
||||
: currentValidations.value;
|
||||
return prevValidations;
|
||||
},
|
||||
{} as Record<string, unknown>
|
||||
);
|
||||
|
||||
const annotations = profileConfig.annotations.reduce(
|
||||
(obj, item) => Object.assign(obj, { [item.key]: item.value }),
|
||||
{}
|
||||
);
|
||||
|
@ -161,6 +197,7 @@ export default function NewAttributeSettings() {
|
|||
selector: profileConfig.selector,
|
||||
permissions: profileConfig.permissions!,
|
||||
annotations,
|
||||
validations,
|
||||
},
|
||||
profileConfig.isRequired
|
||||
? { required: profileConfig.required }
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Modal, ModalVariant } from "@patternfly/react-core";
|
||||
import {
|
||||
Modal,
|
||||
ModalVariant,
|
||||
Text,
|
||||
TextVariants,
|
||||
} from "@patternfly/react-core";
|
||||
import {
|
||||
TableComposable,
|
||||
Tbody,
|
||||
|
@ -10,13 +15,13 @@ import {
|
|||
Tr,
|
||||
} from "@patternfly/react-table";
|
||||
|
||||
import type { KeyValueType } from "../../../components/key-value-form/key-value-convert";
|
||||
import type { IndexedValidations } from "../../NewAttributeSettings";
|
||||
import { AddValidatorRoleDialog } from "./AddValidatorRoleDialog";
|
||||
import { Validator, validators as allValidator } from "./Validators";
|
||||
import useToggle from "../../../utils/useToggle";
|
||||
|
||||
export type AddValidatorDialogProps = {
|
||||
selectedValidators: KeyValueType[];
|
||||
selectedValidators: IndexedValidations[];
|
||||
toggleDialog: () => void;
|
||||
onConfirm: (newValidator: Validator) => void;
|
||||
};
|
||||
|
@ -56,33 +61,39 @@ export const AddValidatorDialog = ({
|
|||
isOpen
|
||||
onClose={toggleDialog}
|
||||
>
|
||||
<TableComposable aria-label="validators-table">
|
||||
<Thead>
|
||||
<Tr>
|
||||
<Th>{t("validatorDialogColNames.colName")}</Th>
|
||||
<Th>{t("validatorDialogColNames.colDescription")}</Th>
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{validators.map((validator) => (
|
||||
<Tr
|
||||
key={validator.name}
|
||||
onRowClick={() => {
|
||||
setSelectedValidator(validator);
|
||||
toggleModal();
|
||||
}}
|
||||
isHoverable
|
||||
>
|
||||
<Td dataLabel={t("validatorDialogColNames.colName")}>
|
||||
{validator.name}
|
||||
</Td>
|
||||
<Td dataLabel={t("validatorDialogColNames.colDescription")}>
|
||||
{validator.description}
|
||||
</Td>
|
||||
{validators.length !== 0 ? (
|
||||
<TableComposable>
|
||||
<Thead>
|
||||
<Tr>
|
||||
<Th>{t("validatorDialogColNames.colName")}</Th>
|
||||
<Th>{t("validatorDialogColNames.colDescription")}</Th>
|
||||
</Tr>
|
||||
))}
|
||||
</Tbody>
|
||||
</TableComposable>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{validators.map((validator) => (
|
||||
<Tr
|
||||
key={validator.name}
|
||||
onRowClick={() => {
|
||||
setSelectedValidator(validator);
|
||||
toggleModal();
|
||||
}}
|
||||
isHoverable
|
||||
>
|
||||
<Td dataLabel={t("validatorDialogColNames.colName")}>
|
||||
{validator.name}
|
||||
</Td>
|
||||
<Td dataLabel={t("validatorDialogColNames.colDescription")}>
|
||||
{validator.description}
|
||||
</Td>
|
||||
</Tr>
|
||||
))}
|
||||
</Tbody>
|
||||
</TableComposable>
|
||||
) : (
|
||||
<Text className="kc-emptyValidators" component={TextVariants.h6}>
|
||||
{t("realm-settings:emptyValidators")}
|
||||
</Text>
|
||||
)}
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -21,6 +21,7 @@ import { useParams } from "react-router-dom";
|
|||
import { isEqual } from "lodash-es";
|
||||
|
||||
import "../../realm-settings-section.css";
|
||||
import { USERNAME_EMAIL } from "../../NewAttributeSettings";
|
||||
|
||||
const REQUIRED_FOR = [
|
||||
{ label: "requiredForLabel.both", value: ["admin", "user"] },
|
||||
|
@ -151,187 +152,44 @@ export const AttributeGeneralSettings = () => {
|
|||
)}
|
||||
></Controller>
|
||||
</FormGroup>
|
||||
<Divider />
|
||||
<FormGroup label={t("enabledWhen")} fieldId="enabledWhen" hasNoPaddingTop>
|
||||
<Radio
|
||||
id="always"
|
||||
data-testid="always"
|
||||
isChecked={selectedScopes.length === clientScopes?.length}
|
||||
name="enabledWhen"
|
||||
label={t("always")}
|
||||
onChange={(value) => {
|
||||
if (value) {
|
||||
form.setValue(
|
||||
"selector.scopes",
|
||||
clientScopes?.map((s) => s.name)
|
||||
);
|
||||
} else {
|
||||
form.setValue("selector.scopes", []);
|
||||
}
|
||||
}}
|
||||
className="pf-u-mb-md"
|
||||
/>
|
||||
<Radio
|
||||
id="scopesAsRequested"
|
||||
data-testid="scopesAsRequested"
|
||||
isChecked={selectedScopes.length !== clientScopes?.length}
|
||||
name="enabledWhen"
|
||||
label={t("scopesAsRequested")}
|
||||
onChange={(value) => {
|
||||
if (value) {
|
||||
form.setValue("selector.scopes", []);
|
||||
} else {
|
||||
form.setValue(
|
||||
"selector.scopes",
|
||||
clientScopes?.map((s) => s.name)
|
||||
);
|
||||
}
|
||||
}}
|
||||
className="pf-u-mb-md"
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup fieldId="kc-scope-enabled-when">
|
||||
<Controller
|
||||
name="selector.scopes"
|
||||
control={form.control}
|
||||
defaultValue={[]}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
name="scopes"
|
||||
data-testid="enabled-when-scope-field"
|
||||
variant={SelectVariant.typeaheadMulti}
|
||||
typeAheadAriaLabel="Select"
|
||||
chipGroupProps={{
|
||||
numChips: 3,
|
||||
expandedText: t("common:hide"),
|
||||
collapsedText: t("common:showRemaining"),
|
||||
}}
|
||||
onToggle={(isOpen) => setSelectEnabledWhenOpen(isOpen)}
|
||||
selections={value}
|
||||
onSelect={(_, selectedValue) => {
|
||||
const option = selectedValue.toString();
|
||||
let changedValue = [""];
|
||||
if (value) {
|
||||
changedValue = value.includes(option)
|
||||
? value.filter((item: string) => item !== option)
|
||||
: [...value, option];
|
||||
} else {
|
||||
changedValue = [option];
|
||||
}
|
||||
|
||||
onChange(changedValue);
|
||||
}}
|
||||
onClear={(selectedValues) => {
|
||||
selectedValues.stopPropagation();
|
||||
onChange([]);
|
||||
}}
|
||||
isOpen={selectEnabledWhenOpen}
|
||||
isDisabled={selectedScopes.length === clientScopes?.length}
|
||||
aria-labelledby={"scope"}
|
||||
>
|
||||
{clientScopes?.map((option) => (
|
||||
<SelectOption key={option.name} value={option.name} />
|
||||
))}
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<Divider />
|
||||
<FormGroup
|
||||
label={t("required")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:requiredHelp"
|
||||
fieldLabelId="realm-settings:required"
|
||||
/>
|
||||
}
|
||||
fieldId="kc-required"
|
||||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="isRequired"
|
||||
data-testid="required"
|
||||
defaultValue={false}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id={"kc-required"}
|
||||
onChange={onChange}
|
||||
isChecked={value}
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
aria-label={t("required")}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
{required && (
|
||||
{!USERNAME_EMAIL.includes(attributeName) && (
|
||||
<>
|
||||
<Divider />
|
||||
<FormGroup
|
||||
label={t("requiredFor")}
|
||||
fieldId="requiredFor"
|
||||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="required.roles"
|
||||
data-testid="requiredFor"
|
||||
defaultValue={REQUIRED_FOR[0].value}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<div className="kc-requiredFor">
|
||||
{REQUIRED_FOR.map((option) => (
|
||||
<Radio
|
||||
id={option.label}
|
||||
key={option.label}
|
||||
data-testid={option.label}
|
||||
isChecked={isEqual(value, option.value)}
|
||||
name="roles"
|
||||
onChange={() => {
|
||||
onChange(option.value);
|
||||
}}
|
||||
label={t(option.label)}
|
||||
className="kc-requiredFor-option"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("requiredWhen")}
|
||||
fieldId="requiredWhen"
|
||||
label={t("enabledWhen")}
|
||||
fieldId="enabledWhen"
|
||||
hasNoPaddingTop
|
||||
>
|
||||
<Radio
|
||||
id="requiredAlways"
|
||||
data-testid="requiredAlways"
|
||||
isChecked={requiredScopes.length === clientScopes?.length}
|
||||
name="requiredWhen"
|
||||
id="always"
|
||||
data-testid="always"
|
||||
isChecked={selectedScopes.length === clientScopes?.length}
|
||||
name="enabledWhen"
|
||||
label={t("always")}
|
||||
onChange={(value) => {
|
||||
if (value) {
|
||||
form.setValue(
|
||||
"required.scopes",
|
||||
"selector.scopes",
|
||||
clientScopes?.map((s) => s.name)
|
||||
);
|
||||
} else {
|
||||
form.setValue("required.scopes", []);
|
||||
form.setValue("selector.scopes", []);
|
||||
}
|
||||
}}
|
||||
className="pf-u-mb-md"
|
||||
/>
|
||||
<Radio
|
||||
id="requiredScopesAsRequested"
|
||||
data-testid="requiredScopesAsRequested"
|
||||
isChecked={requiredScopes.length !== clientScopes?.length}
|
||||
name="requiredWhen"
|
||||
id="scopesAsRequested"
|
||||
data-testid="scopesAsRequested"
|
||||
isChecked={selectedScopes.length !== clientScopes?.length}
|
||||
name="enabledWhen"
|
||||
label={t("scopesAsRequested")}
|
||||
onChange={(value) => {
|
||||
if (value) {
|
||||
form.setValue("required.scopes", []);
|
||||
form.setValue("selector.scopes", []);
|
||||
} else {
|
||||
form.setValue(
|
||||
"required.scopes",
|
||||
"selector.scopes",
|
||||
clientScopes?.map((s) => s.name)
|
||||
);
|
||||
}
|
||||
|
@ -339,15 +197,15 @@ export const AttributeGeneralSettings = () => {
|
|||
className="pf-u-mb-md"
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup fieldId="kc-scope-required-when">
|
||||
<FormGroup fieldId="kc-scope-enabled-when">
|
||||
<Controller
|
||||
name="required.scopes"
|
||||
name="selector.scopes"
|
||||
control={form.control}
|
||||
defaultValue={[]}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
name="scopeRequired"
|
||||
data-testid="required-when-scope-field"
|
||||
name="scopes"
|
||||
data-testid="enabled-when-scope-field"
|
||||
variant={SelectVariant.typeaheadMulti}
|
||||
typeAheadAriaLabel="Select"
|
||||
chipGroupProps={{
|
||||
|
@ -355,7 +213,7 @@ export const AttributeGeneralSettings = () => {
|
|||
expandedText: t("common:hide"),
|
||||
collapsedText: t("common:showRemaining"),
|
||||
}}
|
||||
onToggle={(isOpen) => setSelectRequiredForOpen(isOpen)}
|
||||
onToggle={(isOpen) => setSelectEnabledWhenOpen(isOpen)}
|
||||
selections={value}
|
||||
onSelect={(_, selectedValue) => {
|
||||
const option = selectedValue.toString();
|
||||
|
@ -367,14 +225,15 @@ export const AttributeGeneralSettings = () => {
|
|||
} else {
|
||||
changedValue = [option];
|
||||
}
|
||||
|
||||
onChange(changedValue);
|
||||
}}
|
||||
onClear={(selectedValues) => {
|
||||
selectedValues.stopPropagation();
|
||||
onChange([]);
|
||||
}}
|
||||
isOpen={selectRequiredForOpen}
|
||||
isDisabled={requiredScopes.length === clientScopes?.length}
|
||||
isOpen={selectEnabledWhenOpen}
|
||||
isDisabled={selectedScopes.length === clientScopes?.length}
|
||||
aria-labelledby={"scope"}
|
||||
>
|
||||
{clientScopes?.map((option) => (
|
||||
|
@ -384,6 +243,159 @@ export const AttributeGeneralSettings = () => {
|
|||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
<Divider />
|
||||
<FormGroup
|
||||
label={t("required")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText="realm-settings-help:requiredHelp"
|
||||
fieldLabelId="realm-settings:required"
|
||||
/>
|
||||
}
|
||||
fieldId="kc-required"
|
||||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="isRequired"
|
||||
data-testid="required"
|
||||
defaultValue={false}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<Switch
|
||||
id={"kc-required"}
|
||||
onChange={onChange}
|
||||
isChecked={value}
|
||||
label={t("common:on")}
|
||||
labelOff={t("common:off")}
|
||||
aria-label={t("required")}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
{required && (
|
||||
<>
|
||||
<FormGroup
|
||||
label={t("requiredFor")}
|
||||
fieldId="requiredFor"
|
||||
hasNoPaddingTop
|
||||
>
|
||||
<Controller
|
||||
name="required.roles"
|
||||
data-testid="requiredFor"
|
||||
defaultValue={REQUIRED_FOR[0].value}
|
||||
control={form.control}
|
||||
render={({ onChange, value }) => (
|
||||
<div className="kc-requiredFor">
|
||||
{REQUIRED_FOR.map((option) => (
|
||||
<Radio
|
||||
id={option.label}
|
||||
key={option.label}
|
||||
data-testid={option.label}
|
||||
isChecked={isEqual(value, option.value)}
|
||||
name="roles"
|
||||
onChange={() => {
|
||||
onChange(option.value);
|
||||
}}
|
||||
label={t(option.label)}
|
||||
className="kc-requiredFor-option"
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup
|
||||
label={t("requiredWhen")}
|
||||
fieldId="requiredWhen"
|
||||
hasNoPaddingTop
|
||||
>
|
||||
<Radio
|
||||
id="requiredAlways"
|
||||
data-testid="requiredAlways"
|
||||
isChecked={requiredScopes.length === clientScopes?.length}
|
||||
name="requiredWhen"
|
||||
label={t("always")}
|
||||
onChange={(value) => {
|
||||
if (value) {
|
||||
form.setValue(
|
||||
"required.scopes",
|
||||
clientScopes?.map((s) => s.name)
|
||||
);
|
||||
} else {
|
||||
form.setValue("required.scopes", []);
|
||||
}
|
||||
}}
|
||||
className="pf-u-mb-md"
|
||||
/>
|
||||
<Radio
|
||||
id="requiredScopesAsRequested"
|
||||
data-testid="requiredScopesAsRequested"
|
||||
isChecked={requiredScopes.length !== clientScopes?.length}
|
||||
name="requiredWhen"
|
||||
label={t("scopesAsRequested")}
|
||||
onChange={(value) => {
|
||||
if (value) {
|
||||
form.setValue("required.scopes", []);
|
||||
} else {
|
||||
form.setValue(
|
||||
"required.scopes",
|
||||
clientScopes?.map((s) => s.name)
|
||||
);
|
||||
}
|
||||
}}
|
||||
className="pf-u-mb-md"
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup fieldId="kc-scope-required-when">
|
||||
<Controller
|
||||
name="required.scopes"
|
||||
control={form.control}
|
||||
defaultValue={[]}
|
||||
render={({ onChange, value }) => (
|
||||
<Select
|
||||
name="scopeRequired"
|
||||
data-testid="required-when-scope-field"
|
||||
variant={SelectVariant.typeaheadMulti}
|
||||
typeAheadAriaLabel="Select"
|
||||
chipGroupProps={{
|
||||
numChips: 3,
|
||||
expandedText: t("common:hide"),
|
||||
collapsedText: t("common:showRemaining"),
|
||||
}}
|
||||
onToggle={(isOpen) => setSelectRequiredForOpen(isOpen)}
|
||||
selections={value}
|
||||
onSelect={(_, selectedValue) => {
|
||||
const option = selectedValue.toString();
|
||||
let changedValue = [""];
|
||||
if (value) {
|
||||
changedValue = value.includes(option)
|
||||
? value.filter((item: string) => item !== option)
|
||||
: [...value, option];
|
||||
} else {
|
||||
changedValue = [option];
|
||||
}
|
||||
onChange(changedValue);
|
||||
}}
|
||||
onClear={(selectedValues) => {
|
||||
selectedValues.stopPropagation();
|
||||
onChange([]);
|
||||
}}
|
||||
isOpen={selectRequiredForOpen}
|
||||
isDisabled={
|
||||
requiredScopes.length === clientScopes?.length
|
||||
}
|
||||
aria-labelledby={"scope"}
|
||||
>
|
||||
{clientScopes?.map((option) => (
|
||||
<SelectOption key={option.name} value={option.name} />
|
||||
))}
|
||||
</Select>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</FormAccess>
|
||||
|
|
|
@ -7,7 +7,6 @@ import {
|
|||
TextVariants,
|
||||
} from "@patternfly/react-core";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import "../../realm-settings-section.css";
|
||||
import { PlusCircleIcon } from "@patternfly/react-icons";
|
||||
import { AddValidatorDialog } from "../attribute/AddValidatorDialog";
|
||||
import {
|
||||
|
@ -18,12 +17,12 @@ import {
|
|||
Thead,
|
||||
Tr,
|
||||
} from "@patternfly/react-table";
|
||||
|
||||
import type { IndexedValidations } from "../../NewAttributeSettings";
|
||||
import { useConfirmDialog } from "../../../components/confirm-dialog/ConfirmDialog";
|
||||
import useToggle from "../../../utils/useToggle";
|
||||
import { useFormContext, useWatch } from "react-hook-form";
|
||||
|
||||
import type { KeyValueType } from "../../../components/key-value-form/key-value-convert";
|
||||
|
||||
import "../../realm-settings-section.css";
|
||||
|
||||
export const AttributeValidations = () => {
|
||||
|
@ -34,7 +33,7 @@ export const AttributeValidations = () => {
|
|||
}>();
|
||||
const { setValue, control, register } = useFormContext();
|
||||
|
||||
const validators = useWatch<KeyValueType[]>({
|
||||
const validators = useWatch<IndexedValidations[]>({
|
||||
name: "validations",
|
||||
control,
|
||||
defaultValue: [],
|
||||
|
@ -87,47 +86,48 @@ export const AttributeValidations = () => {
|
|||
{t("realm-settings:addValidator")}
|
||||
</Button>
|
||||
<Divider />
|
||||
<TableComposable aria-label="validators-table">
|
||||
<Thead>
|
||||
<Tr>
|
||||
<Th>{t("validatorColNames.colName")}</Th>
|
||||
<Th>{t("validatorColNames.colConfig")}</Th>
|
||||
<Th />
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{validators.map((validator) => (
|
||||
<Tr key={validator.key}>
|
||||
<Td dataLabel={t("validatorColNames.colName")}>
|
||||
{validator.key}
|
||||
</Td>
|
||||
<Td dataLabel={t("validatorColNames.colConfig")}>
|
||||
{JSON.stringify(validator.value)}
|
||||
</Td>
|
||||
<Td className="kc--attributes-validations--action-cell">
|
||||
<Button
|
||||
key="validator"
|
||||
variant="link"
|
||||
data-testid="deleteValidator"
|
||||
onClick={() => {
|
||||
toggleDeleteDialog();
|
||||
setValidatorToDelete({
|
||||
name: validator.key,
|
||||
});
|
||||
}}
|
||||
>
|
||||
{t("common:delete")}
|
||||
</Button>
|
||||
</Td>
|
||||
{validators.length !== 0 ? (
|
||||
<TableComposable>
|
||||
<Thead>
|
||||
<Tr>
|
||||
<Th>{t("validatorColNames.colName")}</Th>
|
||||
<Th>{t("validatorColNames.colConfig")}</Th>
|
||||
<Th />
|
||||
</Tr>
|
||||
))}
|
||||
{validators.length === 0 && (
|
||||
<Text className="kc-emptyValidators" component={TextVariants.h6}>
|
||||
{t("realm-settings:emptyValidators")}
|
||||
</Text>
|
||||
)}
|
||||
</Tbody>
|
||||
</TableComposable>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{validators.map((validator) => (
|
||||
<Tr key={validator.key}>
|
||||
<Td dataLabel={t("validatorColNames.colName")}>
|
||||
{validator.key}
|
||||
</Td>
|
||||
<Td dataLabel={t("validatorColNames.colConfig")}>
|
||||
{JSON.stringify(validator.value)}
|
||||
</Td>
|
||||
<Td className="kc--attributes-validations--action-cell">
|
||||
<Button
|
||||
key="validator"
|
||||
variant="link"
|
||||
data-testid="deleteValidator"
|
||||
onClick={() => {
|
||||
toggleDeleteDialog();
|
||||
setValidatorToDelete({
|
||||
name: validator.key,
|
||||
});
|
||||
}}
|
||||
>
|
||||
{t("common:delete")}
|
||||
</Button>
|
||||
</Td>
|
||||
</Tr>
|
||||
))}
|
||||
</Tbody>
|
||||
</TableComposable>
|
||||
) : (
|
||||
<Text className="kc-emptyValidators" component={TextVariants.h6}>
|
||||
{t("realm-settings:emptyValidators")}
|
||||
</Text>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue