@defra/forms-engine-plugin 4.0.59 → 4.0.60
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/.public/javascripts/application.min.js +1 -1
- package/.public/javascripts/application.min.js.map +1 -1
- package/.public/stylesheets/application.min.css +2 -2
- package/.public/stylesheets/application.min.css.map +1 -1
- package/.server/server/plugins/engine/components/AutocompleteField.js +0 -2
- package/.server/server/plugins/engine/components/AutocompleteField.js.map +1 -1
- package/.server/server/plugins/engine/components/DatePartsField.js +0 -2
- package/.server/server/plugins/engine/components/DatePartsField.js.map +1 -1
- package/.server/server/plugins/engine/components/FormComponent.js +0 -1
- package/.server/server/plugins/engine/components/FormComponent.js.map +1 -1
- package/.server/server/plugins/engine/components/MonthYearField.js +0 -2
- package/.server/server/plugins/engine/components/MonthYearField.js.map +1 -1
- package/.server/server/plugins/engine/components/NumberField.js +0 -1
- package/.server/server/plugins/engine/components/NumberField.js.map +1 -1
- package/.server/server/plugins/engine/pageControllers/validationOptions.js +0 -1
- package/.server/server/plugins/engine/pageControllers/validationOptions.js.map +1 -1
- package/.server/typings/hapi/index.d.js.map +1 -1
- package/package.json +25 -11
- package/src/server/plugins/engine/components/AutocompleteField.ts +0 -2
- package/src/server/plugins/engine/components/DatePartsField.ts +0 -2
- package/src/server/plugins/engine/components/FormComponent.ts +0 -1
- package/src/server/plugins/engine/components/MonthYearField.ts +0 -2
- package/src/server/plugins/engine/components/NumberField.ts +0 -1
- package/src/server/plugins/engine/pageControllers/validationOptions.ts +0 -1
- package/src/server/plugins/engine/routes/questions.test.ts +0 -1
- package/src/server/routes/dummy-api.test.ts +0 -1
- package/src/typings/hapi/index.d.ts +0 -2
|
@@ -12,9 +12,7 @@ export class AutocompleteField extends SelectField {
|
|
|
12
12
|
if (options.required !== false) {
|
|
13
13
|
const messages = options.customValidationMessages;
|
|
14
14
|
formSchema = formSchema.messages({
|
|
15
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
16
15
|
'any.only': messages?.['any.only'] ?? messageTemplate.required,
|
|
17
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
18
16
|
'any.required': messages?.['any.required'] ?? messageTemplate.required
|
|
19
17
|
});
|
|
20
18
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AutocompleteField.js","names":["SelectField","messageTemplate","AutocompleteField","constructor","def","props","options","formSchema","required","messages","customValidationMessages","getViewModel","payload","errors","viewModel","formGroup","attributes"],"sources":["../../../../../src/server/plugins/engine/components/AutocompleteField.ts"],"sourcesContent":["import { type AutocompleteFieldComponent } from '@defra/forms-model'\n\nimport { SelectField } from '~/src/server/plugins/engine/components/SelectField.js'\nimport { messageTemplate } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'\nimport {\n type FormPayload,\n type FormSubmissionError\n} from '~/src/server/plugins/engine/types.js'\n\nexport class AutocompleteField extends SelectField {\n declare options: AutocompleteFieldComponent['options']\n\n constructor(\n def: AutocompleteFieldComponent,\n props: ConstructorParameters<typeof SelectField>[1]\n ) {\n super(def, props)\n\n const { options } = def\n let { formSchema } = this\n\n if (options.required !== false) {\n const messages = options.customValidationMessages\n\n formSchema = formSchema.messages({\n
|
|
1
|
+
{"version":3,"file":"AutocompleteField.js","names":["SelectField","messageTemplate","AutocompleteField","constructor","def","props","options","formSchema","required","messages","customValidationMessages","getViewModel","payload","errors","viewModel","formGroup","attributes"],"sources":["../../../../../src/server/plugins/engine/components/AutocompleteField.ts"],"sourcesContent":["import { type AutocompleteFieldComponent } from '@defra/forms-model'\n\nimport { SelectField } from '~/src/server/plugins/engine/components/SelectField.js'\nimport { messageTemplate } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'\nimport {\n type FormPayload,\n type FormSubmissionError\n} from '~/src/server/plugins/engine/types.js'\n\nexport class AutocompleteField extends SelectField {\n declare options: AutocompleteFieldComponent['options']\n\n constructor(\n def: AutocompleteFieldComponent,\n props: ConstructorParameters<typeof SelectField>[1]\n ) {\n super(def, props)\n\n const { options } = def\n let { formSchema } = this\n\n if (options.required !== false) {\n const messages = options.customValidationMessages\n\n formSchema = formSchema.messages({\n 'any.only':\n messages?.['any.only'] ?? (messageTemplate.required as string),\n 'any.required':\n messages?.['any.required'] ?? (messageTemplate.required as string)\n })\n }\n\n this.options = options\n this.formSchema = formSchema\n }\n\n getViewModel(payload: FormPayload, errors?: FormSubmissionError[]) {\n const viewModel = super.getViewModel(payload, errors)\n let { formGroup } = viewModel\n\n formGroup ??= {}\n formGroup.attributes = {\n 'data-module': 'govuk-accessible-autocomplete'\n }\n\n return {\n ...viewModel,\n formGroup\n }\n }\n}\n"],"mappings":"AAEA,SAASA,WAAW;AACpB,SAASC,eAAe;AAMxB,OAAO,MAAMC,iBAAiB,SAASF,WAAW,CAAC;EAGjDG,WAAWA,CACTC,GAA+B,EAC/BC,KAAmD,EACnD;IACA,KAAK,CAACD,GAAG,EAAEC,KAAK,CAAC;IAEjB,MAAM;MAAEC;IAAQ,CAAC,GAAGF,GAAG;IACvB,IAAI;MAAEG;IAAW,CAAC,GAAG,IAAI;IAEzB,IAAID,OAAO,CAACE,QAAQ,KAAK,KAAK,EAAE;MAC9B,MAAMC,QAAQ,GAAGH,OAAO,CAACI,wBAAwB;MAEjDH,UAAU,GAAGA,UAAU,CAACE,QAAQ,CAAC;QAC/B,UAAU,EACRA,QAAQ,GAAG,UAAU,CAAC,IAAKR,eAAe,CAACO,QAAmB;QAChE,cAAc,EACZC,QAAQ,GAAG,cAAc,CAAC,IAAKR,eAAe,CAACO;MACnD,CAAC,CAAC;IACJ;IAEA,IAAI,CAACF,OAAO,GAAGA,OAAO;IACtB,IAAI,CAACC,UAAU,GAAGA,UAAU;EAC9B;EAEAI,YAAYA,CAACC,OAAoB,EAAEC,MAA8B,EAAE;IACjE,MAAMC,SAAS,GAAG,KAAK,CAACH,YAAY,CAACC,OAAO,EAAEC,MAAM,CAAC;IACrD,IAAI;MAAEE;IAAU,CAAC,GAAGD,SAAS;IAE7BC,SAAS,KAAK,CAAC,CAAC;IAChBA,SAAS,CAACC,UAAU,GAAG;MACrB,aAAa,EAAE;IACjB,CAAC;IAED,OAAO;MACL,GAAGF,SAAS;MACZC;IACF,CAAC;EACH;AACF","ignoreList":[]}
|
|
@@ -15,9 +15,7 @@ export class DatePartsField extends FormComponent {
|
|
|
15
15
|
} = def;
|
|
16
16
|
const isRequired = options.required !== false;
|
|
17
17
|
const customValidationMessages = convertToLanguageMessages({
|
|
18
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
19
18
|
'any.required': messageTemplate.objectMissing,
|
|
20
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
21
19
|
'number.base': messageTemplate.objectMissing,
|
|
22
20
|
'number.precision': messageTemplate.dateFormat,
|
|
23
21
|
'number.integer': messageTemplate.dateFormat,
|
|
@@ -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","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 =\n options.maxDaysInPast || options.maxDaysInPast === 0\n ? sub(startOfToday(), { days: options.maxDaysInPast })\n : undefined\n\n // Maximum date from today\n const dateMax =\n options.maxDaysInFuture || options.maxDaysInFuture === 0\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,GACX1D,OAAO,CAACuE,aAAa,IAAIvE,OAAO,CAACuE,aAAa,KAAK,CAAC,GAChDrF,GAAG,CAACD,YAAY,CAAC,CAAC,EAAE;MAAEuF,IAAI,EAAExE,OAAO,CAACuE;IAAc,CAAC,CAAC,GACpD9C,SAAS;;IAEf;IACA,MAAMkC,OAAO,GACX3D,OAAO,CAACyE,eAAe,IAAIzE,OAAO,CAACyE,eAAe,KAAK,CAAC,GACpD5F,GAAG,CAACI,YAAY,CAAC,CAAC,EAAE;MAAEuF,IAAI,EAAExE,OAAO,CAACyE;IAAgB,CAAC,CAAC,GACtDhD,SAAS;IAEf,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":[]}
|
|
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 'any.required': messageTemplate.objectMissing,\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 =\n options.maxDaysInPast || options.maxDaysInPast === 0\n ? sub(startOfToday(), { days: options.maxDaysInPast })\n : undefined\n\n // Maximum date from today\n const dateMax =\n options.maxDaysInFuture || options.maxDaysInFuture === 0\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":[]}
|
|
@@ -132,7 +132,6 @@ export class FormComponent extends ComponentBase {
|
|
|
132
132
|
}
|
|
133
133
|
getDisplayStringFromState(state) {
|
|
134
134
|
const value = this.getFormValueFromState(state);
|
|
135
|
-
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
136
135
|
return this.getDisplayStringFromFormValue(value);
|
|
137
136
|
}
|
|
138
137
|
getContextValueFromFormValue(value) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FormComponent.js","names":["ComponentBase","optionalText","FormComponent","type","hint","label","isFormComponent","isAppendageStateSingleObject","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","onSubmit","_request","_metadata","_context","Promise","resolve","isRepeatState","every","isRepeatValue","itemId","isUploadState","isUploadValue","uploadId"],"sources":["../../../../../src/server/plugins/engine/components/FormComponent.ts"],"sourcesContent":["import {\n type FormComponentsDef,\n type FormMetadata,\n type Item\n} 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 FormContext,\n type FormRequestPayload\n} from '~/src/server/plugins/engine/types/index.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 isAppendageStateSingleObject = false\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 onSubmit(\n _request: FormRequestPayload,\n _metadata: FormMetadata,\n _context: FormContext\n ): Promise<void> {\n return Promise.resolve()\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","isAppendageStateSingleObject","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","onSubmit","_request","_metadata","_context","Promise","resolve","isRepeatState","every","isRepeatValue","itemId","isUploadState","isUploadValue","uploadId"],"sources":["../../../../../src/server/plugins/engine/components/FormComponent.ts"],"sourcesContent":["import {\n type FormComponentsDef,\n type FormMetadata,\n type Item\n} 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 FormContext,\n type FormRequestPayload\n} from '~/src/server/plugins/engine/types/index.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 isAppendageStateSingleObject = false\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 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 onSubmit(\n _request: FormRequestPayload,\n _metadata: FormMetadata,\n _context: FormContext\n ): Promise<void> {\n return Promise.resolve()\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,9 +15,7 @@ export class MonthYearField extends FormComponent {
|
|
|
15
15
|
} = def;
|
|
16
16
|
const isRequired = options.required !== false;
|
|
17
17
|
const customValidationMessages = convertToLanguageMessages({
|
|
18
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
19
18
|
'any.required': messageTemplate.objectMissing,
|
|
20
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
21
19
|
'number.base': messageTemplate.objectMissing,
|
|
22
20
|
'number.precision': messageTemplate.dateFormat,
|
|
23
21
|
'number.integer': messageTemplate.dateFormat,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MonthYearField.js","names":["ComponentType","format","isValid","ComponentCollection","FormComponent","isFormState","isFormValue","NumberField","parseStrictDate","messageTemplate","convertToLanguageMessages","MonthYearField","constructor","def","props","name","options","isRequired","required","customValidationMessages","objectMissing","dateFormat","collection","type","title","schema","min","max","precision","optionalText","classes","parent","custom","getValidatorMonthYear","peers","formSchema","stateSchema","getFormValueFromState","state","value","isMonthYear","undefined","getDisplayStringFromFormValue","date","Date","setMonth","month","monthString","toLocaleString","year","getDisplayStringFromState","getContextValueFromFormValue","getContextValueFromState","getViewModel","payload","errors","viewModel","fieldset","label","hasError","some","error","items","map","model","errorMessage","toString","text","trim","id","legend","isState","getAllPossibleErrors","baseErrors","template","advancedSettingsErrors","dateMin","dateMax","isNumber","component","validator","helpers","values","getStateFromValidForm","context","missing","keys","key"],"sources":["../../../../../src/server/plugins/engine/components/MonthYearField.ts"],"sourcesContent":["import { ComponentType, type MonthYearFieldComponent } from '@defra/forms-model'\nimport { format, isValid } from 'date-fns'\nimport {\n type Context,\n type CustomValidator,\n type LanguageMessages,\n type ObjectSchema\n} 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 MonthYearState\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 MonthYearField extends FormComponent {\n declare options: MonthYearFieldComponent['options']\n declare formSchema: ObjectSchema<FormPayload>\n declare stateSchema: ObjectSchema<FormState>\n declare collection: ComponentCollection\n\n constructor(\n def: MonthYearFieldComponent,\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: LanguageMessages =\n 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}__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: getValidatorMonthYear(this),\n peers: [`${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 MonthYearField.isMonthYear(value) ? value : undefined\n }\n\n getDisplayStringFromFormValue(value: MonthYearState | undefined): string {\n if (!value) {\n return ''\n }\n\n const date = new Date()\n date.setMonth(value.month - 1)\n\n const monthString = date.toLocaleString('default', { month: 'long' })\n return `${monthString} ${value.year}`\n }\n\n getDisplayStringFromState(state: FormSubmissionState) {\n const value = this.getFormValueFromState(state)\n\n return this.getDisplayStringFromFormValue(value)\n }\n\n getContextValueFromFormValue(\n value: MonthYearState | undefined\n ): string | null {\n if (\n !value ||\n !isValid(\n parseStrictDate(\n value,\n `${value.year}-${value.month}-01`,\n 'yyyy-MM-dd',\n new Date()\n )\n )\n ) {\n return null\n }\n\n return format(`${value.year}-${value.month}-01`, 'yyyy-MM')\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 MonthYearField.isMonthYear(value)\n }\n\n /**\n * For error preview page that shows all possible errors on a component\n */\n getAllPossibleErrors(): ErrorMessageTemplateList {\n return MonthYearField.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 {\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 isMonthYear(\n value?: FormStateValue | FormState\n ): value is MonthYearState {\n return (\n isFormState(value) &&\n NumberField.isNumber(value.month) &&\n NumberField.isNumber(value.year)\n )\n }\n}\n\nexport function getValidatorMonthYear(component: MonthYearField) {\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 return payload\n }\n\n return validator\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"MonthYearField.js","names":["ComponentType","format","isValid","ComponentCollection","FormComponent","isFormState","isFormValue","NumberField","parseStrictDate","messageTemplate","convertToLanguageMessages","MonthYearField","constructor","def","props","name","options","isRequired","required","customValidationMessages","objectMissing","dateFormat","collection","type","title","schema","min","max","precision","optionalText","classes","parent","custom","getValidatorMonthYear","peers","formSchema","stateSchema","getFormValueFromState","state","value","isMonthYear","undefined","getDisplayStringFromFormValue","date","Date","setMonth","month","monthString","toLocaleString","year","getDisplayStringFromState","getContextValueFromFormValue","getContextValueFromState","getViewModel","payload","errors","viewModel","fieldset","label","hasError","some","error","items","map","model","errorMessage","toString","text","trim","id","legend","isState","getAllPossibleErrors","baseErrors","template","advancedSettingsErrors","dateMin","dateMax","isNumber","component","validator","helpers","values","getStateFromValidForm","context","missing","keys","key"],"sources":["../../../../../src/server/plugins/engine/components/MonthYearField.ts"],"sourcesContent":["import { ComponentType, type MonthYearFieldComponent } from '@defra/forms-model'\nimport { format, isValid } from 'date-fns'\nimport {\n type Context,\n type CustomValidator,\n type LanguageMessages,\n type ObjectSchema\n} 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 MonthYearState\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 MonthYearField extends FormComponent {\n declare options: MonthYearFieldComponent['options']\n declare formSchema: ObjectSchema<FormPayload>\n declare stateSchema: ObjectSchema<FormState>\n declare collection: ComponentCollection\n\n constructor(\n def: MonthYearFieldComponent,\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: LanguageMessages =\n convertToLanguageMessages({\n 'any.required': messageTemplate.objectMissing,\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}__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: getValidatorMonthYear(this),\n peers: [`${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 MonthYearField.isMonthYear(value) ? value : undefined\n }\n\n getDisplayStringFromFormValue(value: MonthYearState | undefined): string {\n if (!value) {\n return ''\n }\n\n const date = new Date()\n date.setMonth(value.month - 1)\n\n const monthString = date.toLocaleString('default', { month: 'long' })\n return `${monthString} ${value.year}`\n }\n\n getDisplayStringFromState(state: FormSubmissionState) {\n const value = this.getFormValueFromState(state)\n\n return this.getDisplayStringFromFormValue(value)\n }\n\n getContextValueFromFormValue(\n value: MonthYearState | undefined\n ): string | null {\n if (\n !value ||\n !isValid(\n parseStrictDate(\n value,\n `${value.year}-${value.month}-01`,\n 'yyyy-MM-dd',\n new Date()\n )\n )\n ) {\n return null\n }\n\n return format(`${value.year}-${value.month}-01`, 'yyyy-MM')\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 MonthYearField.isMonthYear(value)\n }\n\n /**\n * For error preview page that shows all possible errors on a component\n */\n getAllPossibleErrors(): ErrorMessageTemplateList {\n return MonthYearField.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 {\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 isMonthYear(\n value?: FormStateValue | FormState\n ): value is MonthYearState {\n return (\n isFormState(value) &&\n NumberField.isNumber(value.month) &&\n NumberField.isNumber(value.year)\n )\n }\n}\n\nexport function getValidatorMonthYear(component: MonthYearField) {\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 return payload\n }\n\n return validator\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -14,7 +14,6 @@ export class NumberField extends FormComponent {
|
|
|
14
14
|
} else {
|
|
15
15
|
const messages = options.customValidationMessages;
|
|
16
16
|
formSchema = formSchema.empty('').messages({
|
|
17
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
18
17
|
'any.required': messages?.['any.required'] ?? messageTemplate.required
|
|
19
18
|
});
|
|
20
19
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NumberField.js","names":["joi","FormComponent","isFormValue","messageTemplate","NumberField","constructor","def","props","options","schema","formSchema","number","custom","getValidatorPrecision","label","required","allow","messages","customValidationMessages","empty","min","max","precision","integer","customValidationMessage","message","default","stateSchema","getFormValueFromState","state","name","getFormValue","value","isValue","undefined","getViewModel","payload","errors","viewModel","attributes","prefix","suffix","inputmode","text","isNumber","getAllPossibleErrors","baseErrors","type","template","numberInteger","advancedSettingsErrors","numberMin","numberMax","numberPrecision","component","validator","helpers","limit","validationSchema","prefs","convert","attempt","error"],"sources":["../../../../../src/server/plugins/engine/components/NumberField.ts"],"sourcesContent":["import { type NumberFieldComponent } from '@defra/forms-model'\nimport joi, { type CustomValidator, type NumberSchema } from 'joi'\n\nimport {\n FormComponent,\n isFormValue\n} from '~/src/server/plugins/engine/components/FormComponent.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'\n\nexport class NumberField extends FormComponent {\n declare options: NumberFieldComponent['options']\n declare schema: NumberFieldComponent['schema']\n declare formSchema: NumberSchema\n declare stateSchema: NumberSchema\n\n constructor(\n def: NumberFieldComponent,\n props: ConstructorParameters<typeof FormComponent>[1]\n ) {\n super(def, props)\n\n const { options, schema } = def\n\n let formSchema = joi\n .number()\n .custom(getValidatorPrecision(this))\n .label(this.label)\n .required()\n\n if (options.required === false) {\n formSchema = formSchema.allow('')\n } else {\n const messages = options.customValidationMessages\n\n formSchema = formSchema.empty('').messages({\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n 'any.required':\n messages?.['any.required'] ?? (messageTemplate.required as string)\n })\n }\n\n if (typeof schema.min === 'number') {\n formSchema = formSchema.min(schema.min)\n }\n\n if (typeof schema.max === 'number') {\n formSchema = formSchema.max(schema.max)\n }\n\n if (typeof schema.precision === 'number' && schema.precision <= 0) {\n formSchema = formSchema.integer()\n }\n\n if (options.customValidationMessage) {\n const message = options.customValidationMessage\n\n formSchema = formSchema.messages({\n 'any.required': message,\n 'number.base': message,\n 'number.precision': message,\n 'number.integer': message,\n 'number.min': message,\n 'number.max': message\n })\n } else if (options.customValidationMessages) {\n formSchema = formSchema.messages(options.customValidationMessages)\n }\n\n this.formSchema = formSchema.default('')\n this.stateSchema = formSchema.default(null).allow(null)\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 getViewModel(payload: FormPayload, errors?: FormSubmissionError[]) {\n const { options, schema } = this\n\n const viewModel = super.getViewModel(payload, errors)\n let { attributes, prefix, suffix, value } = viewModel\n\n if (typeof schema.precision === 'undefined' || schema.precision <= 0) {\n // If precision isn't provided or provided and\n // less than or equal to 0, use numeric inputmode\n attributes.inputmode = 'numeric'\n }\n\n if (options.prefix) {\n prefix = {\n text: options.prefix\n }\n }\n\n if (options.suffix) {\n suffix = {\n text: options.suffix\n }\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 ...viewModel,\n attributes,\n prefix,\n suffix,\n value\n }\n }\n\n isValue(value?: FormStateValue | FormState) {\n return NumberField.isNumber(value)\n }\n\n /**\n * For error preview page that shows all possible errors on a component\n */\n getAllPossibleErrors(): ErrorMessageTemplateList {\n return NumberField.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: 'numberInteger', template: messageTemplate.numberInteger }\n ],\n advancedSettingsErrors: [\n { type: 'numberMin', template: messageTemplate.numberMin },\n { type: 'numberMax', template: messageTemplate.numberMax },\n { type: 'numberPrecision', template: messageTemplate.numberPrecision }\n ]\n }\n }\n\n static isNumber(value?: FormStateValue | FormState): value is number {\n return typeof value === 'number'\n }\n}\n\nexport function getValidatorPrecision(component: NumberField) {\n const validator: CustomValidator = (value: number, helpers) => {\n const { options, schema } = component\n\n const { customValidationMessage: custom } = options\n const { precision: limit } = schema\n\n if (!limit || limit <= 0) {\n return value\n }\n\n const validationSchema = joi\n .number()\n .precision(limit)\n .prefs({ convert: false })\n\n try {\n return joi.attempt(value, validationSchema)\n } catch {\n return custom\n ? helpers.message({ custom }, { limit })\n : helpers.error('number.precision', { limit })\n }\n }\n\n return validator\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"NumberField.js","names":["joi","FormComponent","isFormValue","messageTemplate","NumberField","constructor","def","props","options","schema","formSchema","number","custom","getValidatorPrecision","label","required","allow","messages","customValidationMessages","empty","min","max","precision","integer","customValidationMessage","message","default","stateSchema","getFormValueFromState","state","name","getFormValue","value","isValue","undefined","getViewModel","payload","errors","viewModel","attributes","prefix","suffix","inputmode","text","isNumber","getAllPossibleErrors","baseErrors","type","template","numberInteger","advancedSettingsErrors","numberMin","numberMax","numberPrecision","component","validator","helpers","limit","validationSchema","prefs","convert","attempt","error"],"sources":["../../../../../src/server/plugins/engine/components/NumberField.ts"],"sourcesContent":["import { type NumberFieldComponent } from '@defra/forms-model'\nimport joi, { type CustomValidator, type NumberSchema } from 'joi'\n\nimport {\n FormComponent,\n isFormValue\n} from '~/src/server/plugins/engine/components/FormComponent.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'\n\nexport class NumberField extends FormComponent {\n declare options: NumberFieldComponent['options']\n declare schema: NumberFieldComponent['schema']\n declare formSchema: NumberSchema\n declare stateSchema: NumberSchema\n\n constructor(\n def: NumberFieldComponent,\n props: ConstructorParameters<typeof FormComponent>[1]\n ) {\n super(def, props)\n\n const { options, schema } = def\n\n let formSchema = joi\n .number()\n .custom(getValidatorPrecision(this))\n .label(this.label)\n .required()\n\n if (options.required === false) {\n formSchema = formSchema.allow('')\n } else {\n const messages = options.customValidationMessages\n\n formSchema = formSchema.empty('').messages({\n 'any.required':\n messages?.['any.required'] ?? (messageTemplate.required as string)\n })\n }\n\n if (typeof schema.min === 'number') {\n formSchema = formSchema.min(schema.min)\n }\n\n if (typeof schema.max === 'number') {\n formSchema = formSchema.max(schema.max)\n }\n\n if (typeof schema.precision === 'number' && schema.precision <= 0) {\n formSchema = formSchema.integer()\n }\n\n if (options.customValidationMessage) {\n const message = options.customValidationMessage\n\n formSchema = formSchema.messages({\n 'any.required': message,\n 'number.base': message,\n 'number.precision': message,\n 'number.integer': message,\n 'number.min': message,\n 'number.max': message\n })\n } else if (options.customValidationMessages) {\n formSchema = formSchema.messages(options.customValidationMessages)\n }\n\n this.formSchema = formSchema.default('')\n this.stateSchema = formSchema.default(null).allow(null)\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 getViewModel(payload: FormPayload, errors?: FormSubmissionError[]) {\n const { options, schema } = this\n\n const viewModel = super.getViewModel(payload, errors)\n let { attributes, prefix, suffix, value } = viewModel\n\n if (typeof schema.precision === 'undefined' || schema.precision <= 0) {\n // If precision isn't provided or provided and\n // less than or equal to 0, use numeric inputmode\n attributes.inputmode = 'numeric'\n }\n\n if (options.prefix) {\n prefix = {\n text: options.prefix\n }\n }\n\n if (options.suffix) {\n suffix = {\n text: options.suffix\n }\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 ...viewModel,\n attributes,\n prefix,\n suffix,\n value\n }\n }\n\n isValue(value?: FormStateValue | FormState) {\n return NumberField.isNumber(value)\n }\n\n /**\n * For error preview page that shows all possible errors on a component\n */\n getAllPossibleErrors(): ErrorMessageTemplateList {\n return NumberField.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: 'numberInteger', template: messageTemplate.numberInteger }\n ],\n advancedSettingsErrors: [\n { type: 'numberMin', template: messageTemplate.numberMin },\n { type: 'numberMax', template: messageTemplate.numberMax },\n { type: 'numberPrecision', template: messageTemplate.numberPrecision }\n ]\n }\n }\n\n static isNumber(value?: FormStateValue | FormState): value is number {\n return typeof value === 'number'\n }\n}\n\nexport function getValidatorPrecision(component: NumberField) {\n const validator: CustomValidator = (value: number, helpers) => {\n const { options, schema } = component\n\n const { customValidationMessage: custom } = options\n const { precision: limit } = schema\n\n if (!limit || limit <= 0) {\n return value\n }\n\n const validationSchema = joi\n .number()\n .precision(limit)\n .prefs({ convert: false })\n\n try {\n return joi.attempt(value, validationSchema)\n } catch {\n return custom\n ? helpers.message({ custom }, { limit })\n : helpers.error('number.precision', { limit })\n }\n }\n\n return validator\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validationOptions.js","names":["joi","lowerFirstPreserveProperNouns","opts","functions","lowerFirst","messageTemplate","declarationRequired","expression","required","selectRequired","selectYesNoRequired","max","min","minMax","pattern","format","number","numberPrecision","numberInteger","numberMin","numberMax","maxWords","objectRequired","objectMissing","dateFormat","dateMin","dateMax","messages","messagesPre","validationOptions","abortEarly","errors","wrap","array","label"],"sources":["../../../../../src/server/plugins/engine/pageControllers/validationOptions.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"validationOptions.js","names":["joi","lowerFirstPreserveProperNouns","opts","functions","lowerFirst","messageTemplate","declarationRequired","expression","required","selectRequired","selectYesNoRequired","max","min","minMax","pattern","format","number","numberPrecision","numberInteger","numberMin","numberMax","maxWords","objectRequired","objectMissing","dateFormat","dateMin","dateMax","messages","messagesPre","validationOptions","abortEarly","errors","wrap","array","label"],"sources":["../../../../../src/server/plugins/engine/pageControllers/validationOptions.ts"],"sourcesContent":["// Declaration above is needed for: https://github.com/hapijs/joi/issues/3064\n\nimport joi, {\n type JoiExpression,\n type LanguageMessages,\n type LanguageMessagesExt,\n type ReferenceOptions,\n type ValidationOptions\n} from 'joi'\n\nimport { lowerFirstPreserveProperNouns } from '~/src/server/plugins/engine/components/helpers/index.js'\n\nconst opts = {\n functions: {\n lowerFirst: lowerFirstPreserveProperNouns\n }\n} as ReferenceOptions\n\n/**\n * see @link https://joi.dev/api/?v=17.4.2#template-syntax for template syntax\n */\nexport const messageTemplate: Record<string, JoiExpression> = {\n declarationRequired: joi.expression(\n 'You must confirm you understand and agree with the {{lowerFirst(#label)}} to continue',\n opts\n ) as JoiExpression,\n required: joi.expression(\n 'Enter {{lowerFirst(#label)}}',\n opts\n ) as JoiExpression,\n selectRequired: joi.expression(\n 'Select {{lowerFirst(#label)}}',\n opts\n ) as JoiExpression,\n selectYesNoRequired: '{{#label}} - select yes or no',\n max: '{{#label}} must be {{#limit}} characters or less',\n min: '{{#label}} must be {{#limit}} characters or more',\n minMax: '{{#label}} must be between {{#min}} and {{#max}} characters',\n pattern: joi.expression(\n 'Enter a valid {{lowerFirst(#label)}}',\n opts\n ) as JoiExpression,\n format: joi.expression(\n 'Enter {{lowerFirst(#label)}} in the correct format',\n opts\n ) as JoiExpression,\n number: '{{#label}} must be a number',\n numberPrecision: '{{#label}} must have {{#limit}} or fewer decimal places',\n numberInteger: '{{#label}} must be a whole number',\n numberMin: '{{#label}} must be {{#limit}} or higher',\n numberMax: '{{#label}} must be {{#limit}} or lower',\n maxWords: '{{#label}} must be {{#limit}} words or fewer',\n\n // Nested fields use component title\n\n objectRequired: joi.expression('Enter {{#label}}', opts) as JoiExpression,\n objectMissing: joi.expression(\n '{{#title}} must include a {{lowerFirst(#label)}}',\n opts\n ) as JoiExpression,\n dateFormat: '{{#title}} must be a real date',\n dateMin: '{{#title}} must be the same as or after {{#limit}}',\n dateMax: '{{#title}} must be the same as or before {{#limit}}'\n}\n\nexport const messages: LanguageMessagesExt = {\n 'string.base': messageTemplate.required,\n 'string.min': messageTemplate.min,\n 'string.empty': messageTemplate.required,\n 'string.max': messageTemplate.max,\n 'string.email': messageTemplate.format,\n 'string.pattern.base': messageTemplate.pattern,\n 'string.maxWords': messageTemplate.maxWords,\n\n 'number.base': messageTemplate.number,\n 'number.precision': messageTemplate.numberPrecision,\n 'number.integer': messageTemplate.numberInteger,\n 'number.unsafe': messageTemplate.format,\n 'number.min': messageTemplate.numberMin,\n 'number.max': messageTemplate.numberMax,\n\n 'object.required': messageTemplate.objectRequired,\n 'object.and': messageTemplate.objectMissing,\n\n 'any.only': messageTemplate.selectRequired,\n 'any.required': messageTemplate.selectRequired,\n 'any.empty': messageTemplate.required,\n\n 'date.base': messageTemplate.dateFormat,\n 'date.format': messageTemplate.dateFormat,\n 'date.min': messageTemplate.dateMin,\n 'date.max': messageTemplate.dateMax\n}\n\nexport const messagesPre: LanguageMessages =\n messages as unknown as LanguageMessages\n\nexport const validationOptions: ValidationOptions = {\n abortEarly: false,\n messages: messagesPre,\n errors: {\n wrap: {\n array: false,\n label: false\n }\n }\n}\n"],"mappings":"AAAA;;AAEA,OAAOA,GAAG,MAMH,KAAK;AAEZ,SAASC,6BAA6B;AAEtC,MAAMC,IAAI,GAAG;EACXC,SAAS,EAAE;IACTC,UAAU,EAAEH;EACd;AACF,CAAqB;;AAErB;AACA;AACA;AACA,OAAO,MAAMI,eAA8C,GAAG;EAC5DC,mBAAmB,EAAEN,GAAG,CAACO,UAAU,CACjC,uFAAuF,EACvFL,IACF,CAAkB;EAClBM,QAAQ,EAAER,GAAG,CAACO,UAAU,CACtB,8BAA8B,EAC9BL,IACF,CAAkB;EAClBO,cAAc,EAAET,GAAG,CAACO,UAAU,CAC5B,+BAA+B,EAC/BL,IACF,CAAkB;EAClBQ,mBAAmB,EAAE,+BAA+B;EACpDC,GAAG,EAAE,kDAAkD;EACvDC,GAAG,EAAE,kDAAkD;EACvDC,MAAM,EAAE,6DAA6D;EACrEC,OAAO,EAAEd,GAAG,CAACO,UAAU,CACrB,sCAAsC,EACtCL,IACF,CAAkB;EAClBa,MAAM,EAAEf,GAAG,CAACO,UAAU,CACpB,oDAAoD,EACpDL,IACF,CAAkB;EAClBc,MAAM,EAAE,6BAA6B;EACrCC,eAAe,EAAE,yDAAyD;EAC1EC,aAAa,EAAE,mCAAmC;EAClDC,SAAS,EAAE,yCAAyC;EACpDC,SAAS,EAAE,wCAAwC;EACnDC,QAAQ,EAAE,8CAA8C;EAExD;;EAEAC,cAAc,EAAEtB,GAAG,CAACO,UAAU,CAAC,kBAAkB,EAAEL,IAAI,CAAkB;EACzEqB,aAAa,EAAEvB,GAAG,CAACO,UAAU,CAC3B,kDAAkD,EAClDL,IACF,CAAkB;EAClBsB,UAAU,EAAE,gCAAgC;EAC5CC,OAAO,EAAE,oDAAoD;EAC7DC,OAAO,EAAE;AACX,CAAC;AAED,OAAO,MAAMC,QAA6B,GAAG;EAC3C,aAAa,EAAEtB,eAAe,CAACG,QAAQ;EACvC,YAAY,EAAEH,eAAe,CAACO,GAAG;EACjC,cAAc,EAAEP,eAAe,CAACG,QAAQ;EACxC,YAAY,EAAEH,eAAe,CAACM,GAAG;EACjC,cAAc,EAAEN,eAAe,CAACU,MAAM;EACtC,qBAAqB,EAAEV,eAAe,CAACS,OAAO;EAC9C,iBAAiB,EAAET,eAAe,CAACgB,QAAQ;EAE3C,aAAa,EAAEhB,eAAe,CAACW,MAAM;EACrC,kBAAkB,EAAEX,eAAe,CAACY,eAAe;EACnD,gBAAgB,EAAEZ,eAAe,CAACa,aAAa;EAC/C,eAAe,EAAEb,eAAe,CAACU,MAAM;EACvC,YAAY,EAAEV,eAAe,CAACc,SAAS;EACvC,YAAY,EAAEd,eAAe,CAACe,SAAS;EAEvC,iBAAiB,EAAEf,eAAe,CAACiB,cAAc;EACjD,YAAY,EAAEjB,eAAe,CAACkB,aAAa;EAE3C,UAAU,EAAElB,eAAe,CAACI,cAAc;EAC1C,cAAc,EAAEJ,eAAe,CAACI,cAAc;EAC9C,WAAW,EAAEJ,eAAe,CAACG,QAAQ;EAErC,WAAW,EAAEH,eAAe,CAACmB,UAAU;EACvC,aAAa,EAAEnB,eAAe,CAACmB,UAAU;EACzC,UAAU,EAAEnB,eAAe,CAACoB,OAAO;EACnC,UAAU,EAAEpB,eAAe,CAACqB;AAC9B,CAAC;AAED,OAAO,MAAME,WAA6B,GACxCD,QAAuC;AAEzC,OAAO,MAAME,iBAAoC,GAAG;EAClDC,UAAU,EAAE,KAAK;EACjBH,QAAQ,EAAEC,WAAW;EACrBG,MAAM,EAAE;IACNC,IAAI,EAAE;MACJC,KAAK,EAAE,KAAK;MACZC,KAAK,EAAE;IACT;EACF;AACF,CAAC","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.js","names":[],"sources":["../../../src/typings/hapi/index.d.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"file":"index.d.js","names":[],"sources":["../../../src/typings/hapi/index.d.ts"],"sourcesContent":["import { type Plugin } from '@hapi/hapi'\nimport { type ServerYar, type Yar } from '@hapi/yar'\nimport { type Logger } from 'pino'\n\nimport {\n type COMPONENT_STATE_ERROR,\n type EXTERNAL_STATE_APPENDAGE,\n type EXTERNAL_STATE_PAYLOAD\n} from '~/src/server/constants.js'\nimport { type FormModel } from '~/src/server/plugins/engine/models/index.js'\nimport {\n type AnyFormRequest,\n type FormSubmissionError,\n type PluginOptions\n} from '~/src/server/plugins/engine/types.ts'\nimport { type CacheService } from '~/src/server/services/index.js'\n\ndeclare module '@hapi/yar' {\n interface YarFlashes {\n [EXTERNAL_STATE_APPENDAGE]: object\n [EXTERNAL_STATE_PAYLOAD]: object\n [COMPONENT_STATE_ERROR]: string\n [key: string]: { errors: FormSubmissionError[] }\n }\n}\n\ndeclare module '@hapi/hapi' {\n // Here we are decorating Hapi interface types with\n // props from plugins which doesn't export @types\n interface PluginProperties {\n crumb: {\n generate?: (request: AnyRequest) => string\n }\n 'forms-engine-plugin': {\n baseLayoutPath: string\n cacheService: CacheService\n viewContext?: (\n request: AnyFormRequest | null\n ) => Record<string, unknown> | Promise<Record<string, unknown>>\n saveAndExit?: PluginOptions['saveAndExit']\n baseUrl: string\n }\n }\n\n interface Request {\n logger: Logger\n yar: Yar\n }\n\n interface RequestApplicationState {\n model?: FormModel\n }\n\n interface Server {\n logger: Logger\n yar: ServerYar\n }\n\n interface ServerApplicationState {\n model?: FormModel\n models: Map<string, { model: FormModel; updatedAt: Date }>\n }\n}\n\ndeclare module 'blankie' {\n declare const blankie: {\n plugin: Plugin<Record<string, boolean | string | string[]>>\n }\n\n export = blankie\n}\n\ndeclare module 'blipp' {\n declare const blipp: {\n plugin: Plugin\n }\n\n export = blipp\n}\n\ndeclare module 'hapi-pulse' {\n declare const hapiPulse: {\n plugin: Plugin<{\n timeout: number\n }>\n }\n\n export = hapiPulse\n}\n"],"mappings":"","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@defra/forms-engine-plugin",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.60",
|
|
4
4
|
"description": "Defra forms engine",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -42,12 +42,17 @@
|
|
|
42
42
|
"dev:debug": "concurrently \"npm run client:watch\" \"npm run server:watch:debug\" --kill-others --names \"client,server\" --prefix-colors \"red.dim,blue.dim\"",
|
|
43
43
|
"format": "npm run format:check -- --write",
|
|
44
44
|
"format:check": "prettier --cache --cache-location .cache/prettier --cache-strategy content --check \"**/*.{cjs,js,json,md,mjs,scss,ts}\"",
|
|
45
|
+
"docs:dev": "BROWSERSLIST_ENV=javascripts docusaurus start --host 0.0.0.0",
|
|
46
|
+
"docs:build": "BROWSERSLIST_ENV=javascripts docusaurus build",
|
|
47
|
+
"docs:build:all": "node scripts/generate-schema-docs.js && npm run docs:build",
|
|
48
|
+
"docs:serve": "docusaurus serve --host 0.0.0.0",
|
|
49
|
+
"docs:clear": "docusaurus clear",
|
|
45
50
|
"generate-schema-docs": "node scripts/generate-schema-docs.js",
|
|
46
51
|
"postinstall": "npm run setup:husky",
|
|
47
52
|
"lint": "npm run lint:editorconfig && npm run lint:js && npm run lint:types",
|
|
48
53
|
"lint:editorconfig": "editorconfig-checker",
|
|
49
54
|
"lint:fix": "npm run lint:js -- --fix",
|
|
50
|
-
"lint:js": "eslint --cache --cache-location .cache/eslint --cache-strategy content --color
|
|
55
|
+
"lint:js": "eslint --cache --cache-location .cache/eslint --cache-strategy content --color .",
|
|
51
56
|
"lint:scss": "stylelint --cache --cache-location .cache/stylelint --cache-strategy content --color --ignore-path .gitignore --max-warnings 0 \"**/*.scss\"",
|
|
52
57
|
"lint:types": "tsc --noEmit",
|
|
53
58
|
"test": "jest --color --coverage --verbose",
|
|
@@ -64,6 +69,12 @@
|
|
|
64
69
|
"type": "git",
|
|
65
70
|
"url": "git+https://github.com/DEFRA/forms-engine-plugin.git"
|
|
66
71
|
},
|
|
72
|
+
"overrides": {
|
|
73
|
+
"serve-handler": {
|
|
74
|
+
"minimatch": "3.1.5"
|
|
75
|
+
},
|
|
76
|
+
"serialize-javascript": ">=7.0.3"
|
|
77
|
+
},
|
|
67
78
|
"engines": {
|
|
68
79
|
"node": ">=22.11.0 <25.0.0",
|
|
69
80
|
"npm": ">=10.9.0 <11.6.4"
|
|
@@ -124,7 +135,12 @@
|
|
|
124
135
|
"@babel/plugin-syntax-import-attributes": "^7.27.1",
|
|
125
136
|
"@babel/preset-env": "^7.28.5",
|
|
126
137
|
"@babel/preset-typescript": "^7.28.5",
|
|
138
|
+
"@defra/docusaurus-theme-govuk": "^0.0.12-alpha",
|
|
139
|
+
"@docusaurus/core": "^3.9.2",
|
|
140
|
+
"@docusaurus/plugin-content-docs": "^3.9.2",
|
|
141
|
+
"@easyops-cn/docusaurus-search-local": "^0.55.0",
|
|
127
142
|
"@hapi/basic": "^7.0.2",
|
|
143
|
+
"@mdx-js/react": "^3.1.1",
|
|
128
144
|
"@testing-library/dom": "^10.4.1",
|
|
129
145
|
"@testing-library/jest-dom": "^6.9.1",
|
|
130
146
|
"@types/atob": "^2.1.4",
|
|
@@ -148,8 +164,6 @@
|
|
|
148
164
|
"@types/url-parse": "^1.4.11",
|
|
149
165
|
"@types/webpack-assets-manifest": "^5.1.4",
|
|
150
166
|
"@types/wreck": "^14.0.5",
|
|
151
|
-
"@typescript-eslint/eslint-plugin": "^8.46.4",
|
|
152
|
-
"@typescript-eslint/parser": "^8.46.4",
|
|
153
167
|
"autoprefixer": "^10.4.22",
|
|
154
168
|
"babel-loader": "^10.0.0",
|
|
155
169
|
"babel-plugin-module-resolver": "^5.0.2",
|
|
@@ -163,15 +177,13 @@
|
|
|
163
177
|
"cssnano": "^7.1.2",
|
|
164
178
|
"cssnano-preset-default": "^7.0.10",
|
|
165
179
|
"editorconfig-checker": "^6.1.1",
|
|
166
|
-
"eslint": "^
|
|
167
|
-
"eslint-config-prettier": "^
|
|
168
|
-
"eslint-config-standard": "^17.1.0",
|
|
169
|
-
"eslint-import-resolver-typescript": "^3.10.1",
|
|
170
|
-
"eslint-plugin-import": "^2.32.0",
|
|
180
|
+
"eslint": "^9.39.3",
|
|
181
|
+
"eslint-config-prettier": "^10.1.8",
|
|
171
182
|
"eslint-plugin-jest": "^28.14.0",
|
|
172
183
|
"eslint-plugin-jsdoc": "^50.8.0",
|
|
173
|
-
"
|
|
174
|
-
"
|
|
184
|
+
"globals": "^17.3.0",
|
|
185
|
+
"neostandard": "^0.12.2",
|
|
186
|
+
"typescript-eslint": "^8.56.1",
|
|
175
187
|
"global-jsdom": "^26.0.0",
|
|
176
188
|
"husky": "^9.1.7",
|
|
177
189
|
"jest": "^30.2.0",
|
|
@@ -185,6 +197,8 @@
|
|
|
185
197
|
"postcss-loader": "^8.2.0",
|
|
186
198
|
"postcss-scss": "^4.0.9",
|
|
187
199
|
"prettier": "^3.6.2",
|
|
200
|
+
"react": "^19.2.4",
|
|
201
|
+
"react-dom": "^19.2.4",
|
|
188
202
|
"sass-embedded": "^1.93.3",
|
|
189
203
|
"sass-loader": "^16.0.6",
|
|
190
204
|
"source-map-loader": "^5.0.0",
|
|
@@ -23,10 +23,8 @@ export class AutocompleteField extends SelectField {
|
|
|
23
23
|
const messages = options.customValidationMessages
|
|
24
24
|
|
|
25
25
|
formSchema = formSchema.messages({
|
|
26
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
27
26
|
'any.only':
|
|
28
27
|
messages?.['any.only'] ?? (messageTemplate.required as string),
|
|
29
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
30
28
|
'any.required':
|
|
31
29
|
messages?.['any.required'] ?? (messageTemplate.required as string)
|
|
32
30
|
})
|
|
@@ -42,9 +42,7 @@ export class DatePartsField extends FormComponent {
|
|
|
42
42
|
const isRequired = options.required !== false
|
|
43
43
|
|
|
44
44
|
const customValidationMessages = convertToLanguageMessages({
|
|
45
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
46
45
|
'any.required': messageTemplate.objectMissing,
|
|
47
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
48
46
|
'number.base': messageTemplate.objectMissing,
|
|
49
47
|
'number.precision': messageTemplate.dateFormat,
|
|
50
48
|
'number.integer': messageTemplate.dateFormat,
|
|
@@ -174,7 +174,6 @@ export class FormComponent extends ComponentBase {
|
|
|
174
174
|
|
|
175
175
|
getDisplayStringFromState(state: FormSubmissionState): string {
|
|
176
176
|
const value = this.getFormValueFromState(state)
|
|
177
|
-
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
178
177
|
return this.getDisplayStringFromFormValue(value)
|
|
179
178
|
}
|
|
180
179
|
|
|
@@ -48,9 +48,7 @@ export class MonthYearField extends FormComponent {
|
|
|
48
48
|
|
|
49
49
|
const customValidationMessages: LanguageMessages =
|
|
50
50
|
convertToLanguageMessages({
|
|
51
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
52
51
|
'any.required': messageTemplate.objectMissing,
|
|
53
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
54
52
|
'number.base': messageTemplate.objectMissing,
|
|
55
53
|
'number.precision': messageTemplate.dateFormat,
|
|
56
54
|
'number.integer': messageTemplate.dateFormat,
|
|
@@ -41,7 +41,6 @@ export class NumberField extends FormComponent {
|
|
|
41
41
|
const messages = options.customValidationMessages
|
|
42
42
|
|
|
43
43
|
formSchema = formSchema.empty('').messages({
|
|
44
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
45
44
|
'any.required':
|
|
46
45
|
messages?.['any.required'] ?? (messageTemplate.required as string)
|
|
47
46
|
})
|