@defra/forms-engine-plugin 5.0.0-alpha.27 → 5.0.0-alpha.29
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/37c964ca545c240f010a.mjs +2 -0
- package/.public/37c964ca545c240f010a.mjs.LICENSE.txt +4 -0
- package/.public/assets-manifest.json +3 -0
- package/.public/javascripts/shared.min.js +1 -1
- package/.public/javascripts/shared.min.js.LICENSE.txt +2 -0
- package/.public/javascripts/shared.min.js.map +1 -1
- package/.public/javascripts/vendor/@defra.min.js +1 -1
- package/.public/javascripts/vendor/@defra.min.js.map +1 -1
- package/.public/javascripts/vendor/maplibre-gl.min.js +1 -1
- package/.public/javascripts/vendor/maplibre-gl.min.js.LICENSE.txt +3 -3
- package/.public/javascripts/vendor/maplibre-gl.min.js.map +1 -1
- package/.public/stylesheets/application.min.css +1 -1
- package/.public/stylesheets/application.min.css.map +1 -1
- package/.server/client/javascripts/geospatial-map.js +3 -3
- package/.server/client/javascripts/geospatial-map.js.map +1 -1
- package/.server/client/javascripts/location-map.js +2 -2
- package/.server/client/javascripts/location-map.js.map +1 -1
- package/.server/client/javascripts/map.d.ts +5 -2
- package/.server/client/javascripts/map.js +17 -5
- package/.server/client/javascripts/map.js.map +1 -1
- package/.server/server/plugins/engine/components/AutocompleteField.d.ts +1 -2
- package/.server/server/plugins/engine/components/AutocompleteField.js +9 -4
- package/.server/server/plugins/engine/components/AutocompleteField.js.map +1 -1
- package/.server/server/plugins/engine/components/CheckboxesField.d.ts +2 -2
- package/.server/server/plugins/engine/components/CheckboxesField.js.map +1 -1
- package/.server/server/plugins/engine/components/ComponentBase.d.ts +1 -1
- package/.server/server/plugins/engine/components/ComponentBase.js.map +1 -1
- package/.server/server/plugins/engine/components/DeclarationField.d.ts +2 -2
- package/.server/server/plugins/engine/components/DeclarationField.js.map +1 -1
- package/.server/server/plugins/engine/components/FileUploadField.d.ts +2 -2
- package/.server/server/plugins/engine/components/FileUploadField.js.map +1 -1
- package/.server/server/plugins/engine/components/ListFormComponent.d.ts +2 -2
- package/.server/server/plugins/engine/components/ListFormComponent.js.map +1 -1
- package/.server/server/plugins/engine/components/LocationFieldBase.js +11 -6
- package/.server/server/plugins/engine/components/LocationFieldBase.js.map +1 -1
- package/.server/server/plugins/engine/components/NumberField.js +14 -8
- package/.server/server/plugins/engine/components/NumberField.js.map +1 -1
- package/.server/server/plugins/engine/components/YesNoField.d.ts +1 -3
- package/.server/server/plugins/engine/components/YesNoField.js +9 -4
- package/.server/server/plugins/engine/components/YesNoField.js.map +1 -1
- package/.server/server/plugins/engine/components/helpers/index.d.ts +14 -1
- package/.server/server/plugins/engine/components/helpers/index.js +32 -0
- package/.server/server/plugins/engine/components/helpers/index.js.map +1 -1
- package/package.json +6 -6
- package/src/client/javascripts/geospatial-map.js +3 -3
- package/src/client/javascripts/location-map.js +2 -2
- package/src/client/javascripts/map.js +19 -8
- package/src/server/plugins/engine/components/AutocompleteField.ts +12 -5
- package/src/server/plugins/engine/components/CheckboxesField.ts +3 -3
- package/src/server/plugins/engine/components/ComponentBase.ts +4 -4
- package/src/server/plugins/engine/components/DeclarationField.ts +3 -4
- package/src/server/plugins/engine/components/FileUploadField.ts +2 -2
- package/src/server/plugins/engine/components/ListFormComponent.ts +4 -4
- package/src/server/plugins/engine/components/LocationFieldBase.ts +18 -8
- package/src/server/plugins/engine/components/NumberField.ts +17 -13
- package/src/server/plugins/engine/components/YesNoField.ts +14 -4
- package/src/server/plugins/engine/components/helpers/index.ts +45 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileUploadField.js","names":["Boom","joi","EN_GB","FormComponent","isUploadState","t","tPlugin","InvalidComponentStateError","messageTemplate","FileStatus","UploadStatus","render","resolveLanguage","uploadIdSchema","string","uuid","required","fileSchema","object","fileId","filename","contentLength","number","tempFileSchema","append","fileStatus","valid","complete","rejected","pending","errorMessage","optional","errorCode","errorParams","any","formFileSchema","metadataSchema","keys","retrievalKey","email","tempStatusSchema","uploadStatus","ready","metadata","form","file","array","items","single","numberOfRejectedFiles","formStatusSchema","itemSchema","uploadId","tempItemSchema","status","formItemSchema","FileUploadField","constructor","def","props","options","schema","formSchema","label","limits","length","max","min","messages","buildErrorMessages","stateSchema","default","allow","getFormValueFromState","state","name","getFormValue","value","isValue","undefined","getDisplayStringFromFormValue","files","translator","count","getDisplayStringFromState","getContextValueFromFormValue","map","getContextValueFromState","getViewModel","context","errors","isForceAccess","page","viewModel","attributes","id","filtered","filter","rows","item","index","tag","classes","text","valueHtml","view","params","trim","keyHtml","path","href","getHref","push","visuallyHiddenText","key","html","actions","accept","allowsMultiple","summaryList","multiple","upload","getValidationMessagesOverride","language","getAllPossibleErrors","onSubmit","request","model","createTranslator","notificationEmail","Error","app","services","formSubmissionService","values","initiatedRetrievalKey","persistFiles","error","isBoom","output","statusCode","baseErrors","type","template","selectRequired","advancedSettingsErrors"],"sources":["../../../../../src/server/plugins/engine/components/FileUploadField.ts"],"sourcesContent":["import {\n type FileUploadFieldComponent,\n type FormMetadata\n} from '@defra/forms-model'\nimport Boom from '@hapi/boom'\nimport joi, { type ArraySchema } from 'joi'\n\nimport { EN_GB } from '~/src/server/constants.js'\nimport {\n FormComponent,\n isUploadState\n} from '~/src/server/plugins/engine/components/FormComponent.js'\nimport { type RenderContext } from '~/src/server/plugins/engine/components/types.js'\nimport { t as tPlugin } from '~/src/server/plugins/engine/i18n/index.js'\nimport { type Translator } from '~/src/server/plugins/engine/i18n/types.js'\nimport { InvalidComponentStateError } from '~/src/server/plugins/engine/pageControllers/errors.js'\nimport { messageTemplate } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'\nimport {\n FileStatus,\n UploadStatus,\n type ErrorMessageTemplateList,\n type FileState,\n type FileUpload,\n type FileUploadMetadata,\n type FormContext,\n type FormState,\n type FormStateValue,\n type FormSubmissionState,\n type SummaryList,\n type SummaryListAction,\n type SummaryListRow,\n type UploadState,\n type UploadStatusFileResponse,\n type UploadStatusResponse\n} from '~/src/server/plugins/engine/types.js'\nimport { render } from '~/src/server/plugins/nunjucks/index.js'\nimport { type FormRequestPayload } from '~/src/server/routes/types.js'\nimport { resolveLanguage } from '~/src/server/utils/utils.js'\n\nexport const uploadIdSchema = joi.string().uuid().required()\n\nexport const fileSchema = joi\n .object<FileUpload>({\n fileId: joi.string().uuid().required(),\n filename: joi.string().required(),\n contentLength: joi.number().required()\n })\n .required()\n\nexport const tempFileSchema = fileSchema.append({\n fileStatus: joi\n .string()\n .valid(FileStatus.complete, FileStatus.rejected, FileStatus.pending)\n .required(),\n errorMessage: joi.string().optional(),\n errorCode: joi.string().optional(),\n errorParams: joi.any().optional()\n})\n\nexport const formFileSchema = fileSchema.append({\n fileStatus: joi.string().valid(FileStatus.complete).required()\n})\n\nexport const metadataSchema = joi\n .object<FileUploadMetadata>()\n .keys({\n retrievalKey: joi.string().email().required()\n })\n .required()\n\nexport const tempStatusSchema = joi\n .object<UploadStatusFileResponse>({\n uploadStatus: joi\n .string()\n .valid(UploadStatus.ready, UploadStatus.pending)\n .required(),\n metadata: metadataSchema,\n form: joi\n .object()\n .required()\n .keys({\n file: joi.array().items(tempFileSchema).single().required()\n }),\n numberOfRejectedFiles: joi.number().optional()\n })\n .required()\n\nexport const formStatusSchema = joi\n .object<UploadStatusResponse>({\n uploadStatus: joi.string().valid(UploadStatus.ready).required(),\n metadata: metadataSchema,\n form: joi.object().required().keys({\n file: formFileSchema\n }),\n numberOfRejectedFiles: joi.number().required()\n })\n .required()\n\nexport const itemSchema = joi.object<FileState>({\n uploadId: uploadIdSchema\n})\n\nexport const tempItemSchema = itemSchema.append({\n status: tempStatusSchema\n})\n\nexport const formItemSchema = itemSchema.append({\n status: formStatusSchema\n})\n\nexport class FileUploadField extends FormComponent {\n declare options: FileUploadFieldComponent['options']\n declare schema: FileUploadFieldComponent['schema']\n declare formSchema: ArraySchema<FileState>\n declare stateSchema: ArraySchema<FileState>\n declare limits: { min?: number; max?: number; length?: number }\n\n constructor(\n def: FileUploadFieldComponent,\n props: ConstructorParameters<typeof FormComponent>[1]\n ) {\n super(def, props)\n\n const { options, schema } = def\n\n let formSchema = joi\n .array<FileState>()\n .label(this.label)\n .single()\n .required()\n\n if (options.required === false) {\n formSchema = formSchema.optional()\n }\n\n const limits: { min?: number; max?: number; length?: number } = {}\n\n if (typeof schema.length !== 'number') {\n if (typeof schema.max === 'number') {\n formSchema = formSchema.max(schema.max)\n limits.max = schema.max\n }\n\n if (typeof schema.min === 'number') {\n formSchema = formSchema.min(schema.min)\n limits.min = schema.min\n } else if (options.required !== false) {\n formSchema = formSchema.min(1)\n limits.min = 1\n }\n } else {\n formSchema = formSchema.length(schema.length)\n limits.length = schema.length\n }\n\n this.limits = limits\n\n formSchema = formSchema.messages(\n FileUploadField.buildErrorMessages(EN_GB, limits)\n )\n\n this.formSchema = formSchema.items(formItemSchema)\n this.stateSchema = formSchema\n .items(formItemSchema)\n .default(null)\n .allow(null)\n\n this.options = options\n this.schema = schema\n }\n\n getFormValueFromState(state: FormSubmissionState) {\n const { name } = this\n return this.getFormValue(state[name])\n }\n\n getFormValue(value?: FormStateValue | FormState) {\n return this.isValue(value) ? value : undefined\n }\n\n getDisplayStringFromFormValue(\n files: FileState[] | undefined,\n translator: Translator\n ): string {\n if (!files?.length) {\n return ''\n }\n\n return translator.t('pages.summary.fileUpload', {\n count: files.length\n })\n }\n\n getDisplayStringFromState(\n state: FormSubmissionState,\n translator: Translator\n ) {\n const files = this.getFormValueFromState(state)\n\n return this.getDisplayStringFromFormValue(files, translator)\n }\n\n getContextValueFromFormValue(\n files: UploadState | undefined\n ): string[] | null {\n return files?.map(({ status }) => status.form.file.fileId) ?? null\n }\n\n getContextValueFromState(state: FormSubmissionState) {\n const files = this.getFormValueFromState(state)\n return this.getContextValueFromFormValue(files)\n }\n\n getViewModel(context: RenderContext) {\n const { errors, isForceAccess = false } = context\n const { t } = context.translator\n const { options, page, schema } = this\n\n const viewModel = super.getViewModel(context)\n const { attributes, id, value } = viewModel\n\n const files = this.getFormValue(value) ?? []\n const filtered = files.filter(\n (file) => file.status.form.file.fileStatus === FileStatus.complete\n )\n const count = filtered.length\n\n const rows: SummaryListRow[] = filtered.map((item, index) => {\n const { status } = item\n const { form } = status\n const { file } = form\n\n const tag = {\n classes: 'govuk-tag--green',\n text: t('components.fileUploadField.uploaded')\n }\n\n const valueHtml = render\n .view('components/fileuploadfield-value.html', {\n context: { params: { tag } }\n })\n .trim()\n\n const keyHtml = render\n .view('components/fileuploadfield-key.html', {\n context: {\n params: {\n name: file.filename,\n errorMessage: errors && file.errorMessage\n }\n }\n })\n .trim()\n\n const items: SummaryListAction[] = []\n\n // Remove summary list actions from previews\n if (!isForceAccess) {\n const path = `/${file.fileId}/confirm-delete`\n const href = page?.getHref(`${page.path}${path}`) ?? '#'\n\n items.push({\n href,\n text: t('pages.fileUpload.remove'),\n classes: 'govuk-link--no-visited-state',\n attributes: { id: `${id}__${index}` },\n visuallyHiddenText: file.filename\n })\n }\n\n return {\n key: {\n html: keyHtml\n },\n value: {\n html: valueHtml\n },\n actions: {\n items\n }\n } satisfies SummaryListRow\n })\n\n // Set up the `accept` attribute\n if ('accept' in options && options.accept) {\n attributes.accept = options.accept\n }\n\n // Allow multiple file selection when schema permits more than 1 file\n const allowsMultiple = schema.max !== 1 && schema.length !== 1\n\n const summaryList: SummaryList = {\n classes: 'govuk-summary-list--long-key',\n rows\n }\n\n return {\n ...viewModel,\n\n // File input can't have a initial value\n value: '',\n\n // Override the component name we send to CDP\n name: 'file',\n\n // Enable multi-file selection in the file picker\n ...(allowsMultiple && { multiple: true }),\n\n upload: {\n count,\n summaryList\n }\n }\n }\n\n isValue(value?: FormStateValue | FormState): value is UploadState {\n return isUploadState(value)\n }\n\n getValidationMessagesOverride(translator: Translator) {\n const { language } = translator\n return {\n [this.name]: FileUploadField.buildErrorMessages(language, this.limits)\n }\n }\n\n /**\n * For error preview page that shows all possible errors on a component\n */\n getAllPossibleErrors(): ErrorMessageTemplateList {\n return FileUploadField.getAllPossibleErrors()\n }\n\n async onSubmit(\n request: FormRequestPayload,\n metadata: FormMetadata,\n context: FormContext\n ) {\n const language = resolveLanguage(request)\n const { t } = this.model.createTranslator(language)\n\n const notificationEmail = metadata.notificationEmail\n\n if (!notificationEmail) {\n // this should not happen because notificationEmail is checked further up\n // the chain in SummaryPageController before submitForm is called.\n throw new Error('Unexpected missing notificationEmail in metadata')\n }\n\n if (!request.app.model?.services.formSubmissionService) {\n throw new Error('No form submission service available in app model')\n }\n\n const { formSubmissionService } = request.app.model.services\n const values = this.getFormValueFromState(context.state) ?? []\n\n const files = values.map((value) => ({\n fileId: value.status.form.file.fileId,\n initiatedRetrievalKey: value.status.metadata.retrievalKey\n }))\n\n if (!files.length) {\n return\n }\n\n try {\n await formSubmissionService.persistFiles(files, notificationEmail)\n } catch (error) {\n if (\n Boom.isBoom(error) &&\n (error.output.statusCode === 403 || // Forbidden - retrieval key invalid\n error.output.statusCode === 404 || // Not Found - file not found\n error.output.statusCode === 410) // Gone - file expired (took to long to submit, etc)\n ) {\n // Failed to persist files. We can't recover from this, the only real way we can recover the submissions is\n // by resetting the problematic components and letting the user re-try.\n // Scenarios: file missing from S3, invalid retrieval key (timing problem), etc.\n throw new InvalidComponentStateError(\n this,\n t('components.fileUploadField.uploadFailed')\n )\n }\n\n throw error\n }\n }\n\n /**\n * Static version of getAllPossibleErrors that doesn't require a component instance.\n */\n static getAllPossibleErrors(): ErrorMessageTemplateList {\n return {\n baseErrors: [\n { type: 'selectRequired', template: messageTemplate.selectRequired },\n {\n type: 'filesMimes',\n template: 'The selected file must be a {{#limit}}'\n },\n {\n type: 'filesSize',\n template: 'The selected file must be smaller than 100MB'\n },\n { type: 'filesEmpty', template: 'The selected file is empty' },\n { type: 'filesVirus', template: 'The selected file contains a virus' },\n {\n type: 'filesPartial',\n template: 'The selected file has not fully uploaded'\n },\n {\n type: 'filesError',\n template: 'The selected file could not be uploaded – try again'\n }\n ],\n advancedSettingsErrors: [\n {\n type: 'filesMin',\n template: 'You must upload {{#limit}} files or more'\n },\n {\n type: 'filesMax',\n template: 'You can only upload {{#limit}} files or less'\n },\n {\n type: 'filesExact',\n template: 'You must upload exactly {{#limit}} files'\n }\n ]\n }\n }\n\n static buildErrorMessages(\n language: string,\n limits: { min?: number; max?: number; length?: number } = {}\n ) {\n return {\n 'array.min': tPlugin('validation.filesMin', language, {\n count: limits.min ?? 1\n }),\n 'array.max': tPlugin('validation.filesMax', language, {\n count: limits.max ?? 1\n }),\n 'array.length': tPlugin('validation.filesLength', language, {\n count: limits.length ?? 1\n })\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"FileUploadField.js","names":["Boom","joi","EN_GB","FormComponent","isUploadState","t","tPlugin","InvalidComponentStateError","messageTemplate","FileStatus","UploadStatus","render","resolveLanguage","uploadIdSchema","string","uuid","required","fileSchema","object","fileId","filename","contentLength","number","tempFileSchema","append","fileStatus","valid","complete","rejected","pending","errorMessage","optional","errorCode","errorParams","any","formFileSchema","metadataSchema","keys","retrievalKey","email","tempStatusSchema","uploadStatus","ready","metadata","form","file","array","items","single","numberOfRejectedFiles","formStatusSchema","itemSchema","uploadId","tempItemSchema","status","formItemSchema","FileUploadField","constructor","def","props","options","schema","formSchema","label","limits","length","max","min","messages","buildErrorMessages","stateSchema","default","allow","getFormValueFromState","state","name","getFormValue","value","isValue","undefined","getDisplayStringFromFormValue","files","translator","count","getDisplayStringFromState","getContextValueFromFormValue","map","getContextValueFromState","getViewModel","context","errors","isForceAccess","page","viewModel","attributes","id","filtered","filter","rows","item","index","tag","classes","text","valueHtml","view","params","trim","keyHtml","path","href","getHref","push","visuallyHiddenText","key","html","actions","accept","allowsMultiple","summaryList","multiple","upload","getValidationMessagesOverride","language","getAllPossibleErrors","onSubmit","request","model","createTranslator","notificationEmail","Error","app","services","formSubmissionService","values","initiatedRetrievalKey","persistFiles","error","isBoom","output","statusCode","baseErrors","type","template","selectRequired","advancedSettingsErrors"],"sources":["../../../../../src/server/plugins/engine/components/FileUploadField.ts"],"sourcesContent":["import {\n type FileUploadFieldComponent,\n type FormMetadata\n} from '@defra/forms-model'\nimport Boom from '@hapi/boom'\nimport joi, { type ArraySchema } from 'joi'\n\nimport { EN_GB } from '~/src/server/constants.js'\nimport {\n FormComponent,\n isUploadState\n} from '~/src/server/plugins/engine/components/FormComponent.js'\nimport { type RenderContext } from '~/src/server/plugins/engine/components/types.js'\nimport { t as tPlugin } from '~/src/server/plugins/engine/i18n/index.js'\nimport { type Translator } from '~/src/server/plugins/engine/i18n/types.js'\nimport { InvalidComponentStateError } from '~/src/server/plugins/engine/pageControllers/errors.js'\nimport { messageTemplate } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'\nimport {\n FileStatus,\n UploadStatus,\n type ErrorMessageTemplateList,\n type FileState,\n type FileUpload,\n type FileUploadMetadata,\n type FormContext,\n type FormState,\n type FormStateValue,\n type FormSubmissionState,\n type SummaryList,\n type SummaryListAction,\n type SummaryListRow,\n type UploadState,\n type UploadStatusFileResponse,\n type UploadStatusResponse\n} from '~/src/server/plugins/engine/types.js'\nimport { render } from '~/src/server/plugins/nunjucks/index.js'\nimport { type FormRequestPayload } from '~/src/server/routes/types.js'\nimport { resolveLanguage } from '~/src/server/utils/utils.js'\n\nexport const uploadIdSchema = joi.string().uuid().required()\n\nexport const fileSchema = joi\n .object<FileUpload>({\n fileId: joi.string().uuid().required(),\n filename: joi.string().required(),\n contentLength: joi.number().required()\n })\n .required()\n\nexport const tempFileSchema = fileSchema.append({\n fileStatus: joi\n .string()\n .valid(FileStatus.complete, FileStatus.rejected, FileStatus.pending)\n .required(),\n errorMessage: joi.string().optional(),\n errorCode: joi.string().optional(),\n errorParams: joi.any().optional()\n})\n\nexport const formFileSchema = fileSchema.append({\n fileStatus: joi.string().valid(FileStatus.complete).required()\n})\n\nexport const metadataSchema = joi\n .object<FileUploadMetadata>()\n .keys({\n retrievalKey: joi.string().email().required()\n })\n .required()\n\nexport const tempStatusSchema = joi\n .object<UploadStatusFileResponse>({\n uploadStatus: joi\n .string()\n .valid(UploadStatus.ready, UploadStatus.pending)\n .required(),\n metadata: metadataSchema,\n form: joi\n .object()\n .required()\n .keys({\n file: joi.array().items(tempFileSchema).single().required()\n }),\n numberOfRejectedFiles: joi.number().optional()\n })\n .required()\n\nexport const formStatusSchema = joi\n .object<UploadStatusResponse>({\n uploadStatus: joi.string().valid(UploadStatus.ready).required(),\n metadata: metadataSchema,\n form: joi.object().required().keys({\n file: formFileSchema\n }),\n numberOfRejectedFiles: joi.number().required()\n })\n .required()\n\nexport const itemSchema = joi.object<FileState>({\n uploadId: uploadIdSchema\n})\n\nexport const tempItemSchema = itemSchema.append({\n status: tempStatusSchema\n})\n\nexport const formItemSchema = itemSchema.append({\n status: formStatusSchema\n})\n\nexport class FileUploadField extends FormComponent {\n declare options: FileUploadFieldComponent['options']\n declare schema: FileUploadFieldComponent['schema']\n declare formSchema: ArraySchema<FileState[]>\n declare stateSchema: ArraySchema<FileState[]>\n declare limits: { min?: number; max?: number; length?: number }\n\n constructor(\n def: FileUploadFieldComponent,\n props: ConstructorParameters<typeof FormComponent>[1]\n ) {\n super(def, props)\n\n const { options, schema } = def\n\n let formSchema = joi\n .array<FileState>()\n .label(this.label)\n .single()\n .required()\n\n if (options.required === false) {\n formSchema = formSchema.optional()\n }\n\n const limits: { min?: number; max?: number; length?: number } = {}\n\n if (typeof schema.length !== 'number') {\n if (typeof schema.max === 'number') {\n formSchema = formSchema.max(schema.max)\n limits.max = schema.max\n }\n\n if (typeof schema.min === 'number') {\n formSchema = formSchema.min(schema.min)\n limits.min = schema.min\n } else if (options.required !== false) {\n formSchema = formSchema.min(1)\n limits.min = 1\n }\n } else {\n formSchema = formSchema.length(schema.length)\n limits.length = schema.length\n }\n\n this.limits = limits\n\n formSchema = formSchema.messages(\n FileUploadField.buildErrorMessages(EN_GB, limits)\n )\n\n this.formSchema = formSchema.items(formItemSchema)\n this.stateSchema = formSchema\n .items(formItemSchema)\n .default(null)\n .allow(null)\n\n this.options = options\n this.schema = schema\n }\n\n getFormValueFromState(state: FormSubmissionState) {\n const { name } = this\n return this.getFormValue(state[name])\n }\n\n getFormValue(value?: FormStateValue | FormState) {\n return this.isValue(value) ? value : undefined\n }\n\n getDisplayStringFromFormValue(\n files: FileState[] | undefined,\n translator: Translator\n ): string {\n if (!files?.length) {\n return ''\n }\n\n return translator.t('pages.summary.fileUpload', {\n count: files.length\n })\n }\n\n getDisplayStringFromState(\n state: FormSubmissionState,\n translator: Translator\n ) {\n const files = this.getFormValueFromState(state)\n\n return this.getDisplayStringFromFormValue(files, translator)\n }\n\n getContextValueFromFormValue(\n files: UploadState | undefined\n ): string[] | null {\n return files?.map(({ status }) => status.form.file.fileId) ?? null\n }\n\n getContextValueFromState(state: FormSubmissionState) {\n const files = this.getFormValueFromState(state)\n return this.getContextValueFromFormValue(files)\n }\n\n getViewModel(context: RenderContext) {\n const { errors, isForceAccess = false } = context\n const { t } = context.translator\n const { options, page, schema } = this\n\n const viewModel = super.getViewModel(context)\n const { attributes, id, value } = viewModel\n\n const files = this.getFormValue(value) ?? []\n const filtered = files.filter(\n (file) => file.status.form.file.fileStatus === FileStatus.complete\n )\n const count = filtered.length\n\n const rows: SummaryListRow[] = filtered.map((item, index) => {\n const { status } = item\n const { form } = status\n const { file } = form\n\n const tag = {\n classes: 'govuk-tag--green',\n text: t('components.fileUploadField.uploaded')\n }\n\n const valueHtml = render\n .view('components/fileuploadfield-value.html', {\n context: { params: { tag } }\n })\n .trim()\n\n const keyHtml = render\n .view('components/fileuploadfield-key.html', {\n context: {\n params: {\n name: file.filename,\n errorMessage: errors && file.errorMessage\n }\n }\n })\n .trim()\n\n const items: SummaryListAction[] = []\n\n // Remove summary list actions from previews\n if (!isForceAccess) {\n const path = `/${file.fileId}/confirm-delete`\n const href = page?.getHref(`${page.path}${path}`) ?? '#'\n\n items.push({\n href,\n text: t('pages.fileUpload.remove'),\n classes: 'govuk-link--no-visited-state',\n attributes: { id: `${id}__${index}` },\n visuallyHiddenText: file.filename\n })\n }\n\n return {\n key: {\n html: keyHtml\n },\n value: {\n html: valueHtml\n },\n actions: {\n items\n }\n } satisfies SummaryListRow\n })\n\n // Set up the `accept` attribute\n if ('accept' in options && options.accept) {\n attributes.accept = options.accept\n }\n\n // Allow multiple file selection when schema permits more than 1 file\n const allowsMultiple = schema.max !== 1 && schema.length !== 1\n\n const summaryList: SummaryList = {\n classes: 'govuk-summary-list--long-key',\n rows\n }\n\n return {\n ...viewModel,\n\n // File input can't have a initial value\n value: '',\n\n // Override the component name we send to CDP\n name: 'file',\n\n // Enable multi-file selection in the file picker\n ...(allowsMultiple && { multiple: true }),\n\n upload: {\n count,\n summaryList\n }\n }\n }\n\n isValue(value?: FormStateValue | FormState): value is UploadState {\n return isUploadState(value)\n }\n\n getValidationMessagesOverride(translator: Translator) {\n const { language } = translator\n return {\n [this.name]: FileUploadField.buildErrorMessages(language, this.limits)\n }\n }\n\n /**\n * For error preview page that shows all possible errors on a component\n */\n getAllPossibleErrors(): ErrorMessageTemplateList {\n return FileUploadField.getAllPossibleErrors()\n }\n\n async onSubmit(\n request: FormRequestPayload,\n metadata: FormMetadata,\n context: FormContext\n ) {\n const language = resolveLanguage(request)\n const { t } = this.model.createTranslator(language)\n\n const notificationEmail = metadata.notificationEmail\n\n if (!notificationEmail) {\n // this should not happen because notificationEmail is checked further up\n // the chain in SummaryPageController before submitForm is called.\n throw new Error('Unexpected missing notificationEmail in metadata')\n }\n\n if (!request.app.model?.services.formSubmissionService) {\n throw new Error('No form submission service available in app model')\n }\n\n const { formSubmissionService } = request.app.model.services\n const values = this.getFormValueFromState(context.state) ?? []\n\n const files = values.map((value) => ({\n fileId: value.status.form.file.fileId,\n initiatedRetrievalKey: value.status.metadata.retrievalKey\n }))\n\n if (!files.length) {\n return\n }\n\n try {\n await formSubmissionService.persistFiles(files, notificationEmail)\n } catch (error) {\n if (\n Boom.isBoom(error) &&\n (error.output.statusCode === 403 || // Forbidden - retrieval key invalid\n error.output.statusCode === 404 || // Not Found - file not found\n error.output.statusCode === 410) // Gone - file expired (took to long to submit, etc)\n ) {\n // Failed to persist files. We can't recover from this, the only real way we can recover the submissions is\n // by resetting the problematic components and letting the user re-try.\n // Scenarios: file missing from S3, invalid retrieval key (timing problem), etc.\n throw new InvalidComponentStateError(\n this,\n t('components.fileUploadField.uploadFailed')\n )\n }\n\n throw error\n }\n }\n\n /**\n * Static version of getAllPossibleErrors that doesn't require a component instance.\n */\n static getAllPossibleErrors(): ErrorMessageTemplateList {\n return {\n baseErrors: [\n { type: 'selectRequired', template: messageTemplate.selectRequired },\n {\n type: 'filesMimes',\n template: 'The selected file must be a {{#limit}}'\n },\n {\n type: 'filesSize',\n template: 'The selected file must be smaller than 100MB'\n },\n { type: 'filesEmpty', template: 'The selected file is empty' },\n { type: 'filesVirus', template: 'The selected file contains a virus' },\n {\n type: 'filesPartial',\n template: 'The selected file has not fully uploaded'\n },\n {\n type: 'filesError',\n template: 'The selected file could not be uploaded – try again'\n }\n ],\n advancedSettingsErrors: [\n {\n type: 'filesMin',\n template: 'You must upload {{#limit}} files or more'\n },\n {\n type: 'filesMax',\n template: 'You can only upload {{#limit}} files or less'\n },\n {\n type: 'filesExact',\n template: 'You must upload exactly {{#limit}} files'\n }\n ]\n }\n }\n\n static buildErrorMessages(\n language: string,\n limits: { min?: number; max?: number; length?: number } = {}\n ) {\n return {\n 'array.min': tPlugin('validation.filesMin', language, {\n count: limits.min ?? 1\n }),\n 'array.max': tPlugin('validation.filesMax', language, {\n count: limits.max ?? 1\n }),\n 'array.length': tPlugin('validation.filesLength', language, {\n count: limits.length ?? 1\n })\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -8,8 +8,8 @@ export declare class ListFormComponent extends FormComponent {
|
|
|
8
8
|
options: Extract<SelectionComponentsDef, {
|
|
9
9
|
options: object;
|
|
10
10
|
}>['options'];
|
|
11
|
-
formSchema: ArraySchema<string> | ArraySchema<number> | BooleanSchema<string> | NumberSchema<string> | NumberSchema | StringSchema;
|
|
12
|
-
stateSchema: ArraySchema<string> | ArraySchema<number> | BooleanSchema<string> | NumberSchema<string> | NumberSchema | StringSchema;
|
|
11
|
+
formSchema: ArraySchema<string[]> | ArraySchema<number[]> | BooleanSchema<string> | NumberSchema<string> | NumberSchema | StringSchema;
|
|
12
|
+
stateSchema: ArraySchema<string[]> | ArraySchema<number[]> | BooleanSchema<string> | NumberSchema<string> | NumberSchema | StringSchema;
|
|
13
13
|
list?: List;
|
|
14
14
|
listType: List['type'];
|
|
15
15
|
get items(): Item[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ListFormComponent.js","names":["joi","FormComponent","messageTemplate","ListFormComponent","list","listType","items","values","map","value","constructor","def","props","options","model","getList","type","formSchema","valid","label","required","customValidationMessages","messages","stateSchema","default","allow","getFormValueFromState","state","name","isValue","flat","selected","filter","item","includes","at","getDisplayStringFromFormValue","translator","tListItem","text","join","getDisplayStringFromState","getViewModel","context","listItems","viewModel","resolvedText","resolvedHint","hint","hintAttr","itemModel","id","description","getAllPossibleErrors","baseErrors","template","selectRequired","advancedSettingsErrors"],"sources":["../../../../../src/server/plugins/engine/components/ListFormComponent.ts"],"sourcesContent":["import {\n type Item,\n type List,\n type ListComponentsDef,\n type SelectionComponentsDef,\n type YesNoFieldComponent\n} from '@defra/forms-model'\nimport joi, {\n type ArraySchema,\n type BooleanSchema,\n type NumberSchema,\n type StringSchema\n} from 'joi'\n\nimport { FormComponent } from '~/src/server/plugins/engine/components/FormComponent.js'\nimport {\n type ListItem,\n type RenderContext\n} from '~/src/server/plugins/engine/components/types.js'\nimport { type Translator } from '~/src/server/plugins/engine/i18n/types.js'\nimport { messageTemplate } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'\nimport {\n type ErrorMessageTemplateList,\n type FormSubmissionState\n} from '~/src/server/plugins/engine/types.js'\n\nexport class ListFormComponent extends FormComponent {\n declare options: Extract<\n SelectionComponentsDef,\n { options: object }\n >['options']\n\n declare formSchema:\n | ArraySchema<string>\n | ArraySchema<number>\n | BooleanSchema<string>\n | NumberSchema<string>\n | NumberSchema\n | StringSchema\n\n declare stateSchema:\n | ArraySchema<string>\n | ArraySchema<number>\n | BooleanSchema<string>\n | NumberSchema<string>\n | NumberSchema\n | StringSchema\n\n list?: List\n listType: List['type'] = 'string'\n\n get items(): Item[] {\n return this.list?.items ?? []\n }\n\n get values(): Item['value'][] {\n return this.items.map(({ value }) => value)\n }\n\n constructor(\n def:\n | SelectionComponentsDef // Allow for Yes/No field custom list\n | (YesNoFieldComponent & Pick<ListComponentsDef, 'list'>),\n props: ConstructorParameters<typeof FormComponent>[1]\n ) {\n super(def, props)\n\n const { options } = def\n const { model } = props\n\n if ('list' in def) {\n this.list = model.getList(def.list)\n this.listType = this.list?.type ?? 'string'\n }\n\n let formSchema = joi[this.listType]()\n .valid(...this.values)\n .label(this.label)\n .required()\n\n if (options.customValidationMessages) {\n formSchema = formSchema.messages(options.customValidationMessages)\n }\n\n this.formSchema = formSchema\n this.stateSchema = formSchema.default(null).allow(null)\n this.options = options\n }\n\n getFormValueFromState(\n state: FormSubmissionState\n ): Item['value'] | Item['value'][] | undefined {\n const { name, items } = this\n\n const value = state[name]\n\n // Allow for array values via subclass\n const values = this.isValue(value) ? [value].flat() : []\n const selected = items.filter((item) => values.includes(item.value))\n\n return selected.at(0)?.value\n }\n\n getDisplayStringFromFormValue(\n value: string | number | boolean | Item['value'][] | undefined,\n translator: Translator\n ): string {\n const { items } = this\n\n const values = [value ?? []].flat()\n\n return items\n .filter((item) => values.includes(item.value))\n .map((item) => translator.tListItem(item, 'text') || item.text)\n .join(', ')\n }\n\n getDisplayStringFromState(\n state: FormSubmissionState,\n translator: Translator\n ) {\n // Allow for array values via subclass\n const value = this.getFormValueFromState(state)\n\n return this.getDisplayStringFromFormValue(value, translator)\n }\n\n getViewModel(context: RenderContext) {\n const { items: listItems } = this\n\n const viewModel = super.getViewModel(context)\n const { value } = viewModel\n\n // Support multiple values for checkboxes\n const values = this.isValue(value) ? [value].flat() : []\n\n const { tListItem } = context.translator\n\n const items = listItems.map((item) => {\n const selected = values.includes(item.value)\n const resolvedText = tListItem(item, 'text') || item.text\n const resolvedHint = tListItem(item, 'hint') || item.hint?.text\n const hintAttr = resolvedHint ? { hint: { text: resolvedHint } } : {}\n const itemModel: ListItem = {\n ...item,\n text: resolvedText,\n selected,\n ...hintAttr\n }\n\n if ('id' in itemModel) {\n delete itemModel.id\n }\n\n if (item.description) {\n itemModel.hint = {\n text: item.description\n }\n }\n\n return itemModel\n })\n\n return {\n ...viewModel,\n items\n }\n }\n\n /**\n * For error preview page that shows all possible errors on a component\n */\n getAllPossibleErrors(): ErrorMessageTemplateList {\n return ListFormComponent.getAllPossibleErrors()\n }\n\n /**\n * Static version of getAllPossibleErrors that doesn't require a component instance.\n */\n static getAllPossibleErrors(): ErrorMessageTemplateList {\n return {\n baseErrors: [\n { type: 'selectRequired', template: messageTemplate.selectRequired }\n ],\n advancedSettingsErrors: []\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"ListFormComponent.js","names":["joi","FormComponent","messageTemplate","ListFormComponent","list","listType","items","values","map","value","constructor","def","props","options","model","getList","type","formSchema","valid","label","required","customValidationMessages","messages","stateSchema","default","allow","getFormValueFromState","state","name","isValue","flat","selected","filter","item","includes","at","getDisplayStringFromFormValue","translator","tListItem","text","join","getDisplayStringFromState","getViewModel","context","listItems","viewModel","resolvedText","resolvedHint","hint","hintAttr","itemModel","id","description","getAllPossibleErrors","baseErrors","template","selectRequired","advancedSettingsErrors"],"sources":["../../../../../src/server/plugins/engine/components/ListFormComponent.ts"],"sourcesContent":["import {\n type Item,\n type List,\n type ListComponentsDef,\n type SelectionComponentsDef,\n type YesNoFieldComponent\n} from '@defra/forms-model'\nimport joi, {\n type ArraySchema,\n type BooleanSchema,\n type NumberSchema,\n type StringSchema\n} from 'joi'\n\nimport { FormComponent } from '~/src/server/plugins/engine/components/FormComponent.js'\nimport {\n type ListItem,\n type RenderContext\n} from '~/src/server/plugins/engine/components/types.js'\nimport { type Translator } from '~/src/server/plugins/engine/i18n/types.js'\nimport { messageTemplate } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'\nimport {\n type ErrorMessageTemplateList,\n type FormSubmissionState\n} from '~/src/server/plugins/engine/types.js'\n\nexport class ListFormComponent extends FormComponent {\n declare options: Extract<\n SelectionComponentsDef,\n { options: object }\n >['options']\n\n declare formSchema:\n | ArraySchema<string[]>\n | ArraySchema<number[]>\n | BooleanSchema<string>\n | NumberSchema<string>\n | NumberSchema\n | StringSchema\n\n declare stateSchema:\n | ArraySchema<string[]>\n | ArraySchema<number[]>\n | BooleanSchema<string>\n | NumberSchema<string>\n | NumberSchema\n | StringSchema\n\n list?: List\n listType: List['type'] = 'string'\n\n get items(): Item[] {\n return this.list?.items ?? []\n }\n\n get values(): Item['value'][] {\n return this.items.map(({ value }) => value)\n }\n\n constructor(\n def:\n | SelectionComponentsDef // Allow for Yes/No field custom list\n | (YesNoFieldComponent & Pick<ListComponentsDef, 'list'>),\n props: ConstructorParameters<typeof FormComponent>[1]\n ) {\n super(def, props)\n\n const { options } = def\n const { model } = props\n\n if ('list' in def) {\n this.list = model.getList(def.list)\n this.listType = this.list?.type ?? 'string'\n }\n\n let formSchema = joi[this.listType]()\n .valid(...this.values)\n .label(this.label)\n .required()\n\n if (options.customValidationMessages) {\n formSchema = formSchema.messages(options.customValidationMessages)\n }\n\n this.formSchema = formSchema\n this.stateSchema = formSchema.default(null).allow(null)\n this.options = options\n }\n\n getFormValueFromState(\n state: FormSubmissionState\n ): Item['value'] | Item['value'][] | undefined {\n const { name, items } = this\n\n const value = state[name]\n\n // Allow for array values via subclass\n const values = this.isValue(value) ? [value].flat() : []\n const selected = items.filter((item) => values.includes(item.value))\n\n return selected.at(0)?.value\n }\n\n getDisplayStringFromFormValue(\n value: string | number | boolean | Item['value'][] | undefined,\n translator: Translator\n ): string {\n const { items } = this\n\n const values = [value ?? []].flat()\n\n return items\n .filter((item) => values.includes(item.value))\n .map((item) => translator.tListItem(item, 'text') || item.text)\n .join(', ')\n }\n\n getDisplayStringFromState(\n state: FormSubmissionState,\n translator: Translator\n ) {\n // Allow for array values via subclass\n const value = this.getFormValueFromState(state)\n\n return this.getDisplayStringFromFormValue(value, translator)\n }\n\n getViewModel(context: RenderContext) {\n const { items: listItems } = this\n\n const viewModel = super.getViewModel(context)\n const { value } = viewModel\n\n // Support multiple values for checkboxes\n const values = this.isValue(value) ? [value].flat() : []\n\n const { tListItem } = context.translator\n\n const items = listItems.map((item) => {\n const selected = values.includes(item.value)\n const resolvedText = tListItem(item, 'text') || item.text\n const resolvedHint = tListItem(item, 'hint') || item.hint?.text\n const hintAttr = resolvedHint ? { hint: { text: resolvedHint } } : {}\n const itemModel: ListItem = {\n ...item,\n text: resolvedText,\n selected,\n ...hintAttr\n }\n\n if ('id' in itemModel) {\n delete itemModel.id\n }\n\n if (item.description) {\n itemModel.hint = {\n text: item.description\n }\n }\n\n return itemModel\n })\n\n return {\n ...viewModel,\n items\n }\n }\n\n /**\n * For error preview page that shows all possible errors on a component\n */\n getAllPossibleErrors(): ErrorMessageTemplateList {\n return ListFormComponent.getAllPossibleErrors()\n }\n\n /**\n * Static version of getAllPossibleErrors that doesn't require a component instance.\n */\n static getAllPossibleErrors(): ErrorMessageTemplateList {\n return {\n baseErrors: [\n { type: 'selectRequired', template: messageTemplate.selectRequired }\n ],\n advancedSettingsErrors: []\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import joi from 'joi';
|
|
2
2
|
import { FormComponent, isFormValue } from "./FormComponent.js";
|
|
3
|
-
import { addClassOptionIfNone } from "./helpers/index.js";
|
|
3
|
+
import { addClassOptionIfNone, withCustomValidationOverrides } from "./helpers/index.js";
|
|
4
4
|
import { buildValidationMessages } from "../i18n/buildValidationMessages.js";
|
|
5
5
|
import { messageTemplate } from "../pageControllers/validationOptions.js";
|
|
6
6
|
/**
|
|
@@ -71,16 +71,21 @@ export class LocationFieldBase extends FormComponent {
|
|
|
71
71
|
return viewModel;
|
|
72
72
|
}
|
|
73
73
|
getValidationMessagesOverride(translator) {
|
|
74
|
+
const {
|
|
75
|
+
customValidationMessage,
|
|
76
|
+
customValidationMessages
|
|
77
|
+
} = this.options;
|
|
74
78
|
const {
|
|
75
79
|
t
|
|
76
80
|
} = translator;
|
|
77
81
|
const config = this.getValidationConfig(translator);
|
|
82
|
+
const defaults = {
|
|
83
|
+
'any.required': config.requiredMessage ?? buildValidationMessages(t).objectRequired,
|
|
84
|
+
'string.empty': config.requiredMessage ?? buildValidationMessages(t).objectRequired,
|
|
85
|
+
'string.pattern.base': config.patternErrorMessage
|
|
86
|
+
};
|
|
78
87
|
return {
|
|
79
|
-
[this.name]:
|
|
80
|
-
'any.required': config.requiredMessage ?? buildValidationMessages(t).objectRequired,
|
|
81
|
-
'string.empty': config.requiredMessage ?? buildValidationMessages(t).objectRequired,
|
|
82
|
-
'string.pattern.base': config.patternErrorMessage
|
|
83
|
-
}
|
|
88
|
+
[this.name]: withCustomValidationOverrides(defaults, customValidationMessage, customValidationMessages)
|
|
84
89
|
};
|
|
85
90
|
}
|
|
86
91
|
getAllPossibleErrors() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LocationFieldBase.js","names":["joi","FormComponent","isFormValue","addClassOptionIfNone","buildValidationMessages","messageTemplate","LocationFieldBase","instructionText","constructor","def","props","options","locationOptions","config","getValidationConfig","undefined","requiredMessage","required","messages","patternErrorMessage","formSchema","string","trim","label","pattern","allow","customValidationMessage","message","messageKeys","reduce","acc","key","customValidationMessages","default","stateSchema","getFormValueFromState","state","name","getFormValue","value","isValue","isText","getViewModel","context","viewModel","Object","assign","lang","translator","language","tComponent","getValidationMessagesOverride","t","objectRequired","getAllPossibleErrors","baseErrors","type","template","getErrorTemplates","advancedSettingsErrors"],"sources":["../../../../../src/server/plugins/engine/components/LocationFieldBase.ts"],"sourcesContent":["import { type FormComponentsDef } from '@defra/forms-model'\nimport joi, {\n type JoiExpression,\n type LanguageMessages,\n type StringSchema\n} from 'joi'\n\nimport {\n FormComponent,\n isFormValue\n} from '~/src/server/plugins/engine/components/FormComponent.js'\nimport {
|
|
1
|
+
{"version":3,"file":"LocationFieldBase.js","names":["joi","FormComponent","isFormValue","addClassOptionIfNone","withCustomValidationOverrides","buildValidationMessages","messageTemplate","LocationFieldBase","instructionText","constructor","def","props","options","locationOptions","config","getValidationConfig","undefined","requiredMessage","required","messages","patternErrorMessage","formSchema","string","trim","label","pattern","allow","customValidationMessage","message","messageKeys","reduce","acc","key","customValidationMessages","default","stateSchema","getFormValueFromState","state","name","getFormValue","value","isValue","isText","getViewModel","context","viewModel","Object","assign","lang","translator","language","tComponent","getValidationMessagesOverride","t","defaults","objectRequired","getAllPossibleErrors","baseErrors","type","template","getErrorTemplates","advancedSettingsErrors"],"sources":["../../../../../src/server/plugins/engine/components/LocationFieldBase.ts"],"sourcesContent":["import { type FormComponentsDef } from '@defra/forms-model'\nimport joi, {\n type JoiExpression,\n type LanguageMessages,\n type StringSchema\n} from 'joi'\n\nimport {\n FormComponent,\n isFormValue\n} from '~/src/server/plugins/engine/components/FormComponent.js'\nimport {\n addClassOptionIfNone,\n withCustomValidationOverrides\n} from '~/src/server/plugins/engine/components/helpers/index.js'\nimport { type RenderContext } from '~/src/server/plugins/engine/components/types.js'\nimport { buildValidationMessages } from '~/src/server/plugins/engine/i18n/buildValidationMessages.js'\nimport { messageTemplate } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'\nimport { type Translator } from '~/src/server/plugins/engine/types/index.js'\nimport {\n type ErrorMessageTemplateList,\n type FormState,\n type FormStateValue,\n type FormSubmissionState\n} from '~/src/server/plugins/engine/types.js'\n\ninterface LocationFieldOptions {\n instructionText?: string\n required?: boolean\n customValidationMessage?: string\n customValidationMessages?: LanguageMessages\n classes?: string\n}\n\ninterface ValidationConfig {\n pattern: RegExp\n patternErrorMessage: JoiExpression\n requiredMessage?: JoiExpression\n}\n\n/**\n * Abstract base class for location-based field components\n */\nexport abstract class LocationFieldBase extends FormComponent {\n declare options: LocationFieldOptions\n declare formSchema: StringSchema\n declare stateSchema: StringSchema\n instructionText?: string\n\n protected abstract getValidationConfig(\n translator: Translator | undefined\n ): ValidationConfig\n protected abstract getErrorTemplates(): {\n type: string\n template: JoiExpression\n }[]\n\n constructor(\n def: FormComponentsDef,\n props: ConstructorParameters<typeof FormComponent>[1]\n ) {\n super(def, props)\n\n const { options } = def\n const locationOptions = options as LocationFieldOptions\n this.instructionText = locationOptions.instructionText\n\n addClassOptionIfNone(locationOptions, 'govuk-input--width-10')\n\n const config = this.getValidationConfig(undefined)\n const requiredMessage = config.requiredMessage ?? messageTemplate.required\n\n const messages = {\n 'any.required': requiredMessage,\n 'string.empty': requiredMessage,\n 'string.pattern.base': config.patternErrorMessage\n } as LanguageMessages\n\n let formSchema = joi\n .string()\n .trim()\n .label(this.label)\n .required()\n .pattern(config.pattern)\n .messages(messages)\n\n if (locationOptions.required === false) {\n formSchema = formSchema.allow('')\n }\n\n if (locationOptions.customValidationMessage) {\n const message = locationOptions.customValidationMessage\n const messageKeys = [\n 'any.required',\n 'string.empty',\n 'string.pattern.base'\n ]\n\n const messages = messageKeys.reduce<LanguageMessages>((acc, key) => {\n acc[key] = message\n return acc\n }, {})\n\n formSchema = formSchema.messages(messages)\n } else if (locationOptions.customValidationMessages) {\n formSchema = formSchema.messages(locationOptions.customValidationMessages)\n }\n\n this.formSchema = formSchema.default('')\n this.stateSchema = formSchema.default(null).allow(null)\n this.options = locationOptions\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 isValue(value?: FormStateValue | FormState): value is string {\n return LocationFieldBase.isText(value)\n }\n\n getViewModel(context: RenderContext) {\n const viewModel = super.getViewModel(context)\n\n Object.assign(viewModel, {\n lang: context.translator.language\n })\n\n if (this.instructionText) {\n const { tComponent } = context.translator\n return {\n ...viewModel,\n instructionText:\n tComponent(this.def, 'instructionText') || this.instructionText\n }\n }\n\n return viewModel\n }\n\n getValidationMessagesOverride(translator: Translator) {\n const { customValidationMessage, customValidationMessages } = this.options\n const { t } = translator\n const config = this.getValidationConfig(translator)\n const defaults = {\n 'any.required':\n config.requiredMessage ?? buildValidationMessages(t).objectRequired,\n 'string.empty':\n config.requiredMessage ?? buildValidationMessages(t).objectRequired,\n 'string.pattern.base': config.patternErrorMessage\n }\n\n return {\n [this.name]: withCustomValidationOverrides(\n defaults,\n customValidationMessage,\n customValidationMessages\n )\n }\n }\n\n getAllPossibleErrors(): ErrorMessageTemplateList {\n const config = this.getValidationConfig(undefined)\n\n return {\n baseErrors: [\n {\n type: 'required',\n template: config.requiredMessage ?? messageTemplate.required\n },\n ...this.getErrorTemplates()\n ],\n advancedSettingsErrors: []\n }\n }\n\n static isText(value?: FormStateValue | FormState): value is string {\n return isFormValue(value) && typeof value === 'string'\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import joi from 'joi';
|
|
2
2
|
import { FormComponent, isFormValue } from "./FormComponent.js";
|
|
3
|
+
import { withCustomValidationOverrides } from "./helpers/index.js";
|
|
3
4
|
import { buildValidationMessages } from "../i18n/buildValidationMessages.js";
|
|
4
5
|
import { messageTemplate } from "../pageControllers/validationOptions.js";
|
|
5
6
|
export class NumberField extends FormComponent {
|
|
@@ -99,18 +100,23 @@ export class NumberField extends FormComponent {
|
|
|
99
100
|
return NumberField.isNumber(value);
|
|
100
101
|
}
|
|
101
102
|
getValidationMessagesOverride(translator) {
|
|
103
|
+
const {
|
|
104
|
+
customValidationMessage,
|
|
105
|
+
customValidationMessages
|
|
106
|
+
} = this.options;
|
|
102
107
|
const {
|
|
103
108
|
t
|
|
104
109
|
} = translator;
|
|
110
|
+
const defaults = {
|
|
111
|
+
'any.required': buildValidationMessages(t).objectRequired,
|
|
112
|
+
'number.base': buildValidationMessages(t).objectMissing,
|
|
113
|
+
'number.precision': buildValidationMessages(t).numberPrecision,
|
|
114
|
+
'number.integer': buildValidationMessages(t).numberInteger,
|
|
115
|
+
'number.min': buildValidationMessages(t).numberMin,
|
|
116
|
+
'number.max': buildValidationMessages(t).numberMax
|
|
117
|
+
};
|
|
105
118
|
return {
|
|
106
|
-
[this.name]:
|
|
107
|
-
'any.required': buildValidationMessages(t).objectRequired,
|
|
108
|
-
'number.base': buildValidationMessages(t).objectMissing,
|
|
109
|
-
'number.precision': buildValidationMessages(t).numberPrecision,
|
|
110
|
-
'number.integer': buildValidationMessages(t).numberInteger,
|
|
111
|
-
'number.min': buildValidationMessages(t).numberMin,
|
|
112
|
-
'number.max': buildValidationMessages(t).numberMax
|
|
113
|
-
}
|
|
119
|
+
[this.name]: withCustomValidationOverrides(defaults, customValidationMessage, customValidationMessages)
|
|
114
120
|
};
|
|
115
121
|
}
|
|
116
122
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NumberField.js","names":["joi","FormComponent","isFormValue","buildValidationMessages","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","context","viewModel","attributes","prefix","suffix","inputmode","text","isNumber","getValidationMessagesOverride","translator","t","objectRequired","objectMissing","numberPrecision","numberInteger","numberMin","numberMax","getAllPossibleErrors","baseErrors","type","template","advancedSettingsErrors","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, {\n type CustomValidator,\n type LanguageMessages,\n type NumberSchema\n} from 'joi'\n\nimport {\n FormComponent,\n isFormValue\n} from '~/src/server/plugins/engine/components/FormComponent.js'\nimport { type RenderContext } from '~/src/server/plugins/engine/components/types.js'\nimport { buildValidationMessages } from '~/src/server/plugins/engine/i18n/buildValidationMessages.js'\nimport { messageTemplate } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'\nimport { type Translator } from '~/src/server/plugins/engine/types/index.js'\nimport {\n type ErrorMessageTemplateList,\n type FormState,\n type FormStateValue,\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(context: RenderContext) {\n const { options, schema } = this\n\n const viewModel = super.getViewModel(context)\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 getValidationMessagesOverride(translator: Translator) {\n const { t } = translator\n return {\n [this.name]: {\n 'any.required': buildValidationMessages(t).objectRequired,\n 'number.base': buildValidationMessages(t).objectMissing,\n 'number.precision': buildValidationMessages(t).numberPrecision,\n 'number.integer': buildValidationMessages(t).numberInteger,\n 'number.min': buildValidationMessages(t).numberMin,\n 'number.max': buildValidationMessages(t).numberMax\n } as LanguageMessages\n }\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":"AACA,OAAOA,GAAG,MAIH,KAAK;AAEZ,SACEC,aAAa,EACbC,WAAW;AAGb,SAASC,uBAAuB;AAChC,SAASC,eAAe;AASxB,OAAO,MAAMC,WAAW,SAASJ,aAAa,CAAC;EAM7CK,WAAWA,CACTC,GAAyB,EACzBC,KAAqD,EACrD;IACA,KAAK,CAACD,GAAG,EAAEC,KAAK,CAAC;IAEjB,MAAM;MAAEC,OAAO;MAAEC;IAAO,CAAC,GAAGH,GAAG;IAE/B,IAAII,UAAU,GAAGX,GAAG,CACjBY,MAAM,CAAC,CAAC,CACRC,MAAM,CAACC,qBAAqB,CAAC,IAAI,CAAC,CAAC,CACnCC,KAAK,CAAC,IAAI,CAACA,KAAK,CAAC,CACjBC,QAAQ,CAAC,CAAC;IAEb,IAAIP,OAAO,CAACO,QAAQ,KAAK,KAAK,EAAE;MAC9BL,UAAU,GAAGA,UAAU,CAACM,KAAK,CAAC,EAAE,CAAC;IACnC,CAAC,MAAM;MACL,MAAMC,QAAQ,GAAGT,OAAO,CAACU,wBAAwB;MAEjDR,UAAU,GAAGA,UAAU,CAACS,KAAK,CAAC,EAAE,CAAC,CAACF,QAAQ,CAAC;QACzC,cAAc,EACZA,QAAQ,GAAG,cAAc,CAAC,IAAKd,eAAe,CAACY;MACnD,CAAC,CAAC;IACJ;IAEA,IAAI,OAAON,MAAM,CAACW,GAAG,KAAK,QAAQ,EAAE;MAClCV,UAAU,GAAGA,UAAU,CAACU,GAAG,CAACX,MAAM,CAACW,GAAG,CAAC;IACzC;IAEA,IAAI,OAAOX,MAAM,CAACY,GAAG,KAAK,QAAQ,EAAE;MAClCX,UAAU,GAAGA,UAAU,CAACW,GAAG,CAACZ,MAAM,CAACY,GAAG,CAAC;IACzC;IAEA,IAAI,OAAOZ,MAAM,CAACa,SAAS,KAAK,QAAQ,IAAIb,MAAM,CAACa,SAAS,IAAI,CAAC,EAAE;MACjEZ,UAAU,GAAGA,UAAU,CAACa,OAAO,CAAC,CAAC;IACnC;IAEA,IAAIf,OAAO,CAACgB,uBAAuB,EAAE;MACnC,MAAMC,OAAO,GAAGjB,OAAO,CAACgB,uBAAuB;MAE/Cd,UAAU,GAAGA,UAAU,CAACO,QAAQ,CAAC;QAC/B,cAAc,EAAEQ,OAAO;QACvB,aAAa,EAAEA,OAAO;QACtB,kBAAkB,EAAEA,OAAO;QAC3B,gBAAgB,EAAEA,OAAO;QACzB,YAAY,EAAEA,OAAO;QACrB,YAAY,EAAEA;MAChB,CAAC,CAAC;IACJ,CAAC,MAAM,IAAIjB,OAAO,CAACU,wBAAwB,EAAE;MAC3CR,UAAU,GAAGA,UAAU,CAACO,QAAQ,CAACT,OAAO,CAACU,wBAAwB,CAAC;IACpE;IAEA,IAAI,CAACR,UAAU,GAAGA,UAAU,CAACgB,OAAO,CAAC,EAAE,CAAC;IACxC,IAAI,CAACC,WAAW,GAAGjB,UAAU,CAACgB,OAAO,CAAC,IAAI,CAAC,CAACV,KAAK,CAAC,IAAI,CAAC;IACvD,IAAI,CAACR,OAAO,GAAGA,OAAO;IACtB,IAAI,CAACC,MAAM,GAAGA,MAAM;EACtB;EAEAmB,qBAAqBA,CAACC,KAA0B,EAAE;IAChD,MAAM;MAAEC;IAAK,CAAC,GAAG,IAAI;IACrB,OAAO,IAAI,CAACC,YAAY,CAACF,KAAK,CAACC,IAAI,CAAC,CAAC;EACvC;EAEAC,YAAYA,CAACC,KAAkC,EAAE;IAC/C,OAAO,IAAI,CAACC,OAAO,CAACD,KAAK,CAAC,GAAGA,KAAK,GAAGE,SAAS;EAChD;EAEAC,YAAYA,CAACC,OAAsB,EAAE;IACnC,MAAM;MAAE5B,OAAO;MAAEC;IAAO,CAAC,GAAG,IAAI;IAEhC,MAAM4B,SAAS,GAAG,KAAK,CAACF,YAAY,CAACC,OAAO,CAAC;IAC7C,IAAI;MAAEE,UAAU;MAAEC,MAAM;MAAEC,MAAM;MAAER;IAAM,CAAC,GAAGK,SAAS;IAErD,IAAI,OAAO5B,MAAM,CAACa,SAAS,KAAK,WAAW,IAAIb,MAAM,CAACa,SAAS,IAAI,CAAC,EAAE;MACpE;MACA;MACAgB,UAAU,CAACG,SAAS,GAAG,SAAS;IAClC;IAEA,IAAIjC,OAAO,CAAC+B,MAAM,EAAE;MAClBA,MAAM,GAAG;QACPG,IAAI,EAAElC,OAAO,CAAC+B;MAChB,CAAC;IACH;IAEA,IAAI/B,OAAO,CAACgC,MAAM,EAAE;MAClBA,MAAM,GAAG;QACPE,IAAI,EAAElC,OAAO,CAACgC;MAChB,CAAC;IACH;;IAEA;IACA;IACA,IAAI,CAACvC,WAAW,CAAC+B,KAAK,CAAC,EAAE;MACvBA,KAAK,GAAGE,SAAS;IACnB;IAEA,OAAO;MACL,GAAGG,SAAS;MACZC,UAAU;MACVC,MAAM;MACNC,MAAM;MACNR;IACF,CAAC;EACH;EAEAC,OAAOA,CAACD,KAAkC,EAAE;IAC1C,OAAO5B,WAAW,CAACuC,QAAQ,CAACX,KAAK,CAAC;EACpC;EAEAY,6BAA6BA,CAACC,UAAsB,EAAE;IACpD,MAAM;MAAEC;IAAE,CAAC,GAAGD,UAAU;IACxB,OAAO;MACL,CAAC,IAAI,CAACf,IAAI,GAAG;QACX,cAAc,EAAE5B,uBAAuB,CAAC4C,CAAC,CAAC,CAACC,cAAc;QACzD,aAAa,EAAE7C,uBAAuB,CAAC4C,CAAC,CAAC,CAACE,aAAa;QACvD,kBAAkB,EAAE9C,uBAAuB,CAAC4C,CAAC,CAAC,CAACG,eAAe;QAC9D,gBAAgB,EAAE/C,uBAAuB,CAAC4C,CAAC,CAAC,CAACI,aAAa;QAC1D,YAAY,EAAEhD,uBAAuB,CAAC4C,CAAC,CAAC,CAACK,SAAS;QAClD,YAAY,EAAEjD,uBAAuB,CAAC4C,CAAC,CAAC,CAACM;MAC3C;IACF,CAAC;EACH;;EAEA;AACF;AACA;EACEC,oBAAoBA,CAAA,EAA6B;IAC/C,OAAOjD,WAAW,CAACiD,oBAAoB,CAAC,CAAC;EAC3C;;EAEA;AACF;AACA;EACE,OAAOA,oBAAoBA,CAAA,EAA6B;IACtD,OAAO;MACLC,UAAU,EAAE,CACV;QAAEC,IAAI,EAAE,UAAU;QAAEC,QAAQ,EAAErD,eAAe,CAACY;MAAS,CAAC,EACxD;QAAEwC,IAAI,EAAE,eAAe;QAAEC,QAAQ,EAAErD,eAAe,CAAC+C;MAAc,CAAC,CACnE;MACDO,sBAAsB,EAAE,CACtB;QAAEF,IAAI,EAAE,WAAW;QAAEC,QAAQ,EAAErD,eAAe,CAACgD;MAAU,CAAC,EAC1D;QAAEI,IAAI,EAAE,WAAW;QAAEC,QAAQ,EAAErD,eAAe,CAACiD;MAAU,CAAC,EAC1D;QAAEG,IAAI,EAAE,iBAAiB;QAAEC,QAAQ,EAAErD,eAAe,CAAC8C;MAAgB,CAAC;IAE1E,CAAC;EACH;EAEA,OAAON,QAAQA,CAACX,KAAkC,EAAmB;IACnE,OAAO,OAAOA,KAAK,KAAK,QAAQ;EAClC;AACF;AAEA,OAAO,SAASnB,qBAAqBA,CAAC6C,SAAsB,EAAE;EAC5D,MAAMC,SAA0B,GAAGA,CAAC3B,KAAa,EAAE4B,OAAO,KAAK;IAC7D,MAAM;MAAEpD,OAAO;MAAEC;IAAO,CAAC,GAAGiD,SAAS;IAErC,MAAM;MAAElC,uBAAuB,EAAEZ;IAAO,CAAC,GAAGJ,OAAO;IACnD,MAAM;MAAEc,SAAS,EAAEuC;IAAM,CAAC,GAAGpD,MAAM;IAEnC,IAAI,CAACoD,KAAK,IAAIA,KAAK,IAAI,CAAC,EAAE;MACxB,OAAO7B,KAAK;IACd;IAEA,MAAM8B,gBAAgB,GAAG/D,GAAG,CACzBY,MAAM,CAAC,CAAC,CACRW,SAAS,CAACuC,KAAK,CAAC,CAChBE,KAAK,CAAC;MAAEC,OAAO,EAAE;IAAM,CAAC,CAAC;IAE5B,IAAI;MACF,OAAOjE,GAAG,CAACkE,OAAO,CAACjC,KAAK,EAAE8B,gBAAgB,CAAC;IAC7C,CAAC,CAAC,MAAM;MACN,OAAOlD,MAAM,GACTgD,OAAO,CAACnC,OAAO,CAAC;QAAEb;MAAO,CAAC,EAAE;QAAEiD;MAAM,CAAC,CAAC,GACtCD,OAAO,CAACM,KAAK,CAAC,kBAAkB,EAAE;QAAEL;MAAM,CAAC,CAAC;IAClD;EACF,CAAC;EAED,OAAOF,SAAS;AAClB","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"NumberField.js","names":["joi","FormComponent","isFormValue","withCustomValidationOverrides","buildValidationMessages","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","context","viewModel","attributes","prefix","suffix","inputmode","text","isNumber","getValidationMessagesOverride","translator","t","defaults","objectRequired","objectMissing","numberPrecision","numberInteger","numberMin","numberMax","getAllPossibleErrors","baseErrors","type","template","advancedSettingsErrors","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 { withCustomValidationOverrides } from '~/src/server/plugins/engine/components/helpers/index.js'\nimport { type RenderContext } from '~/src/server/plugins/engine/components/types.js'\nimport { buildValidationMessages } from '~/src/server/plugins/engine/i18n/buildValidationMessages.js'\nimport { messageTemplate } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'\nimport { type Translator } from '~/src/server/plugins/engine/types/index.js'\nimport {\n type ErrorMessageTemplateList,\n type FormState,\n type FormStateValue,\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(context: RenderContext) {\n const { options, schema } = this\n\n const viewModel = super.getViewModel(context)\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 getValidationMessagesOverride(translator: Translator) {\n const { customValidationMessage, customValidationMessages } = this.options\n const { t } = translator\n const defaults = {\n 'any.required': buildValidationMessages(t).objectRequired,\n 'number.base': buildValidationMessages(t).objectMissing,\n 'number.precision': buildValidationMessages(t).numberPrecision,\n 'number.integer': buildValidationMessages(t).numberInteger,\n 'number.min': buildValidationMessages(t).numberMin,\n 'number.max': buildValidationMessages(t).numberMax\n }\n\n return {\n [this.name]: withCustomValidationOverrides(\n defaults,\n customValidationMessage,\n customValidationMessages\n )\n }\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":[]}
|
|
@@ -10,9 +10,7 @@ export declare class YesNoField extends SelectionControlField {
|
|
|
10
10
|
options: YesNoFieldComponent['options'];
|
|
11
11
|
constructor(def: YesNoFieldComponent, props: ConstructorParameters<typeof SelectionControlField>[1]);
|
|
12
12
|
getValidationMessagesOverride(translator: Translator): {
|
|
13
|
-
[x: string]:
|
|
14
|
-
'any.required': string;
|
|
15
|
-
};
|
|
13
|
+
[x: string]: import("joi").LanguageMessages;
|
|
16
14
|
};
|
|
17
15
|
/**
|
|
18
16
|
* For error preview page that shows all possible errors on a component
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SchemaVersion, yesNoListId, yesNoListName } from '@defra/forms-model';
|
|
2
2
|
import { SelectionControlField } from "./SelectionControlField.js";
|
|
3
|
-
import { addClassOptionIfNone } from "./helpers/index.js";
|
|
3
|
+
import { addClassOptionIfNone, withCustomValidationOverrides } from "./helpers/index.js";
|
|
4
4
|
import { buildValidationMessages } from "../i18n/buildValidationMessages.js";
|
|
5
5
|
import { messageTemplate } from "../pageControllers/validationOptions.js";
|
|
6
6
|
/**
|
|
@@ -39,13 +39,18 @@ export class YesNoField extends SelectionControlField {
|
|
|
39
39
|
this.options = options;
|
|
40
40
|
}
|
|
41
41
|
getValidationMessagesOverride(translator) {
|
|
42
|
+
const {
|
|
43
|
+
customValidationMessage,
|
|
44
|
+
customValidationMessages
|
|
45
|
+
} = this.options;
|
|
42
46
|
const {
|
|
43
47
|
selectYesNoRequired
|
|
44
48
|
} = buildValidationMessages(translator.t);
|
|
49
|
+
const defaults = {
|
|
50
|
+
'any.required': selectYesNoRequired
|
|
51
|
+
};
|
|
45
52
|
return {
|
|
46
|
-
[this.name]:
|
|
47
|
-
'any.required': selectYesNoRequired
|
|
48
|
-
}
|
|
53
|
+
[this.name]: withCustomValidationOverrides(defaults, customValidationMessage, customValidationMessages)
|
|
49
54
|
};
|
|
50
55
|
}
|
|
51
56
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"YesNoField.js","names":["SchemaVersion","yesNoListId","yesNoListName","SelectionControlField","addClassOptionIfNone","buildValidationMessages","messageTemplate","YesNoField","constructor","def","props","list","model","schemaVersion","V1","options","formSchema","required","optional","customValidationMessage","message","messages","customValidationMessages","selectYesNoRequired","getValidationMessagesOverride","translator","t","name","getAllPossibleErrors","baseErrors","type","template","advancedSettingsErrors"],"sources":["../../../../../src/server/plugins/engine/components/YesNoField.ts"],"sourcesContent":["import {\n SchemaVersion,\n yesNoListId,\n yesNoListName,\n type YesNoFieldComponent\n} from '@defra/forms-model'\n\nimport { SelectionControlField } from '~/src/server/plugins/engine/components/SelectionControlField.js'\nimport {
|
|
1
|
+
{"version":3,"file":"YesNoField.js","names":["SchemaVersion","yesNoListId","yesNoListName","SelectionControlField","addClassOptionIfNone","withCustomValidationOverrides","buildValidationMessages","messageTemplate","YesNoField","constructor","def","props","list","model","schemaVersion","V1","options","formSchema","required","optional","customValidationMessage","message","messages","customValidationMessages","selectYesNoRequired","getValidationMessagesOverride","translator","t","defaults","name","getAllPossibleErrors","baseErrors","type","template","advancedSettingsErrors"],"sources":["../../../../../src/server/plugins/engine/components/YesNoField.ts"],"sourcesContent":["import {\n SchemaVersion,\n yesNoListId,\n yesNoListName,\n type YesNoFieldComponent\n} from '@defra/forms-model'\n\nimport { SelectionControlField } from '~/src/server/plugins/engine/components/SelectionControlField.js'\nimport {\n addClassOptionIfNone,\n withCustomValidationOverrides\n} from '~/src/server/plugins/engine/components/helpers/index.js'\nimport { buildValidationMessages } from '~/src/server/plugins/engine/i18n/buildValidationMessages.js'\nimport { type Translator } from '~/src/server/plugins/engine/i18n/types.js'\nimport { messageTemplate } from '~/src/server/plugins/engine/pageControllers/validationOptions.js'\nimport { type ErrorMessageTemplateList } from '~/src/server/plugins/engine/types.js'\n\n/**\n * @description\n * YesNoField is a radiosField with predefined values.\n */\nexport class YesNoField extends SelectionControlField {\n declare options: YesNoFieldComponent['options']\n\n constructor(\n def: YesNoFieldComponent,\n props: ConstructorParameters<typeof SelectionControlField>[1]\n ) {\n super(\n {\n ...def,\n list:\n props.model.schemaVersion === SchemaVersion.V1\n ? yesNoListName\n : yesNoListId\n },\n props\n )\n\n const { options } = def\n let { formSchema } = this\n\n addClassOptionIfNone(options, 'govuk-radios--inline')\n\n if (options.required === false) {\n formSchema = formSchema.optional()\n }\n\n if (options.customValidationMessage) {\n const message = options.customValidationMessage\n\n formSchema = formSchema.messages({\n 'any.required': message\n })\n } else if (options.customValidationMessages) {\n formSchema = formSchema.messages(options.customValidationMessages)\n } else {\n formSchema = formSchema.messages({\n 'any.required': messageTemplate.selectYesNoRequired\n })\n }\n\n this.formSchema = formSchema\n this.options = options\n }\n\n getValidationMessagesOverride(translator: Translator) {\n const { customValidationMessage, customValidationMessages } = this.options\n const { selectYesNoRequired } = buildValidationMessages(translator.t)\n const defaults = {\n 'any.required': selectYesNoRequired\n }\n\n return {\n [this.name]: withCustomValidationOverrides(\n defaults,\n customValidationMessage,\n customValidationMessages\n )\n }\n }\n\n /**\n * For error preview page that shows all possible errors on a component\n */\n getAllPossibleErrors(): ErrorMessageTemplateList {\n return YesNoField.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 {\n type: 'selectYesNoRequired',\n template: messageTemplate.selectYesNoRequired\n }\n ],\n advancedSettingsErrors: []\n }\n }\n}\n"],"mappings":"AAAA,SACEA,aAAa,EACbC,WAAW,EACXC,aAAa,QAER,oBAAoB;AAE3B,SAASC,qBAAqB;AAC9B,SACEC,oBAAoB,EACpBC,6BAA6B;AAE/B,SAASC,uBAAuB;AAEhC,SAASC,eAAe;AAGxB;AACA;AACA;AACA;AACA,OAAO,MAAMC,UAAU,SAASL,qBAAqB,CAAC;EAGpDM,WAAWA,CACTC,GAAwB,EACxBC,KAA6D,EAC7D;IACA,KAAK,CACH;MACE,GAAGD,GAAG;MACNE,IAAI,EACFD,KAAK,CAACE,KAAK,CAACC,aAAa,KAAKd,aAAa,CAACe,EAAE,GAC1Cb,aAAa,GACbD;IACR,CAAC,EACDU,KACF,CAAC;IAED,MAAM;MAAEK;IAAQ,CAAC,GAAGN,GAAG;IACvB,IAAI;MAAEO;IAAW,CAAC,GAAG,IAAI;IAEzBb,oBAAoB,CAACY,OAAO,EAAE,sBAAsB,CAAC;IAErD,IAAIA,OAAO,CAACE,QAAQ,KAAK,KAAK,EAAE;MAC9BD,UAAU,GAAGA,UAAU,CAACE,QAAQ,CAAC,CAAC;IACpC;IAEA,IAAIH,OAAO,CAACI,uBAAuB,EAAE;MACnC,MAAMC,OAAO,GAAGL,OAAO,CAACI,uBAAuB;MAE/CH,UAAU,GAAGA,UAAU,CAACK,QAAQ,CAAC;QAC/B,cAAc,EAAED;MAClB,CAAC,CAAC;IACJ,CAAC,MAAM,IAAIL,OAAO,CAACO,wBAAwB,EAAE;MAC3CN,UAAU,GAAGA,UAAU,CAACK,QAAQ,CAACN,OAAO,CAACO,wBAAwB,CAAC;IACpE,CAAC,MAAM;MACLN,UAAU,GAAGA,UAAU,CAACK,QAAQ,CAAC;QAC/B,cAAc,EAAEf,eAAe,CAACiB;MAClC,CAAC,CAAC;IACJ;IAEA,IAAI,CAACP,UAAU,GAAGA,UAAU;IAC5B,IAAI,CAACD,OAAO,GAAGA,OAAO;EACxB;EAEAS,6BAA6BA,CAACC,UAAsB,EAAE;IACpD,MAAM;MAAEN,uBAAuB;MAAEG;IAAyB,CAAC,GAAG,IAAI,CAACP,OAAO;IAC1E,MAAM;MAAEQ;IAAoB,CAAC,GAAGlB,uBAAuB,CAACoB,UAAU,CAACC,CAAC,CAAC;IACrE,MAAMC,QAAQ,GAAG;MACf,cAAc,EAAEJ;IAClB,CAAC;IAED,OAAO;MACL,CAAC,IAAI,CAACK,IAAI,GAAGxB,6BAA6B,CACxCuB,QAAQ,EACRR,uBAAuB,EACvBG,wBACF;IACF,CAAC;EACH;;EAEA;AACF;AACA;EACEO,oBAAoBA,CAAA,EAA6B;IAC/C,OAAOtB,UAAU,CAACsB,oBAAoB,CAAC,CAAC;EAC1C;;EAEA;AACF;AACA;EACE,OAAOA,oBAAoBA,CAAA,EAA6B;IACtD,OAAO;MACLC,UAAU,EAAE,CACV;QACEC,IAAI,EAAE,qBAAqB;QAC3BC,QAAQ,EAAE1B,eAAe,CAACiB;MAC5B,CAAC,CACF;MACDU,sBAAsB,EAAE;IAC1B,CAAC;EACH;AACF","ignoreList":[]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ComponentDef } from '@defra/forms-model';
|
|
2
|
-
import { type JoiExpression, type ReferenceOptions } from 'joi';
|
|
2
|
+
import { type JoiExpression, type LanguageMessages, type ReferenceOptions } from 'joi';
|
|
3
3
|
import { type Translator } from '../../../../../server/plugins/engine/i18n/types.js';
|
|
4
4
|
/**
|
|
5
5
|
* Prevent Markdown formatting
|
|
@@ -25,9 +25,22 @@ export declare const lowerFirstExpressionOptions: ReferenceOptions;
|
|
|
25
25
|
* Used for error messages in location field components
|
|
26
26
|
*/
|
|
27
27
|
export declare const createLowerFirstExpression: (template: string) => JoiExpression;
|
|
28
|
+
/**
|
|
29
|
+
* Joi's own LanguageMessages type only allows string values, but
|
|
30
|
+
* buildValidationMessages() returns JoiExpression for templated messages,
|
|
31
|
+
* which Joi accepts at runtime. This type covers both.
|
|
32
|
+
*/
|
|
33
|
+
type TranslatedValidationMessages = Record<string, string | JoiExpression>;
|
|
34
|
+
/**
|
|
35
|
+
* Keep the form author's custom validation message for any key they set,
|
|
36
|
+
* so translated defaults only fill in the keys the author left blank.
|
|
37
|
+
* A single customValidationMessage covers every key in the schema.
|
|
38
|
+
*/
|
|
39
|
+
export declare function withCustomValidationOverrides(defaults: TranslatedValidationMessages, customValidationMessage?: string, customValidationMessages?: LanguageMessages): LanguageMessages;
|
|
28
40
|
/**
|
|
29
41
|
* Translate a component label, in precedence order of errorDescription, then shortDesciption, then title
|
|
30
42
|
* @param {ComponentDef} component
|
|
31
43
|
* @param {Translator} translator
|
|
32
44
|
*/
|
|
33
45
|
export declare function getTranslatedLabel(component: ComponentDef, translator: Translator): string;
|
|
46
|
+
export {};
|
|
@@ -39,6 +39,38 @@ export const lowerFirstExpressionOptions = {
|
|
|
39
39
|
*/
|
|
40
40
|
export const createLowerFirstExpression = template => joi.expression(template, lowerFirstExpressionOptions);
|
|
41
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Joi's own LanguageMessages type only allows string values, but
|
|
44
|
+
* buildValidationMessages() returns JoiExpression for templated messages,
|
|
45
|
+
* which Joi accepts at runtime. This type covers both.
|
|
46
|
+
*/
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Keep the form author's custom validation message for any key they set,
|
|
50
|
+
* so translated defaults only fill in the keys the author left blank.
|
|
51
|
+
* A single customValidationMessage covers every key in the schema.
|
|
52
|
+
*/
|
|
53
|
+
export function withCustomValidationOverrides(defaults, customValidationMessage, customValidationMessages) {
|
|
54
|
+
const messages = {};
|
|
55
|
+
|
|
56
|
+
// A global override for all messages is the value for all scenarios
|
|
57
|
+
if (customValidationMessage) {
|
|
58
|
+
for (const key of Object.keys(defaults)) {
|
|
59
|
+
messages[key] = customValidationMessage;
|
|
60
|
+
}
|
|
61
|
+
return messages;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// A default only fills a key that the user has not configured
|
|
65
|
+
const authorKeys = Object.keys(customValidationMessages ?? {});
|
|
66
|
+
for (const [key, message] of Object.entries(defaults)) {
|
|
67
|
+
if (!authorKeys.includes(key)) {
|
|
68
|
+
messages[key] = message;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return messages;
|
|
72
|
+
}
|
|
73
|
+
|
|
42
74
|
/**
|
|
43
75
|
* Translate a component label, in precedence order of errorDescription, then shortDesciption, then title
|
|
44
76
|
* @param {ComponentDef} component
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["joi","lowerFirst","escapeMarkdown","answer","punctuation","character","replaceAll","addClassOptionIfNone","options","className","classes","lowerFirstPreserveProperNouns","text","result","replace","lowerFirstExpressionOptions","functions","createLowerFirstExpression","template","expression","getTranslatedLabel","component","translator","tComponent","translatedLabel"],"sources":["../../../../../../src/server/plugins/engine/components/helpers/index.ts"],"sourcesContent":["import { type ComponentDef } from '@defra/forms-model'\nimport joi, {
|
|
1
|
+
{"version":3,"file":"index.js","names":["joi","lowerFirst","escapeMarkdown","answer","punctuation","character","replaceAll","addClassOptionIfNone","options","className","classes","lowerFirstPreserveProperNouns","text","result","replace","lowerFirstExpressionOptions","functions","createLowerFirstExpression","template","expression","withCustomValidationOverrides","defaults","customValidationMessage","customValidationMessages","messages","key","Object","keys","authorKeys","message","entries","includes","getTranslatedLabel","component","translator","tComponent","translatedLabel"],"sources":["../../../../../../src/server/plugins/engine/components/helpers/index.ts"],"sourcesContent":["import { type ComponentDef } from '@defra/forms-model'\nimport joi, {\n type JoiExpression,\n type LanguageMessages,\n type ReferenceOptions\n} from 'joi'\nimport lowerFirst from 'lodash/lowerFirst.js'\n\nimport { type Translator } from '~/src/server/plugins/engine/i18n/types.js'\n\n/**\n * Prevent Markdown formatting\n * @see {@link https://pandoc.org/chunkedhtml-demo/8.11-backslash-escapes.html}\n */\nexport function escapeMarkdown(answer: string) {\n const punctuation = [\n '`',\n \"'\",\n '*',\n '_',\n '{',\n '}',\n '[',\n ']',\n '(',\n ')',\n '#',\n '+',\n '-',\n '.',\n '!'\n ]\n\n for (const character of punctuation) {\n answer = answer.replaceAll(character, `\\\\${character}`)\n }\n\n return answer\n}\n\nexport const addClassOptionIfNone = (\n options: Extract<ComponentDef, { options: { classes?: string } }>['options'],\n className: string\n) => {\n options.classes ??= className\n}\n\n/**\n * Applies lowerFirst but preserves capitalisation of proper nouns\n * like \"National Grid\", \"Ordnance Survey\" and \"OS\".\n */\nexport function lowerFirstPreserveProperNouns(text: string): string {\n const result = lowerFirst(text)\n return result\n .replace(/\\bnational [Gg]rid\\b/g, 'National Grid')\n .replace(/\\bordnance [Ss]urvey\\b/g, 'Ordnance Survey')\n .replace(/\\b[oO][sS]\\b/g, 'OS')\n}\n\n/**\n * Configuration for Joi expressions that use lowerFirst function\n */\nexport const lowerFirstExpressionOptions = {\n functions: {\n lowerFirst: lowerFirstPreserveProperNouns\n }\n} as ReferenceOptions\n\n/**\n * Creates a Joi expression with lowerFirst function support\n * Used for error messages in location field components\n */\nexport const createLowerFirstExpression = (template: string): JoiExpression =>\n joi.expression(template, lowerFirstExpressionOptions) as JoiExpression\n\n/**\n * Joi's own LanguageMessages type only allows string values, but\n * buildValidationMessages() returns JoiExpression for templated messages,\n * which Joi accepts at runtime. This type covers both.\n */\ntype TranslatedValidationMessages = Record<string, string | JoiExpression>\n\n/**\n * Keep the form author's custom validation message for any key they set,\n * so translated defaults only fill in the keys the author left blank.\n * A single customValidationMessage covers every key in the schema.\n */\nexport function withCustomValidationOverrides(\n defaults: TranslatedValidationMessages,\n customValidationMessage?: string,\n customValidationMessages?: LanguageMessages\n): LanguageMessages {\n const messages: TranslatedValidationMessages = {}\n\n // A global override for all messages is the value for all scenarios\n if (customValidationMessage) {\n for (const key of Object.keys(defaults)) {\n messages[key] = customValidationMessage\n }\n\n return messages as LanguageMessages\n }\n\n // A default only fills a key that the user has not configured\n const authorKeys = Object.keys(customValidationMessages ?? {})\n\n for (const [key, message] of Object.entries(defaults)) {\n if (!authorKeys.includes(key)) {\n messages[key] = message\n }\n }\n\n return messages as LanguageMessages\n}\n\n/**\n * Translate a component label, in precedence order of errorDescription, then shortDesciption, then title\n * @param {ComponentDef} component\n * @param {Translator} translator\n */\nexport function getTranslatedLabel(\n component: ComponentDef,\n translator: Translator\n) {\n const { tComponent } = translator\n const translatedLabel =\n tComponent(component, 'errorDescription') ||\n tComponent(component, 'shortDescription') ||\n tComponent(component, 'title')\n return translatedLabel\n}\n"],"mappings":"AACA,OAAOA,GAAG,MAIH,KAAK;AACZ,OAAOC,UAAU,MAAM,sBAAsB;AAI7C;AACA;AACA;AACA;AACA,OAAO,SAASC,cAAcA,CAACC,MAAc,EAAE;EAC7C,MAAMC,WAAW,GAAG,CAClB,GAAG,EACH,GAAG,EACH,GAAG,EACH,GAAG,EACH,GAAG,EACH,GAAG,EACH,GAAG,EACH,GAAG,EACH,GAAG,EACH,GAAG,EACH,GAAG,EACH,GAAG,EACH,GAAG,EACH,GAAG,EACH,GAAG,CACJ;EAED,KAAK,MAAMC,SAAS,IAAID,WAAW,EAAE;IACnCD,MAAM,GAAGA,MAAM,CAACG,UAAU,CAACD,SAAS,EAAE,KAAKA,SAAS,EAAE,CAAC;EACzD;EAEA,OAAOF,MAAM;AACf;AAEA,OAAO,MAAMI,oBAAoB,GAAGA,CAClCC,OAA4E,EAC5EC,SAAiB,KACd;EACHD,OAAO,CAACE,OAAO,KAAKD,SAAS;AAC/B,CAAC;;AAED;AACA;AACA;AACA;AACA,OAAO,SAASE,6BAA6BA,CAACC,IAAY,EAAU;EAClE,MAAMC,MAAM,GAAGZ,UAAU,CAACW,IAAI,CAAC;EAC/B,OAAOC,MAAM,CACVC,OAAO,CAAC,uBAAuB,EAAE,eAAe,CAAC,CACjDA,OAAO,CAAC,yBAAyB,EAAE,iBAAiB,CAAC,CACrDA,OAAO,CAAC,eAAe,EAAE,IAAI,CAAC;AACnC;;AAEA;AACA;AACA;AACA,OAAO,MAAMC,2BAA2B,GAAG;EACzCC,SAAS,EAAE;IACTf,UAAU,EAAEU;EACd;AACF,CAAqB;;AAErB;AACA;AACA;AACA;AACA,OAAO,MAAMM,0BAA0B,GAAIC,QAAgB,IACzDlB,GAAG,CAACmB,UAAU,CAACD,QAAQ,EAAEH,2BAA2B,CAAkB;;AAExE;AACA;AACA;AACA;AACA;;AAGA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASK,6BAA6BA,CAC3CC,QAAsC,EACtCC,uBAAgC,EAChCC,wBAA2C,EACzB;EAClB,MAAMC,QAAsC,GAAG,CAAC,CAAC;;EAEjD;EACA,IAAIF,uBAAuB,EAAE;IAC3B,KAAK,MAAMG,GAAG,IAAIC,MAAM,CAACC,IAAI,CAACN,QAAQ,CAAC,EAAE;MACvCG,QAAQ,CAACC,GAAG,CAAC,GAAGH,uBAAuB;IACzC;IAEA,OAAOE,QAAQ;EACjB;;EAEA;EACA,MAAMI,UAAU,GAAGF,MAAM,CAACC,IAAI,CAACJ,wBAAwB,IAAI,CAAC,CAAC,CAAC;EAE9D,KAAK,MAAM,CAACE,GAAG,EAAEI,OAAO,CAAC,IAAIH,MAAM,CAACI,OAAO,CAACT,QAAQ,CAAC,EAAE;IACrD,IAAI,CAACO,UAAU,CAACG,QAAQ,CAACN,GAAG,CAAC,EAAE;MAC7BD,QAAQ,CAACC,GAAG,CAAC,GAAGI,OAAO;IACzB;EACF;EAEA,OAAOL,QAAQ;AACjB;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO,SAASQ,kBAAkBA,CAChCC,SAAuB,EACvBC,UAAsB,EACtB;EACA,MAAM;IAAEC;EAAW,CAAC,GAAGD,UAAU;EACjC,MAAME,eAAe,GACnBD,UAAU,CAACF,SAAS,EAAE,kBAAkB,CAAC,IACzCE,UAAU,CAACF,SAAS,EAAE,kBAAkB,CAAC,IACzCE,UAAU,CAACF,SAAS,EAAE,OAAO,CAAC;EAChC,OAAOG,eAAe;AACxB","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@defra/forms-engine-plugin",
|
|
3
|
-
"version": "5.0.0-alpha.
|
|
3
|
+
"version": "5.0.0-alpha.29",
|
|
4
4
|
"description": "Defra forms engine",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
@@ -92,9 +92,9 @@
|
|
|
92
92
|
},
|
|
93
93
|
"license": "SEE LICENSE IN LICENSE",
|
|
94
94
|
"dependencies": {
|
|
95
|
-
"@defra/forms-model": "^
|
|
95
|
+
"@defra/forms-model": "^4.0.0",
|
|
96
96
|
"@defra/hapi-tracing": "^1.29.0",
|
|
97
|
-
"@defra/interactive-map": "0.0.
|
|
97
|
+
"@defra/interactive-map": "^0.0.56-alpha",
|
|
98
98
|
"@elastic/ecs-pino-format": "^1.5.0",
|
|
99
99
|
"@hapi/boom": "^10.0.1",
|
|
100
100
|
"@hapi/bourne": "^3.0.0",
|
|
@@ -134,11 +134,10 @@
|
|
|
134
134
|
"humanize-duration": "^3.33.1",
|
|
135
135
|
"i18next": "^26.0.5",
|
|
136
136
|
"ioredis": "^5.8.2",
|
|
137
|
-
"joi": "^
|
|
137
|
+
"joi": "^18.2.9",
|
|
138
138
|
"liquidjs": "^10.24.0",
|
|
139
139
|
"lodash": "^4.17.21",
|
|
140
140
|
"lru-cache": "^11.5.1",
|
|
141
|
-
"maplibre-gl": "^5.24.0",
|
|
142
141
|
"marked": "^15.0.12",
|
|
143
142
|
"nunjucks": "^3.2.4",
|
|
144
143
|
"obscenity": "^0.4.5",
|
|
@@ -155,7 +154,7 @@
|
|
|
155
154
|
"@babel/plugin-syntax-import-attributes": "^7.27.1",
|
|
156
155
|
"@babel/preset-env": "^7.28.5",
|
|
157
156
|
"@babel/preset-typescript": "^7.28.5",
|
|
158
|
-
"@defra/docusaurus-theme-govuk": "^0.0
|
|
157
|
+
"@defra/docusaurus-theme-govuk": "^1.0.0",
|
|
159
158
|
"@docusaurus/core": "^3.10.1",
|
|
160
159
|
"@docusaurus/plugin-content-docs": "^3.10.1",
|
|
161
160
|
"@easyops-cn/docusaurus-search-local": "^0.55.0",
|
|
@@ -219,6 +218,7 @@
|
|
|
219
218
|
"prettier": "^3.6.2",
|
|
220
219
|
"react": "^19.2.4",
|
|
221
220
|
"react-dom": "^19.2.4",
|
|
221
|
+
"react-router-dom": "^5.3.4",
|
|
222
222
|
"sass-embedded": "^1.93.3",
|
|
223
223
|
"sass-loader": "^16.0.6",
|
|
224
224
|
"source-map-loader": "^5.0.0",
|