@digigov/form 0.10.8 → 0.10.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -1
- package/Form.stories.playwright.json +0 -72
- package/FormBuilder/FormBuilder.mdx +1 -1
- package/MultiplicityField/__stories__/PreviewDisplay.js +6 -6
- package/Questions/__stories__/Default.js +2 -2
- package/Questions/index.mdx +1 -1
- package/es/Form.stories.playwright.json +0 -72
- package/es/FormBuilder/FormBuilder.mdx +1 -1
- package/es/MultiplicityField/__stories__/PreviewDisplay.js +6 -6
- package/es/Questions/__stories__/Default.js +1 -1
- package/es/Questions/index.mdx +1 -1
- package/esm/Form.stories.playwright.json +0 -72
- package/esm/FormBuilder/FormBuilder.mdx +1 -1
- package/esm/MultiplicityField/__stories__/PreviewDisplay.js +6 -6
- package/esm/Questions/__stories__/Default.js +1 -1
- package/esm/Questions/index.mdx +1 -1
- package/esm/index.js +1 -1
- package/package.json +4 -4
- package/src/Field/FieldBase.tsx +99 -0
- package/src/Field/FieldBaseContainer.tsx +57 -0
- package/src/Field/FieldConditional.tsx +75 -0
- package/src/Field/index.mdx +6 -0
- package/src/Field/index.tsx +92 -0
- package/src/Field/types.tsx +102 -0
- package/src/Field/utils.ts +164 -0
- package/src/FieldArray/FieldArray.stories.js +8 -0
- package/src/FieldArray/FieldArray.stories.playwright.json +353 -0
- package/src/FieldArray/__stories__/Default.tsx +95 -0
- package/src/FieldArray/__stories__/WithExactLength.tsx +95 -0
- package/src/FieldArray/index.tsx +83 -0
- package/src/FieldObject/index.tsx +92 -0
- package/src/Fieldset/FieldsetWithContext.tsx +41 -0
- package/src/Fieldset/index.tsx +40 -0
- package/src/Fieldset/types.tsx +6 -0
- package/src/Form.stories.js +5 -0
- package/src/Form.stories.playwright.json +71 -0
- package/src/FormBuilder/FormBuilder.mdx +271 -0
- package/src/FormBuilder/FormBuilder.stories.js +7 -0
- package/src/FormBuilder/FormBuilder.stories.playwright.json +52 -0
- package/src/FormBuilder/FormBuilder.tsx +165 -0
- package/src/FormBuilder/__stories__/Default.tsx +23 -0
- package/src/FormBuilder/index.tsx +3 -0
- package/src/FormContext.tsx +8 -0
- package/src/MultiplicityField/MultiplicityField.mdx +580 -0
- package/src/MultiplicityField/MultiplicityField.stories.js +12 -0
- package/src/MultiplicityField/MultiplicityField.stories.playwright.json +1370 -0
- package/src/MultiplicityField/__stories__/Default.tsx +100 -0
- package/src/MultiplicityField/__stories__/PreviewDisplay.tsx +160 -0
- package/src/MultiplicityField/__stories__/WithExactLength.tsx +99 -0
- package/src/MultiplicityField/__stories__/WithMaxLength.tsx +102 -0
- package/src/MultiplicityField/__stories__/WithMinAndMaxLength.tsx +103 -0
- package/src/MultiplicityField/__stories__/WithMinLength.tsx +102 -0
- package/src/MultiplicityField/add-objects.tsx +186 -0
- package/src/MultiplicityField/index.tsx +166 -0
- package/src/Questions/Questions.stories.js +7 -0
- package/src/Questions/Questions.tsx +74 -0
- package/src/Questions/QuestionsContext.tsx +9 -0
- package/src/Questions/Step/ReviewStep.tsx +63 -0
- package/src/Questions/Step/Step.tsx +67 -0
- package/src/Questions/Step/StepArrayReview.tsx +68 -0
- package/src/Questions/Step/StepContext.tsx +21 -0
- package/src/Questions/Step/StepDescription.tsx +33 -0
- package/src/Questions/Step/StepForm.tsx +60 -0
- package/src/Questions/Step/StepQuote.tsx +8 -0
- package/src/Questions/Step/StepTitle.tsx +60 -0
- package/src/Questions/Step/getAddMoreFields.tsx +28 -0
- package/src/Questions/Step/index.ts +13 -0
- package/src/Questions/Step/types.tsx +32 -0
- package/src/Questions/__snapshots__/index.spec.tsx.snap +887 -0
- package/src/Questions/__stories__/Default.tsx +130 -0
- package/src/Questions/getNextStep.tsx +24 -0
- package/src/Questions/index.mdx +418 -0
- package/src/Questions/index.spec.tsx +72 -0
- package/src/Questions/index.tsx +5 -0
- package/src/Questions/types.tsx +25 -0
- package/src/__stories__/AutoCompleteField.tsx +45 -0
- package/src/__stories__/IntField.tsx +38 -0
- package/src/create-simple-form.mdx +518 -0
- package/src/index.mdx +44 -0
- package/src/index.ts +3 -0
- package/src/inputs/AutoComplete/index.tsx +85 -0
- package/src/inputs/Checkboxes/Checkboxes.stories.js +7 -0
- package/src/inputs/Checkboxes/Checkboxes.stories.playwright.json +69 -0
- package/src/inputs/Checkboxes/__stories__/Default.tsx +39 -0
- package/src/inputs/Checkboxes/index.mdx +0 -0
- package/src/inputs/Checkboxes/index.tsx +77 -0
- package/src/inputs/DateInput/DateInput.stories.js +7 -0
- package/src/inputs/DateInput/DateInput.stories.playwright.json +72 -0
- package/src/inputs/DateInput/__stories__/Default.tsx +41 -0
- package/src/inputs/DateInput/index.tsx +130 -0
- package/src/inputs/FileInput/FileInput.stories.js +7 -0
- package/src/inputs/FileInput/FileInput.stories.playwright.json +75 -0
- package/src/inputs/FileInput/__stories__/Default.tsx +23 -0
- package/src/inputs/FileInput/index.tsx +76 -0
- package/src/inputs/Input/Input.stories.js +14 -0
- package/src/inputs/Input/Input.stories.playwright.json +376 -0
- package/src/inputs/Input/__stories__/AFM.tsx +24 -0
- package/src/inputs/Input/__stories__/Boolean.tsx +26 -0
- package/src/inputs/Input/__stories__/Default.tsx +25 -0
- package/src/inputs/Input/__stories__/IBAN.tsx +26 -0
- package/src/inputs/Input/__stories__/Integer.tsx +25 -0
- package/src/inputs/Input/__stories__/MobilePhone.tsx +24 -0
- package/src/inputs/Input/__stories__/PhoneNumber.tsx +24 -0
- package/src/inputs/Input/__stories__/PostalCode.tsx +25 -0
- package/src/inputs/Input/index.mdx +8 -0
- package/src/inputs/Input/index.tsx +62 -0
- package/src/inputs/Label/Label.stories.js +7 -0
- package/src/inputs/Label/Label.stories.playwright.json +40 -0
- package/src/inputs/Label/__stories__/Default.tsx +28 -0
- package/src/inputs/Label/index.mdx +0 -0
- package/src/inputs/Label/index.tsx +44 -0
- package/src/inputs/Radio/Radio.stories.js +7 -0
- package/src/inputs/Radio/Radio.stories.playwright.json +57 -0
- package/src/inputs/Radio/__stories__/Default.tsx +42 -0
- package/src/inputs/Radio/index.mdx +0 -0
- package/src/inputs/Radio/index.tsx +57 -0
- package/src/inputs/Select/Select.stories.js +7 -0
- package/src/inputs/Select/Select.stories.playwright.json +22 -0
- package/src/inputs/Select/__stories__/Default.tsx +47 -0
- package/src/inputs/Select/index.tsx +37 -0
- package/src/inputs/index.ts +7 -0
- package/src/installation.mdx +72 -0
- package/src/internal.ts +34 -0
- package/src/registry.js +134 -0
- package/src/types.tsx +110 -0
- package/src/utils.ts +78 -0
- package/src/validators/index.ts +203 -0
- package/src/validators/types.ts +2 -0
- package/src/validators/utils/afm.ts +37 -0
- package/src/validators/utils/file.ts +25 -0
- package/src/validators/utils/iban.ts +119 -0
- package/src/validators/utils/index.ts +94 -0
- package/src/validators/utils/int.ts +22 -0
- package/src/validators/utils/number.ts +18 -0
- package/src/validators/utils/phone.ts +120 -0
- package/src/validators/utils/postal_code.ts +33 -0
- package/src/validators/utils/uuid4.ts +21 -0
- package/src/validators/validators.spec.ts +122 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { FieldSpec } from '@digigov/form/types';
|
|
2
|
+
import { ValidatorSchema } from '@digigov/form/validators/types';
|
|
3
|
+
export function validateIban(value: string, countryCode: string): boolean {
|
|
4
|
+
value = value.replace(/\s/g, '').replace(/-/g, '');
|
|
5
|
+
if (value.match(/^[0-9]*$/i)) {
|
|
6
|
+
// this is for greek iban without the country code
|
|
7
|
+
if (value.length !== 25) {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
} else {
|
|
11
|
+
value = value.toUpperCase();
|
|
12
|
+
if (countryCode) {
|
|
13
|
+
if (!value.startsWith(countryCode.toUpperCase())) {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
if (value.length === ibanCountryCodesLengths[countryCode.toUpperCase()]) {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
if (value.length !== 27) {
|
|
21
|
+
// this is for greek iban
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const IBAN_VALIDATOR = (field: FieldSpec): ValidatorSchema => {
|
|
29
|
+
const countryCode = field?.extra?.country;
|
|
30
|
+
return {
|
|
31
|
+
name: 'iban-validator',
|
|
32
|
+
message: 'form.error.iban',
|
|
33
|
+
test: (value: string): boolean => {
|
|
34
|
+
if (!value) {
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
return validateIban(value, countryCode);
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const ibanCountryCodesLengths = {
|
|
43
|
+
AD: 24,
|
|
44
|
+
AT: 20,
|
|
45
|
+
AZ: 28,
|
|
46
|
+
BH: 22,
|
|
47
|
+
BY: 28,
|
|
48
|
+
BE: 16,
|
|
49
|
+
BA: 20,
|
|
50
|
+
BR: 29,
|
|
51
|
+
BG: 22,
|
|
52
|
+
CR: 22,
|
|
53
|
+
HR: 21,
|
|
54
|
+
CY: 28,
|
|
55
|
+
CZ: 24,
|
|
56
|
+
DK: 18,
|
|
57
|
+
DO: 28,
|
|
58
|
+
EG: 29,
|
|
59
|
+
SV: 28,
|
|
60
|
+
EE: 20,
|
|
61
|
+
FO: 18,
|
|
62
|
+
FI: 18,
|
|
63
|
+
FR: 27,
|
|
64
|
+
GE: 22,
|
|
65
|
+
DE: 22,
|
|
66
|
+
GI: 23,
|
|
67
|
+
GR: 27,
|
|
68
|
+
GL: 18,
|
|
69
|
+
GT: 28,
|
|
70
|
+
VA: 22,
|
|
71
|
+
HU: 28,
|
|
72
|
+
IS: 26,
|
|
73
|
+
IQ: 23,
|
|
74
|
+
IE: 22,
|
|
75
|
+
IL: 23,
|
|
76
|
+
IT: 27,
|
|
77
|
+
JO: 30,
|
|
78
|
+
KZ: 20,
|
|
79
|
+
XK: 20,
|
|
80
|
+
KW: 30,
|
|
81
|
+
LV: 21,
|
|
82
|
+
LB: 28,
|
|
83
|
+
LI: 21,
|
|
84
|
+
LT: 20,
|
|
85
|
+
LU: 20,
|
|
86
|
+
MT: 31,
|
|
87
|
+
MR: 27,
|
|
88
|
+
MU: 30,
|
|
89
|
+
MD: 24,
|
|
90
|
+
MC: 27,
|
|
91
|
+
ME: 22,
|
|
92
|
+
NL: 18,
|
|
93
|
+
MK: 19,
|
|
94
|
+
NO: 15,
|
|
95
|
+
PK: 24,
|
|
96
|
+
PS: 29,
|
|
97
|
+
PL: 28,
|
|
98
|
+
PT: 25,
|
|
99
|
+
QA: 29,
|
|
100
|
+
RO: 24,
|
|
101
|
+
LC: 32,
|
|
102
|
+
SM: 27,
|
|
103
|
+
ST: 25,
|
|
104
|
+
SA: 24,
|
|
105
|
+
RS: 22,
|
|
106
|
+
SC: 31,
|
|
107
|
+
SK: 24,
|
|
108
|
+
SI: 19,
|
|
109
|
+
ES: 24,
|
|
110
|
+
SE: 24,
|
|
111
|
+
CH: 21,
|
|
112
|
+
TL: 23,
|
|
113
|
+
TN: 24,
|
|
114
|
+
TR: 26,
|
|
115
|
+
UA: 29,
|
|
116
|
+
AE: 23,
|
|
117
|
+
GB: 22,
|
|
118
|
+
VG: 24,
|
|
119
|
+
};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import * as yup from 'yup';
|
|
2
|
+
import { FieldSpec } from '@digigov/form/types';
|
|
3
|
+
import { ValidatorSchema } from '@digigov/form/validators/types';
|
|
4
|
+
|
|
5
|
+
export * from '@digigov/form/validators/utils/afm';
|
|
6
|
+
export * from '@digigov/form/validators/utils/file';
|
|
7
|
+
export * from '@digigov/form/validators/utils/iban';
|
|
8
|
+
export * from '@digigov/form/validators/utils/phone';
|
|
9
|
+
export * from '@digigov/form/validators/utils/postal_code';
|
|
10
|
+
export * from '@digigov/form/validators/utils/uuid4';
|
|
11
|
+
|
|
12
|
+
export function getYupField(field: FieldSpec, yupTypeMap: Record<string, any>) {
|
|
13
|
+
const yupField = yupTypeMap[field?.type || 'string'] || yupTypeMap['string'];
|
|
14
|
+
return yupField(field);
|
|
15
|
+
}
|
|
16
|
+
export function computeShape(
|
|
17
|
+
fields: FieldSpec[],
|
|
18
|
+
yupTypeMap: Record<string, ValidatorSchema>,
|
|
19
|
+
validatorRegistry: Record<string, ValidatorSchema[]> | undefined
|
|
20
|
+
) {
|
|
21
|
+
const fieldSchemas = {};
|
|
22
|
+
const objectFields: Record<string, FieldSpec[]> = {};
|
|
23
|
+
fields.forEach((field) => {
|
|
24
|
+
let yupField = getYupField(field, yupTypeMap);
|
|
25
|
+
if (field.condition) {
|
|
26
|
+
for (const key in field.condition) {
|
|
27
|
+
let then: any, otherwise: any;
|
|
28
|
+
if (field.condition[key].then) {
|
|
29
|
+
if (field.condition[key].then?.required === false) {
|
|
30
|
+
then = yupField;
|
|
31
|
+
} else if (field.condition[key].then?.required === true) {
|
|
32
|
+
then = yupField.required('form.error.required');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (field.condition[key].else) {
|
|
36
|
+
if (field.condition[key].else?.required === false) {
|
|
37
|
+
otherwise = yupField;
|
|
38
|
+
} else if (field.condition[key].else?.required === true) {
|
|
39
|
+
otherwise = yupField.required('form.error.required');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (then || otherwise) {
|
|
43
|
+
yupField = yupField.when(key, {
|
|
44
|
+
is: field.condition[key].is,
|
|
45
|
+
then,
|
|
46
|
+
otherwise,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
} else if (field.required) {
|
|
51
|
+
yupField = yupField.required('form.error.required');
|
|
52
|
+
}
|
|
53
|
+
if (validatorRegistry && field.type && validatorRegistry[field.type]) {
|
|
54
|
+
validatorRegistry[field.type].forEach((validator: any) => {
|
|
55
|
+
yupField = yupField.test(validator);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
if (field.validators) {
|
|
59
|
+
field.validators.forEach((validator) => {
|
|
60
|
+
yupField = yupField.test(validator);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
fieldSchemas[field.key] = yupField;
|
|
64
|
+
});
|
|
65
|
+
for (const objectKey in objectFields) {
|
|
66
|
+
fieldSchemas[objectKey] = getYupObjectShape(
|
|
67
|
+
objectFields[objectKey],
|
|
68
|
+
yupTypeMap,
|
|
69
|
+
validatorRegistry
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
return fieldSchemas;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function getYupObjectShape(
|
|
76
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
77
|
+
fields: FieldSpec[] | any,
|
|
78
|
+
yupTypeMap: Record<string, any>,
|
|
79
|
+
validatorRegistry?: Record<string, ValidatorSchema[]>
|
|
80
|
+
) {
|
|
81
|
+
if (!fields.current) {
|
|
82
|
+
const fieldSchemas = computeShape(fields, yupTypeMap, validatorRegistry);
|
|
83
|
+
return yup.object().shape(fieldSchemas);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return yup.lazy(function () {
|
|
87
|
+
const fieldSchemas = computeShape(
|
|
88
|
+
Object.values(fields.current),
|
|
89
|
+
yupTypeMap,
|
|
90
|
+
validatorRegistry
|
|
91
|
+
);
|
|
92
|
+
return yup.object().shape(fieldSchemas);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ValidatorSchema } from '@digigov/form/validators/types';
|
|
2
|
+
|
|
3
|
+
export function validateIntNumber(number: number): boolean {
|
|
4
|
+
if (number === undefined) {
|
|
5
|
+
return false;
|
|
6
|
+
} else {
|
|
7
|
+
return Number.isInteger(number) && Number(number) > 0;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const INT_VALIDATOR = (): ValidatorSchema => {
|
|
12
|
+
return {
|
|
13
|
+
name: 'int-validator',
|
|
14
|
+
message: 'form.error.positive_integer_number',
|
|
15
|
+
test: (value: number): boolean => {
|
|
16
|
+
if (value === null) {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
return validateIntNumber(value);
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ValidatorSchema } from '@digigov/form/validators/types';
|
|
2
|
+
|
|
3
|
+
export function validateNumber(number: number): boolean {
|
|
4
|
+
return !Number.isNaN(number);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const NUMBER_VALIDATOR = (): ValidatorSchema => {
|
|
8
|
+
return {
|
|
9
|
+
name: 'number-validator',
|
|
10
|
+
message: 'form.error.number',
|
|
11
|
+
test: (value: number): boolean => {
|
|
12
|
+
if (value === null) {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
return validateNumber(value);
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import * as gPhoneNumber from 'google-libphonenumber';
|
|
2
|
+
import { ValidatorSchema } from '@digigov/form/validators/types';
|
|
3
|
+
import { FieldSpec } from '@digigov/form/types';
|
|
4
|
+
|
|
5
|
+
export type PhoneNumberType = 'landline' | 'mobile' | null;
|
|
6
|
+
|
|
7
|
+
export function validatePhoneNumber(
|
|
8
|
+
phoneNumber: string,
|
|
9
|
+
countries: Array<string> = ['gr'],
|
|
10
|
+
typeOfPhoneNumber: PhoneNumberType
|
|
11
|
+
): boolean {
|
|
12
|
+
const phoneUtil = gPhoneNumber.PhoneNumberUtil.getInstance();
|
|
13
|
+
if (!countries || countries.length === 0) {
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
return countries.some((country) => {
|
|
17
|
+
try {
|
|
18
|
+
const phone = phoneUtil.parse(phoneNumber, country.toUpperCase());
|
|
19
|
+
if (phoneUtil.isValidNumber(phone)) {
|
|
20
|
+
if (typeOfPhoneNumber) {
|
|
21
|
+
if (matchTypeOfPhoneNumber(phone, typeOfPhoneNumber, phoneUtil)) {
|
|
22
|
+
return true;
|
|
23
|
+
} else {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
} else {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return false;
|
|
31
|
+
} catch (error) {
|
|
32
|
+
console.error(error);
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
const phoneNumberTypes = {
|
|
38
|
+
0: 'landline',
|
|
39
|
+
1: 'mobile',
|
|
40
|
+
2: 'landline_or_mobile',
|
|
41
|
+
};
|
|
42
|
+
export function matchTypeOfPhoneNumber(
|
|
43
|
+
phone: any,
|
|
44
|
+
type: string,
|
|
45
|
+
phoneUtil: any
|
|
46
|
+
): boolean {
|
|
47
|
+
try {
|
|
48
|
+
const phoneNumberType = phoneUtil.getNumberType(phone);
|
|
49
|
+
const numberType = phoneNumberTypes[phoneNumberType];
|
|
50
|
+
if (numberType === 'landline_or_mobile' || numberType === type) {
|
|
51
|
+
return true;
|
|
52
|
+
} else {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
} catch (error) {
|
|
56
|
+
console.error(error);
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function validateMobile(value): boolean {
|
|
61
|
+
const phoneUtil = gPhoneNumber.PhoneNumberUtil.getInstance();
|
|
62
|
+
const origValue = value;
|
|
63
|
+
// probably catch all the cases with a regex instead of gphonenumber
|
|
64
|
+
if (!value.match(/^((\+|00){0,1}\d{1,3}[- ]?)?\d{10}$/)) {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
try {
|
|
68
|
+
let phone;
|
|
69
|
+
try {
|
|
70
|
+
phone = phoneUtil.parse(value);
|
|
71
|
+
} catch (err) {
|
|
72
|
+
try {
|
|
73
|
+
value = '+' + value;
|
|
74
|
+
phone = phoneUtil.parse(value);
|
|
75
|
+
} catch (err) {
|
|
76
|
+
value = '+30' + origValue;
|
|
77
|
+
phone = phoneUtil.parse(value);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return phoneUtil.isValidNumber(phone);
|
|
81
|
+
} catch (err) {
|
|
82
|
+
console.error(err);
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export const MOBILE_PHONE_VALIDATOR = {
|
|
88
|
+
name: 'mobile-phone-validator',
|
|
89
|
+
message: 'form.error.mobile_phone',
|
|
90
|
+
test: (value): boolean => {
|
|
91
|
+
if (value) {
|
|
92
|
+
return validateMobile(value);
|
|
93
|
+
}
|
|
94
|
+
return true;
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export const PHONE_NUMBER_VALIDATOR = (field: FieldSpec): ValidatorSchema => {
|
|
99
|
+
const countryCode = field?.extra?.countries;
|
|
100
|
+
const typeOfPhone: PhoneNumberType | null = field?.extra?.phoneType;
|
|
101
|
+
return {
|
|
102
|
+
name: 'phone-number-validator',
|
|
103
|
+
message: (): string => {
|
|
104
|
+
if (typeOfPhone === 'mobile') {
|
|
105
|
+
return 'form.error.mobile_phone';
|
|
106
|
+
}
|
|
107
|
+
if (typeOfPhone === 'landline') {
|
|
108
|
+
return 'form.error.landline';
|
|
109
|
+
} else {
|
|
110
|
+
return 'form.error.phone_number';
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
test: (value: string): boolean => {
|
|
114
|
+
if (!value) {
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
return validatePhoneNumber(value, countryCode, typeOfPhone);
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ValidatorSchema } from '@digigov/form/validators/types';
|
|
2
|
+
import { FieldSpec } from '@digigov/form/types';
|
|
3
|
+
|
|
4
|
+
const CODE_REGEX = /^[12345678][0-9]{4}$/;
|
|
5
|
+
export function validatePostalCode(
|
|
6
|
+
number: string,
|
|
7
|
+
countries: Array<string>
|
|
8
|
+
): boolean {
|
|
9
|
+
if (!countries) {
|
|
10
|
+
return false;
|
|
11
|
+
} else {
|
|
12
|
+
if (countries.length === 1 && countries[0].toUpperCase() === 'GR') {
|
|
13
|
+
// Greek postal code must be 5 digits long and shouldn't start with 0 or 9.
|
|
14
|
+
return CODE_REGEX.test(number);
|
|
15
|
+
} else {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const POSTALCODE_VALIDATOR = (field: FieldSpec): ValidatorSchema => {
|
|
22
|
+
const countryCode = field?.extra?.countries;
|
|
23
|
+
return {
|
|
24
|
+
name: 'postal-code-validator',
|
|
25
|
+
message: 'form.error.postalCode',
|
|
26
|
+
test: (value: string): boolean => {
|
|
27
|
+
if (!value) {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
return validatePostalCode(value, countryCode);
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const UUID4_PATTERN = /^[0-9A-F]{8}-[0-9A-F]{4}-[4][0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i;
|
|
2
|
+
|
|
3
|
+
export function validateUUID4(uuid4: string): boolean {
|
|
4
|
+
if (uuid4.length !== 36) {
|
|
5
|
+
// This uuid4 should be 36 characters long
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
return UUID4_PATTERN.test(uuid4);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const UUID4_VALIDATOR = {
|
|
13
|
+
name: 'uuid4-validator',
|
|
14
|
+
message: 'form.error.uuid4',
|
|
15
|
+
test: (value): boolean => {
|
|
16
|
+
if (value) {
|
|
17
|
+
return validateUUID4(value);
|
|
18
|
+
}
|
|
19
|
+
return true;
|
|
20
|
+
},
|
|
21
|
+
};
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import {
|
|
2
|
+
validateUUID4,
|
|
3
|
+
validateIban,
|
|
4
|
+
validatePostalCode,
|
|
5
|
+
validatePhoneNumber,
|
|
6
|
+
} from '@digigov/form/validators/utils';
|
|
7
|
+
|
|
8
|
+
it('validates wrong uuid4 for empty value', () => {
|
|
9
|
+
expect(validateUUID4('')).toBe(false);
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('validates wrong uuid4 because of length', () => {
|
|
13
|
+
expect(validateUUID4('9e463bc44a294bab8ee23af6cc3cbbe3')).toBe(false);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('validates wrong uuid4 with correct length and wrong form', () => {
|
|
17
|
+
expect(validateUUID4('ab123cd1-1234-ad34-ad45-12345abcdefg')).toBe(false);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('validates correct uuid4 validator', () => {
|
|
21
|
+
expect(validateUUID4('9e463bc4-4a29-4bab-8ee2-3af6cc3cbbe3')).toBe(true);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('validates correct gr iban', () => {
|
|
25
|
+
expect(validateIban('GR7801100800000008009825202', 'GR')).toBe(true);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('validates correct iban with spaces and dashes', () => {
|
|
29
|
+
expect(validateIban('GR 7801-1008 0000-0008 0098-25202', 'GR')).toBe(true);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('validates correct foreign iban', () => {
|
|
33
|
+
expect(validateIban('DE75512108001245126199', 'DE')).toBe(true);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('validates wrong iban for empty value', () => {
|
|
37
|
+
expect(validateIban('', '')).toBe(false);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('validates wrong greek iban for wrong length', () => {
|
|
41
|
+
expect(validateIban('GR78011008000000080098252020', 'gr')).toBe(false);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('validates wrong iban for non existing country code', () => {
|
|
45
|
+
expect(validateIban('AAA78011008000000080098252020', 'aaa')).toBe(false);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('validates correct greek iban whithout country code', () => {
|
|
49
|
+
expect(validateIban('7801100800000008009825202', '')).toBe(true);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('validates wrong postal code without country code', () => {
|
|
53
|
+
expect(validatePostalCode('123', [])).toBe(true);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it('validates wrong postal code with wrong country code', () => {
|
|
57
|
+
expect(validatePostalCode('123', ['FR'])).toBe(true);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('validates wrong postal code with greek country code', () => {
|
|
61
|
+
expect(validatePostalCode('123', ['GR'])).toBe(false);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('validates postal code with greek country code', () => {
|
|
65
|
+
expect(validatePostalCode('11143', ['GR'])).toBe(true);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('validates phone number type landline with greek country code', () => {
|
|
69
|
+
expect(validatePhoneNumber('2102934896', ['GR'], 'landline')).toBe(true);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('validates phone number type landline with ch country code', () => {
|
|
73
|
+
expect(validatePhoneNumber('2102934896', ['CH'], 'landline')).toBe(false);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('validates phone number type landline with ch and gr countries code', () => {
|
|
77
|
+
expect(validatePhoneNumber('2102934896', ['GR', 'CH'], 'landline')).toBe(
|
|
78
|
+
true
|
|
79
|
+
);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('validatesphone number type landline with ch and gr countries code', () => {
|
|
83
|
+
expect(validatePhoneNumber('41446681800', ['GR', 'CH'], 'landline')).toBe(
|
|
84
|
+
true
|
|
85
|
+
);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('validates phone number type landline with ch and gr countries code but phone number is mobile', () => {
|
|
89
|
+
expect(validatePhoneNumber('2102934896', ['GR', 'CH'], 'mobile')).toBe(false);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('validates phone number type mobile with ch and gr countries code', () => {
|
|
93
|
+
expect(validatePhoneNumber('6934100982', ['GR', 'CH'], 'mobile')).toBe(true);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it('validates phone number type mobile with gr country code', () => {
|
|
97
|
+
expect(validatePhoneNumber('6934100982', ['GR'], 'mobile')).toBe(true);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('validates phone number type mobile with ch country code', () => {
|
|
101
|
+
expect(validatePhoneNumber('6934100982', ['CH'], 'mobile')).toBe(false);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('validates phone number with no type and ch country code', () => {
|
|
105
|
+
expect(validatePhoneNumber('6934100982', ['CH'], null)).toBe(false);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('validates phone number with no type and gr country code', () => {
|
|
109
|
+
expect(validatePhoneNumber('6934100982', ['gr'], null)).toBe(true);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('validates phone number with no type and ch country code', () => {
|
|
113
|
+
expect(validatePhoneNumber('41446681800', ['CH'], null)).toBe(true);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('validates phone number with no type and gr country code', () => {
|
|
117
|
+
expect(validatePhoneNumber('41446681800', ['gr'], null)).toBe(false);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('validates phone number with no type and gr and ch countries code', () => {
|
|
121
|
+
expect(validatePhoneNumber('41446681800', ['gr', 'ch'], null)).toBe(true);
|
|
122
|
+
});
|