diff --git a/CHANGES.md b/CHANGES.md index 8411413e..901a31ba 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,33 +1,51 @@ +## 16.3.1 + +--- + +- Included bugfix from version 16.2.3 in current version + +## 16.3.0 + +--- + +- Changed default validation mode to onTouched + +## 16.2.3 + +--- + +- Bugfix in attachment: Wrong validation texts were displayed on error ## 16.2.2 --- -- Formatted code +- Formatted code ## 16.2.1 --- -- Support for Microweb Form buttons override in case custom props is set +- Support for Microweb Form buttons override in case custom props is set ## 16.2.0 --- + - Support for accepting a prop for rendering your own action buttons in the form component - Updated props description for form component - ## 16.1.0 --- + - Support for Microweb Step in refero - Callbacks and override for formbuttons - ## 16.0.9 --- + - add dompurify to peerdependencies and remove from dependencies - Bugfix: fix decimal field to only accept numbers and one period diff --git a/package-lock.json b/package-lock.json index d3cc9645..cefa4daa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@helsenorge/refero", - "version": "16.2.2", + "version": "16.3.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@helsenorge/refero", - "version": "16.2.2", + "version": "16.3.1", "license": "MIT", "dependencies": { "@helsenorge/core-utils": "^33.0.0", @@ -1353,38 +1353,38 @@ } }, "node_modules/@microsoft/api-extractor": { - "version": "7.48.1", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.48.1.tgz", - "integrity": "sha512-HN9Osa1WxqLM66RaqB5nPAadx+nTIQmY/XtkFdaJvusjG8Tus++QqZtD7KPZDSkhEMGHsYeSyeU8qUzCDUXPjg==", + "version": "7.49.1", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor/-/api-extractor-7.49.1.tgz", + "integrity": "sha512-jRTR/XbQF2kb+dYn8hfYSicOGA99+Fo00GrsdMwdfE3eIgLtKdH6Qa2M3wZV9S2XmbgCaGX1OdPtYctbfu5jQg==", "dev": true, "dependencies": { - "@microsoft/api-extractor-model": "7.30.1", + "@microsoft/api-extractor-model": "7.30.2", "@microsoft/tsdoc": "~0.15.1", "@microsoft/tsdoc-config": "~0.17.1", - "@rushstack/node-core-library": "5.10.1", + "@rushstack/node-core-library": "5.10.2", "@rushstack/rig-package": "0.5.3", - "@rushstack/terminal": "0.14.4", - "@rushstack/ts-command-line": "4.23.2", + "@rushstack/terminal": "0.14.5", + "@rushstack/ts-command-line": "4.23.3", "lodash": "~4.17.15", "minimatch": "~3.0.3", "resolve": "~1.22.1", "semver": "~7.5.4", "source-map": "~0.6.1", - "typescript": "5.4.2" + "typescript": "5.7.2" }, "bin": { "api-extractor": "bin/api-extractor" } }, "node_modules/@microsoft/api-extractor-model": { - "version": "7.30.1", - "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.30.1.tgz", - "integrity": "sha512-CTS2PlASJHxVY8hqHORVb1HdECWOEMcMnM6/kDkPr0RZapAFSIHhg9D4jxuE8g+OWYHtPc10LCpmde5pylTRlA==", + "version": "7.30.2", + "resolved": "https://registry.npmjs.org/@microsoft/api-extractor-model/-/api-extractor-model-7.30.2.tgz", + "integrity": "sha512-3/t2F+WhkJgBzSNwlkTIL0tBgUoBqDqL66pT+nh2mPbM0NIDGVGtpqbGWPgHIzn/mn7kGS/Ep8D8po58e8UUIw==", "dev": true, "dependencies": { "@microsoft/tsdoc": "~0.15.1", "@microsoft/tsdoc-config": "~0.17.1", - "@rushstack/node-core-library": "5.10.1" + "@rushstack/node-core-library": "5.10.2" } }, "node_modules/@microsoft/api-extractor/node_modules/brace-expansion": { @@ -1437,9 +1437,9 @@ } }, "node_modules/@microsoft/api-extractor/node_modules/typescript": { - "version": "5.4.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.2.tgz", - "integrity": "sha512-+2/g0Fds1ERlP6JsakQQDXjZdZMM+rqpamFZJEKh4kwTIn3iDkgKtby0CeNd5ATNZ4Ry1ax15TMx0W2V+miizQ==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", + "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -2203,9 +2203,9 @@ "license": "MIT" }, "node_modules/@rushstack/node-core-library": { - "version": "5.10.1", - "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.10.1.tgz", - "integrity": "sha512-BSb/KcyBHmUQwINrgtzo6jiH0HlGFmrUy33vO6unmceuVKTEyL2q+P0fQq2oB5hvXVWOEUhxB2QvlkZluvUEmg==", + "version": "5.10.2", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-5.10.2.tgz", + "integrity": "sha512-xOF/2gVJZTfjTxbo4BDj9RtQq/HFnrrKdtem4JkyRLnwsRz2UDTg8gA1/et10fBx5RxmZD9bYVGST69W8ME5OQ==", "dev": true, "dependencies": { "ajv": "~8.13.0", @@ -2329,12 +2329,12 @@ } }, "node_modules/@rushstack/terminal": { - "version": "0.14.4", - "resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.14.4.tgz", - "integrity": "sha512-NxACqERW0PHq8Rpq1V6v5iTHEwkRGxenjEW+VWqRYQ8T9puUzgmGHmEZUaUEDHAe9Qyvp0/Ew04sAiQw9XjhJg==", + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/@rushstack/terminal/-/terminal-0.14.5.tgz", + "integrity": "sha512-TEOpNwwmsZVrkp0omnuTUTGZRJKTr6n6m4OITiNjkqzLAkcazVpwR1SOtBg6uzpkIBLgrcNHETqI8rbw3uiUfw==", "dev": true, "dependencies": { - "@rushstack/node-core-library": "5.10.1", + "@rushstack/node-core-library": "5.10.2", "supports-color": "~8.1.1" }, "peerDependencies": { @@ -2362,12 +2362,12 @@ } }, "node_modules/@rushstack/ts-command-line": { - "version": "4.23.2", - "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.23.2.tgz", - "integrity": "sha512-JJ7XZX5K3ThBBva38aomgsPv1L7FV6XmSOcR6HtM7HDFZJkepqT65imw26h9ggGqMjsY0R9jcl30tzKcVj9aOQ==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/@rushstack/ts-command-line/-/ts-command-line-4.23.3.tgz", + "integrity": "sha512-HazKL8fv4HMQMzrKJCrOrhyBPPdzk7iajUXgsASwjQ8ROo1cmgyqxt/k9+SdmrNLGE1zATgRqMUH3s/6smbRMA==", "dev": true, "dependencies": { - "@rushstack/terminal": "0.14.4", + "@rushstack/terminal": "0.14.5", "@types/argparse": "1.0.38", "argparse": "~1.0.9", "string-argv": "~0.3.1" @@ -2689,11 +2689,10 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "20.17.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.10.tgz", - "integrity": "sha512-/jrvh5h6NXhEauFFexRin69nA0uHJ5gwk4iDivp/DeoEua3uwCUto6PC86IpRITBOs4+6i2I56K5x5b6WYGXHA==", + "version": "20.17.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.12.tgz", + "integrity": "sha512-vo/wmBgMIiEA23A/knMfn/cf37VnuF52nZh5ZoW0GWt4e4sxNquibrMRJ7UQsA06+MBx9r/H1jsI9grYjQCQlw==", "dev": true, - "license": "MIT", "dependencies": { "undici-types": "~6.19.2" } @@ -3271,16 +3270,16 @@ } }, "node_modules/@vue/language-core": { - "version": "2.1.10", - "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.1.10.tgz", - "integrity": "sha512-DAI289d0K3AB5TUG3xDp9OuQ71CnrujQwJrQnfuZDwo6eGNf0UoRlPuaVNO+Zrn65PC3j0oB2i7mNmVPggeGeQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-2.2.0.tgz", + "integrity": "sha512-O1ZZFaaBGkKbsRfnVH1ifOK1/1BUkyK+3SQsfnh6PmMmD4qJcTU8godCeA96jjDRTL6zgnK7YzCHfaUlH2r0Mw==", "dev": true, "dependencies": { - "@volar/language-core": "~2.4.8", + "@volar/language-core": "~2.4.11", "@vue/compiler-dom": "^3.5.0", "@vue/compiler-vue2": "^2.7.16", "@vue/shared": "^3.5.0", - "alien-signals": "^0.2.0", + "alien-signals": "^0.4.9", "minimatch": "^9.0.3", "muggle-string": "^0.4.1", "path-browserify": "^1.0.1" @@ -3605,9 +3604,9 @@ } }, "node_modules/alien-signals": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-0.2.2.tgz", - "integrity": "sha512-cZIRkbERILsBOXTQmMrxc9hgpxglstn69zm+F1ARf4aPAzdAFYd6sBq87ErO0Fj3DV94tglcyHG5kQz9nDC/8A==", + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-0.4.14.tgz", + "integrity": "sha512-itUAVzhczTmP2U5yX67xVpsbbOiquusbWVyA9N+sy6+r6YVbFkahXvNCeEPWEOMhwDYwbVbGHFkVL03N9I5g+Q==", "dev": true }, "node_modules/ansi-regex": { @@ -6013,10 +6012,20 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", - "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", - "dev": true + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.5.tgz", + "integrity": "sha512-5JnBCWpFlMo0a3ciDy/JckMzzv1U9coZrIhedq+HXxxUfDTAiS0LA8OKVao4G9BxmCVck/jtA5r3KAtRWEyD8Q==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ] }, "node_modules/fastq": { "version": "1.17.1", @@ -10985,11 +10994,10 @@ } }, "node_modules/typescript": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", - "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", + "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", "dev": true, - "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -11210,24 +11218,21 @@ } }, "node_modules/vite-plugin-dts": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/vite-plugin-dts/-/vite-plugin-dts-4.4.0.tgz", - "integrity": "sha512-CJ6phvnnPLF+aFk8Jz2ZcMBLleJ4gKJOXb9We5Kzmsp5bPuD+uMDeVefjFNYSXZ+wdcqnf+Yp2P7oA5hBKQTlQ==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/vite-plugin-dts/-/vite-plugin-dts-4.5.0.tgz", + "integrity": "sha512-M1lrPTdi7gilLYRZoLmGYnl4fbPryVYsehPN9JgaxjJKTs8/f7tuAlvCCvOLB5gRDQTTKnptBcB0ACsaw2wNLw==", "dev": true, "dependencies": { - "@microsoft/api-extractor": "^7.48.1", + "@microsoft/api-extractor": "^7.49.1", "@rollup/pluginutils": "^5.1.4", "@volar/typescript": "^2.4.11", - "@vue/language-core": "2.1.10", + "@vue/language-core": "2.2.0", "compare-versions": "^6.1.1", "debug": "^4.4.0", "kolorist": "^1.8.0", "local-pkg": "^0.5.1", "magic-string": "^0.30.17" }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, "peerDependencies": { "typescript": "*", "vite": "*" diff --git a/package.json b/package.json index d31e3d28..1343a81f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@helsenorge/refero", - "version": "16.2.2", + "version": "16.3.1", "description": "Refero is a library that uses a fhir r4 schema and creates a interactive form using helsenorge packages.", "keywords": [ "react", diff --git a/preview/resources/referoResources.ts b/preview/resources/referoResources.ts index 56239a60..6b77a0dc 100644 --- a/preview/resources/referoResources.ts +++ b/preview/resources/referoResources.ts @@ -64,7 +64,8 @@ export const getResources = (language: string): Resources => { previousStep: 'Previous', attachmentError_required: 'Upload file', attachmentError_minFiles: 'Add at least {0} file(s)', - attachmentError_maxFiles: 'Maximum of {0} file(s) are allowed', + attachmentError_maxFiles: 'Maximum of {1} file(s) are allowed', + attachmentError_minFiles_and_maxFiles: 'At least {0} file(s) and a maximum of {1} file(s) are allowed', attachmentError_fileSize: 'File size must be less than {0}MB', attachmentError_fileType: 'Allowed file types are:', dateError_invalid: 'Invalid date', @@ -152,7 +153,8 @@ export const getResources = (language: string): Resources => { previousStep: 'Précédent', attachmentError_required: 'Upload file', attachmentError_minFiles: 'Add at least {0} file(s)', - attachmentError_maxFiles: 'Maximum of {0} file(s) are allowed', + attachmentError_maxFiles: 'Maximum of {1} file(s) are allowed', + attachmentError_minFiles_and_maxFiles: 'At least {0} file(s) and a maximum of {1} file(s) are allowed', attachmentError_fileSize: 'File size must be less than {0}MB', attachmentError_fileType: 'Allowed file types are:', dateError_invalid: 'Invalid date', @@ -239,7 +241,8 @@ export const getResources = (language: string): Resources => { previousStep: 'Forrige', attachmentError_required: 'Last opp fil', attachmentError_minFiles: 'Legg til minst {0} fil(er)', - attachmentError_maxFiles: 'Maks {0} fil(er) er tillatt', + attachmentError_maxFiles: 'Maks {1} fil(er) er tillatt', + attachmentError_minFiles_and_maxFiles: 'Minst {0} fil(er) og maks {1} fil(er) er tillatt', attachmentError_fileSize: 'Filstørrelse må være mindre enn {0}MB', attachmentError_fileType: 'Tillatte filtyper er:', dateError_invalid: 'Ugyldig dato', diff --git a/preview/skjema/q.json b/preview/skjema/q.json index d380e01f..d3bd1f70 100644 --- a/preview/skjema/q.json +++ b/preview/skjema/q.json @@ -102,155 +102,25 @@ ], "item": [ { - "linkId": "3c1d0ce2-0092-47f5-80d9-49ee4c408e9a", - "type": "group", - "text": "Masse text", - "item": [ - { - "linkId": "e92f2c98-7725-4054-8b8b-b1eedbfca679", - "type": "display", - "text": "Textenba sda adasdsdg sfsdgdfgdfb dsdssd f= minFiles)) { return true; } - if (getCustomValidationText(item, genericErrorText)) { - return getCustomValidationText(item, genericErrorText); + if (getValidationTextForAttachment(item, genericErrorText)) { + return getValidationTextForAttachment(item, genericErrorText); } return errorMessage ? errorMessage.replace('{0}', minFiles.toString()) : ''; }; @@ -31,8 +32,8 @@ export const validateMaxFiles = ( if (!maxFiles || (files && files.length <= maxFiles)) { return true; } - if (getCustomValidationText(item, genericErrorText)) { - return getCustomValidationText(item, genericErrorText); + if (getValidationTextForAttachment(item, genericErrorText)) { + return getValidationTextForAttachment(item, genericErrorText); } return errorMessage ? errorMessage.replace('{0}', maxFiles.toString()) : ''; }; @@ -47,8 +48,8 @@ export const validateFileSize = ( if (sizeIsValid(file, maxSize)) { return true; } - if (getCustomValidationText(item, genericErrorText)) { - return getCustomValidationText(item, genericErrorText); + if (getValidationTextForAttachment(item, genericErrorText)) { + return getValidationTextForAttachment(item, genericErrorText); } return errorMessage ? errorMessage.replace('{0}', convertBytesToMBString(maxSize)) : ''; }; @@ -63,8 +64,8 @@ export const validateFileType = ( if (mimeTypeIsValid(file, validTypes)) { return true; } - if (getCustomValidationText(item, genericErrorText)) { - return getCustomValidationText(item, genericErrorText); + if (getValidationTextForAttachment(item, genericErrorText)) { + return getValidationTextForAttachment(item, genericErrorText); } return errorMessage ? errorMessage + ` ${validTypes.join(', ')}.` : ''; }; @@ -83,14 +84,36 @@ const sizeIsValid = (file: UploadFile, size: number): boolean => { return true; }; -export const getCustomValidationText = (item?: QuestionnaireItem, genericErrorText?: string): string => { - const validationText = getValidationTextExtension(item); - if (validationText) { - return validationText; +export const getNumberOfFilesValidationText = ( + item: QuestionnaireItem | undefined, + minFiles: number | undefined, + maxFiles: number | undefined, + resources: Resources | undefined +): string => { + let validationText = + (minFiles && !maxFiles && resources?.attachmentError_minFiles) || + (maxFiles && !minFiles && resources?.attachmentError_maxFiles) || + (maxFiles && minFiles && resources?.attachmentError_minFiles_and_maxFiles) || + undefined; + + if (minFiles) { + validationText = validationText?.replace('{0}', minFiles?.toString()); + } + if (maxFiles) { + validationText = validationText?.replace('{1}', maxFiles?.toString()); + } + + return getValidationTextForAttachment(item, validationText); +}; + +export const getValidationTextForAttachment = (item?: QuestionnaireItem, validationText?: string): string => { + const validationTextExtension = getValidationTextExtension(item); + if (validationTextExtension) { + return validationTextExtension; } - if (genericErrorText) { - return genericErrorText; + if (validationText) { + return validationText; } return ''; }; diff --git a/src/components/formcomponents/attachment/attachmenthtml.tsx b/src/components/formcomponents/attachment/attachmenthtml.tsx index a244ed59..a3bede7c 100644 --- a/src/components/formcomponents/attachment/attachmenthtml.tsx +++ b/src/components/formcomponents/attachment/attachmenthtml.tsx @@ -7,7 +7,7 @@ import NotificationPanel from '@helsenorge/designsystem-react/components/Notific import FileUpload, { MimeTypes, UploadFile } from '@helsenorge/file-upload/components/file-upload'; import { useFileUpload } from '@helsenorge/file-upload/components/file-upload/useFileUpload'; -import { getCustomValidationText } from './attachment-validation'; +import { getNumberOfFilesValidationText, getValidationTextForAttachment } from './attachment-validation'; import { validateNumberOfFiles, validateFileType, @@ -20,12 +20,12 @@ import { getId, isReadOnly } from '@/util'; import { Resources } from '@/util/resources'; import { ReferoLabel } from '@/components/referoLabel/ReferoLabel'; -import { TextMessage } from '@/types/text-message'; import { QuestionnaireComponentItemProps } from '@/components/createQuestionnaire/GenerateQuestionnaireComponents'; import { ReadOnly } from '../read-only/readOnly'; import { getErrorMessage } from '@/components/validation/rules'; import { shouldValidate } from '@/components/validation/utils'; import { useAttachmentSync } from './useAttachmentSync'; +import { TextMessage } from '@/types/text-message'; type Props = QuestionnaireComponentItemProps & { onUpload: (files: UploadFile[]) => void; @@ -78,18 +78,12 @@ const AttachmentHtml = (props: Props): JSX.Element | null => { const fieldState = getFieldState(idWithLinkIdAndItemIndex, formState); const { error } = fieldState; - const numberOfFilesMessage = getCustomValidationText( - item, - (minFiles && !maxFiles && resources?.attachmentError_minFiles) || - (maxFiles && !minFiles && resources?.attachmentError_maxFiles) || - (maxFiles && minFiles && resources?.attachmentError_minFiles) || - undefined - ); - const validationFileTypesMessage = getCustomValidationText(item, resources?.attachmentError_fileType); + const numberOfFilesValidationText = getNumberOfFilesValidationText(item, minFiles, maxFiles, resources); + const fileTypesValidationText = getValidationTextForAttachment(item, resources?.attachmentError_fileType); const maxValueBytes = getAttachmentMaxSizeBytesToUse(attachmentMaxFileSize, item); const validFileTypes: MimeTypes[] = attachmentValidTypes ? attachmentValidTypes : VALID_FILE_TYPES; - const filSizeErrorMessage = resources?.attachmentError_fileSize?.replace( + const filSizeValidationText = resources?.attachmentError_fileSize?.replace( '{0}', convertBytesToMBString(getAttachmentMaxSizeBytesToUse(attachmentMaxFileSize, item)) ); @@ -102,12 +96,12 @@ const AttachmentHtml = (props: Props): JSX.Element | null => { } = useFileUpload( internalRegister, [ - validateFileType(validFileTypes, validationFileTypesMessage), - validateFileSize(0, maxValueBytes, getCustomValidationText(item, filSizeErrorMessage || 'total file size')), + validateFileType(validFileTypes, fileTypesValidationText), + validateFileSize(0, maxValueBytes, getValidationTextForAttachment(item, filSizeValidationText || 'total file size')), ], [ - validateNumberOfFiles(minFiles ?? 0, maxFiles ?? 20, numberOfFilesMessage || 'Number of files'), - validateTotalFileSize(0, maxValueBytes, getCustomValidationText(item, filSizeErrorMessage || 'total file size')), + validateNumberOfFiles(minFiles ?? 0, maxFiles ?? 20, numberOfFilesValidationText || 'Number of files'), + validateTotalFileSize(0, maxValueBytes, getValidationTextForAttachment(item, filSizeValidationText || 'total file size')), ] ); diff --git a/src/util/resources.ts b/src/util/resources.ts index 0d8918fd..be644895 100644 --- a/src/util/resources.ts +++ b/src/util/resources.ts @@ -244,9 +244,13 @@ export interface Resources { */ attachmentError_minFiles?: string; /** - * Maks {0} fil(er) er tillatt + * Maks {1} fil(er) er tillatt */ attachmentError_maxFiles?: string; + /** + * Minst {0} fil(er) og maks {1} fil(er) er tillatt + */ + attachmentError_minFiles_and_maxFiles?: string; /** * Filstørrelse må være mindre enn {0}MB */