* feat(input-file): create input-file component
* chore: improvements after review
* chore: update after review
* chore: update translations
* chore: - fixed demo with form submit, submit was not prevented
- fixed checking allowed file extensions
- fixed clicking on select file button in drag and drop area
* chore: since the input-file does not upload files itself but enables user to select files, I replaced "upload" and "upload" with "select" and "selected" where applicable
* chore: - removed unused properties allowedFileTypes and allowedFileExtensions from lion-input-file
- cleaned up docs
* chore: - changed type Array.<type> to Array<type>
- removed redundant type definition
* fix: - FocusMixin: moved registering events for from connectedCallback to firstUpdated since _focusableNode is sometimes not available yet
- SlotMixin: changed updated to update in since slots were rendered too late (related to previous fix in FocusMixin.js)
* fix: renamed lion-uploaded-file-list.js to lion-selected-file-list.js
* fix: fixed test for lion-selected-file-list
* fix: fixed typ
* wip
* fix: - fixed issue with multiple file selection where element would not select valid files after invalid ones
- added getMessage method to FileValidation that returns empty string to prevent message being shown that error message must be configured
- fixed tests
* chore: replaced `uploadOnFormSubmit` with `uploadOnSelect` and flipped the default value to false. When `uploadOnSelect` is set to true, the file will be uploaded as soon as it is selected.
* fix: - replaced `uploadOnFormSubmit` with `uploadOnSelect` and flipped the default value to false. When `uploadOnSelect` is set to true, the file will be uploaded as soon as it is selected.
- fixed issue where a valid file was not selected and added to the file list if it was preceded by an invalid file
* chore: removed redundant README.md
* fix: fixed failing test
* chore: added missing type annotation
* chore: annotated event param as optional
---------
Co-authored-by: Danny Moerkerke <danny.moerkerke@ing.com>
Co-authored-by: Thijs Louisse <Thijs.Louisse@ing.com>
114 lines
3.5 KiB
JavaScript
114 lines
3.5 KiB
JavaScript
import { Validator } from '@lion/ui/form-core.js';
|
|
import { getLocalizeManager } from '@lion/ui/localize-no-side-effects.js';
|
|
|
|
/**
|
|
* @typedef {import('../../form-core/types/validate/validate.js').ValidatorConfig} ValidatorConfig
|
|
* @typedef {import('../../form-core/types/validate/validate.js').ValidatorParam} ValidatorParam
|
|
* @typedef {import('../../form-core/types/validate/validate.js').ValidatorOutcome} ValidatorOutcome
|
|
* @typedef {import('../types/input-file.js').InputFile} InputFile
|
|
*/
|
|
|
|
/* eslint max-classes-per-file: ["error", 2] */
|
|
export class IsAcceptedFile extends Validator {
|
|
static validatorName = 'IsAcceptedFile';
|
|
|
|
/**
|
|
* @param {number} fileFileSize
|
|
* @param {number} maxFileSize
|
|
*/
|
|
static checkFileSize(fileFileSize, maxFileSize) {
|
|
return fileFileSize <= maxFileSize;
|
|
}
|
|
|
|
/**
|
|
* Gets the extension of a file name
|
|
* @param {string} fileName like myFile.txt
|
|
* @return {string} like .txt
|
|
*/
|
|
static getExtension(fileName) {
|
|
return fileName?.slice(fileName.lastIndexOf('.'));
|
|
}
|
|
|
|
/**
|
|
* @param {string} extension
|
|
* @param {string[]} allowedFileExtensions
|
|
*/
|
|
static isExtensionAllowed(extension, allowedFileExtensions) {
|
|
return allowedFileExtensions?.find(
|
|
allowedExtension => allowedExtension.toUpperCase() === extension.toUpperCase(),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param {string} type
|
|
* @param {string[]} allowedFileTypes
|
|
*/
|
|
static isFileTypeAllowed(type, allowedFileTypes) {
|
|
return allowedFileTypes?.find(allowedType => allowedType.toUpperCase() === type.toUpperCase());
|
|
}
|
|
|
|
/**
|
|
* @param {Array<File>} modelValue array of file objects
|
|
* @param {{ allowedFileTypes: string[]; allowedFileExtensions: string[]; maxFileSize: number; }} params
|
|
* @returns {Boolean}
|
|
*/
|
|
execute(modelValue, params = this.param) {
|
|
let isInvalidType;
|
|
let isInvalidFileExt;
|
|
|
|
const ctor = /** @type {typeof IsAcceptedFile} */ (this.constructor);
|
|
const { allowedFileTypes, allowedFileExtensions, maxFileSize } = params;
|
|
if (allowedFileTypes?.length) {
|
|
isInvalidType = modelValue.some(file => !ctor.isFileTypeAllowed(file.type, allowedFileTypes));
|
|
return isInvalidType;
|
|
}
|
|
if (allowedFileExtensions?.length) {
|
|
isInvalidFileExt = modelValue.some(
|
|
file => !ctor.isExtensionAllowed(ctor.getExtension(file.name), allowedFileExtensions),
|
|
);
|
|
return isInvalidFileExt;
|
|
}
|
|
const invalidFileSize = modelValue.findIndex(
|
|
file => !ctor.checkFileSize(file.size, maxFileSize),
|
|
);
|
|
return invalidFileSize > -1;
|
|
}
|
|
|
|
// @todo: validation should be handled with ValidateMixin so overriding getMessage to return an empty string should
|
|
// not be necessary anymore
|
|
static async getMessage() {
|
|
return '';
|
|
}
|
|
}
|
|
|
|
export class DuplicateFileNames extends Validator {
|
|
static validatorName = 'DuplicateFileNames';
|
|
|
|
/**
|
|
* @param {ValidatorParam} [param]
|
|
* @param {ValidatorConfig} [config]
|
|
*/
|
|
constructor(param, config) {
|
|
super(param, config);
|
|
this.type = 'info';
|
|
}
|
|
|
|
/**
|
|
* @param {InputFile[]} modelValue
|
|
* @param {ValidatorParam} [params]
|
|
* @returns {ValidatorOutcome|Promise<ValidatorOutcome>}
|
|
*/
|
|
execute(modelValue, params = this.param) {
|
|
return params.show;
|
|
}
|
|
|
|
/**
|
|
* @returns {Promise<string|Element>}
|
|
*/
|
|
static async getMessage() {
|
|
const localizeManager = getLocalizeManager();
|
|
// TODO: we need to make sure namespace is loaded
|
|
// TODO: keep Validators localize system agnostic
|
|
return localizeManager.msg('lion-input-file:uploadTextDuplicateFileName');
|
|
}
|
|
}
|