@defra/forms-engine-plugin 2.1.6 → 2.1.8
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/.server/server/plugins/engine/components/CheckboxesField.d.ts +2 -0
- package/.server/server/plugins/engine/components/CheckboxesField.js +13 -7
- package/.server/server/plugins/engine/components/CheckboxesField.js.map +1 -1
- package/.server/server/plugins/engine/components/DatePartsField.d.ts +2 -0
- package/.server/server/plugins/engine/components/DatePartsField.js +11 -5
- package/.server/server/plugins/engine/components/DatePartsField.js.map +1 -1
- package/.server/server/plugins/engine/components/FileUploadField.d.ts +2 -0
- package/.server/server/plugins/engine/components/FileUploadField.js +9 -3
- package/.server/server/plugins/engine/components/FileUploadField.js.map +1 -1
- package/.server/server/plugins/engine/components/FormComponent.d.ts +2 -0
- package/.server/server/plugins/engine/components/FormComponent.js +11 -4
- package/.server/server/plugins/engine/components/FormComponent.js.map +1 -1
- package/.server/server/plugins/engine/components/ListFormComponent.d.ts +1 -0
- package/.server/server/plugins/engine/components/ListFormComponent.js +6 -4
- package/.server/server/plugins/engine/components/ListFormComponent.js.map +1 -1
- package/.server/server/plugins/engine/components/MonthYearField.d.ts +2 -0
- package/.server/server/plugins/engine/components/MonthYearField.js +9 -3
- package/.server/server/plugins/engine/components/MonthYearField.js.map +1 -1
- package/.server/server/plugins/engine/components/UkAddressField.d.ts +3 -1
- package/.server/server/plugins/engine/components/UkAddressField.js +12 -5
- package/.server/server/plugins/engine/components/UkAddressField.js.map +1 -1
- package/.server/server/plugins/engine/outputFormatters/adapter/v1.js +1 -1
- package/.server/server/plugins/engine/outputFormatters/adapter/v1.js.map +1 -1
- package/.server/server/plugins/engine/types/enums.d.ts +13 -0
- package/.server/server/plugins/engine/types/enums.js +17 -0
- package/.server/server/plugins/engine/types/enums.js.map +1 -0
- package/.server/server/plugins/engine/types/index.d.ts +2 -1
- package/.server/server/plugins/engine/types/index.js +2 -1
- package/.server/server/plugins/engine/types/index.js.map +1 -1
- package/.server/server/plugins/engine/types/schema.js +1 -1
- package/.server/server/plugins/engine/types/schema.js.map +1 -1
- package/.server/server/plugins/engine/types.d.ts +2 -14
- package/.server/server/plugins/engine/types.js +1 -16
- package/.server/server/plugins/engine/types.js.map +1 -1
- package/package.json +1 -1
- package/src/server/plugins/engine/components/CheckboxesField.ts +18 -7
- package/src/server/plugins/engine/components/DatePartsField.ts +17 -6
- package/src/server/plugins/engine/components/FileUploadField.ts +14 -3
- package/src/server/plugins/engine/components/FormComponent.ts +17 -5
- package/src/server/plugins/engine/components/ListFormComponent.ts +10 -3
- package/src/server/plugins/engine/components/MonthYearField.ts +14 -4
- package/src/server/plugins/engine/components/UkAddressField.ts +16 -6
- package/src/server/plugins/engine/outputFormatters/adapter/v1.test.ts +1 -1
- package/src/server/plugins/engine/outputFormatters/adapter/v1.ts +1 -1
- package/src/server/plugins/engine/types/enums.ts +15 -0
- package/src/server/plugins/engine/types/index.ts +2 -5
- package/src/server/plugins/engine/types/schema.test.ts +1 -1
- package/src/server/plugins/engine/types/schema.ts +1 -1
- package/src/server/plugins/engine/types.ts +9 -15
|
@@ -9,6 +9,8 @@ export declare class CheckboxesField extends SelectionControlField {
|
|
|
9
9
|
constructor(def: CheckboxesFieldComponent, props: ConstructorParameters<typeof SelectionControlField>[1]);
|
|
10
10
|
getFormValueFromState(state: FormSubmissionState): (string | number | boolean)[] | undefined;
|
|
11
11
|
getFormValue(value?: FormStateValue | FormState): (string | number | boolean)[] | undefined;
|
|
12
|
+
getDisplayStringFromFormValue(selected: (string | number | boolean)[]): string;
|
|
13
|
+
getContextValueFromFormValue(values: (string | number | boolean)[] | undefined): (string | number | boolean)[];
|
|
12
14
|
getDisplayStringFromState(state: FormSubmissionState): string;
|
|
13
15
|
getContextValueFromState(state: FormSubmissionState): (string | number | boolean)[];
|
|
14
16
|
isValue(value?: FormStateValue | FormState): value is Item['value'][];
|
|
@@ -36,20 +36,15 @@ export class CheckboxesField extends SelectionControlField {
|
|
|
36
36
|
getFormValue(value) {
|
|
37
37
|
return this.isValue(value) ? value : undefined;
|
|
38
38
|
}
|
|
39
|
-
|
|
39
|
+
getDisplayStringFromFormValue(selected) {
|
|
40
40
|
const {
|
|
41
41
|
items
|
|
42
42
|
} = this;
|
|
43
43
|
|
|
44
|
-
// Selected checkbox values
|
|
45
|
-
const selected = this.getFormValueFromState(state) ?? [];
|
|
46
|
-
|
|
47
44
|
// Map selected values to text
|
|
48
45
|
return items.filter(item => selected.includes(item.value)).map(item => item.text).join(', ');
|
|
49
46
|
}
|
|
50
|
-
|
|
51
|
-
const values = this.getFormValueFromState(state);
|
|
52
|
-
|
|
47
|
+
getContextValueFromFormValue(values) {
|
|
53
48
|
/**
|
|
54
49
|
* For evaluation context purposes, optional {@link CheckboxesField}
|
|
55
50
|
* with an undefined value (i.e. nothing selected) should default to [].
|
|
@@ -63,6 +58,17 @@ export class CheckboxesField extends SelectionControlField {
|
|
|
63
58
|
*/
|
|
64
59
|
return values ?? [];
|
|
65
60
|
}
|
|
61
|
+
getDisplayStringFromState(state) {
|
|
62
|
+
// Selected checkbox values
|
|
63
|
+
const selected = this.getFormValueFromState(state) ?? [];
|
|
64
|
+
|
|
65
|
+
// Map selected values to text
|
|
66
|
+
return this.getDisplayStringFromFormValue(selected);
|
|
67
|
+
}
|
|
68
|
+
getContextValueFromState(state) {
|
|
69
|
+
const values = this.getFormValueFromState(state);
|
|
70
|
+
return this.getContextValueFromFormValue(values);
|
|
71
|
+
}
|
|
66
72
|
isValue(value) {
|
|
67
73
|
if (!Array.isArray(value)) {
|
|
68
74
|
return false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CheckboxesField.js","names":["joi","isFormValue","SelectionControlField","CheckboxesField","constructor","def","props","listType","type","options","formSchema","array","itemsSchema","valid","values","label","items","single","required","optional","default","stateSchema","allow","getFormValueFromState","state","name","getFormValue","selected","filter","item","includes","value","map","length","undefined","isValue","
|
|
1
|
+
{"version":3,"file":"CheckboxesField.js","names":["joi","isFormValue","SelectionControlField","CheckboxesField","constructor","def","props","listType","type","options","formSchema","array","itemsSchema","valid","values","label","items","single","required","optional","default","stateSchema","allow","getFormValueFromState","state","name","getFormValue","selected","filter","item","includes","value","map","length","undefined","isValue","getDisplayStringFromFormValue","text","join","getContextValueFromFormValue","getDisplayStringFromState","getContextValueFromState","Array","isArray","every"],"sources":["../../../../../src/server/plugins/engine/components/CheckboxesField.ts"],"sourcesContent":["import { type CheckboxesFieldComponent, type Item } from '@defra/forms-model'\nimport joi, { type ArraySchema } from 'joi'\n\nimport { isFormValue } from '~/src/server/plugins/engine/components/FormComponent.js'\nimport { SelectionControlField } from '~/src/server/plugins/engine/components/SelectionControlField.js'\nimport { type FormModel } from '~/src/server/plugins/engine/models/FormModel.js'\nimport { type QuestionPageController } from '~/src/server/plugins/engine/pageControllers/QuestionPageController.js'\nimport {\n type FormState,\n type FormStateValue,\n type FormSubmissionState\n} from '~/src/server/plugins/engine/types.js'\n\nexport class CheckboxesField extends SelectionControlField {\n declare options: CheckboxesFieldComponent['options']\n declare formSchema: ArraySchema<string> | ArraySchema<number>\n declare stateSchema: ArraySchema<string> | ArraySchema<number>\n\n constructor(\n def: CheckboxesFieldComponent,\n props: ConstructorParameters<typeof SelectionControlField>[1]\n ) {\n super(def, props)\n\n const { listType: type } = this\n const { options } = def\n\n let formSchema =\n type === 'string' ? joi.array<string>() : joi.array<number>()\n\n const itemsSchema = joi[type]()\n .valid(...this.values)\n .label(this.label)\n\n formSchema = formSchema\n .items(itemsSchema)\n .single()\n .label(this.label)\n .required()\n\n if (options.required === false) {\n formSchema = formSchema.optional()\n }\n\n this.formSchema = formSchema.default([])\n this.stateSchema = formSchema.default(null).allow(null)\n this.options = options\n }\n\n getFormValueFromState(state: FormSubmissionState) {\n const { items, name } = this\n\n // State checkbox values\n const values = this.getFormValue(state[name]) ?? []\n\n // Map (or discard) state values to item values\n const selected = items\n .filter((item) => values.includes(item.value))\n .map((item) => item.value)\n\n return selected.length ? selected : undefined\n }\n\n getFormValue(value?: FormStateValue | FormState) {\n return this.isValue(value) ? value : undefined\n }\n\n getDisplayStringFromFormValue(selected: (string | number | boolean)[]) {\n const { items } = this\n\n // Map selected values to text\n return items\n .filter((item) => selected.includes(item.value))\n .map((item) => item.text)\n .join(', ')\n }\n\n getContextValueFromFormValue(\n values: (string | number | boolean)[] | undefined\n ): (string | number | boolean)[] {\n /**\n * For evaluation context purposes, optional {@link CheckboxesField}\n * with an undefined value (i.e. nothing selected) should default to [].\n * This way conditions are not evaluated against `undefined` which throws errors.\n * Currently these errors are caught and the evaluation returns default `false`.\n * @see {@link QuestionPageController.getNextPath} for `undefined` return value\n * @see {@link FormModel.makeCondition} for try/catch block with default `false`\n * For negative conditions this is a problem because E.g.\n * The condition: 'selectedchecks' does not contain 'someval'\n * should return true IF 'selectedchecks' is undefined, not throw and return false.\n */\n return values ?? []\n }\n\n getDisplayStringFromState(state: FormSubmissionState) {\n // Selected checkbox values\n const selected = this.getFormValueFromState(state) ?? []\n\n // Map selected values to text\n return this.getDisplayStringFromFormValue(selected)\n }\n\n getContextValueFromState(state: FormSubmissionState) {\n const values = this.getFormValueFromState(state)\n\n return this.getContextValueFromFormValue(values)\n }\n\n isValue(value?: FormStateValue | FormState): value is Item['value'][] {\n if (!Array.isArray(value)) {\n return false\n }\n\n // Skip checks when empty\n if (!value.length) {\n return true\n }\n\n return value.every(isFormValue)\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -11,7 +11,9 @@ export declare class DatePartsField extends FormComponent {
|
|
|
11
11
|
collection: ComponentCollection;
|
|
12
12
|
constructor(def: DatePartsFieldComponent, props: ConstructorParameters<typeof FormComponent>[1]);
|
|
13
13
|
getFormValueFromState(state: FormSubmissionState): DatePartsState | undefined;
|
|
14
|
+
getDisplayStringFromFormValue(formValue: DatePartsState | undefined): string;
|
|
14
15
|
getDisplayStringFromState(state: FormSubmissionState): string;
|
|
16
|
+
getContextValueFromFormValue(value: DatePartsState | undefined): string | null;
|
|
15
17
|
getContextValueFromState(state: FormSubmissionState): string | null;
|
|
16
18
|
getViewModel(payload: FormPayload, errors?: FormSubmissionError[]): {
|
|
17
19
|
fieldset: {
|
|
@@ -85,20 +85,26 @@ export class DatePartsField extends FormComponent {
|
|
|
85
85
|
const value = super.getFormValueFromState(state);
|
|
86
86
|
return this.isState(value) ? value : undefined;
|
|
87
87
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
if (!value) {
|
|
88
|
+
getDisplayStringFromFormValue(formValue) {
|
|
89
|
+
if (!formValue) {
|
|
91
90
|
return '';
|
|
92
91
|
}
|
|
93
|
-
return format(`${
|
|
92
|
+
return format(`${formValue.year}-${formValue.month}-${formValue.day}`, 'd MMMM yyyy');
|
|
94
93
|
}
|
|
95
|
-
|
|
94
|
+
getDisplayStringFromState(state) {
|
|
96
95
|
const value = this.getFormValueFromState(state);
|
|
96
|
+
return this.getDisplayStringFromFormValue(value);
|
|
97
|
+
}
|
|
98
|
+
getContextValueFromFormValue(value) {
|
|
97
99
|
if (!value || !isValid(parseStrictDate(value, `${value.year}-${value.month}-${value.day}`, 'yyyy-MM-dd', new Date()))) {
|
|
98
100
|
return null;
|
|
99
101
|
}
|
|
100
102
|
return format(`${value.year}-${value.month}-${value.day}`, 'yyyy-MM-dd');
|
|
101
103
|
}
|
|
104
|
+
getContextValueFromState(state) {
|
|
105
|
+
const value = this.getFormValueFromState(state);
|
|
106
|
+
return this.getContextValueFromFormValue(value);
|
|
107
|
+
}
|
|
102
108
|
getViewModel(payload, errors) {
|
|
103
109
|
const {
|
|
104
110
|
collection,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DatePartsField.js","names":["ComponentType","add","format","isValid","parse","startOfToday","sub","ComponentCollection","FormComponent","isFormState","isFormValue","NumberField","parseStrictDate","messageTemplate","convertToLanguageMessages","DatePartsField","constructor","def","props","name","options","isRequired","required","customValidationMessages","objectMissing","dateFormat","collection","type","title","schema","min","max","precision","optionalText","classes","parent","custom","getValidatorDate","peers","formSchema","stateSchema","getFormValueFromState","state","value","isState","undefined","getDisplayStringFromState","year","month","day","getContextValueFromState","Date","getViewModel","payload","errors","viewModel","fieldset","label","hasError","some","error","items","map","model","errorMessage","toString","text","trim","id","legend","isDateParts","getAllPossibleErrors","baseErrors","template","advancedSettingsErrors","dateMin","dateMax","isNumber","component","validator","helpers","values","getStateFromValidForm","context","missing","keys","key","date","maxDaysInPast","days","maxDaysInFuture","limit"],"sources":["../../../../../src/server/plugins/engine/components/DatePartsField.ts"],"sourcesContent":["import { ComponentType, type DatePartsFieldComponent } from '@defra/forms-model'\nimport { add, format, isValid, parse, startOfToday, sub } from 'date-fns'\nimport { type Context, type CustomValidator, type ObjectSchema } from 'joi'\n\nimport { ComponentCollection } from '~/src/server/plugins/engine/components/ComponentCollection.js'\nimport {\n FormComponent,\n isFormState,\n isFormValue\n} from '~/src/server/plugins/engine/components/FormComponent.js'\nimport { NumberField } from '~/src/server/plugins/engine/components/NumberField.js'\nimport {\n type DateInputItem,\n type DatePartsState\n} from '~/src/server/plugins/engine/components/types.js'\nimport { parseStrictDate } from '~/src/server/plugins/engine/date-helper.js'\nimport { messageTemplate } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'\nimport {\n type ErrorMessageTemplateList,\n type FormPayload,\n type FormState,\n type FormStateValue,\n type FormSubmissionError,\n type FormSubmissionState\n} from '~/src/server/plugins/engine/types.js'\nimport { convertToLanguageMessages } from '~/src/server/utils/type-utils.js'\n\nexport class DatePartsField extends FormComponent {\n declare options: DatePartsFieldComponent['options']\n declare formSchema: ObjectSchema<FormPayload>\n declare stateSchema: ObjectSchema<FormState>\n declare collection: ComponentCollection\n\n constructor(\n def: DatePartsFieldComponent,\n props: ConstructorParameters<typeof FormComponent>[1]\n ) {\n super(def, props)\n\n const { name, options } = def\n\n const isRequired = options.required !== false\n\n const customValidationMessages = convertToLanguageMessages({\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n 'any.required': messageTemplate.objectMissing,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n 'number.base': messageTemplate.objectMissing,\n 'number.precision': messageTemplate.dateFormat,\n 'number.integer': messageTemplate.dateFormat,\n 'number.unsafe': messageTemplate.dateFormat,\n 'number.min': messageTemplate.dateFormat,\n 'number.max': messageTemplate.dateFormat\n })\n\n this.collection = new ComponentCollection(\n [\n {\n type: ComponentType.NumberField,\n name: `${name}__day`,\n title: 'Day',\n schema: { min: 1, max: 31, precision: 0 },\n options: {\n required: isRequired,\n optionalText: true,\n classes: 'govuk-input--width-2',\n customValidationMessages\n }\n },\n {\n type: ComponentType.NumberField,\n name: `${name}__month`,\n title: 'Month',\n schema: { min: 1, max: 12, precision: 0 },\n options: {\n required: isRequired,\n optionalText: true,\n classes: 'govuk-input--width-2',\n customValidationMessages\n }\n },\n {\n type: ComponentType.NumberField,\n name: `${name}__year`,\n title: 'Year',\n schema: { min: 1000, max: 3000, precision: 0 },\n options: {\n required: isRequired,\n optionalText: true,\n classes: 'govuk-input--width-4',\n customValidationMessages\n }\n }\n ],\n { ...props, parent: this },\n {\n custom: getValidatorDate(this),\n peers: [`${name}__day`, `${name}__month`, `${name}__year`]\n }\n )\n\n this.options = options\n this.formSchema = this.collection.formSchema\n this.stateSchema = this.collection.stateSchema\n }\n\n getFormValueFromState(state: FormSubmissionState) {\n const value = super.getFormValueFromState(state)\n return this.isState(value) ? value : undefined\n }\n\n getDisplayStringFromState(state: FormSubmissionState) {\n const value = this.getFormValueFromState(state)\n\n if (!value) {\n return ''\n }\n\n return format(`${value.year}-${value.month}-${value.day}`, 'd MMMM yyyy')\n }\n\n getContextValueFromState(state: FormSubmissionState) {\n const value = this.getFormValueFromState(state)\n\n if (\n !value ||\n !isValid(\n parseStrictDate(\n value,\n `${value.year}-${value.month}-${value.day}`,\n 'yyyy-MM-dd',\n new Date()\n )\n )\n ) {\n return null\n }\n\n return format(`${value.year}-${value.month}-${value.day}`, 'yyyy-MM-dd')\n }\n\n getViewModel(payload: FormPayload, errors?: FormSubmissionError[]) {\n const { collection, name } = this\n\n const viewModel = super.getViewModel(payload, errors)\n let { fieldset, label } = viewModel\n\n // Check for component errors only\n const hasError = errors?.some((error) => error.name === name)\n\n // Use the component collection to generate the subitems\n const items: DateInputItem[] = collection\n .getViewModel(payload, errors)\n .map(({ model }) => {\n let { label, type, value, classes, errorMessage } = model\n\n if (label) {\n label.toString = () => label.text // Date component uses string labels\n }\n\n if (hasError || errorMessage) {\n classes = `${classes} govuk-input--error`.trim()\n }\n\n // Allow any `toString()`-able value so non-numeric\n // values are shown alongside their error messages\n if (!isFormValue(value)) {\n value = undefined\n }\n\n return {\n label,\n id: model.id,\n name: model.name,\n type,\n value,\n classes\n }\n })\n\n fieldset ??= {\n legend: {\n text: label.text,\n classes: 'govuk-fieldset__legend--m'\n }\n }\n\n return {\n ...viewModel,\n fieldset,\n items\n }\n }\n\n isState(value?: FormStateValue | FormState) {\n return DatePartsField.isDateParts(value)\n }\n\n /**\n * For error preview page that shows all possible errors on a component\n */\n getAllPossibleErrors(): ErrorMessageTemplateList {\n return DatePartsField.getAllPossibleErrors()\n }\n\n /**\n * Static version of getAllPossibleErrors that doesn't require a component instance.\n */\n static getAllPossibleErrors(): ErrorMessageTemplateList {\n return {\n baseErrors: [\n { type: 'required', template: messageTemplate.required },\n { type: 'dateFormat', template: messageTemplate.dateFormat },\n { type: 'dateFormatDay', template: '{{#label}} must include a day' },\n {\n type: 'dateFormatMonth',\n template: '{{#label}} must include a month'\n },\n { type: 'dateFormatYear', template: '{{#label}} must include a year' }\n ],\n advancedSettingsErrors: [\n { type: 'dateMin', template: messageTemplate.dateMin },\n { type: 'dateMax', template: messageTemplate.dateMax }\n ]\n }\n }\n\n static isDateParts(\n value?: FormStateValue | FormState\n ): value is DatePartsState {\n return (\n isFormState(value) &&\n NumberField.isNumber(value.day) &&\n NumberField.isNumber(value.month) &&\n NumberField.isNumber(value.year)\n )\n }\n}\n\nexport function getValidatorDate(component: DatePartsField) {\n const validator: CustomValidator = (payload: FormPayload, helpers) => {\n const { collection, name, options } = component\n\n const values = component.getFormValueFromState(\n component.getStateFromValidForm(payload)\n )\n\n const context: Context = {\n missing: collection.keys,\n key: name\n }\n\n if (!component.isState(values)) {\n return options.required !== false\n ? helpers.error('object.required', context)\n : payload\n }\n\n const date = parse(\n `${values.year}-${values.month}-${values.day}`,\n 'yyyy-MM-dd',\n new Date()\n )\n\n if (!isValid(date)) {\n return helpers.error('date.format', context)\n }\n\n // Minimum date from today\n const dateMin = options.maxDaysInPast\n ? sub(startOfToday(), { days: options.maxDaysInPast })\n : undefined\n\n // Maximum date from today\n const dateMax = options.maxDaysInFuture\n ? add(startOfToday(), { days: options.maxDaysInFuture })\n : undefined\n\n if (dateMin && date < dateMin) {\n return helpers.error('date.min', { ...context, limit: dateMin })\n }\n\n if (dateMax && date > dateMax) {\n return helpers.error('date.max', { ...context, limit: dateMax })\n }\n\n return payload\n }\n\n return validator\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"DatePartsField.js","names":["ComponentType","add","format","isValid","parse","startOfToday","sub","ComponentCollection","FormComponent","isFormState","isFormValue","NumberField","parseStrictDate","messageTemplate","convertToLanguageMessages","DatePartsField","constructor","def","props","name","options","isRequired","required","customValidationMessages","objectMissing","dateFormat","collection","type","title","schema","min","max","precision","optionalText","classes","parent","custom","getValidatorDate","peers","formSchema","stateSchema","getFormValueFromState","state","value","isState","undefined","getDisplayStringFromFormValue","formValue","year","month","day","getDisplayStringFromState","getContextValueFromFormValue","Date","getContextValueFromState","getViewModel","payload","errors","viewModel","fieldset","label","hasError","some","error","items","map","model","errorMessage","toString","text","trim","id","legend","isDateParts","getAllPossibleErrors","baseErrors","template","advancedSettingsErrors","dateMin","dateMax","isNumber","component","validator","helpers","values","getStateFromValidForm","context","missing","keys","key","date","maxDaysInPast","days","maxDaysInFuture","limit"],"sources":["../../../../../src/server/plugins/engine/components/DatePartsField.ts"],"sourcesContent":["import { ComponentType, type DatePartsFieldComponent } from '@defra/forms-model'\nimport { add, format, isValid, parse, startOfToday, sub } from 'date-fns'\nimport { type Context, type CustomValidator, type ObjectSchema } from 'joi'\n\nimport { ComponentCollection } from '~/src/server/plugins/engine/components/ComponentCollection.js'\nimport {\n FormComponent,\n isFormState,\n isFormValue\n} from '~/src/server/plugins/engine/components/FormComponent.js'\nimport { NumberField } from '~/src/server/plugins/engine/components/NumberField.js'\nimport {\n type DateInputItem,\n type DatePartsState\n} from '~/src/server/plugins/engine/components/types.js'\nimport { parseStrictDate } from '~/src/server/plugins/engine/date-helper.js'\nimport { messageTemplate } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'\nimport {\n type ErrorMessageTemplateList,\n type FormPayload,\n type FormState,\n type FormStateValue,\n type FormSubmissionError,\n type FormSubmissionState\n} from '~/src/server/plugins/engine/types.js'\nimport { convertToLanguageMessages } from '~/src/server/utils/type-utils.js'\n\nexport class DatePartsField extends FormComponent {\n declare options: DatePartsFieldComponent['options']\n declare formSchema: ObjectSchema<FormPayload>\n declare stateSchema: ObjectSchema<FormState>\n declare collection: ComponentCollection\n\n constructor(\n def: DatePartsFieldComponent,\n props: ConstructorParameters<typeof FormComponent>[1]\n ) {\n super(def, props)\n\n const { name, options } = def\n\n const isRequired = options.required !== false\n\n const customValidationMessages = convertToLanguageMessages({\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n 'any.required': messageTemplate.objectMissing,\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n 'number.base': messageTemplate.objectMissing,\n 'number.precision': messageTemplate.dateFormat,\n 'number.integer': messageTemplate.dateFormat,\n 'number.unsafe': messageTemplate.dateFormat,\n 'number.min': messageTemplate.dateFormat,\n 'number.max': messageTemplate.dateFormat\n })\n\n this.collection = new ComponentCollection(\n [\n {\n type: ComponentType.NumberField,\n name: `${name}__day`,\n title: 'Day',\n schema: { min: 1, max: 31, precision: 0 },\n options: {\n required: isRequired,\n optionalText: true,\n classes: 'govuk-input--width-2',\n customValidationMessages\n }\n },\n {\n type: ComponentType.NumberField,\n name: `${name}__month`,\n title: 'Month',\n schema: { min: 1, max: 12, precision: 0 },\n options: {\n required: isRequired,\n optionalText: true,\n classes: 'govuk-input--width-2',\n customValidationMessages\n }\n },\n {\n type: ComponentType.NumberField,\n name: `${name}__year`,\n title: 'Year',\n schema: { min: 1000, max: 3000, precision: 0 },\n options: {\n required: isRequired,\n optionalText: true,\n classes: 'govuk-input--width-4',\n customValidationMessages\n }\n }\n ],\n { ...props, parent: this },\n {\n custom: getValidatorDate(this),\n peers: [`${name}__day`, `${name}__month`, `${name}__year`]\n }\n )\n\n this.options = options\n this.formSchema = this.collection.formSchema\n this.stateSchema = this.collection.stateSchema\n }\n\n getFormValueFromState(state: FormSubmissionState) {\n const value = super.getFormValueFromState(state)\n return this.isState(value) ? value : undefined\n }\n\n getDisplayStringFromFormValue(formValue: DatePartsState | undefined) {\n if (!formValue) {\n return ''\n }\n\n return format(\n `${formValue.year}-${formValue.month}-${formValue.day}`,\n 'd MMMM yyyy'\n )\n }\n\n getDisplayStringFromState(state: FormSubmissionState) {\n const value = this.getFormValueFromState(state)\n\n return this.getDisplayStringFromFormValue(value)\n }\n\n getContextValueFromFormValue(value: DatePartsState | undefined) {\n if (\n !value ||\n !isValid(\n parseStrictDate(\n value,\n `${value.year}-${value.month}-${value.day}`,\n 'yyyy-MM-dd',\n new Date()\n )\n )\n ) {\n return null\n }\n\n return format(`${value.year}-${value.month}-${value.day}`, 'yyyy-MM-dd')\n }\n\n getContextValueFromState(state: FormSubmissionState) {\n const value = this.getFormValueFromState(state)\n\n return this.getContextValueFromFormValue(value)\n }\n\n getViewModel(payload: FormPayload, errors?: FormSubmissionError[]) {\n const { collection, name } = this\n\n const viewModel = super.getViewModel(payload, errors)\n let { fieldset, label } = viewModel\n\n // Check for component errors only\n const hasError = errors?.some((error) => error.name === name)\n\n // Use the component collection to generate the subitems\n const items: DateInputItem[] = collection\n .getViewModel(payload, errors)\n .map(({ model }) => {\n let { label, type, value, classes, errorMessage } = model\n\n if (label) {\n label.toString = () => label.text // Date component uses string labels\n }\n\n if (hasError || errorMessage) {\n classes = `${classes} govuk-input--error`.trim()\n }\n\n // Allow any `toString()`-able value so non-numeric\n // values are shown alongside their error messages\n if (!isFormValue(value)) {\n value = undefined\n }\n\n return {\n label,\n id: model.id,\n name: model.name,\n type,\n value,\n classes\n }\n })\n\n fieldset ??= {\n legend: {\n text: label.text,\n classes: 'govuk-fieldset__legend--m'\n }\n }\n\n return {\n ...viewModel,\n fieldset,\n items\n }\n }\n\n isState(value?: FormStateValue | FormState) {\n return DatePartsField.isDateParts(value)\n }\n\n /**\n * For error preview page that shows all possible errors on a component\n */\n getAllPossibleErrors(): ErrorMessageTemplateList {\n return DatePartsField.getAllPossibleErrors()\n }\n\n /**\n * Static version of getAllPossibleErrors that doesn't require a component instance.\n */\n static getAllPossibleErrors(): ErrorMessageTemplateList {\n return {\n baseErrors: [\n { type: 'required', template: messageTemplate.required },\n { type: 'dateFormat', template: messageTemplate.dateFormat },\n { type: 'dateFormatDay', template: '{{#label}} must include a day' },\n {\n type: 'dateFormatMonth',\n template: '{{#label}} must include a month'\n },\n { type: 'dateFormatYear', template: '{{#label}} must include a year' }\n ],\n advancedSettingsErrors: [\n { type: 'dateMin', template: messageTemplate.dateMin },\n { type: 'dateMax', template: messageTemplate.dateMax }\n ]\n }\n }\n\n static isDateParts(\n value?: FormStateValue | FormState\n ): value is DatePartsState {\n return (\n isFormState(value) &&\n NumberField.isNumber(value.day) &&\n NumberField.isNumber(value.month) &&\n NumberField.isNumber(value.year)\n )\n }\n}\n\nexport function getValidatorDate(component: DatePartsField) {\n const validator: CustomValidator = (payload: FormPayload, helpers) => {\n const { collection, name, options } = component\n\n const values = component.getFormValueFromState(\n component.getStateFromValidForm(payload)\n )\n\n const context: Context = {\n missing: collection.keys,\n key: name\n }\n\n if (!component.isState(values)) {\n return options.required !== false\n ? helpers.error('object.required', context)\n : payload\n }\n\n const date = parse(\n `${values.year}-${values.month}-${values.day}`,\n 'yyyy-MM-dd',\n new Date()\n )\n\n if (!isValid(date)) {\n return helpers.error('date.format', context)\n }\n\n // Minimum date from today\n const dateMin = options.maxDaysInPast\n ? sub(startOfToday(), { days: options.maxDaysInPast })\n : undefined\n\n // Maximum date from today\n const dateMax = options.maxDaysInFuture\n ? add(startOfToday(), { days: options.maxDaysInFuture })\n : undefined\n\n if (dateMin && date < dateMin) {\n return helpers.error('date.min', { ...context, limit: dateMin })\n }\n\n if (dateMax && date > dateMax) {\n return helpers.error('date.max', { ...context, limit: dateMax })\n }\n\n return payload\n }\n\n return validator\n}\n"],"mappings":"AAAA,SAASA,aAAa,QAAsC,oBAAoB;AAChF,SAASC,GAAG,EAAEC,MAAM,EAAEC,OAAO,EAAEC,KAAK,EAAEC,YAAY,EAAEC,GAAG,QAAQ,UAAU;AAGzE,SAASC,mBAAmB;AAC5B,SACEC,aAAa,EACbC,WAAW,EACXC,WAAW;AAEb,SAASC,WAAW;AAKpB,SAASC,eAAe;AACxB,SAASC,eAAe;AASxB,SAASC,yBAAyB;AAElC,OAAO,MAAMC,cAAc,SAASP,aAAa,CAAC;EAMhDQ,WAAWA,CACTC,GAA4B,EAC5BC,KAAqD,EACrD;IACA,KAAK,CAACD,GAAG,EAAEC,KAAK,CAAC;IAEjB,MAAM;MAAEC,IAAI;MAAEC;IAAQ,CAAC,GAAGH,GAAG;IAE7B,MAAMI,UAAU,GAAGD,OAAO,CAACE,QAAQ,KAAK,KAAK;IAE7C,MAAMC,wBAAwB,GAAGT,yBAAyB,CAAC;MACzD;MACA,cAAc,EAAED,eAAe,CAACW,aAAa;MAC7C;MACA,aAAa,EAAEX,eAAe,CAACW,aAAa;MAC5C,kBAAkB,EAAEX,eAAe,CAACY,UAAU;MAC9C,gBAAgB,EAAEZ,eAAe,CAACY,UAAU;MAC5C,eAAe,EAAEZ,eAAe,CAACY,UAAU;MAC3C,YAAY,EAAEZ,eAAe,CAACY,UAAU;MACxC,YAAY,EAAEZ,eAAe,CAACY;IAChC,CAAC,CAAC;IAEF,IAAI,CAACC,UAAU,GAAG,IAAInB,mBAAmB,CACvC,CACE;MACEoB,IAAI,EAAE3B,aAAa,CAACW,WAAW;MAC/BQ,IAAI,EAAE,GAAGA,IAAI,OAAO;MACpBS,KAAK,EAAE,KAAK;MACZC,MAAM,EAAE;QAAEC,GAAG,EAAE,CAAC;QAAEC,GAAG,EAAE,EAAE;QAAEC,SAAS,EAAE;MAAE,CAAC;MACzCZ,OAAO,EAAE;QACPE,QAAQ,EAAED,UAAU;QACpBY,YAAY,EAAE,IAAI;QAClBC,OAAO,EAAE,sBAAsB;QAC/BX;MACF;IACF,CAAC,EACD;MACEI,IAAI,EAAE3B,aAAa,CAACW,WAAW;MAC/BQ,IAAI,EAAE,GAAGA,IAAI,SAAS;MACtBS,KAAK,EAAE,OAAO;MACdC,MAAM,EAAE;QAAEC,GAAG,EAAE,CAAC;QAAEC,GAAG,EAAE,EAAE;QAAEC,SAAS,EAAE;MAAE,CAAC;MACzCZ,OAAO,EAAE;QACPE,QAAQ,EAAED,UAAU;QACpBY,YAAY,EAAE,IAAI;QAClBC,OAAO,EAAE,sBAAsB;QAC/BX;MACF;IACF,CAAC,EACD;MACEI,IAAI,EAAE3B,aAAa,CAACW,WAAW;MAC/BQ,IAAI,EAAE,GAAGA,IAAI,QAAQ;MACrBS,KAAK,EAAE,MAAM;MACbC,MAAM,EAAE;QAAEC,GAAG,EAAE,IAAI;QAAEC,GAAG,EAAE,IAAI;QAAEC,SAAS,EAAE;MAAE,CAAC;MAC9CZ,OAAO,EAAE;QACPE,QAAQ,EAAED,UAAU;QACpBY,YAAY,EAAE,IAAI;QAClBC,OAAO,EAAE,sBAAsB;QAC/BX;MACF;IACF,CAAC,CACF,EACD;MAAE,GAAGL,KAAK;MAAEiB,MAAM,EAAE;IAAK,CAAC,EAC1B;MACEC,MAAM,EAAEC,gBAAgB,CAAC,IAAI,CAAC;MAC9BC,KAAK,EAAE,CAAC,GAAGnB,IAAI,OAAO,EAAE,GAAGA,IAAI,SAAS,EAAE,GAAGA,IAAI,QAAQ;IAC3D,CACF,CAAC;IAED,IAAI,CAACC,OAAO,GAAGA,OAAO;IACtB,IAAI,CAACmB,UAAU,GAAG,IAAI,CAACb,UAAU,CAACa,UAAU;IAC5C,IAAI,CAACC,WAAW,GAAG,IAAI,CAACd,UAAU,CAACc,WAAW;EAChD;EAEAC,qBAAqBA,CAACC,KAA0B,EAAE;IAChD,MAAMC,KAAK,GAAG,KAAK,CAACF,qBAAqB,CAACC,KAAK,CAAC;IAChD,OAAO,IAAI,CAACE,OAAO,CAACD,KAAK,CAAC,GAAGA,KAAK,GAAGE,SAAS;EAChD;EAEAC,6BAA6BA,CAACC,SAAqC,EAAE;IACnE,IAAI,CAACA,SAAS,EAAE;MACd,OAAO,EAAE;IACX;IAEA,OAAO7C,MAAM,CACX,GAAG6C,SAAS,CAACC,IAAI,IAAID,SAAS,CAACE,KAAK,IAAIF,SAAS,CAACG,GAAG,EAAE,EACvD,aACF,CAAC;EACH;EAEAC,yBAAyBA,CAACT,KAA0B,EAAE;IACpD,MAAMC,KAAK,GAAG,IAAI,CAACF,qBAAqB,CAACC,KAAK,CAAC;IAE/C,OAAO,IAAI,CAACI,6BAA6B,CAACH,KAAK,CAAC;EAClD;EAEAS,4BAA4BA,CAACT,KAAiC,EAAE;IAC9D,IACE,CAACA,KAAK,IACN,CAACxC,OAAO,CACNS,eAAe,CACb+B,KAAK,EACL,GAAGA,KAAK,CAACK,IAAI,IAAIL,KAAK,CAACM,KAAK,IAAIN,KAAK,CAACO,GAAG,EAAE,EAC3C,YAAY,EACZ,IAAIG,IAAI,CAAC,CACX,CACF,CAAC,EACD;MACA,OAAO,IAAI;IACb;IAEA,OAAOnD,MAAM,CAAC,GAAGyC,KAAK,CAACK,IAAI,IAAIL,KAAK,CAACM,KAAK,IAAIN,KAAK,CAACO,GAAG,EAAE,EAAE,YAAY,CAAC;EAC1E;EAEAI,wBAAwBA,CAACZ,KAA0B,EAAE;IACnD,MAAMC,KAAK,GAAG,IAAI,CAACF,qBAAqB,CAACC,KAAK,CAAC;IAE/C,OAAO,IAAI,CAACU,4BAA4B,CAACT,KAAK,CAAC;EACjD;EAEAY,YAAYA,CAACC,OAAoB,EAAEC,MAA8B,EAAE;IACjE,MAAM;MAAE/B,UAAU;MAAEP;IAAK,CAAC,GAAG,IAAI;IAEjC,MAAMuC,SAAS,GAAG,KAAK,CAACH,YAAY,CAACC,OAAO,EAAEC,MAAM,CAAC;IACrD,IAAI;MAAEE,QAAQ;MAAEC;IAAM,CAAC,GAAGF,SAAS;;IAEnC;IACA,MAAMG,QAAQ,GAAGJ,MAAM,EAAEK,IAAI,CAAEC,KAAK,IAAKA,KAAK,CAAC5C,IAAI,KAAKA,IAAI,CAAC;;IAE7D;IACA,MAAM6C,KAAsB,GAAGtC,UAAU,CACtC6B,YAAY,CAACC,OAAO,EAAEC,MAAM,CAAC,CAC7BQ,GAAG,CAAC,CAAC;MAAEC;IAAM,CAAC,KAAK;MAClB,IAAI;QAAEN,KAAK;QAAEjC,IAAI;QAAEgB,KAAK;QAAET,OAAO;QAAEiC;MAAa,CAAC,GAAGD,KAAK;MAEzD,IAAIN,KAAK,EAAE;QACTA,KAAK,CAACQ,QAAQ,GAAG,MAAMR,KAAK,CAACS,IAAI,EAAC;MACpC;MAEA,IAAIR,QAAQ,IAAIM,YAAY,EAAE;QAC5BjC,OAAO,GAAG,GAAGA,OAAO,qBAAqB,CAACoC,IAAI,CAAC,CAAC;MAClD;;MAEA;MACA;MACA,IAAI,CAAC5D,WAAW,CAACiC,KAAK,CAAC,EAAE;QACvBA,KAAK,GAAGE,SAAS;MACnB;MAEA,OAAO;QACLe,KAAK;QACLW,EAAE,EAAEL,KAAK,CAACK,EAAE;QACZpD,IAAI,EAAE+C,KAAK,CAAC/C,IAAI;QAChBQ,IAAI;QACJgB,KAAK;QACLT;MACF,CAAC;IACH,CAAC,CAAC;IAEJyB,QAAQ,KAAK;MACXa,MAAM,EAAE;QACNH,IAAI,EAAET,KAAK,CAACS,IAAI;QAChBnC,OAAO,EAAE;MACX;IACF,CAAC;IAED,OAAO;MACL,GAAGwB,SAAS;MACZC,QAAQ;MACRK;IACF,CAAC;EACH;EAEApB,OAAOA,CAACD,KAAkC,EAAE;IAC1C,OAAO5B,cAAc,CAAC0D,WAAW,CAAC9B,KAAK,CAAC;EAC1C;;EAEA;AACF;AACA;EACE+B,oBAAoBA,CAAA,EAA6B;IAC/C,OAAO3D,cAAc,CAAC2D,oBAAoB,CAAC,CAAC;EAC9C;;EAEA;AACF;AACA;EACE,OAAOA,oBAAoBA,CAAA,EAA6B;IACtD,OAAO;MACLC,UAAU,EAAE,CACV;QAAEhD,IAAI,EAAE,UAAU;QAAEiD,QAAQ,EAAE/D,eAAe,CAACS;MAAS,CAAC,EACxD;QAAEK,IAAI,EAAE,YAAY;QAAEiD,QAAQ,EAAE/D,eAAe,CAACY;MAAW,CAAC,EAC5D;QAAEE,IAAI,EAAE,eAAe;QAAEiD,QAAQ,EAAE;MAAgC,CAAC,EACpE;QACEjD,IAAI,EAAE,iBAAiB;QACvBiD,QAAQ,EAAE;MACZ,CAAC,EACD;QAAEjD,IAAI,EAAE,gBAAgB;QAAEiD,QAAQ,EAAE;MAAiC,CAAC,CACvE;MACDC,sBAAsB,EAAE,CACtB;QAAElD,IAAI,EAAE,SAAS;QAAEiD,QAAQ,EAAE/D,eAAe,CAACiE;MAAQ,CAAC,EACtD;QAAEnD,IAAI,EAAE,SAAS;QAAEiD,QAAQ,EAAE/D,eAAe,CAACkE;MAAQ,CAAC;IAE1D,CAAC;EACH;EAEA,OAAON,WAAWA,CAChB9B,KAAkC,EACT;IACzB,OACElC,WAAW,CAACkC,KAAK,CAAC,IAClBhC,WAAW,CAACqE,QAAQ,CAACrC,KAAK,CAACO,GAAG,CAAC,IAC/BvC,WAAW,CAACqE,QAAQ,CAACrC,KAAK,CAACM,KAAK,CAAC,IACjCtC,WAAW,CAACqE,QAAQ,CAACrC,KAAK,CAACK,IAAI,CAAC;EAEpC;AACF;AAEA,OAAO,SAASX,gBAAgBA,CAAC4C,SAAyB,EAAE;EAC1D,MAAMC,SAA0B,GAAGA,CAAC1B,OAAoB,EAAE2B,OAAO,KAAK;IACpE,MAAM;MAAEzD,UAAU;MAAEP,IAAI;MAAEC;IAAQ,CAAC,GAAG6D,SAAS;IAE/C,MAAMG,MAAM,GAAGH,SAAS,CAACxC,qBAAqB,CAC5CwC,SAAS,CAACI,qBAAqB,CAAC7B,OAAO,CACzC,CAAC;IAED,MAAM8B,OAAgB,GAAG;MACvBC,OAAO,EAAE7D,UAAU,CAAC8D,IAAI;MACxBC,GAAG,EAAEtE;IACP,CAAC;IAED,IAAI,CAAC8D,SAAS,CAACrC,OAAO,CAACwC,MAAM,CAAC,EAAE;MAC9B,OAAOhE,OAAO,CAACE,QAAQ,KAAK,KAAK,GAC7B6D,OAAO,CAACpB,KAAK,CAAC,iBAAiB,EAAEuB,OAAO,CAAC,GACzC9B,OAAO;IACb;IAEA,MAAMkC,IAAI,GAAGtF,KAAK,CAChB,GAAGgF,MAAM,CAACpC,IAAI,IAAIoC,MAAM,CAACnC,KAAK,IAAImC,MAAM,CAAClC,GAAG,EAAE,EAC9C,YAAY,EACZ,IAAIG,IAAI,CAAC,CACX,CAAC;IAED,IAAI,CAAClD,OAAO,CAACuF,IAAI,CAAC,EAAE;MAClB,OAAOP,OAAO,CAACpB,KAAK,CAAC,aAAa,EAAEuB,OAAO,CAAC;IAC9C;;IAEA;IACA,MAAMR,OAAO,GAAG1D,OAAO,CAACuE,aAAa,GACjCrF,GAAG,CAACD,YAAY,CAAC,CAAC,EAAE;MAAEuF,IAAI,EAAExE,OAAO,CAACuE;IAAc,CAAC,CAAC,GACpD9C,SAAS;;IAEb;IACA,MAAMkC,OAAO,GAAG3D,OAAO,CAACyE,eAAe,GACnC5F,GAAG,CAACI,YAAY,CAAC,CAAC,EAAE;MAAEuF,IAAI,EAAExE,OAAO,CAACyE;IAAgB,CAAC,CAAC,GACtDhD,SAAS;IAEb,IAAIiC,OAAO,IAAIY,IAAI,GAAGZ,OAAO,EAAE;MAC7B,OAAOK,OAAO,CAACpB,KAAK,CAAC,UAAU,EAAE;QAAE,GAAGuB,OAAO;QAAEQ,KAAK,EAAEhB;MAAQ,CAAC,CAAC;IAClE;IAEA,IAAIC,OAAO,IAAIW,IAAI,GAAGX,OAAO,EAAE;MAC7B,OAAOI,OAAO,CAACpB,KAAK,CAAC,UAAU,EAAE;QAAE,GAAGuB,OAAO;QAAEQ,KAAK,EAAEf;MAAQ,CAAC,CAAC;IAClE;IAEA,OAAOvB,OAAO;EAChB,CAAC;EAED,OAAO0B,SAAS;AAClB","ignoreList":[]}
|
|
@@ -21,7 +21,9 @@ export declare class FileUploadField extends FormComponent {
|
|
|
21
21
|
constructor(def: FileUploadFieldComponent, props: ConstructorParameters<typeof FormComponent>[1]);
|
|
22
22
|
getFormValueFromState(state: FormSubmissionState): UploadState | undefined;
|
|
23
23
|
getFormValue(value?: FormStateValue | FormState): UploadState | undefined;
|
|
24
|
+
getDisplayStringFromFormValue(files: FileState[] | undefined): string;
|
|
24
25
|
getDisplayStringFromState(state: FormSubmissionState): string;
|
|
26
|
+
getContextValueFromFormValue(files: UploadState | undefined): string[] | null;
|
|
25
27
|
getContextValueFromState(state: FormSubmissionState): string[] | null;
|
|
26
28
|
getViewModel(payload: FormPayload, errors?: FormSubmissionError[], query?: FormQuery): {
|
|
27
29
|
value: string;
|
|
@@ -79,20 +79,26 @@ export class FileUploadField extends FormComponent {
|
|
|
79
79
|
getFormValue(value) {
|
|
80
80
|
return this.isValue(value) ? value : undefined;
|
|
81
81
|
}
|
|
82
|
-
|
|
83
|
-
const files = this.getFormValueFromState(state);
|
|
82
|
+
getDisplayStringFromFormValue(files) {
|
|
84
83
|
if (!files?.length) {
|
|
85
84
|
return '';
|
|
86
85
|
}
|
|
87
86
|
const unit = files.length === 1 ? 'file' : 'files';
|
|
88
87
|
return `Uploaded ${files.length} ${unit}`;
|
|
89
88
|
}
|
|
90
|
-
|
|
89
|
+
getDisplayStringFromState(state) {
|
|
91
90
|
const files = this.getFormValueFromState(state);
|
|
91
|
+
return this.getDisplayStringFromFormValue(files);
|
|
92
|
+
}
|
|
93
|
+
getContextValueFromFormValue(files) {
|
|
92
94
|
return files?.map(({
|
|
93
95
|
status
|
|
94
96
|
}) => status.form.file.fileId) ?? null;
|
|
95
97
|
}
|
|
98
|
+
getContextValueFromState(state) {
|
|
99
|
+
const files = this.getFormValueFromState(state);
|
|
100
|
+
return this.getContextValueFromFormValue(files);
|
|
101
|
+
}
|
|
96
102
|
getViewModel(payload, errors, query = {}) {
|
|
97
103
|
const {
|
|
98
104
|
options,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileUploadField.js","names":["joi","FormComponent","isUploadState","messageTemplate","FileStatus","UploadStatus","render","uploadIdSchema","string","uuid","required","fileSchema","object","fileId","filename","contentLength","number","tempFileSchema","append","fileStatus","valid","complete","rejected","pending","errorMessage","optional","formFileSchema","metadataSchema","keys","retrievalKey","email","tempStatusSchema","uploadStatus","ready","metadata","form","file","numberOfRejectedFiles","formStatusSchema","itemSchema","uploadId","tempItemSchema","status","formItemSchema","FileUploadField","constructor","def","props","options","schema","formSchema","array","label","single","length","max","min","items","stateSchema","default","allow","getFormValueFromState","state","name","getFormValue","value","isValue","undefined","getDisplayStringFromState","files","unit","getContextValueFromState","map","getViewModel","payload","errors","query","page","isForceAccess","viewModel","attributes","id","filtered","filter","count","rows","item","index","tag","classes","text","valueHtml","view","context","params","trim","keyHtml","path","href","getHref","push","visuallyHiddenText","key","html","actions","accept","summaryList","upload","getAllPossibleErrors","baseErrors","type","template","selectRequired","advancedSettingsErrors"],"sources":["../../../../../src/server/plugins/engine/components/FileUploadField.ts"],"sourcesContent":["import { type FileUploadFieldComponent } from '@defra/forms-model'\nimport joi, { type ArraySchema } from 'joi'\n\nimport {\n FormComponent,\n isUploadState\n} from '~/src/server/plugins/engine/components/FormComponent.js'\nimport { messageTemplate } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'\nimport {\n FileStatus,\n UploadStatus,\n type ErrorMessageTemplateList,\n type FileState,\n type FileUpload,\n type FileUploadMetadata,\n type FormPayload,\n type FormState,\n type FormStateValue,\n type FormSubmissionError,\n type FormSubmissionState,\n type SummaryList,\n type SummaryListAction,\n type SummaryListRow,\n type UploadState,\n type UploadStatusFileResponse,\n type UploadStatusResponse\n} from '~/src/server/plugins/engine/types.js'\nimport { render } from '~/src/server/plugins/nunjucks/index.js'\nimport { type FormQuery } from '~/src/server/routes/types.js'\n\nexport const uploadIdSchema = joi.string().uuid().required()\n\nexport const fileSchema = joi\n .object<FileUpload>({\n fileId: joi.string().uuid().required(),\n filename: joi.string().required(),\n contentLength: joi.number().required()\n })\n .required()\n\nexport const tempFileSchema = fileSchema.append({\n fileStatus: joi\n .string()\n .valid(FileStatus.complete, FileStatus.rejected, FileStatus.pending)\n .required(),\n errorMessage: joi.string().optional()\n})\n\nexport const formFileSchema = fileSchema.append({\n fileStatus: joi.string().valid(FileStatus.complete).required()\n})\n\nexport const metadataSchema = joi\n .object<FileUploadMetadata>()\n .keys({\n retrievalKey: joi.string().email().required()\n })\n .required()\n\nexport const tempStatusSchema = joi\n .object<UploadStatusFileResponse>({\n uploadStatus: joi\n .string()\n .valid(UploadStatus.ready, UploadStatus.pending)\n .required(),\n metadata: metadataSchema,\n form: joi.object().required().keys({\n file: tempFileSchema\n }),\n numberOfRejectedFiles: joi.number().optional()\n })\n .required()\n\nexport const formStatusSchema = joi\n .object<UploadStatusResponse>({\n uploadStatus: joi.string().valid(UploadStatus.ready).required(),\n metadata: metadataSchema,\n form: joi.object().required().keys({\n file: formFileSchema\n }),\n numberOfRejectedFiles: joi.number().valid(0).required()\n })\n .required()\n\nexport const itemSchema = joi.object<FileState>({\n uploadId: uploadIdSchema\n})\n\nexport const tempItemSchema = itemSchema.append({\n status: tempStatusSchema\n})\n\nexport const formItemSchema = itemSchema.append({\n status: formStatusSchema\n})\n\nexport class FileUploadField extends FormComponent {\n declare options: FileUploadFieldComponent['options']\n declare schema: FileUploadFieldComponent['schema']\n declare formSchema: ArraySchema<FileState>\n declare stateSchema: ArraySchema<FileState>\n\n constructor(\n def: FileUploadFieldComponent,\n props: ConstructorParameters<typeof FormComponent>[1]\n ) {\n super(def, props)\n\n const { options, schema } = def\n\n let formSchema = joi\n .array<FileState>()\n .label(this.label)\n .single()\n .required()\n\n if (options.required === false) {\n formSchema = formSchema.optional()\n }\n\n if (typeof schema.length !== 'number') {\n if (typeof schema.max === 'number') {\n formSchema = formSchema.max(schema.max)\n }\n\n if (typeof schema.min === 'number') {\n formSchema = formSchema.min(schema.min)\n }\n } else {\n formSchema = formSchema.length(schema.length)\n }\n\n this.formSchema = formSchema.items(formItemSchema)\n this.stateSchema = formSchema\n .items(formItemSchema)\n .default(null)\n .allow(null)\n\n this.options = options\n this.schema = schema\n }\n\n getFormValueFromState(state: FormSubmissionState) {\n const { name } = this\n return this.getFormValue(state[name])\n }\n\n getFormValue(value?: FormStateValue | FormState) {\n return this.isValue(value) ? value : undefined\n }\n\n getDisplayStringFromState(state: FormSubmissionState) {\n const files = this.getFormValueFromState(state)\n if (!files?.length) {\n return ''\n }\n\n const unit = files.length === 1 ? 'file' : 'files'\n return `Uploaded ${files.length} ${unit}`\n }\n\n getContextValueFromState(state: FormSubmissionState) {\n const files = this.getFormValueFromState(state)\n return files?.map(({ status }) => status.form.file.fileId) ?? null\n }\n\n getViewModel(\n payload: FormPayload,\n errors?: FormSubmissionError[],\n query: FormQuery = {}\n ) {\n const { options, page } = this\n\n // Allow preview URL direct access\n const isForceAccess = 'force' in query\n\n const viewModel = super.getViewModel(payload, errors)\n const { attributes, id, value } = viewModel\n\n const files = this.getFormValue(value) ?? []\n const filtered = files.filter(\n (file) => file.status.form.file.fileStatus === FileStatus.complete\n )\n const count = filtered.length\n\n const rows: SummaryListRow[] = filtered.map((item, index) => {\n const { status } = item\n const { form } = status\n const { file } = form\n\n const tag = { classes: 'govuk-tag--green', text: 'Uploaded' }\n\n const valueHtml = render\n .view('components/fileuploadfield-value.html', {\n context: { params: { tag } }\n })\n .trim()\n\n const keyHtml = render\n .view('components/fileuploadfield-key.html', {\n context: {\n params: {\n name: file.filename,\n errorMessage: errors && file.errorMessage\n }\n }\n })\n .trim()\n\n const items: SummaryListAction[] = []\n\n // Remove summary list actions from previews\n if (!isForceAccess) {\n const path = `/${item.uploadId}/confirm-delete`\n const href = page?.getHref(`${page.path}${path}`) ?? '#'\n\n items.push({\n href,\n text: 'Remove',\n classes: 'govuk-link--no-visited-state',\n attributes: { id: `${id}__${index}` },\n visuallyHiddenText: file.filename\n })\n }\n\n return {\n key: {\n html: keyHtml\n },\n value: {\n html: valueHtml\n },\n actions: {\n items\n }\n } satisfies SummaryListRow\n })\n\n // Set up the `accept` attribute\n if ('accept' in options && options.accept) {\n attributes.accept = options.accept\n }\n\n const summaryList: SummaryList = {\n classes: 'govuk-summary-list--long-key',\n rows\n }\n\n return {\n ...viewModel,\n\n // File input can't have a initial value\n value: '',\n\n // Override the component name we send to CDP\n name: 'file',\n\n upload: {\n count,\n summaryList\n }\n }\n }\n\n isValue(value?: FormStateValue | FormState): value is UploadState {\n return isUploadState(value)\n }\n\n /**\n * For error preview page that shows all possible errors on a component\n */\n getAllPossibleErrors(): ErrorMessageTemplateList {\n return FileUploadField.getAllPossibleErrors()\n }\n\n /**\n * Static version of getAllPossibleErrors that doesn't require a component instance.\n */\n static getAllPossibleErrors(): ErrorMessageTemplateList {\n return {\n baseErrors: [\n { type: 'selectRequired', template: messageTemplate.selectRequired },\n {\n type: 'filesMimes',\n template: 'The selected file must be a {{#limit}}'\n },\n {\n type: 'filesSize',\n template: 'The selected file must be smaller than 100MB'\n },\n { type: 'filesEmpty', template: 'The selected file is empty' },\n { type: 'filesVirus', template: 'The selected file contains a virus' },\n {\n type: 'filesPartial',\n template: 'The selected file has not fully uploaded'\n },\n {\n type: 'filesError',\n template: 'The selected file could not be uploaded – try again'\n }\n ],\n advancedSettingsErrors: [\n {\n type: 'filesMin',\n template: 'You must upload {{#limit}} files or more'\n },\n {\n type: 'filesMax',\n template: 'You can only upload {{#limit}} files or less'\n },\n {\n type: 'filesExact',\n template: 'You must upload exactly {{#limit}} files'\n }\n ]\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"FileUploadField.js","names":["joi","FormComponent","isUploadState","messageTemplate","FileStatus","UploadStatus","render","uploadIdSchema","string","uuid","required","fileSchema","object","fileId","filename","contentLength","number","tempFileSchema","append","fileStatus","valid","complete","rejected","pending","errorMessage","optional","formFileSchema","metadataSchema","keys","retrievalKey","email","tempStatusSchema","uploadStatus","ready","metadata","form","file","numberOfRejectedFiles","formStatusSchema","itemSchema","uploadId","tempItemSchema","status","formItemSchema","FileUploadField","constructor","def","props","options","schema","formSchema","array","label","single","length","max","min","items","stateSchema","default","allow","getFormValueFromState","state","name","getFormValue","value","isValue","undefined","getDisplayStringFromFormValue","files","unit","getDisplayStringFromState","getContextValueFromFormValue","map","getContextValueFromState","getViewModel","payload","errors","query","page","isForceAccess","viewModel","attributes","id","filtered","filter","count","rows","item","index","tag","classes","text","valueHtml","view","context","params","trim","keyHtml","path","href","getHref","push","visuallyHiddenText","key","html","actions","accept","summaryList","upload","getAllPossibleErrors","baseErrors","type","template","selectRequired","advancedSettingsErrors"],"sources":["../../../../../src/server/plugins/engine/components/FileUploadField.ts"],"sourcesContent":["import { type FileUploadFieldComponent } from '@defra/forms-model'\nimport joi, { type ArraySchema } from 'joi'\n\nimport {\n FormComponent,\n isUploadState\n} from '~/src/server/plugins/engine/components/FormComponent.js'\nimport { messageTemplate } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'\nimport {\n FileStatus,\n UploadStatus,\n type ErrorMessageTemplateList,\n type FileState,\n type FileUpload,\n type FileUploadMetadata,\n type FormPayload,\n type FormState,\n type FormStateValue,\n type FormSubmissionError,\n type FormSubmissionState,\n type SummaryList,\n type SummaryListAction,\n type SummaryListRow,\n type UploadState,\n type UploadStatusFileResponse,\n type UploadStatusResponse\n} from '~/src/server/plugins/engine/types.js'\nimport { render } from '~/src/server/plugins/nunjucks/index.js'\nimport { type FormQuery } from '~/src/server/routes/types.js'\n\nexport const uploadIdSchema = joi.string().uuid().required()\n\nexport const fileSchema = joi\n .object<FileUpload>({\n fileId: joi.string().uuid().required(),\n filename: joi.string().required(),\n contentLength: joi.number().required()\n })\n .required()\n\nexport const tempFileSchema = fileSchema.append({\n fileStatus: joi\n .string()\n .valid(FileStatus.complete, FileStatus.rejected, FileStatus.pending)\n .required(),\n errorMessage: joi.string().optional()\n})\n\nexport const formFileSchema = fileSchema.append({\n fileStatus: joi.string().valid(FileStatus.complete).required()\n})\n\nexport const metadataSchema = joi\n .object<FileUploadMetadata>()\n .keys({\n retrievalKey: joi.string().email().required()\n })\n .required()\n\nexport const tempStatusSchema = joi\n .object<UploadStatusFileResponse>({\n uploadStatus: joi\n .string()\n .valid(UploadStatus.ready, UploadStatus.pending)\n .required(),\n metadata: metadataSchema,\n form: joi.object().required().keys({\n file: tempFileSchema\n }),\n numberOfRejectedFiles: joi.number().optional()\n })\n .required()\n\nexport const formStatusSchema = joi\n .object<UploadStatusResponse>({\n uploadStatus: joi.string().valid(UploadStatus.ready).required(),\n metadata: metadataSchema,\n form: joi.object().required().keys({\n file: formFileSchema\n }),\n numberOfRejectedFiles: joi.number().valid(0).required()\n })\n .required()\n\nexport const itemSchema = joi.object<FileState>({\n uploadId: uploadIdSchema\n})\n\nexport const tempItemSchema = itemSchema.append({\n status: tempStatusSchema\n})\n\nexport const formItemSchema = itemSchema.append({\n status: formStatusSchema\n})\n\nexport class FileUploadField extends FormComponent {\n declare options: FileUploadFieldComponent['options']\n declare schema: FileUploadFieldComponent['schema']\n declare formSchema: ArraySchema<FileState>\n declare stateSchema: ArraySchema<FileState>\n\n constructor(\n def: FileUploadFieldComponent,\n props: ConstructorParameters<typeof FormComponent>[1]\n ) {\n super(def, props)\n\n const { options, schema } = def\n\n let formSchema = joi\n .array<FileState>()\n .label(this.label)\n .single()\n .required()\n\n if (options.required === false) {\n formSchema = formSchema.optional()\n }\n\n if (typeof schema.length !== 'number') {\n if (typeof schema.max === 'number') {\n formSchema = formSchema.max(schema.max)\n }\n\n if (typeof schema.min === 'number') {\n formSchema = formSchema.min(schema.min)\n }\n } else {\n formSchema = formSchema.length(schema.length)\n }\n\n this.formSchema = formSchema.items(formItemSchema)\n this.stateSchema = formSchema\n .items(formItemSchema)\n .default(null)\n .allow(null)\n\n this.options = options\n this.schema = schema\n }\n\n getFormValueFromState(state: FormSubmissionState) {\n const { name } = this\n return this.getFormValue(state[name])\n }\n\n getFormValue(value?: FormStateValue | FormState) {\n return this.isValue(value) ? value : undefined\n }\n\n getDisplayStringFromFormValue(files: FileState[] | undefined): string {\n if (!files?.length) {\n return ''\n }\n\n const unit = files.length === 1 ? 'file' : 'files'\n return `Uploaded ${files.length} ${unit}`\n }\n\n getDisplayStringFromState(state: FormSubmissionState) {\n const files = this.getFormValueFromState(state)\n\n return this.getDisplayStringFromFormValue(files)\n }\n\n getContextValueFromFormValue(\n files: UploadState | undefined\n ): string[] | null {\n return files?.map(({ status }) => status.form.file.fileId) ?? null\n }\n\n getContextValueFromState(state: FormSubmissionState) {\n const files = this.getFormValueFromState(state)\n return this.getContextValueFromFormValue(files)\n }\n\n getViewModel(\n payload: FormPayload,\n errors?: FormSubmissionError[],\n query: FormQuery = {}\n ) {\n const { options, page } = this\n\n // Allow preview URL direct access\n const isForceAccess = 'force' in query\n\n const viewModel = super.getViewModel(payload, errors)\n const { attributes, id, value } = viewModel\n\n const files = this.getFormValue(value) ?? []\n const filtered = files.filter(\n (file) => file.status.form.file.fileStatus === FileStatus.complete\n )\n const count = filtered.length\n\n const rows: SummaryListRow[] = filtered.map((item, index) => {\n const { status } = item\n const { form } = status\n const { file } = form\n\n const tag = { classes: 'govuk-tag--green', text: 'Uploaded' }\n\n const valueHtml = render\n .view('components/fileuploadfield-value.html', {\n context: { params: { tag } }\n })\n .trim()\n\n const keyHtml = render\n .view('components/fileuploadfield-key.html', {\n context: {\n params: {\n name: file.filename,\n errorMessage: errors && file.errorMessage\n }\n }\n })\n .trim()\n\n const items: SummaryListAction[] = []\n\n // Remove summary list actions from previews\n if (!isForceAccess) {\n const path = `/${item.uploadId}/confirm-delete`\n const href = page?.getHref(`${page.path}${path}`) ?? '#'\n\n items.push({\n href,\n text: 'Remove',\n classes: 'govuk-link--no-visited-state',\n attributes: { id: `${id}__${index}` },\n visuallyHiddenText: file.filename\n })\n }\n\n return {\n key: {\n html: keyHtml\n },\n value: {\n html: valueHtml\n },\n actions: {\n items\n }\n } satisfies SummaryListRow\n })\n\n // Set up the `accept` attribute\n if ('accept' in options && options.accept) {\n attributes.accept = options.accept\n }\n\n const summaryList: SummaryList = {\n classes: 'govuk-summary-list--long-key',\n rows\n }\n\n return {\n ...viewModel,\n\n // File input can't have a initial value\n value: '',\n\n // Override the component name we send to CDP\n name: 'file',\n\n upload: {\n count,\n summaryList\n }\n }\n }\n\n isValue(value?: FormStateValue | FormState): value is UploadState {\n return isUploadState(value)\n }\n\n /**\n * For error preview page that shows all possible errors on a component\n */\n getAllPossibleErrors(): ErrorMessageTemplateList {\n return FileUploadField.getAllPossibleErrors()\n }\n\n /**\n * Static version of getAllPossibleErrors that doesn't require a component instance.\n */\n static getAllPossibleErrors(): ErrorMessageTemplateList {\n return {\n baseErrors: [\n { type: 'selectRequired', template: messageTemplate.selectRequired },\n {\n type: 'filesMimes',\n template: 'The selected file must be a {{#limit}}'\n },\n {\n type: 'filesSize',\n template: 'The selected file must be smaller than 100MB'\n },\n { type: 'filesEmpty', template: 'The selected file is empty' },\n { type: 'filesVirus', template: 'The selected file contains a virus' },\n {\n type: 'filesPartial',\n template: 'The selected file has not fully uploaded'\n },\n {\n type: 'filesError',\n template: 'The selected file could not be uploaded – try again'\n }\n ],\n advancedSettingsErrors: [\n {\n type: 'filesMin',\n template: 'You must upload {{#limit}} files or more'\n },\n {\n type: 'filesMax',\n template: 'You can only upload {{#limit}} files or less'\n },\n {\n type: 'filesExact',\n template: 'You must upload exactly {{#limit}} files'\n }\n ]\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -63,7 +63,9 @@ export declare class FormComponent extends ComponentBase {
|
|
|
63
63
|
summaryList: import("~/src/server/plugins/engine/types.js").SummaryList;
|
|
64
64
|
};
|
|
65
65
|
};
|
|
66
|
+
getDisplayStringFromFormValue(value: FormValue | FormPayload): string;
|
|
66
67
|
getDisplayStringFromState(state: FormSubmissionState): string;
|
|
68
|
+
getContextValueFromFormValue(value: FormValue | FormPayload): Item['value'] | Item['value'][] | null;
|
|
67
69
|
getContextValueFromState(state: FormSubmissionState): Item['value'] | Item['value'][] | null;
|
|
68
70
|
isValue(value?: FormStateValue | FormState): value is NonNullable<FormStateValue>;
|
|
69
71
|
isState(value?: FormStateValue | FormState): value is FormState;
|
|
@@ -124,14 +124,17 @@ export class FormComponent extends ComponentBase {
|
|
|
124
124
|
value: payload[name]
|
|
125
125
|
};
|
|
126
126
|
}
|
|
127
|
-
|
|
128
|
-
|
|
127
|
+
getDisplayStringFromFormValue(value) {
|
|
128
|
+
// Map selected values to text
|
|
129
129
|
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
130
130
|
return this.isValue(value) ? value.toString() : '';
|
|
131
131
|
}
|
|
132
|
-
|
|
132
|
+
getDisplayStringFromState(state) {
|
|
133
133
|
const value = this.getFormValueFromState(state);
|
|
134
|
-
|
|
134
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
135
|
+
return this.getDisplayStringFromFormValue(value);
|
|
136
|
+
}
|
|
137
|
+
getContextValueFromFormValue(value) {
|
|
135
138
|
// Filter object field values
|
|
136
139
|
if (this.isState(value)) {
|
|
137
140
|
const values = Object.values(value).filter(isFormValue);
|
|
@@ -144,6 +147,10 @@ export class FormComponent extends ComponentBase {
|
|
|
144
147
|
}
|
|
145
148
|
return this.isValue(value) ? value : null;
|
|
146
149
|
}
|
|
150
|
+
getContextValueFromState(state) {
|
|
151
|
+
const value = this.getFormValueFromState(state);
|
|
152
|
+
return this.getContextValueFromFormValue(value);
|
|
153
|
+
}
|
|
147
154
|
isValue(value) {
|
|
148
155
|
return isFormValue(value);
|
|
149
156
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormComponent.js","names":["ComponentBase","optionalText","FormComponent","type","hint","label","isFormComponent","constructor","def","props","shortDescription","title","keys","collection","name","fields","map","getFormDataFromState","state","getFormValue","getFormValueFromState","value","isValue","undefined","getStateFromValidForm","payload","getErrors","errors","list","filter","error","path","includes","length","getFirstError","getViewErrors","firstError","getViewModel","options","viewModel","isRequired","required","hideOptional","text","componentErrors","componentError","errorMessage","id","getDisplayStringFromState","toString","getContextValueFromState","isState","values","Object","isFormValue","Array","isArray","isFormState","getAllPossibleErrors","baseErrors","advancedSettingsErrors","isRepeatState","every","isRepeatValue","itemId","isUploadState","isUploadValue","uploadId"],"sources":["../../../../../src/server/plugins/engine/components/FormComponent.ts"],"sourcesContent":["import { type FormComponentsDef, type Item } from '@defra/forms-model'\n\nimport { ComponentBase } from '~/src/server/plugins/engine/components/ComponentBase.js'\nimport { optionalText } from '~/src/server/plugins/engine/components/constants.js'\nimport {\n type ErrorMessageTemplateList,\n type FileState,\n type FormPayload,\n type FormState,\n type FormStateValue,\n type FormSubmissionError,\n type FormSubmissionState,\n type FormValue,\n type RepeatItemState,\n type RepeatListState,\n type UploadState\n} from '~/src/server/plugins/engine/types.js'\n\nexport class FormComponent extends ComponentBase {\n type: FormComponentsDef['type']\n hint: FormComponentsDef['hint']\n label: string\n\n isFormComponent = true\n\n constructor(\n def: FormComponentsDef,\n props: ConstructorParameters<typeof ComponentBase>[1]\n ) {\n super(def, props)\n\n const { hint, type } = def\n\n this.type = type\n this.hint = hint\n this.label =\n 'shortDescription' in def && def.shortDescription\n ? def.shortDescription\n : def.title\n }\n\n get keys() {\n const { collection, name } = this\n\n if (collection) {\n const { fields } = collection\n return [name, ...fields.map(({ name }) => name)]\n }\n\n return [name]\n }\n\n getFormDataFromState(state: FormSubmissionState): FormPayload {\n const { collection, name } = this\n\n if (collection) {\n return collection.getFormDataFromState(state)\n }\n\n return {\n [name]: this.getFormValue(state[name])\n }\n }\n\n getFormValueFromState(state: FormSubmissionState): FormValue | FormPayload {\n const { collection, name } = this\n\n if (collection) {\n return collection.getFormValueFromState(state)\n }\n\n return this.getFormValue(state[name])\n }\n\n getFormValue(value?: FormStateValue | FormState) {\n return this.isValue(value) ? value : undefined\n }\n\n getStateFromValidForm(payload: FormPayload): FormState {\n const { collection, name } = this\n\n if (collection) {\n return collection.getStateFromValidForm(payload)\n }\n\n return {\n [name]: this.getFormValue(payload[name]) ?? null\n }\n }\n\n getErrors(errors?: FormSubmissionError[]): FormSubmissionError[] | undefined {\n const { name } = this\n\n // Filter component and child errors only\n const list = errors?.filter(\n (error) =>\n error.name === name ||\n error.path.includes(name) ||\n this.keys.includes(error.name)\n )\n\n if (!list?.length) {\n return\n }\n\n return list\n }\n\n getFirstError(\n errors?: FormSubmissionError[]\n ): FormSubmissionError | undefined {\n return this.getErrors(errors)?.[0]\n }\n\n getViewErrors(\n errors?: FormSubmissionError[]\n ): FormSubmissionError[] | undefined {\n const firstError = this.getFirstError(errors)\n return firstError && [firstError]\n }\n\n getViewModel(payload: FormPayload, errors?: FormSubmissionError[]) {\n const { hint, name, options = {}, title, viewModel } = this\n\n const isRequired = !('required' in options) || options.required !== false\n const hideOptional = 'optionalText' in options && options.optionalText\n const label = `${title}${!isRequired && !hideOptional ? optionalText : ''}`\n\n if (hint) {\n viewModel.hint = {\n text: hint\n }\n }\n\n // Filter component errors only\n const componentErrors = this.getErrors(errors)\n const componentError = this.getFirstError(componentErrors)\n\n if (componentErrors) {\n viewModel.errors = componentErrors\n }\n\n if (componentError) {\n viewModel.errorMessage = {\n text: componentError.text\n }\n }\n\n return {\n ...viewModel,\n label: {\n text: label\n },\n id: name,\n name,\n value: payload[name]\n }\n }\n\n getDisplayStringFromState(state: FormSubmissionState): string {\n const value = this.getFormValueFromState(state)\n // eslint-disable-next-line @typescript-eslint/no-base-to-string\n return this.isValue(value) ? value.toString() : ''\n }\n\n getContextValueFromState(\n state: FormSubmissionState\n ): Item['value'] | Item['value'][] | null {\n const value = this.getFormValueFromState(state)\n\n // Filter object field values\n if (this.isState(value)) {\n const values = Object.values(value).filter(isFormValue)\n return values.length ? values : null\n }\n\n // Filter array field values\n if (this.isValue(value) && Array.isArray(value)) {\n return value.filter(isFormValue)\n }\n\n return this.isValue(value) ? value : null\n }\n\n isValue(\n value?: FormStateValue | FormState\n ): value is NonNullable<FormStateValue> {\n return isFormValue(value)\n }\n\n isState(value?: FormStateValue | FormState): value is FormState {\n return isFormState(value)\n }\n\n /**\n * For error preview page that shows all possible errors on a component\n */\n getAllPossibleErrors(): ErrorMessageTemplateList {\n return FormComponent.getAllPossibleErrors()\n }\n\n /**\n * Static version of getAllPossibleErrors that doesn't require a component instance.\n */\n static getAllPossibleErrors(): ErrorMessageTemplateList {\n return {\n baseErrors: [],\n advancedSettingsErrors: []\n }\n }\n}\n\n/**\n * Check for form value\n */\nexport function isFormValue(\n value?: unknown\n): value is string | number | boolean {\n return (\n (typeof value === 'string' && value.length > 0) ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n )\n}\n\n/**\n * Check for form state with nested values\n */\nexport function isFormState(value?: unknown): value is FormState {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n return false\n }\n\n // Skip empty objects\n return !!Object.values(value).length\n}\n\n/**\n * Check for repeat list state\n */\nexport function isRepeatState(value?: unknown): value is RepeatListState {\n if (!Array.isArray(value)) {\n return false\n }\n\n // Skip checks when empty\n if (!value.length) {\n return true\n }\n\n return value.every(isRepeatValue)\n}\n\n/**\n * Check for repeat list value\n */\nexport function isRepeatValue(value?: unknown): value is RepeatItemState {\n return isFormState(value) && typeof value.itemId === 'string'\n}\n\n/**\n * Check for upload state\n */\nexport function isUploadState(value?: unknown): value is UploadState {\n if (!Array.isArray(value)) {\n return false\n }\n\n // Skip checks when empty\n if (!value.length) {\n return true\n }\n\n return value.every(isUploadValue)\n}\n\n/**\n * Check for upload state value\n */\nexport function isUploadValue(value?: unknown): value is FileState {\n return isFormState(value) && typeof value.uploadId === 'string'\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"FormComponent.js","names":["ComponentBase","optionalText","FormComponent","type","hint","label","isFormComponent","constructor","def","props","shortDescription","title","keys","collection","name","fields","map","getFormDataFromState","state","getFormValue","getFormValueFromState","value","isValue","undefined","getStateFromValidForm","payload","getErrors","errors","list","filter","error","path","includes","length","getFirstError","getViewErrors","firstError","getViewModel","options","viewModel","isRequired","required","hideOptional","text","componentErrors","componentError","errorMessage","id","getDisplayStringFromFormValue","toString","getDisplayStringFromState","getContextValueFromFormValue","isState","values","Object","isFormValue","Array","isArray","getContextValueFromState","isFormState","getAllPossibleErrors","baseErrors","advancedSettingsErrors","isRepeatState","every","isRepeatValue","itemId","isUploadState","isUploadValue","uploadId"],"sources":["../../../../../src/server/plugins/engine/components/FormComponent.ts"],"sourcesContent":["import { type FormComponentsDef, type Item } from '@defra/forms-model'\n\nimport { ComponentBase } from '~/src/server/plugins/engine/components/ComponentBase.js'\nimport { optionalText } from '~/src/server/plugins/engine/components/constants.js'\nimport {\n type ErrorMessageTemplateList,\n type FileState,\n type FormPayload,\n type FormState,\n type FormStateValue,\n type FormSubmissionError,\n type FormSubmissionState,\n type FormValue,\n type RepeatItemState,\n type RepeatListState,\n type UploadState\n} from '~/src/server/plugins/engine/types.js'\n\nexport class FormComponent extends ComponentBase {\n type: FormComponentsDef['type']\n hint: FormComponentsDef['hint']\n label: string\n\n isFormComponent = true\n\n constructor(\n def: FormComponentsDef,\n props: ConstructorParameters<typeof ComponentBase>[1]\n ) {\n super(def, props)\n\n const { hint, type } = def\n\n this.type = type\n this.hint = hint\n this.label =\n 'shortDescription' in def && def.shortDescription\n ? def.shortDescription\n : def.title\n }\n\n get keys() {\n const { collection, name } = this\n\n if (collection) {\n const { fields } = collection\n return [name, ...fields.map(({ name }) => name)]\n }\n\n return [name]\n }\n\n getFormDataFromState(state: FormSubmissionState): FormPayload {\n const { collection, name } = this\n\n if (collection) {\n return collection.getFormDataFromState(state)\n }\n\n return {\n [name]: this.getFormValue(state[name])\n }\n }\n\n getFormValueFromState(state: FormSubmissionState): FormValue | FormPayload {\n const { collection, name } = this\n\n if (collection) {\n return collection.getFormValueFromState(state)\n }\n\n return this.getFormValue(state[name])\n }\n\n getFormValue(value?: FormStateValue | FormState) {\n return this.isValue(value) ? value : undefined\n }\n\n getStateFromValidForm(payload: FormPayload): FormState {\n const { collection, name } = this\n\n if (collection) {\n return collection.getStateFromValidForm(payload)\n }\n\n return {\n [name]: this.getFormValue(payload[name]) ?? null\n }\n }\n\n getErrors(errors?: FormSubmissionError[]): FormSubmissionError[] | undefined {\n const { name } = this\n\n // Filter component and child errors only\n const list = errors?.filter(\n (error) =>\n error.name === name ||\n error.path.includes(name) ||\n this.keys.includes(error.name)\n )\n\n if (!list?.length) {\n return\n }\n\n return list\n }\n\n getFirstError(\n errors?: FormSubmissionError[]\n ): FormSubmissionError | undefined {\n return this.getErrors(errors)?.[0]\n }\n\n getViewErrors(\n errors?: FormSubmissionError[]\n ): FormSubmissionError[] | undefined {\n const firstError = this.getFirstError(errors)\n return firstError && [firstError]\n }\n\n getViewModel(payload: FormPayload, errors?: FormSubmissionError[]) {\n const { hint, name, options = {}, title, viewModel } = this\n\n const isRequired = !('required' in options) || options.required !== false\n const hideOptional = 'optionalText' in options && options.optionalText\n const label = `${title}${!isRequired && !hideOptional ? optionalText : ''}`\n\n if (hint) {\n viewModel.hint = {\n text: hint\n }\n }\n\n // Filter component errors only\n const componentErrors = this.getErrors(errors)\n const componentError = this.getFirstError(componentErrors)\n\n if (componentErrors) {\n viewModel.errors = componentErrors\n }\n\n if (componentError) {\n viewModel.errorMessage = {\n text: componentError.text\n }\n }\n\n return {\n ...viewModel,\n label: {\n text: label\n },\n id: name,\n name,\n value: payload[name]\n }\n }\n\n getDisplayStringFromFormValue(value: FormValue | FormPayload): string {\n // Map selected values to text\n // eslint-disable-next-line @typescript-eslint/no-base-to-string\n return this.isValue(value) ? value.toString() : ''\n }\n\n getDisplayStringFromState(state: FormSubmissionState): string {\n const value = this.getFormValueFromState(state)\n // eslint-disable-next-line @typescript-eslint/no-base-to-string\n return this.getDisplayStringFromFormValue(value)\n }\n\n getContextValueFromFormValue(\n value: FormValue | FormPayload\n ): Item['value'] | Item['value'][] | null {\n // Filter object field values\n if (this.isState(value)) {\n const values = Object.values(value).filter(isFormValue)\n return values.length ? values : null\n }\n\n // Filter array field values\n if (this.isValue(value) && Array.isArray(value)) {\n return value.filter(isFormValue)\n }\n\n return this.isValue(value) ? value : null\n }\n\n getContextValueFromState(\n state: FormSubmissionState\n ): Item['value'] | Item['value'][] | null {\n const value = this.getFormValueFromState(state)\n\n return this.getContextValueFromFormValue(value)\n }\n\n isValue(\n value?: FormStateValue | FormState\n ): value is NonNullable<FormStateValue> {\n return isFormValue(value)\n }\n\n isState(value?: FormStateValue | FormState): value is FormState {\n return isFormState(value)\n }\n\n /**\n * For error preview page that shows all possible errors on a component\n */\n getAllPossibleErrors(): ErrorMessageTemplateList {\n return FormComponent.getAllPossibleErrors()\n }\n\n /**\n * Static version of getAllPossibleErrors that doesn't require a component instance.\n */\n static getAllPossibleErrors(): ErrorMessageTemplateList {\n return {\n baseErrors: [],\n advancedSettingsErrors: []\n }\n }\n}\n\n/**\n * Check for form value\n */\nexport function isFormValue(\n value?: unknown\n): value is string | number | boolean {\n return (\n (typeof value === 'string' && value.length > 0) ||\n typeof value === 'number' ||\n typeof value === 'boolean'\n )\n}\n\n/**\n * Check for form state with nested values\n */\nexport function isFormState(value?: unknown): value is FormState {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n return false\n }\n\n // Skip empty objects\n return !!Object.values(value).length\n}\n\n/**\n * Check for repeat list state\n */\nexport function isRepeatState(value?: unknown): value is RepeatListState {\n if (!Array.isArray(value)) {\n return false\n }\n\n // Skip checks when empty\n if (!value.length) {\n return true\n }\n\n return value.every(isRepeatValue)\n}\n\n/**\n * Check for repeat list value\n */\nexport function isRepeatValue(value?: unknown): value is RepeatItemState {\n return isFormState(value) && typeof value.itemId === 'string'\n}\n\n/**\n * Check for upload state\n */\nexport function isUploadState(value?: unknown): value is UploadState {\n if (!Array.isArray(value)) {\n return false\n }\n\n // Skip checks when empty\n if (!value.length) {\n return true\n }\n\n return value.every(isUploadValue)\n}\n\n/**\n * Check for upload state value\n */\nexport function isUploadValue(value?: unknown): value is FileState {\n return isFormState(value) && typeof value.uploadId === 'string'\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -15,6 +15,7 @@ export declare class ListFormComponent extends FormComponent {
|
|
|
15
15
|
get values(): Item['value'][];
|
|
16
16
|
constructor(def: SelectionComponentsDef | (YesNoFieldComponent & Pick<ListComponentsDef, 'list'>), props: ConstructorParameters<typeof FormComponent>[1]);
|
|
17
17
|
getFormValueFromState(state: FormSubmissionState): Item['value'] | Item['value'][] | undefined;
|
|
18
|
+
getDisplayStringFromFormValue(value: string | number | boolean | Item['value'][] | undefined): string;
|
|
18
19
|
getDisplayStringFromState(state: FormSubmissionState): string;
|
|
19
20
|
getViewModel(payload: FormPayload, errors?: FormSubmissionError[]): {
|
|
20
21
|
items: ListItem[];
|
|
@@ -44,16 +44,18 @@ export class ListFormComponent extends FormComponent {
|
|
|
44
44
|
const selected = items.filter(item => values.includes(item.value));
|
|
45
45
|
return selected.at(0)?.value;
|
|
46
46
|
}
|
|
47
|
-
|
|
47
|
+
getDisplayStringFromFormValue(value) {
|
|
48
48
|
const {
|
|
49
49
|
items
|
|
50
50
|
} = this;
|
|
51
|
-
|
|
52
|
-
// Allow for array values via subclass
|
|
53
|
-
const value = this.getFormValueFromState(state);
|
|
54
51
|
const values = [value ?? []].flat();
|
|
55
52
|
return items.filter(item => values.includes(item.value)).map(item => item.text).join(', ');
|
|
56
53
|
}
|
|
54
|
+
getDisplayStringFromState(state) {
|
|
55
|
+
// Allow for array values via subclass
|
|
56
|
+
const value = this.getFormValueFromState(state);
|
|
57
|
+
return this.getDisplayStringFromFormValue(value);
|
|
58
|
+
}
|
|
57
59
|
getViewModel(payload, errors) {
|
|
58
60
|
const {
|
|
59
61
|
items: listItems
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ListFormComponent.js","names":["joi","FormComponent","messageTemplate","ListFormComponent","list","listType","items","values","map","value","constructor","def","props","options","model","getList","type","formSchema","valid","label","required","customValidationMessages","messages","stateSchema","default","allow","getFormValueFromState","state","name","isValue","flat","selected","filter","item","includes","at","
|
|
1
|
+
{"version":3,"file":"ListFormComponent.js","names":["joi","FormComponent","messageTemplate","ListFormComponent","list","listType","items","values","map","value","constructor","def","props","options","model","getList","type","formSchema","valid","label","required","customValidationMessages","messages","stateSchema","default","allow","getFormValueFromState","state","name","isValue","flat","selected","filter","item","includes","at","getDisplayStringFromFormValue","text","join","getDisplayStringFromState","getViewModel","payload","errors","listItems","viewModel","itemModel","id","description","hint","getAllPossibleErrors","baseErrors","template","selectRequired","advancedSettingsErrors"],"sources":["../../../../../src/server/plugins/engine/components/ListFormComponent.ts"],"sourcesContent":["import {\n type Item,\n type List,\n type ListComponentsDef,\n type SelectionComponentsDef,\n type YesNoFieldComponent\n} from '@defra/forms-model'\nimport joi, {\n type ArraySchema,\n type BooleanSchema,\n type NumberSchema,\n type StringSchema\n} from 'joi'\n\nimport { FormComponent } from '~/src/server/plugins/engine/components/FormComponent.js'\nimport { type ListItem } from '~/src/server/plugins/engine/components/types.js'\nimport { messageTemplate } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'\nimport {\n type ErrorMessageTemplateList,\n type FormPayload,\n type FormSubmissionError,\n type FormSubmissionState\n} from '~/src/server/plugins/engine/types.js'\n\nexport class ListFormComponent extends FormComponent {\n declare options: Extract<\n SelectionComponentsDef,\n { options: object }\n >['options']\n\n declare formSchema:\n | ArraySchema<string>\n | ArraySchema<number>\n | BooleanSchema<string>\n | NumberSchema<string>\n | NumberSchema\n | StringSchema\n\n declare stateSchema:\n | ArraySchema<string>\n | ArraySchema<number>\n | BooleanSchema<string>\n | NumberSchema<string>\n | NumberSchema\n | StringSchema\n\n list?: List\n listType: List['type'] = 'string'\n\n get items(): Item[] {\n return this.list?.items ?? []\n }\n\n get values(): Item['value'][] {\n return this.items.map(({ value }) => value)\n }\n\n constructor(\n def:\n | SelectionComponentsDef // Allow for Yes/No field custom list\n | (YesNoFieldComponent & Pick<ListComponentsDef, 'list'>),\n props: ConstructorParameters<typeof FormComponent>[1]\n ) {\n super(def, props)\n\n const { options } = def\n const { model } = props\n\n if ('list' in def) {\n this.list = model.getList(def.list)\n this.listType = this.list?.type ?? 'string'\n }\n\n let formSchema = joi[this.listType]()\n .valid(...this.values)\n .label(this.label)\n .required()\n\n if (options.customValidationMessages) {\n formSchema = formSchema.messages(options.customValidationMessages)\n }\n\n this.formSchema = formSchema\n this.stateSchema = formSchema.default(null).allow(null)\n this.options = options\n }\n\n getFormValueFromState(\n state: FormSubmissionState\n ): Item['value'] | Item['value'][] | undefined {\n const { name, items } = this\n\n const value = state[name]\n\n // Allow for array values via subclass\n const values = this.isValue(value) ? [value].flat() : []\n const selected = items.filter((item) => values.includes(item.value))\n\n return selected.at(0)?.value\n }\n\n getDisplayStringFromFormValue(\n value: string | number | boolean | Item['value'][] | undefined\n ): string {\n const { items } = this\n\n const values = [value ?? []].flat()\n\n return items\n .filter((item) => values.includes(item.value))\n .map((item) => item.text)\n .join(', ')\n }\n\n getDisplayStringFromState(state: FormSubmissionState) {\n // Allow for array values via subclass\n const value = this.getFormValueFromState(state)\n\n return this.getDisplayStringFromFormValue(value)\n }\n\n getViewModel(payload: FormPayload, errors?: FormSubmissionError[]) {\n const { items: listItems } = this\n\n const viewModel = super.getViewModel(payload, errors)\n const { value } = viewModel\n\n // Support multiple values for checkboxes\n const values = this.isValue(value) ? [value].flat() : []\n\n const items = listItems.map((item) => {\n const selected = values.includes(item.value)\n const itemModel: ListItem = { ...item, selected }\n\n if ('id' in itemModel) {\n delete itemModel.id\n }\n\n if (item.description) {\n itemModel.hint = {\n text: item.description\n }\n }\n\n return itemModel\n })\n\n return {\n ...viewModel,\n items\n }\n }\n\n /**\n * For error preview page that shows all possible errors on a component\n */\n getAllPossibleErrors(): ErrorMessageTemplateList {\n return ListFormComponent.getAllPossibleErrors()\n }\n\n /**\n * Static version of getAllPossibleErrors that doesn't require a component instance.\n */\n static getAllPossibleErrors(): ErrorMessageTemplateList {\n return {\n baseErrors: [\n { type: 'selectRequired', template: messageTemplate.selectRequired }\n ],\n advancedSettingsErrors: []\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -11,7 +11,9 @@ export declare class MonthYearField extends FormComponent {
|
|
|
11
11
|
collection: ComponentCollection;
|
|
12
12
|
constructor(def: MonthYearFieldComponent, props: ConstructorParameters<typeof FormComponent>[1]);
|
|
13
13
|
getFormValueFromState(state: FormSubmissionState): MonthYearState | undefined;
|
|
14
|
+
getDisplayStringFromFormValue(value: MonthYearState | undefined): string;
|
|
14
15
|
getDisplayStringFromState(state: FormSubmissionState): string;
|
|
16
|
+
getContextValueFromFormValue(value: MonthYearState | undefined): string | null;
|
|
15
17
|
getContextValueFromState(state: FormSubmissionState): string | null;
|
|
16
18
|
getViewModel(payload: FormPayload, errors?: FormSubmissionError[]): {
|
|
17
19
|
fieldset: {
|
|
@@ -70,8 +70,7 @@ export class MonthYearField extends FormComponent {
|
|
|
70
70
|
const value = super.getFormValueFromState(state);
|
|
71
71
|
return MonthYearField.isMonthYear(value) ? value : undefined;
|
|
72
72
|
}
|
|
73
|
-
|
|
74
|
-
const value = this.getFormValueFromState(state);
|
|
73
|
+
getDisplayStringFromFormValue(value) {
|
|
75
74
|
if (!value) {
|
|
76
75
|
return '';
|
|
77
76
|
}
|
|
@@ -82,13 +81,20 @@ export class MonthYearField extends FormComponent {
|
|
|
82
81
|
});
|
|
83
82
|
return `${monthString} ${value.year}`;
|
|
84
83
|
}
|
|
85
|
-
|
|
84
|
+
getDisplayStringFromState(state) {
|
|
86
85
|
const value = this.getFormValueFromState(state);
|
|
86
|
+
return this.getDisplayStringFromFormValue(value);
|
|
87
|
+
}
|
|
88
|
+
getContextValueFromFormValue(value) {
|
|
87
89
|
if (!value || !isValid(parseStrictDate(value, `${value.year}-${value.month}-01`, 'yyyy-MM-dd', new Date()))) {
|
|
88
90
|
return null;
|
|
89
91
|
}
|
|
90
92
|
return format(`${value.year}-${value.month}-01`, 'yyyy-MM');
|
|
91
93
|
}
|
|
94
|
+
getContextValueFromState(state) {
|
|
95
|
+
const value = this.getFormValueFromState(state);
|
|
96
|
+
return this.getContextValueFromFormValue(value);
|
|
97
|
+
}
|
|
92
98
|
getViewModel(payload, errors) {
|
|
93
99
|
const {
|
|
94
100
|
collection,
|