Checkpoint validation supporting various multi valued fields
This commit is contained in:
parent
fc040d8302
commit
a612fce78b
@ -616,26 +616,28 @@ export type LegacyAttribute = Omit<Attribute, "group" | "html5DataAnnotations">
|
|||||||
|
|
||||||
export type Validators = Partial<{
|
export type Validators = Partial<{
|
||||||
length: Validators.DoIgnoreEmpty & Validators.Range;
|
length: Validators.DoIgnoreEmpty & Validators.Range;
|
||||||
double: Validators.DoIgnoreEmpty & Validators.Range;
|
|
||||||
integer: Validators.DoIgnoreEmpty & Validators.Range;
|
integer: Validators.DoIgnoreEmpty & Validators.Range;
|
||||||
email: Validators.DoIgnoreEmpty;
|
email: Validators.DoIgnoreEmpty;
|
||||||
|
pattern: Validators.DoIgnoreEmpty & Validators.ErrorMessage & { pattern: string };
|
||||||
|
options: Validators.Options;
|
||||||
|
multivalued: Validators.DoIgnoreEmpty & Validators.Range;
|
||||||
|
// NOTE: Following are the validators for which we don't implement client side validation yet
|
||||||
|
// or for which the validation can't be performed on the client side.
|
||||||
|
/*
|
||||||
|
double: Validators.DoIgnoreEmpty & Validators.Range;
|
||||||
"up-immutable-attribute": {};
|
"up-immutable-attribute": {};
|
||||||
"up-attribute-required-by-metadata-value": {};
|
"up-attribute-required-by-metadata-value": {};
|
||||||
"up-username-has-value": {};
|
"up-username-has-value": {};
|
||||||
"up-duplicate-username": {};
|
"up-duplicate-username": {};
|
||||||
"up-username-mutation": {};
|
"up-username-mutation": {};
|
||||||
"up-email-exists-as-username": {};
|
"up-email-exists-as-username": {};
|
||||||
"up-blank-attribute-value": Validators.ErrorMessage & {
|
"up-blank-attribute-value": Validators.ErrorMessage & { "fail-on-null": boolean; };
|
||||||
"fail-on-null": boolean;
|
|
||||||
};
|
|
||||||
"up-duplicate-email": {};
|
"up-duplicate-email": {};
|
||||||
"local-date": Validators.DoIgnoreEmpty;
|
"local-date": Validators.DoIgnoreEmpty;
|
||||||
pattern: Validators.DoIgnoreEmpty & Validators.ErrorMessage & { pattern: string };
|
|
||||||
"person-name-prohibited-characters": Validators.DoIgnoreEmpty & Validators.ErrorMessage;
|
"person-name-prohibited-characters": Validators.DoIgnoreEmpty & Validators.ErrorMessage;
|
||||||
uri: Validators.DoIgnoreEmpty;
|
uri: Validators.DoIgnoreEmpty;
|
||||||
"username-prohibited-characters": Validators.DoIgnoreEmpty & Validators.ErrorMessage;
|
"username-prohibited-characters": Validators.DoIgnoreEmpty & Validators.ErrorMessage;
|
||||||
options: Validators.Options;
|
*/
|
||||||
multivalued: Validators.DoIgnoreEmpty & Validators.Range;
|
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
export declare namespace Validators {
|
export declare namespace Validators {
|
||||||
|
@ -12,12 +12,33 @@ import type { I18n } from "../i18n";
|
|||||||
export type FormFieldError = {
|
export type FormFieldError = {
|
||||||
errorMessage: JSX.Element;
|
errorMessage: JSX.Element;
|
||||||
errorMessageStr: string;
|
errorMessageStr: string;
|
||||||
// TODO: This is not enough, we should be able to tell
|
source: FormFieldError.Source;
|
||||||
// if it's a server side error, a validator error or a password policy error.
|
|
||||||
validatorName: keyof Validators | undefined;
|
|
||||||
fieldIndex: number | undefined;
|
fieldIndex: number | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export namespace FormFieldError {
|
||||||
|
export type Source = Source.Validator | Source.PasswordPolicy | Source.Server | Source.Other;
|
||||||
|
|
||||||
|
export namespace Source {
|
||||||
|
export type Validator = {
|
||||||
|
type: "validator";
|
||||||
|
name: keyof Validators;
|
||||||
|
};
|
||||||
|
export type PasswordPolicy = {
|
||||||
|
type: "passwordPolicy";
|
||||||
|
name: keyof PasswordPolicies;
|
||||||
|
};
|
||||||
|
export type Server = {
|
||||||
|
type: "server";
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Other = {
|
||||||
|
type: "other";
|
||||||
|
rule: "passwordConfirmMatchesPassword" | "requiredField";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export type FormFieldState = FormFieldState.Simple | FormFieldState.MultiValued;
|
export type FormFieldState = FormFieldState.Simple | FormFieldState.MultiValued;
|
||||||
|
|
||||||
export namespace FormFieldState {
|
export namespace FormFieldState {
|
||||||
@ -299,23 +320,67 @@ export function useUserProfileForm(params: ParamsOfUseUserProfileForm): ReturnTy
|
|||||||
|
|
||||||
const formState: FormState = useMemo(
|
const formState: FormState = useMemo(
|
||||||
() => ({
|
() => ({
|
||||||
"formFieldStates": state.formFieldStates.map(({ errors, hasLostFocusAtLeastOnce, attribute, ...valueOrValuesWrap }) => ({
|
"formFieldStates": state.formFieldStates.map(
|
||||||
"displayableErrors":
|
({ errors, hasLostFocusAtLeastOnce: hasLostFocusAtLeastOnceOrArr, attribute, ...valueOrValuesWrap }) => ({
|
||||||
typeof hasLostFocusAtLeastOnce === "boolean"
|
"displayableErrors": errors.filter(error => {
|
||||||
? hasLostFocusAtLeastOnce
|
const hasLostFocusAtLeastOnce =
|
||||||
? errors
|
typeof hasLostFocusAtLeastOnceOrArr === "boolean"
|
||||||
: []
|
? hasLostFocusAtLeastOnceOrArr
|
||||||
: errors.filter(error => {
|
: error.fieldIndex !== undefined
|
||||||
//TODO
|
? hasLostFocusAtLeastOnceOrArr[error.fieldIndex]
|
||||||
|
: hasLostFocusAtLeastOnceOrArr[hasLostFocusAtLeastOnceOrArr.length - 1];
|
||||||
|
|
||||||
// TODO: The errors from server should be always displayed.
|
switch (error.source.type) {
|
||||||
// even before focus lost.
|
case "server":
|
||||||
|
return true;
|
||||||
return true;
|
case "other":
|
||||||
}),
|
switch (error.source.rule) {
|
||||||
attribute,
|
case "requiredField":
|
||||||
...valueOrValuesWrap
|
return hasLostFocusAtLeastOnce;
|
||||||
})),
|
case "passwordConfirmMatchesPassword":
|
||||||
|
return hasLostFocusAtLeastOnce;
|
||||||
|
}
|
||||||
|
assert<Equals<typeof error.source.rule, never>>(false);
|
||||||
|
case "passwordPolicy":
|
||||||
|
switch (error.source.name) {
|
||||||
|
case "length":
|
||||||
|
return hasLostFocusAtLeastOnce;
|
||||||
|
case "digits":
|
||||||
|
return hasLostFocusAtLeastOnce;
|
||||||
|
case "lowerCase":
|
||||||
|
return hasLostFocusAtLeastOnce;
|
||||||
|
case "upperCase":
|
||||||
|
return hasLostFocusAtLeastOnce;
|
||||||
|
case "specialChars":
|
||||||
|
return hasLostFocusAtLeastOnce;
|
||||||
|
case "notUsername":
|
||||||
|
return true;
|
||||||
|
case "notEmail":
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
assert<Equals<typeof error.source, never>>(false);
|
||||||
|
case "validator":
|
||||||
|
switch (error.source.name) {
|
||||||
|
case "length":
|
||||||
|
return hasLostFocusAtLeastOnce;
|
||||||
|
case "pattern":
|
||||||
|
return hasLostFocusAtLeastOnce;
|
||||||
|
case "email":
|
||||||
|
return hasLostFocusAtLeastOnce;
|
||||||
|
case "integer":
|
||||||
|
return hasLostFocusAtLeastOnce;
|
||||||
|
case "multivalued":
|
||||||
|
return hasLostFocusAtLeastOnce;
|
||||||
|
case "options":
|
||||||
|
return hasLostFocusAtLeastOnce;
|
||||||
|
}
|
||||||
|
assert<Equals<typeof error.source, never>>(false);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
attribute,
|
||||||
|
...valueOrValuesWrap
|
||||||
|
})
|
||||||
|
),
|
||||||
"isFormSubmittable": state.formFieldStates.every(({ errors }) => errors.length === 0)
|
"isFormSubmittable": state.formFieldStates.every(({ errors }) => errors.length === 0)
|
||||||
}),
|
}),
|
||||||
[state]
|
[state]
|
||||||
@ -388,34 +453,36 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
"validatorName": undefined,
|
|
||||||
errorMessageStr,
|
errorMessageStr,
|
||||||
"errorMessage": <span key={0}>{errorMessageStr}</span>,
|
"errorMessage": <span key={0}>{errorMessageStr}</span>,
|
||||||
"fieldIndex": undefined
|
"fieldIndex": undefined,
|
||||||
|
"source": {
|
||||||
|
"type": "server"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_multi_valued_text_input: {
|
handle_multi_valued_multi_fields: {
|
||||||
if (!attribute.multivalued) {
|
if (!attribute.multivalued) {
|
||||||
break handle_multi_valued_text_input;
|
break handle_multi_valued_multi_fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attribute.annotations.inputType === "multiselect") {
|
if (attribute.annotations.inputType === "multiselect") {
|
||||||
break handle_multi_valued_text_input;
|
break handle_multi_valued_multi_fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attribute.annotations.inputType === "multiselect-checkboxes") {
|
if (attribute.annotations.inputType === "multiselect-checkboxes") {
|
||||||
break handle_multi_valued_text_input;
|
break handle_multi_valued_multi_fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert("values" in fieldValue);
|
assert("values" in fieldValue);
|
||||||
|
|
||||||
const { values } = fieldValue;
|
const { values } = fieldValue;
|
||||||
|
|
||||||
return values
|
const errors = values
|
||||||
.map((value, index) => {
|
.map((value, index) => {
|
||||||
const errors = getErrors({
|
const specificValueErrors = getErrors({
|
||||||
attributeName,
|
attributeName,
|
||||||
"fieldValues": fieldValues.map(fieldValue => {
|
"fieldValues": fieldValues.map(fieldValue => {
|
||||||
if (fieldValue.attribute.name === attributeName) {
|
if (fieldValue.attribute.name === attributeName) {
|
||||||
@ -435,18 +502,50 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
return errors.map((error): FormFieldError => ({ ...error, "fieldIndex": index }));
|
return specificValueErrors
|
||||||
|
.filter(error => {
|
||||||
|
if (error.source.type === "other" && error.source.rule === "requiredField") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
.map((error): FormFieldError => ({ ...error, "fieldIndex": index }));
|
||||||
})
|
})
|
||||||
.reduce((acc, errors) => [...acc, ...errors], []);
|
.reduce((acc, errors) => [...acc, ...errors], []);
|
||||||
|
|
||||||
|
required_field: {
|
||||||
|
if (!attribute.required) {
|
||||||
|
break required_field;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (values.find(value => value !== "") !== undefined) {
|
||||||
|
break required_field;
|
||||||
|
}
|
||||||
|
|
||||||
|
const msgArgs = ["error-user-attribute-required"] as const;
|
||||||
|
|
||||||
|
errors.push({
|
||||||
|
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
||||||
|
"errorMessageStr": msgStr(...msgArgs),
|
||||||
|
"fieldIndex": undefined,
|
||||||
|
"source": {
|
||||||
|
"type": "other",
|
||||||
|
"rule": "requiredField"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_multi_select_or_checkbox: {
|
handle_multi_select_single_field: {
|
||||||
if (!attribute.multivalued) {
|
if (!attribute.multivalued) {
|
||||||
break handle_multi_select_or_checkbox;
|
break handle_multi_select_single_field;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attribute.annotations.inputType !== "multiselect" && attribute.annotations.inputType !== "multiselect-checkboxes") {
|
if (attribute.annotations.inputType !== "multiselect" && attribute.annotations.inputType !== "multiselect-checkboxes") {
|
||||||
break handle_multi_select_or_checkbox;
|
break handle_multi_select_single_field;
|
||||||
}
|
}
|
||||||
|
|
||||||
const validatorName = "multivalued";
|
const validatorName = "multivalued";
|
||||||
@ -483,8 +582,11 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
|
|||||||
{
|
{
|
||||||
"errorMessage": <Fragment key={0}>{msg(...msgArgs)}</Fragment>,
|
"errorMessage": <Fragment key={0}>{msg(...msgArgs)}</Fragment>,
|
||||||
"errorMessageStr": msgStr(...msgArgs),
|
"errorMessageStr": msgStr(...msgArgs),
|
||||||
validatorName,
|
"fieldIndex": undefined,
|
||||||
"fieldIndex": undefined
|
"source": {
|
||||||
|
"type": "validator",
|
||||||
|
"name": validatorName
|
||||||
|
}
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -524,10 +626,13 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
|
|||||||
const msgArgs = ["invalidPasswordMinLengthMessage", `${minLength}`] as const;
|
const msgArgs = ["invalidPasswordMinLengthMessage", `${minLength}`] as const;
|
||||||
|
|
||||||
errors.push({
|
errors.push({
|
||||||
"validatorName": undefined,
|
|
||||||
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
||||||
"errorMessageStr": msgStr(...msgArgs),
|
"errorMessageStr": msgStr(...msgArgs),
|
||||||
"fieldIndex": undefined
|
"fieldIndex": undefined,
|
||||||
|
"source": {
|
||||||
|
"type": "passwordPolicy",
|
||||||
|
"name": policyName
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -551,10 +656,13 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
|
|||||||
const msgArgs = ["invalidPasswordMinDigitsMessage", `${minNumberOfDigits}`] as const;
|
const msgArgs = ["invalidPasswordMinDigitsMessage", `${minNumberOfDigits}`] as const;
|
||||||
|
|
||||||
errors.push({
|
errors.push({
|
||||||
"validatorName": undefined,
|
|
||||||
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
||||||
"errorMessageStr": msgStr(...msgArgs),
|
"errorMessageStr": msgStr(...msgArgs),
|
||||||
"fieldIndex": undefined
|
"fieldIndex": undefined,
|
||||||
|
"source": {
|
||||||
|
"type": "passwordPolicy",
|
||||||
|
"name": policyName
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -580,10 +688,13 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
|
|||||||
const msgArgs = ["invalidPasswordMinLowerCaseCharsMessage", `${minNumberOfLowerCaseChar}`] as const;
|
const msgArgs = ["invalidPasswordMinLowerCaseCharsMessage", `${minNumberOfLowerCaseChar}`] as const;
|
||||||
|
|
||||||
errors.push({
|
errors.push({
|
||||||
"validatorName": undefined,
|
|
||||||
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
||||||
"errorMessageStr": msgStr(...msgArgs),
|
"errorMessageStr": msgStr(...msgArgs),
|
||||||
"fieldIndex": undefined
|
"fieldIndex": undefined,
|
||||||
|
"source": {
|
||||||
|
"type": "passwordPolicy",
|
||||||
|
"name": policyName
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -609,10 +720,13 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
|
|||||||
const msgArgs = ["invalidPasswordMinUpperCaseCharsMessage", `${minNumberOfUpperCaseChar}`] as const;
|
const msgArgs = ["invalidPasswordMinUpperCaseCharsMessage", `${minNumberOfUpperCaseChar}`] as const;
|
||||||
|
|
||||||
errors.push({
|
errors.push({
|
||||||
"validatorName": undefined,
|
|
||||||
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
||||||
"errorMessageStr": msgStr(...msgArgs),
|
"errorMessageStr": msgStr(...msgArgs),
|
||||||
"fieldIndex": undefined
|
"fieldIndex": undefined,
|
||||||
|
"source": {
|
||||||
|
"type": "passwordPolicy",
|
||||||
|
"name": policyName
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -636,10 +750,13 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
|
|||||||
const msgArgs = ["invalidPasswordMinSpecialCharsMessage", `${minNumberOfSpecialChar}`] as const;
|
const msgArgs = ["invalidPasswordMinSpecialCharsMessage", `${minNumberOfSpecialChar}`] as const;
|
||||||
|
|
||||||
errors.push({
|
errors.push({
|
||||||
"validatorName": undefined,
|
|
||||||
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
||||||
"errorMessageStr": msgStr(...msgArgs),
|
"errorMessageStr": msgStr(...msgArgs),
|
||||||
"fieldIndex": undefined
|
"fieldIndex": undefined,
|
||||||
|
"source": {
|
||||||
|
"type": "passwordPolicy",
|
||||||
|
"name": policyName
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -667,10 +784,13 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
|
|||||||
const msgArgs = ["invalidPasswordNotUsernameMessage"] as const;
|
const msgArgs = ["invalidPasswordNotUsernameMessage"] as const;
|
||||||
|
|
||||||
errors.push({
|
errors.push({
|
||||||
"validatorName": undefined,
|
|
||||||
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
||||||
"errorMessageStr": msgStr(...msgArgs),
|
"errorMessageStr": msgStr(...msgArgs),
|
||||||
"fieldIndex": undefined
|
"fieldIndex": undefined,
|
||||||
|
"source": {
|
||||||
|
"type": "passwordPolicy",
|
||||||
|
"name": policyName
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -698,10 +818,13 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
|
|||||||
const msgArgs = ["invalidPasswordNotEmailMessage"] as const;
|
const msgArgs = ["invalidPasswordNotEmailMessage"] as const;
|
||||||
|
|
||||||
errors.push({
|
errors.push({
|
||||||
"validatorName": undefined,
|
|
||||||
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
||||||
"errorMessageStr": msgStr(...msgArgs),
|
"errorMessageStr": msgStr(...msgArgs),
|
||||||
"fieldIndex": undefined
|
"fieldIndex": undefined,
|
||||||
|
"source": {
|
||||||
|
"type": "passwordPolicy",
|
||||||
|
"name": policyName
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -724,10 +847,13 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
|
|||||||
const msgArgs = ["invalidPasswordConfirmMessage"] as const;
|
const msgArgs = ["invalidPasswordConfirmMessage"] as const;
|
||||||
|
|
||||||
errors.push({
|
errors.push({
|
||||||
"validatorName": undefined,
|
|
||||||
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
||||||
"errorMessageStr": msgStr(...msgArgs),
|
"errorMessageStr": msgStr(...msgArgs),
|
||||||
"fieldIndex": undefined
|
"fieldIndex": undefined,
|
||||||
|
"source": {
|
||||||
|
"type": "other",
|
||||||
|
"rule": "passwordConfirmMatchesPassword"
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -745,10 +871,13 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
|
|||||||
const msgArgs = ["error-user-attribute-required"] as const;
|
const msgArgs = ["error-user-attribute-required"] as const;
|
||||||
|
|
||||||
errors.push({
|
errors.push({
|
||||||
"validatorName": undefined,
|
|
||||||
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
||||||
"errorMessageStr": msgStr(...msgArgs),
|
"errorMessageStr": msgStr(...msgArgs),
|
||||||
"fieldIndex": undefined
|
"fieldIndex": undefined,
|
||||||
|
"source": {
|
||||||
|
"type": "other",
|
||||||
|
"rule": "requiredField"
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -767,14 +896,19 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
|
|||||||
break validator_x;
|
break validator_x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const source: FormFieldError.Source = {
|
||||||
|
"type": "validator",
|
||||||
|
"name": validatorName
|
||||||
|
};
|
||||||
|
|
||||||
if (max !== undefined && value.length > parseInt(max)) {
|
if (max !== undefined && value.length > parseInt(max)) {
|
||||||
const msgArgs = ["error-invalid-length-too-long", max] as const;
|
const msgArgs = ["error-invalid-length-too-long", max] as const;
|
||||||
|
|
||||||
errors.push({
|
errors.push({
|
||||||
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
||||||
"errorMessageStr": msgStr(...msgArgs),
|
"errorMessageStr": msgStr(...msgArgs),
|
||||||
validatorName,
|
"fieldIndex": undefined,
|
||||||
"fieldIndex": undefined
|
source
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -784,8 +918,8 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
|
|||||||
errors.push({
|
errors.push({
|
||||||
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
||||||
"errorMessageStr": msgStr(...msgArgs),
|
"errorMessageStr": msgStr(...msgArgs),
|
||||||
validatorName,
|
"fieldIndex": undefined,
|
||||||
"fieldIndex": undefined
|
source
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -812,16 +946,22 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
|
|||||||
const msgArgs = [errorMessageKey ?? id<MessageKey>("shouldMatchPattern"), pattern] as const;
|
const msgArgs = [errorMessageKey ?? id<MessageKey>("shouldMatchPattern"), pattern] as const;
|
||||||
|
|
||||||
errors.push({
|
errors.push({
|
||||||
validatorName,
|
|
||||||
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{advancedMsg(...msgArgs)}</Fragment>,
|
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{advancedMsg(...msgArgs)}</Fragment>,
|
||||||
"errorMessageStr": advancedMsgStr(...msgArgs),
|
"errorMessageStr": advancedMsgStr(...msgArgs),
|
||||||
"fieldIndex": undefined
|
"fieldIndex": undefined,
|
||||||
|
"source": {
|
||||||
|
"type": "validator",
|
||||||
|
"name": validatorName
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
validator_x: {
|
validator_x: {
|
||||||
if ([...errors].reverse()[0]?.validatorName === "pattern") {
|
{
|
||||||
break validator_x;
|
const lastError = errors[errors.length - 1];
|
||||||
|
if (lastError !== undefined && lastError.source.type === "validator" && lastError.source.name === "pattern") {
|
||||||
|
break validator_x;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const validatorName = "email";
|
const validatorName = "email";
|
||||||
@ -845,10 +985,13 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
|
|||||||
const msgArgs = [id<MessageKey>("invalidEmailMessage")] as const;
|
const msgArgs = [id<MessageKey>("invalidEmailMessage")] as const;
|
||||||
|
|
||||||
errors.push({
|
errors.push({
|
||||||
validatorName,
|
|
||||||
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
||||||
"errorMessageStr": msgStr(...msgArgs),
|
"errorMessageStr": msgStr(...msgArgs),
|
||||||
"fieldIndex": undefined
|
"fieldIndex": undefined,
|
||||||
|
"source": {
|
||||||
|
"type": "validator",
|
||||||
|
"name": validatorName
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -869,14 +1012,19 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
|
|||||||
|
|
||||||
const intValue = parseInt(value);
|
const intValue = parseInt(value);
|
||||||
|
|
||||||
|
const source: FormFieldError.Source = {
|
||||||
|
"type": "validator",
|
||||||
|
"name": validatorName
|
||||||
|
};
|
||||||
|
|
||||||
if (isNaN(intValue)) {
|
if (isNaN(intValue)) {
|
||||||
const msgArgs = ["mustBeAnInteger"] as const;
|
const msgArgs = ["mustBeAnInteger"] as const;
|
||||||
|
|
||||||
errors.push({
|
errors.push({
|
||||||
validatorName,
|
|
||||||
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
||||||
"errorMessageStr": msgStr(...msgArgs),
|
"errorMessageStr": msgStr(...msgArgs),
|
||||||
"fieldIndex": undefined
|
"fieldIndex": undefined,
|
||||||
|
source
|
||||||
});
|
});
|
||||||
|
|
||||||
break validator_x;
|
break validator_x;
|
||||||
@ -886,10 +1034,10 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
|
|||||||
const msgArgs = ["error-number-out-of-range-too-big", max] as const;
|
const msgArgs = ["error-number-out-of-range-too-big", max] as const;
|
||||||
|
|
||||||
errors.push({
|
errors.push({
|
||||||
validatorName,
|
|
||||||
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
||||||
"errorMessageStr": msgStr(...msgArgs),
|
"errorMessageStr": msgStr(...msgArgs),
|
||||||
"fieldIndex": undefined
|
"fieldIndex": undefined,
|
||||||
|
source
|
||||||
});
|
});
|
||||||
|
|
||||||
break validator_x;
|
break validator_x;
|
||||||
@ -899,10 +1047,10 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
|
|||||||
const msgArgs = ["error-number-out-of-range-too-small", min] as const;
|
const msgArgs = ["error-number-out-of-range-too-small", min] as const;
|
||||||
|
|
||||||
errors.push({
|
errors.push({
|
||||||
validatorName,
|
|
||||||
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{msg(...msgArgs)}</Fragment>,
|
||||||
"errorMessageStr": msgStr(...msgArgs),
|
"errorMessageStr": msgStr(...msgArgs),
|
||||||
"fieldIndex": undefined
|
"fieldIndex": undefined,
|
||||||
|
source
|
||||||
});
|
});
|
||||||
|
|
||||||
break validator_x;
|
break validator_x;
|
||||||
@ -929,14 +1077,17 @@ function useGetErrors(params: { kcContext: Pick<KcContextLike, "messagesPerField
|
|||||||
const msgArgs = [id<MessageKey>("notAValidOption")] as const;
|
const msgArgs = [id<MessageKey>("notAValidOption")] as const;
|
||||||
|
|
||||||
errors.push({
|
errors.push({
|
||||||
validatorName,
|
|
||||||
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{advancedMsg(...msgArgs)}</Fragment>,
|
"errorMessage": <Fragment key={`${attributeName}-${errors.length}`}>{advancedMsg(...msgArgs)}</Fragment>,
|
||||||
"errorMessageStr": advancedMsgStr(...msgArgs),
|
"errorMessageStr": advancedMsgStr(...msgArgs),
|
||||||
"fieldIndex": undefined
|
"fieldIndex": undefined,
|
||||||
|
"source": {
|
||||||
|
"type": "validator",
|
||||||
|
"name": validatorName
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Implement missing validators.
|
//TODO: Implement missing validators. See Validators type definition.
|
||||||
|
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user