required can have a value that is a boolean when used with controls (#34251)
* required is a boolean when used with controls fixes: #33614 Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * simplified rules declaration Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * added missing messages Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> * use value when it's present Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com> --------- Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>
This commit is contained in:
parent
624817bdc1
commit
2f64f43266
17 changed files with 43 additions and 127 deletions
|
@ -84,7 +84,7 @@ export default class ProviderBaseGeneralSettingsPage extends PageObject {
|
|||
#jwksUrl = "config.jwksUrl";
|
||||
#pkceSwitch = "#config\\.pkceEnabled";
|
||||
#pkceMethod = "#pkceMethod";
|
||||
#clientAuth = "#clientAuthentication";
|
||||
#clientAuth = "#clientAuthMethod";
|
||||
#clientAssertionSigningAlg = "#clientAssertionSigningAlg";
|
||||
#clientAssertionAudienceInput = "#clientAssertionAudience";
|
||||
#jwtX509HeadersSwitch = "#jwtX509HeadersEnabled";
|
||||
|
|
|
@ -84,7 +84,7 @@ export const EditFlow = ({ execution, onRowChange }: EditFlowProps) => {
|
|||
name="displayName"
|
||||
label={t("name")}
|
||||
labelIcon={t("flowNameHelp")}
|
||||
rules={{ required: { value: true, message: t("required") } }}
|
||||
rules={{ required: t("required") }}
|
||||
/>
|
||||
<TextAreaControl
|
||||
name="description"
|
||||
|
|
|
@ -161,7 +161,7 @@ export const ExecutionConfigModal = ({
|
|||
name="alias"
|
||||
label={t("alias")}
|
||||
labelIcon={t("authenticationAliasHelp")}
|
||||
rules={{ required: { value: true, message: t("required") } }}
|
||||
rules={{ required: t("required") }}
|
||||
isDisabled={!!config}
|
||||
/>
|
||||
<DynamicComponents
|
||||
|
|
|
@ -90,7 +90,7 @@ export const AddSubFlowModal = ({
|
|||
name="name"
|
||||
label={t("name")}
|
||||
labelIcon={t("clientIdHelp")}
|
||||
rules={{ required: { value: true, message: t("required") } }}
|
||||
rules={{ required: t("required") }}
|
||||
/>
|
||||
<TextControl
|
||||
name="description"
|
||||
|
|
|
@ -10,7 +10,7 @@ export const NameDescription = () => {
|
|||
name="alias"
|
||||
label={t("name")}
|
||||
labelIcon={t("flowNameHelp")}
|
||||
rules={{ required: { value: true, message: t("required") } }}
|
||||
rules={{ required: t("required") }}
|
||||
/>
|
||||
<TextControl
|
||||
name="description"
|
||||
|
|
|
@ -100,10 +100,7 @@ export const CibaPolicy = ({ realm, realmUpdated }: CibaPolicyProps) => {
|
|||
value: CIBA_EXPIRES_IN_MAX,
|
||||
message: t("lessThan", { value: CIBA_EXPIRES_IN_MAX }),
|
||||
},
|
||||
required: {
|
||||
value: true,
|
||||
message: t("required"),
|
||||
},
|
||||
required: t("required"),
|
||||
}}
|
||||
/>
|
||||
<TextControl
|
||||
|
@ -124,10 +121,7 @@ export const CibaPolicy = ({ realm, realmUpdated }: CibaPolicyProps) => {
|
|||
value: CIBA_INTERVAL_MAX,
|
||||
message: t("lessThan", { value: CIBA_INTERVAL_MAX }),
|
||||
},
|
||||
required: {
|
||||
value: true,
|
||||
message: t("required"),
|
||||
},
|
||||
required: t("required"),
|
||||
}}
|
||||
/>
|
||||
<SelectControl
|
||||
|
|
|
@ -161,7 +161,7 @@ export const WebauthnPolicy = ({
|
|||
name={`${namePrefix}RpEntityName`}
|
||||
label={t("webAuthnPolicyRpEntityName")}
|
||||
labelIcon={t("webAuthnPolicyRpEntityNameHelp")}
|
||||
rules={{ required: { value: true, message: t("required") } }}
|
||||
rules={{ required: t("required") }}
|
||||
/>
|
||||
<WebauthnSelect
|
||||
name={`${namePrefix}SignatureAlgorithms`}
|
||||
|
|
|
@ -217,7 +217,7 @@ export default function MappingDetails() {
|
|||
label={t("name")}
|
||||
labelIcon={t("mapperNameHelp")}
|
||||
readOnlyVariant={isUpdating ? "default" : undefined}
|
||||
rules={{ required: { value: true, message: t("required") } }}
|
||||
rules={{ required: t("required") }}
|
||||
/>
|
||||
<DynamicComponents
|
||||
properties={mapping?.properties || []}
|
||||
|
|
|
@ -79,10 +79,7 @@ export const ScopeForm = ({ clientScope, save }: ScopeFormProps) => {
|
|||
label={t("name")}
|
||||
labelIcon={t("scopeNameHelp")}
|
||||
rules={{
|
||||
required: {
|
||||
value: true,
|
||||
message: t("required"),
|
||||
},
|
||||
required: t("required"),
|
||||
onChange: (e) => {
|
||||
if (isDynamicScopesEnabled)
|
||||
setDynamicRegex(e.target.validated, true);
|
||||
|
|
|
@ -19,7 +19,7 @@ export const ClientDescription = ({
|
|||
name="clientId"
|
||||
label={t("clientId")}
|
||||
labelIcon={t("clientIdHelp")}
|
||||
rules={{ required: { value: true, message: t("required") } }}
|
||||
rules={{ required: t("required") }}
|
||||
/>
|
||||
<TextControl
|
||||
name="name"
|
||||
|
|
|
@ -1,11 +1,5 @@
|
|||
import {
|
||||
HelpItem,
|
||||
KeycloakSelect,
|
||||
SelectVariant,
|
||||
} from "@keycloak/keycloak-ui-shared";
|
||||
import { FormGroup, SelectOption } from "@patternfly/react-core";
|
||||
import { useState } from "react";
|
||||
import { Controller, useFormContext, useWatch } from "react-hook-form";
|
||||
import { SelectControl } from "@keycloak/keycloak-ui-shared";
|
||||
import { useFormContext, useWatch } from "react-hook-form";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useServerInfo } from "../../context/server-info/ServerInfoProvider";
|
||||
import { sortProviders } from "../../util";
|
||||
|
@ -25,8 +19,6 @@ export const OIDCAuthentication = ({ create = true }: { create?: boolean }) => {
|
|||
const { t } = useTranslation();
|
||||
|
||||
const { control } = useFormContext();
|
||||
const [openClientAuth, setOpenClientAuth] = useState(false);
|
||||
const [openClientAuthSigAlg, setOpenClientAuthSigAlg] = useState(false);
|
||||
|
||||
const clientAuthMethod = useWatch({
|
||||
control: control,
|
||||
|
@ -35,96 +27,34 @@ export const OIDCAuthentication = ({ create = true }: { create?: boolean }) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<FormGroup
|
||||
<SelectControl
|
||||
name="config.clientAuthMethod"
|
||||
label={t("clientAuthentication")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={t("clientAuthenticationHelp")}
|
||||
fieldLabelId="clientAuthentication"
|
||||
/>
|
||||
}
|
||||
fieldId="clientAuthentication"
|
||||
>
|
||||
<Controller
|
||||
name="config.clientAuthMethod"
|
||||
defaultValue={clientAuthentications[0]}
|
||||
control={control}
|
||||
render={({ field }) => (
|
||||
<KeycloakSelect
|
||||
toggleId="clientAuthentication"
|
||||
onToggle={() => setOpenClientAuth(!openClientAuth)}
|
||||
onSelect={(value) => {
|
||||
field.onChange(value as string);
|
||||
setOpenClientAuth(false);
|
||||
}}
|
||||
selections={field.value}
|
||||
variant={SelectVariant.single}
|
||||
aria-label={t("clientAuthentication")}
|
||||
isOpen={openClientAuth}
|
||||
>
|
||||
{clientAuthentications.map((option) => (
|
||||
<SelectOption
|
||||
selected={option === field.value}
|
||||
key={option}
|
||||
value={option}
|
||||
>
|
||||
{t(`clientAuthentications.${option}`)}
|
||||
</SelectOption>
|
||||
))}
|
||||
</KeycloakSelect>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
labelIcon={t("clientAuthenticationHelp")}
|
||||
options={clientAuthentications.map((auth) => ({
|
||||
key: auth,
|
||||
value: t(`clientAuthentications.${auth}`),
|
||||
}))}
|
||||
controller={{
|
||||
defaultValue: clientAuthentications[0],
|
||||
}}
|
||||
/>
|
||||
<ClientIdSecret
|
||||
secretRequired={clientAuthMethod !== "private_key_jwt"}
|
||||
create={create}
|
||||
/>
|
||||
<FormGroup
|
||||
<SelectControl
|
||||
name="config.clientAssertionSigningAlg"
|
||||
label={t("clientAssertionSigningAlg")}
|
||||
labelIcon={
|
||||
<HelpItem
|
||||
helpText={t("clientAssertionSigningAlgHelp")}
|
||||
fieldLabelId="clientAssertionSigningAlg"
|
||||
/>
|
||||
}
|
||||
fieldId="clientAssertionSigningAlg"
|
||||
>
|
||||
<Controller
|
||||
name="config.clientAssertionSigningAlg"
|
||||
defaultValue=""
|
||||
control={control}
|
||||
render={({ field }) => (
|
||||
<KeycloakSelect
|
||||
maxHeight={200}
|
||||
toggleId="clientAssertionSigningAlg"
|
||||
onToggle={() => setOpenClientAuthSigAlg(!openClientAuthSigAlg)}
|
||||
onSelect={(value) => {
|
||||
field.onChange(value.toString());
|
||||
setOpenClientAuthSigAlg(false);
|
||||
}}
|
||||
selections={field.value || t("algorithmNotSpecified")}
|
||||
variant={SelectVariant.single}
|
||||
aria-label={t("selectClientAssertionSigningAlg")}
|
||||
isOpen={openClientAuthSigAlg}
|
||||
>
|
||||
{[
|
||||
<SelectOption selected={field.value === ""} key="" value="">
|
||||
{t("algorithmNotSpecified")}
|
||||
</SelectOption>,
|
||||
...sortProviders(providers).map((option) => (
|
||||
<SelectOption
|
||||
selected={option === field.value}
|
||||
key={option}
|
||||
value={option}
|
||||
>
|
||||
{option}
|
||||
</SelectOption>
|
||||
)),
|
||||
]}
|
||||
</KeycloakSelect>
|
||||
)}
|
||||
/>
|
||||
</FormGroup>
|
||||
labelIcon={t("clientAssertionSigningAlgHelp")}
|
||||
options={[
|
||||
{ key: "", value: t("algorithmNotSpecified") },
|
||||
...sortProviders(providers).map((p) => ({ key: p, value: p })),
|
||||
]}
|
||||
controller={{
|
||||
defaultValue: "",
|
||||
}}
|
||||
/>
|
||||
{(clientAuthMethod === "private_key_jwt" ||
|
||||
clientAuthMethod === "client_secret_jwt") && (
|
||||
<TextField
|
||||
|
|
|
@ -476,7 +476,7 @@ export default function NewClientPolicy() {
|
|||
name="name"
|
||||
label={t("name")}
|
||||
rules={{
|
||||
required: { value: true, message: t("required") },
|
||||
required: t("required"),
|
||||
validate: (value) =>
|
||||
policies.some((policy) => policy.name === value)
|
||||
? t("createClientProfileNameHelperText").toString()
|
||||
|
|
|
@ -467,10 +467,7 @@ export default function AttributesGroupForm() {
|
|||
labelIcon={t("nameHintHelp")}
|
||||
isDisabled={!!matchingGroup || editMode}
|
||||
rules={{
|
||||
required: {
|
||||
value: true,
|
||||
message: t("required"),
|
||||
},
|
||||
required: t("required"),
|
||||
onChange: (event) => {
|
||||
handleAttributesGroupNameChange(event, event.target.value);
|
||||
},
|
||||
|
|
|
@ -332,10 +332,7 @@ export const AddTranslationsDialog = ({
|
|||
label={t("translationValue")}
|
||||
data-testid={`translation-value-${rowIndex}`}
|
||||
rules={{
|
||||
required: {
|
||||
value: true,
|
||||
message: t("required"),
|
||||
},
|
||||
required: t("required"),
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -41,7 +41,7 @@ export const LdapSettingsSearching = ({
|
|||
controller={{
|
||||
defaultValue: "",
|
||||
rules: {
|
||||
required: { value: true, message: t("validateEditMode") },
|
||||
required: t("validateEditMode"),
|
||||
},
|
||||
}}
|
||||
options={["", "READ_ONLY", "WRITABLE", "UNSYNCED"]}
|
||||
|
|
|
@ -11,6 +11,7 @@ import {
|
|||
UseControllerProps,
|
||||
useController,
|
||||
} from "react-hook-form";
|
||||
import { getRuleValue } from "../utils/getRuleValue";
|
||||
import { FormLabel } from "./FormLabel";
|
||||
import { PasswordInput, PasswordInputProps } from "./PasswordInput";
|
||||
|
||||
|
@ -32,7 +33,7 @@ export const PasswordControl = <
|
|||
props: PasswordControlProps<T, P>,
|
||||
) => {
|
||||
const { labelIcon, ...rest } = props;
|
||||
const required = !!props.rules?.required;
|
||||
const required = !!getRuleValue(props.rules?.required);
|
||||
const defaultValue = props.defaultValue ?? ("" as PathValue<T, P>);
|
||||
|
||||
const { field, fieldState } = useController({
|
||||
|
|
|
@ -14,7 +14,7 @@ import {
|
|||
UseControllerProps,
|
||||
useController,
|
||||
} from "react-hook-form";
|
||||
|
||||
import { getRuleValue } from "../utils/getRuleValue";
|
||||
import { FormLabel } from "./FormLabel";
|
||||
|
||||
export type TextControlProps<
|
||||
|
@ -36,7 +36,7 @@ export const TextControl = <
|
|||
props: TextControlProps<T, P>,
|
||||
) => {
|
||||
const { labelIcon, helperText, ...rest } = props;
|
||||
const required = !!props.rules?.required;
|
||||
const required = !!getRuleValue(props.rules?.required);
|
||||
const defaultValue = props.defaultValue ?? ("" as PathValue<T, P>);
|
||||
|
||||
const { field, fieldState } = useController({
|
||||
|
|
Loading…
Reference in a new issue