@formio/js 5.0.0-rc.34 → 5.0.0-rc.35
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/dist/fonts/bootstrap-icons.woff +0 -0
- package/dist/fonts/bootstrap-icons.woff2 +0 -0
- package/dist/formio.builder.css +19 -15
- package/dist/formio.builder.min.css +1 -1
- package/dist/formio.embed.js +1 -1
- package/dist/formio.embed.min.js +1 -1
- package/dist/formio.form.css +19 -15
- package/dist/formio.form.js +19 -19
- package/dist/formio.form.min.css +1 -1
- package/dist/formio.form.min.js +1 -1
- package/dist/formio.form.min.js.LICENSE.txt +1 -1
- package/dist/formio.full.css +363 -19
- package/dist/formio.full.js +20 -20
- package/dist/formio.full.min.css +3 -3
- package/dist/formio.full.min.js +1 -1
- package/dist/formio.full.min.js.LICENSE.txt +1 -1
- package/dist/formio.js +8 -8
- package/dist/formio.min.js +1 -1
- package/lib/cjs/CDN.js +12 -6
- package/lib/cjs/Webform.js +4 -1
- package/lib/cjs/Wizard.js +6 -9
- package/lib/cjs/components/_classes/component/Component.js +6 -1
- package/lib/cjs/components/_classes/nested/NestedComponent.js +1 -1
- package/lib/cjs/components/container/fixtures/comp4.js +45 -0
- package/lib/cjs/components/container/fixtures/index.js +3 -1
- package/lib/cjs/components/datetime/DateTime.js +6 -0
- package/lib/cjs/components/file/File.js +465 -215
- package/lib/cjs/components/file/editForm/File.edit.display.js +17 -0
- package/lib/cjs/components/textarea/TextArea.js +2 -2
- package/lib/cjs/components/textfield/TextField.js +3 -1
- package/lib/cjs/components/time/Time.js +3 -0
- package/lib/cjs/providers/storage/azure.js +6 -1
- package/lib/cjs/providers/storage/base64.js +1 -1
- package/lib/cjs/providers/storage/googleDrive.js +5 -1
- package/lib/cjs/providers/storage/indexeddb.js +1 -1
- package/lib/cjs/providers/storage/s3.js +5 -1
- package/lib/cjs/providers/storage/xhr.js +10 -0
- package/lib/mjs/CDN.js +12 -6
- package/lib/mjs/Webform.js +4 -1
- package/lib/mjs/Wizard.js +6 -9
- package/lib/mjs/components/_classes/component/Component.js +6 -1
- package/lib/mjs/components/_classes/nested/NestedComponent.js +1 -1
- package/lib/mjs/components/container/fixtures/comp4.js +43 -0
- package/lib/mjs/components/container/fixtures/index.js +2 -1
- package/lib/mjs/components/datetime/DateTime.js +6 -0
- package/lib/mjs/components/file/File.js +463 -224
- package/lib/mjs/components/file/editForm/File.edit.display.js +17 -0
- package/lib/mjs/components/textarea/TextArea.js +2 -2
- package/lib/mjs/components/textfield/TextField.js +6 -0
- package/lib/mjs/components/time/Time.js +3 -0
- package/lib/mjs/providers/storage/azure.js +6 -1
- package/lib/mjs/providers/storage/base64.js +1 -1
- package/lib/mjs/providers/storage/googleDrive.js +5 -1
- package/lib/mjs/providers/storage/indexeddb.js +1 -1
- package/lib/mjs/providers/storage/s3.js +5 -1
- package/lib/mjs/providers/storage/xhr.js +10 -0
- package/package.json +2 -2
| @@ -28,6 +28,7 @@ if (htmlCanvasElement && !htmlCanvasElement.prototype.toBlob) { | |
| 28 28 | 
             
                    }
         | 
| 29 29 | 
             
                });
         | 
| 30 30 | 
             
            }
         | 
| 31 | 
            +
            const createRandomString = () => Math.random().toString(36).substring(2, 15);
         | 
| 31 32 | 
             
            export default class FileComponent extends Field {
         | 
| 32 33 | 
             
                static schema(...extend) {
         | 
| 33 34 | 
             
                    return Field.schema({
         | 
| @@ -79,8 +80,13 @@ export default class FileComponent extends Field { | |
| 79 80 | 
             
                        progress: progressSupported,
         | 
| 80 81 | 
             
                    };
         | 
| 81 82 | 
             
                    this.cameraMode = false;
         | 
| 82 | 
            -
                    this.statuses = [];
         | 
| 83 83 | 
             
                    this.fileDropHidden = false;
         | 
| 84 | 
            +
                    this.filesToSync = {
         | 
| 85 | 
            +
                        filesToUpload: [],
         | 
| 86 | 
            +
                        filesToDelete: [],
         | 
| 87 | 
            +
                    };
         | 
| 88 | 
            +
                    this.isSyncing = false;
         | 
| 89 | 
            +
                    this.abortUploads = [];
         | 
| 84 90 | 
             
                }
         | 
| 85 91 | 
             
                get dataReady() {
         | 
| 86 92 | 
             
                    return this.filesReady || Promise.resolve();
         | 
| @@ -125,14 +131,37 @@ export default class FileComponent extends Field { | |
| 125 131 | 
             
                    }
         | 
| 126 132 | 
             
                    this._fileBrowseHidden = value;
         | 
| 127 133 | 
             
                }
         | 
| 134 | 
            +
                get shouldSyncFiles() {
         | 
| 135 | 
            +
                    return Boolean(this.filesToSync.filesToDelete.length || this.filesToSync.filesToUpload.length);
         | 
| 136 | 
            +
                }
         | 
| 137 | 
            +
                get autoSync() {
         | 
| 138 | 
            +
                    return _.get(this, 'component.autoSync', false);
         | 
| 139 | 
            +
                }
         | 
| 140 | 
            +
                get columnsSize() {
         | 
| 141 | 
            +
                    const actionsColumn = this.disabled ? 0 : this.autoSync ? 2 : 1;
         | 
| 142 | 
            +
                    const typeColumn = this.hasTypes ? 2 : 0;
         | 
| 143 | 
            +
                    const sizeColumn = 2;
         | 
| 144 | 
            +
                    const nameColumn = 12 - actionsColumn - typeColumn - sizeColumn;
         | 
| 145 | 
            +
                    return {
         | 
| 146 | 
            +
                        name: nameColumn,
         | 
| 147 | 
            +
                        size: sizeColumn,
         | 
| 148 | 
            +
                        type: typeColumn,
         | 
| 149 | 
            +
                        actions: actionsColumn,
         | 
| 150 | 
            +
                    };
         | 
| 151 | 
            +
                }
         | 
| 128 152 | 
             
                render() {
         | 
| 153 | 
            +
                    const { filesToDelete, filesToUpload } = this.filesToSync;
         | 
| 129 154 | 
             
                    return super.render(this.renderTemplate('file', {
         | 
| 130 155 | 
             
                        fileSize: this.fileSize,
         | 
| 131 156 | 
             
                        files: this.dataValue || [],
         | 
| 132 | 
            -
                         | 
| 157 | 
            +
                        filesToDelete,
         | 
| 158 | 
            +
                        filesToUpload,
         | 
| 133 159 | 
             
                        disabled: this.disabled,
         | 
| 134 160 | 
             
                        support: this.support,
         | 
| 135 | 
            -
                        fileDropHidden: this.fileDropHidden
         | 
| 161 | 
            +
                        fileDropHidden: this.fileDropHidden,
         | 
| 162 | 
            +
                        showSyncButton: this.autoSync && (filesToDelete.length || filesToUpload.length),
         | 
| 163 | 
            +
                        isSyncing: this.isSyncing,
         | 
| 164 | 
            +
                        columns: this.columnsSize,
         | 
| 136 165 | 
             
                    }));
         | 
| 137 166 | 
             
                }
         | 
| 138 167 | 
             
                getVideoStream(constraints) {
         | 
| @@ -198,7 +227,7 @@ export default class FileComponent extends Field { | |
| 198 227 | 
             
                    this.getFrame(videoPlayer)
         | 
| 199 228 | 
             
                        .then((frame) => {
         | 
| 200 229 | 
             
                        frame.name = `photo-${Date.now()}.png`;
         | 
| 201 | 
            -
                        this. | 
| 230 | 
            +
                        this.handleFilesToUpload([frame]);
         | 
| 202 231 | 
             
                        this.cameraMode = false;
         | 
| 203 232 | 
             
                        this.redraw();
         | 
| 204 233 | 
             
                    });
         | 
| @@ -280,20 +309,10 @@ export default class FileComponent extends Field { | |
| 280 309 | 
             
                    }
         | 
| 281 310 | 
             
                    return options;
         | 
| 282 311 | 
             
                }
         | 
| 283 | 
            -
                 | 
| 284 | 
            -
                     | 
| 285 | 
            -
             | 
| 286 | 
            -
             | 
| 287 | 
            -
                        if (fileService && typeof fileService.deleteFile === 'function') {
         | 
| 288 | 
            -
                            fileService.deleteFile(fileInfo, options);
         | 
| 289 | 
            -
                        }
         | 
| 290 | 
            -
                        else {
         | 
| 291 | 
            -
                            const formio = this.options.formio || (this.root && this.root.formio);
         | 
| 292 | 
            -
                            if (formio) {
         | 
| 293 | 
            -
                                formio.makeRequest('', fileInfo.url, 'delete');
         | 
| 294 | 
            -
                            }
         | 
| 295 | 
            -
                        }
         | 
| 296 | 
            -
                    }
         | 
| 312 | 
            +
                get actions() {
         | 
| 313 | 
            +
                    return {
         | 
| 314 | 
            +
                        abort: this.abortRequest.bind(this),
         | 
| 315 | 
            +
                    };
         | 
| 297 316 | 
             
                }
         | 
| 298 317 | 
             
                attach(element) {
         | 
| 299 318 | 
             
                    this.loadRefs(element, {
         | 
| @@ -306,19 +325,22 @@ export default class FileComponent extends Field { | |
| 306 325 | 
             
                        videoPlayer: 'single',
         | 
| 307 326 | 
             
                        fileLink: 'multiple',
         | 
| 308 327 | 
             
                        removeLink: 'multiple',
         | 
| 309 | 
            -
                         | 
| 328 | 
            +
                        fileToSyncRemove: 'multiple',
         | 
| 310 329 | 
             
                        fileImage: 'multiple',
         | 
| 311 330 | 
             
                        fileType: 'multiple',
         | 
| 312 331 | 
             
                        fileProcessingLoader: 'single',
         | 
| 332 | 
            +
                        syncNow: 'single',
         | 
| 333 | 
            +
                        restoreFile: 'multiple',
         | 
| 334 | 
            +
                        progress: 'multiple',
         | 
| 313 335 | 
             
                    });
         | 
| 314 336 | 
             
                    // Ensure we have an empty input refs. We need this for the setValue method to redraw the control when it is set.
         | 
| 315 337 | 
             
                    this.refs.input = [];
         | 
| 316 338 | 
             
                    const superAttach = super.attach(element);
         | 
| 317 339 | 
             
                    if (this.refs.fileDrop) {
         | 
| 318 | 
            -
                        if (!this.statuses.length) {
         | 
| 319 | 
            -
             | 
| 320 | 
            -
                        }
         | 
| 321 | 
            -
                        const  | 
| 340 | 
            +
                        // if (!this.statuses.length) {
         | 
| 341 | 
            +
                        //   this.refs.fileDrop.removeAttribute('hidden');
         | 
| 342 | 
            +
                        // }
         | 
| 343 | 
            +
                        const _this = this;
         | 
| 322 344 | 
             
                        this.addEventListener(this.refs.fileDrop, 'dragover', function (event) {
         | 
| 323 345 | 
             
                            this.className = 'fileSelector fileDragOver';
         | 
| 324 346 | 
             
                            event.preventDefault();
         | 
| @@ -330,15 +352,18 @@ export default class FileComponent extends Field { | |
| 330 352 | 
             
                        this.addEventListener(this.refs.fileDrop, 'drop', function (event) {
         | 
| 331 353 | 
             
                            this.className = 'fileSelector';
         | 
| 332 354 | 
             
                            event.preventDefault();
         | 
| 333 | 
            -
                             | 
| 355 | 
            +
                            _this.handleFilesToUpload(event.dataTransfer.files);
         | 
| 334 356 | 
             
                        });
         | 
| 335 357 | 
             
                    }
         | 
| 358 | 
            +
                    this.addEventListener(element, 'click', (event) => {
         | 
| 359 | 
            +
                        this.handleAction(event);
         | 
| 360 | 
            +
                    });
         | 
| 336 361 | 
             
                    if (this.refs.fileBrowse) {
         | 
| 337 362 | 
             
                        this.addEventListener(this.refs.fileBrowse, 'click', (event) => {
         | 
| 338 363 | 
             
                            event.preventDefault();
         | 
| 339 364 | 
             
                            this.browseFiles(this.browseOptions)
         | 
| 340 365 | 
             
                                .then((files) => {
         | 
| 341 | 
            -
                                this. | 
| 366 | 
            +
                                this.handleFilesToUpload(files);
         | 
| 342 367 | 
             
                            });
         | 
| 343 368 | 
             
                        });
         | 
| 344 369 | 
             
                    }
         | 
| @@ -350,22 +375,27 @@ export default class FileComponent extends Field { | |
| 350 375 | 
             
                    });
         | 
| 351 376 | 
             
                    this.refs.removeLink.forEach((removeLink, index) => {
         | 
| 352 377 | 
             
                        this.addEventListener(removeLink, 'click', (event) => {
         | 
| 378 | 
            +
                            event.preventDefault();
         | 
| 353 379 | 
             
                            const fileInfo = this.dataValue[index];
         | 
| 354 | 
            -
                            this. | 
| 380 | 
            +
                            this.handleFileToRemove(fileInfo);
         | 
| 381 | 
            +
                        });
         | 
| 382 | 
            +
                    });
         | 
| 383 | 
            +
                    this.refs.fileToSyncRemove.forEach((fileToSyncRemove, index) => {
         | 
| 384 | 
            +
                        this.addEventListener(fileToSyncRemove, 'click', (event) => {
         | 
| 355 385 | 
             
                            event.preventDefault();
         | 
| 356 | 
            -
                            this.splice(index);
         | 
| 386 | 
            +
                            this.filesToSync.filesToUpload.splice(index, 1);
         | 
| 357 387 | 
             
                            this.redraw();
         | 
| 358 388 | 
             
                        });
         | 
| 359 389 | 
             
                    });
         | 
| 360 | 
            -
                    this.refs. | 
| 361 | 
            -
                        this.addEventListener( | 
| 390 | 
            +
                    this.refs.restoreFile.forEach((fileToRestore, index) => {
         | 
| 391 | 
            +
                        this.addEventListener(fileToRestore, 'click', (event) => {
         | 
| 362 392 | 
             
                            event.preventDefault();
         | 
| 363 | 
            -
                            const  | 
| 364 | 
            -
                             | 
| 365 | 
            -
                             | 
| 366 | 
            -
             | 
| 367 | 
            -
                             | 
| 368 | 
            -
                            this. | 
| 393 | 
            +
                            const fileInfo = this.filesToSync.filesToDelete[index];
         | 
| 394 | 
            +
                            delete fileInfo.status;
         | 
| 395 | 
            +
                            delete fileInfo.message;
         | 
| 396 | 
            +
                            this.filesToSync.filesToDelete.splice(index, 1);
         | 
| 397 | 
            +
                            this.dataValue.push(fileInfo);
         | 
| 398 | 
            +
                            this.triggerChange();
         | 
| 369 399 | 
             
                            this.redraw();
         | 
| 370 400 | 
             
                        });
         | 
| 371 401 | 
             
                    });
         | 
| @@ -379,7 +409,7 @@ export default class FileComponent extends Field { | |
| 379 409 | 
             
                                        reader.onloadend = (evt) => {
         | 
| 380 410 | 
             
                                            const blob = new Blob([new Uint8Array(evt.target.result)], { type: file.type });
         | 
| 381 411 | 
             
                                            blob.name = file.name;
         | 
| 382 | 
            -
                                            this. | 
| 412 | 
            +
                                            this.handleFilesToUpload([blob]);
         | 
| 383 413 | 
             
                                        };
         | 
| 384 414 | 
             
                                        reader.readAsArrayBuffer(file);
         | 
| 385 415 | 
             
                                    });
         | 
| @@ -401,7 +431,7 @@ export default class FileComponent extends Field { | |
| 401 431 | 
             
                                        reader.onloadend = (evt) => {
         | 
| 402 432 | 
             
                                            const blob = new Blob([new Uint8Array(evt.target.result)], { type: file.type });
         | 
| 403 433 | 
             
                                            blob.name = file.name;
         | 
| 404 | 
            -
                                            this. | 
| 434 | 
            +
                                            this.handleFilesToUpload([blob]);
         | 
| 405 435 | 
             
                                        };
         | 
| 406 436 | 
             
                                        reader.readAsArrayBuffer(file);
         | 
| 407 437 | 
             
                                    });
         | 
| @@ -431,6 +461,9 @@ export default class FileComponent extends Field { | |
| 431 461 | 
             
                        });
         | 
| 432 462 | 
             
                    }
         | 
| 433 463 | 
             
                    this.refs.fileType.forEach((fileType, index) => {
         | 
| 464 | 
            +
                        if (!this.dataValue[index]) {
         | 
| 465 | 
            +
                            return;
         | 
| 466 | 
            +
                        }
         | 
| 434 467 | 
             
                        this.dataValue[index].fileType = this.dataValue[index].fileType || this.component.fileTypes[0].label;
         | 
| 435 468 | 
             
                        this.addEventListener(fileType, 'change', (event) => {
         | 
| 436 469 | 
             
                            event.preventDefault();
         | 
| @@ -438,6 +471,10 @@ export default class FileComponent extends Field { | |
| 438 471 | 
             
                            this.dataValue[index].fileType = fileType.label;
         | 
| 439 472 | 
             
                        });
         | 
| 440 473 | 
             
                    });
         | 
| 474 | 
            +
                    this.addEventListener(this.refs.syncNow, 'click', (event) => {
         | 
| 475 | 
            +
                        event.preventDefault();
         | 
| 476 | 
            +
                        this.syncFiles();
         | 
| 477 | 
            +
                    });
         | 
| 441 478 | 
             
                    const fileService = this.fileService;
         | 
| 442 479 | 
             
                    if (fileService) {
         | 
| 443 480 | 
             
                        const loadingImages = [];
         | 
| @@ -553,201 +590,389 @@ export default class FileComponent extends Field { | |
| 553 590 | 
             
                validateMaxSize(file, val) {
         | 
| 554 591 | 
             
                    return file.size - 0.1 <= this.translateScalars(val);
         | 
| 555 592 | 
             
                }
         | 
| 556 | 
            -
                 | 
| 593 | 
            +
                abortRequest(id) {
         | 
| 594 | 
            +
                    const abortUpload = this.abortUploads.find(abortUpload => abortUpload.id === id);
         | 
| 595 | 
            +
                    if (abortUpload) {
         | 
| 596 | 
            +
                        abortUpload.abort();
         | 
| 597 | 
            +
                    }
         | 
| 598 | 
            +
                }
         | 
| 599 | 
            +
                handleAction(event) {
         | 
| 600 | 
            +
                    const target = event.target;
         | 
| 601 | 
            +
                    if (!target.id) {
         | 
| 602 | 
            +
                        return;
         | 
| 603 | 
            +
                    }
         | 
| 604 | 
            +
                    const [action, id] = target.id.split('-');
         | 
| 605 | 
            +
                    if (!action || !id || !this.actions[action]) {
         | 
| 606 | 
            +
                        return;
         | 
| 607 | 
            +
                    }
         | 
| 608 | 
            +
                    this.actions[action](id);
         | 
| 609 | 
            +
                }
         | 
| 610 | 
            +
                getFileName(file) {
         | 
| 611 | 
            +
                    return uniqueName(file.name, this.component.fileNameTemplate, this.evalContext());
         | 
| 612 | 
            +
                }
         | 
| 613 | 
            +
                getInitFileToSync(file) {
         | 
| 614 | 
            +
                    const escapedFileName = file.name ? file.name.replaceAll('<', '<').replaceAll('>', '>') : file.name;
         | 
| 615 | 
            +
                    return {
         | 
| 616 | 
            +
                        id: createRandomString(),
         | 
| 617 | 
            +
                        // Get a unique name for this file to keep file collisions from occurring.
         | 
| 618 | 
            +
                        dir: this.interpolate(this.component.dir || ''),
         | 
| 619 | 
            +
                        name: this.getFileName(file),
         | 
| 620 | 
            +
                        originalName: escapedFileName,
         | 
| 621 | 
            +
                        fileKey: this.component.fileKey || 'file',
         | 
| 622 | 
            +
                        storage: this.component.storage,
         | 
| 623 | 
            +
                        options: this.component.options,
         | 
| 624 | 
            +
                        file,
         | 
| 625 | 
            +
                        size: file.size,
         | 
| 626 | 
            +
                        status: 'info',
         | 
| 627 | 
            +
                        message: this.t('Processing file. Please wait...'),
         | 
| 628 | 
            +
                        hash: '',
         | 
| 629 | 
            +
                    };
         | 
| 630 | 
            +
                }
         | 
| 631 | 
            +
                async handleSubmissionRevisions(file) {
         | 
| 632 | 
            +
                    if (this.root.form.submissionRevisions !== 'true') {
         | 
| 633 | 
            +
                        return '';
         | 
| 634 | 
            +
                    }
         | 
| 635 | 
            +
                    const bmf = new BMF();
         | 
| 636 | 
            +
                    const hash = await new Promise((resolve, reject) => {
         | 
| 637 | 
            +
                        this.emit('fileUploadingStart');
         | 
| 638 | 
            +
                        bmf.md5(file, (err, md5) => {
         | 
| 639 | 
            +
                            if (err) {
         | 
| 640 | 
            +
                                return reject(err);
         | 
| 641 | 
            +
                            }
         | 
| 642 | 
            +
                            return resolve(md5);
         | 
| 643 | 
            +
                        });
         | 
| 644 | 
            +
                    });
         | 
| 645 | 
            +
                    this.emit('fileUploadingEnd');
         | 
| 646 | 
            +
                    return hash;
         | 
| 647 | 
            +
                }
         | 
| 648 | 
            +
                validateFileName(file) {
         | 
| 649 | 
            +
                    // Check if file with the same name is being uploaded
         | 
| 650 | 
            +
                    const fileWithSameNameUploading = this.filesToSync.filesToUpload
         | 
| 651 | 
            +
                        .some(fileToSync => fileToSync.file?.name === file.name);
         | 
| 652 | 
            +
                    const fileWithSameNameUploaded = this.dataValue
         | 
| 653 | 
            +
                        .some(fileStatus => fileStatus.originalName === file.name);
         | 
| 654 | 
            +
                    return fileWithSameNameUploaded || fileWithSameNameUploading
         | 
| 655 | 
            +
                        ? {
         | 
| 656 | 
            +
                            status: 'error',
         | 
| 657 | 
            +
                            message: this.t(`File with the same name is already ${fileWithSameNameUploading ? 'being ' : ''}uploaded`),
         | 
| 658 | 
            +
                        }
         | 
| 659 | 
            +
                        : {};
         | 
| 660 | 
            +
                }
         | 
| 661 | 
            +
                validateFileSettings(file) {
         | 
| 662 | 
            +
                    // Check file pattern
         | 
| 663 | 
            +
                    if (this.component.filePattern && !this.validatePattern(file, this.component.filePattern)) {
         | 
| 664 | 
            +
                        return {
         | 
| 665 | 
            +
                            status: 'error',
         | 
| 666 | 
            +
                            message: this.t('File is the wrong type; it must be {{ pattern }}', {
         | 
| 667 | 
            +
                                pattern: this.component.filePattern,
         | 
| 668 | 
            +
                            }),
         | 
| 669 | 
            +
                        };
         | 
| 670 | 
            +
                    }
         | 
| 671 | 
            +
                    // Check file minimum size
         | 
| 672 | 
            +
                    if (this.component.fileMinSize && !this.validateMinSize(file, this.component.fileMinSize)) {
         | 
| 673 | 
            +
                        return {
         | 
| 674 | 
            +
                            status: 'error',
         | 
| 675 | 
            +
                            message: this.t('File is too small; it must be at least {{ size }}', {
         | 
| 676 | 
            +
                                size: this.component.fileMinSize,
         | 
| 677 | 
            +
                            }),
         | 
| 678 | 
            +
                        };
         | 
| 679 | 
            +
                    }
         | 
| 680 | 
            +
                    // Check file maximum size
         | 
| 681 | 
            +
                    if (this.component.fileMaxSize && !this.validateMaxSize(file, this.component.fileMaxSize)) {
         | 
| 682 | 
            +
                        return {
         | 
| 683 | 
            +
                            status: 'error',
         | 
| 684 | 
            +
                            message: this.t('File is too big; it must be at most {{ size }}', {
         | 
| 685 | 
            +
                                size: this.component.fileMaxSize,
         | 
| 686 | 
            +
                            }),
         | 
| 687 | 
            +
                        };
         | 
| 688 | 
            +
                    }
         | 
| 689 | 
            +
                    return {};
         | 
| 690 | 
            +
                }
         | 
| 691 | 
            +
                validateFileService() {
         | 
| 692 | 
            +
                    const { fileService } = this;
         | 
| 693 | 
            +
                    return !fileService
         | 
| 694 | 
            +
                        ? {
         | 
| 695 | 
            +
                            status: 'error',
         | 
| 696 | 
            +
                            message: this.t('File Service not provided.'),
         | 
| 697 | 
            +
                        }
         | 
| 698 | 
            +
                        : {};
         | 
| 699 | 
            +
                }
         | 
| 700 | 
            +
                validateFile(file) {
         | 
| 701 | 
            +
                    const fileServiceValidation = this.validateFileService();
         | 
| 702 | 
            +
                    if (fileServiceValidation.status === 'error') {
         | 
| 703 | 
            +
                        return fileServiceValidation;
         | 
| 704 | 
            +
                    }
         | 
| 705 | 
            +
                    const fileNameValidation = this.validateFileName(file);
         | 
| 706 | 
            +
                    if (fileNameValidation.status === 'error') {
         | 
| 707 | 
            +
                        return fileNameValidation;
         | 
| 708 | 
            +
                    }
         | 
| 709 | 
            +
                    return this.validateFileSettings(file);
         | 
| 710 | 
            +
                }
         | 
| 711 | 
            +
                getGroupPermissions() {
         | 
| 712 | 
            +
                    let groupKey = null;
         | 
| 713 | 
            +
                    let groupPermissions = null;
         | 
| 714 | 
            +
                    //Iterate through form components to find group resource if one exists
         | 
| 715 | 
            +
                    this.root.everyComponent((element) => {
         | 
| 716 | 
            +
                        if (element.component?.submissionAccess || element.component?.defaultPermission) {
         | 
| 717 | 
            +
                            groupPermissions = !element.component.submissionAccess ? [
         | 
| 718 | 
            +
                                {
         | 
| 719 | 
            +
                                    type: element.component.defaultPermission,
         | 
| 720 | 
            +
                                    roles: [],
         | 
| 721 | 
            +
                                },
         | 
| 722 | 
            +
                            ] : element.component.submissionAccess;
         | 
| 723 | 
            +
                            groupPermissions.forEach((permission) => {
         | 
| 724 | 
            +
                                groupKey = ['admin', 'write', 'create'].includes(permission.type) ? element.component.key : null;
         | 
| 725 | 
            +
                            });
         | 
| 726 | 
            +
                        }
         | 
| 727 | 
            +
                    });
         | 
| 728 | 
            +
                    return { groupKey, groupPermissions };
         | 
| 729 | 
            +
                }
         | 
| 730 | 
            +
                async triggerFileProcessor(file) {
         | 
| 731 | 
            +
                    let processedFile = null;
         | 
| 732 | 
            +
                    if (this.root.options.fileProcessor) {
         | 
| 733 | 
            +
                        try {
         | 
| 734 | 
            +
                            if (this.refs.fileProcessingLoader) {
         | 
| 735 | 
            +
                                this.refs.fileProcessingLoader.style.display = 'block';
         | 
| 736 | 
            +
                            }
         | 
| 737 | 
            +
                            const fileProcessorHandler = fileProcessor(this.fileService, this.root.options.fileProcessor);
         | 
| 738 | 
            +
                            processedFile = await fileProcessorHandler(file, this.component.properties);
         | 
| 739 | 
            +
                        }
         | 
| 740 | 
            +
                        catch (err) {
         | 
| 741 | 
            +
                            this.fileDropHidden = false;
         | 
| 742 | 
            +
                            return {
         | 
| 743 | 
            +
                                status: 'error',
         | 
| 744 | 
            +
                                message: this.t('File processing has been failed.'),
         | 
| 745 | 
            +
                            };
         | 
| 746 | 
            +
                        }
         | 
| 747 | 
            +
                        finally {
         | 
| 748 | 
            +
                            if (this.refs.fileProcessingLoader) {
         | 
| 749 | 
            +
                                this.refs.fileProcessingLoader.style.display = 'none';
         | 
| 750 | 
            +
                            }
         | 
| 751 | 
            +
                        }
         | 
| 752 | 
            +
                    }
         | 
| 753 | 
            +
                    return {
         | 
| 754 | 
            +
                        file: processedFile,
         | 
| 755 | 
            +
                    };
         | 
| 756 | 
            +
                }
         | 
| 757 | 
            +
                async prepareFileToUpload(file) {
         | 
| 758 | 
            +
                    const fileToSync = this.getInitFileToSync(file);
         | 
| 759 | 
            +
                    fileToSync.hash = await this.handleSubmissionRevisions(file);
         | 
| 760 | 
            +
                    const { status, message } = this.validateFile(file);
         | 
| 761 | 
            +
                    if (status === 'error') {
         | 
| 762 | 
            +
                        fileToSync.isValidationError = true;
         | 
| 763 | 
            +
                        fileToSync.status = status;
         | 
| 764 | 
            +
                        fileToSync.message = message;
         | 
| 765 | 
            +
                        return this.filesToSync.filesToUpload.push(fileToSync);
         | 
| 766 | 
            +
                    }
         | 
| 767 | 
            +
                    if (this.component.privateDownload) {
         | 
| 768 | 
            +
                        file.private = true;
         | 
| 769 | 
            +
                    }
         | 
| 770 | 
            +
                    const { groupKey, groupPermissions } = this.getGroupPermissions();
         | 
| 771 | 
            +
                    const processedFile = await this.triggerFileProcessor(file);
         | 
| 772 | 
            +
                    if (processedFile.status === 'error') {
         | 
| 773 | 
            +
                        fileToSync.status === 'error';
         | 
| 774 | 
            +
                        fileToSync.message = processedFile.message;
         | 
| 775 | 
            +
                        return this.filesToSync.filesToUpload.push(fileToSync);
         | 
| 776 | 
            +
                    }
         | 
| 777 | 
            +
                    if (this.autoSync) {
         | 
| 778 | 
            +
                        fileToSync.message = this.t('Ready to be uploaded into storage');
         | 
| 779 | 
            +
                    }
         | 
| 780 | 
            +
                    this.filesToSync.filesToUpload.push({
         | 
| 781 | 
            +
                        ...fileToSync,
         | 
| 782 | 
            +
                        message: fileToSync.message,
         | 
| 783 | 
            +
                        file: processedFile.file || file,
         | 
| 784 | 
            +
                        url: this.interpolate(this.component.url, { file: fileToSync }),
         | 
| 785 | 
            +
                        groupPermissions,
         | 
| 786 | 
            +
                        groupResourceId: groupKey ? this.currentForm.submission.data[groupKey]._id : null,
         | 
| 787 | 
            +
                    });
         | 
| 788 | 
            +
                }
         | 
| 789 | 
            +
                async prepareFilesToUpload(files) {
         | 
| 557 790 | 
             
                    // Only allow one upload if not multiple.
         | 
| 558 791 | 
             
                    if (!this.component.multiple) {
         | 
| 559 | 
            -
                        if (this.statuses.length) {
         | 
| 560 | 
            -
                            this.statuses = [];
         | 
| 561 | 
            -
                        }
         | 
| 562 792 | 
             
                        files = Array.prototype.slice.call(files, 0, 1);
         | 
| 563 793 | 
             
                    }
         | 
| 564 794 | 
             
                    if (this.component.storage && files && files.length) {
         | 
| 565 795 | 
             
                        this.fileDropHidden = true;
         | 
| 566 | 
            -
                         | 
| 567 | 
            -
             | 
| 568 | 
            -
             | 
| 569 | 
            -
             | 
| 570 | 
            -
             | 
| 571 | 
            -
             | 
| 572 | 
            -
             | 
| 573 | 
            -
             | 
| 574 | 
            -
             | 
| 575 | 
            -
             | 
| 576 | 
            -
             | 
| 577 | 
            -
             | 
| 578 | 
            -
             | 
| 579 | 
            -
             | 
| 580 | 
            -
             | 
| 581 | 
            -
             | 
| 582 | 
            -
             | 
| 583 | 
            -
             | 
| 584 | 
            -
             | 
| 585 | 
            -
             | 
| 586 | 
            -
             | 
| 587 | 
            -
             | 
| 588 | 
            -
             | 
| 589 | 
            -
             | 
| 590 | 
            -
             | 
| 591 | 
            -
             | 
| 592 | 
            -
             | 
| 593 | 
            -
             | 
| 594 | 
            -
             | 
| 595 | 
            -
             | 
| 596 | 
            -
             | 
| 597 | 
            -
             | 
| 598 | 
            -
             | 
| 599 | 
            -
             | 
| 600 | 
            -
             | 
| 601 | 
            -
             | 
| 602 | 
            -
             | 
| 603 | 
            -
             | 
| 604 | 
            -
             | 
| 605 | 
            -
             | 
| 606 | 
            -
             | 
| 607 | 
            -
             | 
| 608 | 
            -
                             | 
| 609 | 
            -
             | 
| 610 | 
            -
                                this.statuses.splice(fileWithSameNameUploadedWithError, 1);
         | 
| 611 | 
            -
                                this.redraw();
         | 
| 612 | 
            -
                            }
         | 
| 613 | 
            -
                            // Check file pattern
         | 
| 614 | 
            -
                            if (this.component.filePattern && !this.validatePattern(file, this.component.filePattern)) {
         | 
| 615 | 
            -
                                fileUpload.status = 'error';
         | 
| 616 | 
            -
                                fileUpload.message = this.t('File is the wrong type; it must be {{ pattern }}', {
         | 
| 617 | 
            -
                                    pattern: this.component.filePattern,
         | 
| 618 | 
            -
                                });
         | 
| 619 | 
            -
                            }
         | 
| 620 | 
            -
                            // Check file minimum size
         | 
| 621 | 
            -
                            if (this.component.fileMinSize && !this.validateMinSize(file, this.component.fileMinSize)) {
         | 
| 622 | 
            -
                                fileUpload.status = 'error';
         | 
| 623 | 
            -
                                fileUpload.message = this.t('File is too small; it must be at least {{ size }}', {
         | 
| 624 | 
            -
                                    size: this.component.fileMinSize,
         | 
| 625 | 
            -
                                });
         | 
| 626 | 
            -
                            }
         | 
| 627 | 
            -
                            // Check file maximum size
         | 
| 628 | 
            -
                            if (this.component.fileMaxSize && !this.validateMaxSize(file, this.component.fileMaxSize)) {
         | 
| 629 | 
            -
                                fileUpload.status = 'error';
         | 
| 630 | 
            -
                                fileUpload.message = this.t('File is too big; it must be at most {{ size }}', {
         | 
| 631 | 
            -
                                    size: this.component.fileMaxSize,
         | 
| 632 | 
            -
                                });
         | 
| 633 | 
            -
                            }
         | 
| 634 | 
            -
                            // Get a unique name for this file to keep file collisions from occurring.
         | 
| 635 | 
            -
                            const dir = this.interpolate(this.component.dir || '');
         | 
| 636 | 
            -
                            const { fileService } = this;
         | 
| 637 | 
            -
                            if (!fileService) {
         | 
| 638 | 
            -
                                fileUpload.status = 'error';
         | 
| 639 | 
            -
                                fileUpload.message = this.t('File Service not provided.');
         | 
| 640 | 
            -
                            }
         | 
| 641 | 
            -
                            if (this.root.form.submissionRevisions !== 'true') {
         | 
| 642 | 
            -
                                this.statuses.push(fileUpload);
         | 
| 643 | 
            -
                                this.redraw();
         | 
| 796 | 
            +
                        return Promise.all([...files].map(async (file) => {
         | 
| 797 | 
            +
                            await this.prepareFileToUpload(file);
         | 
| 798 | 
            +
                            this.redraw();
         | 
| 799 | 
            +
                        }));
         | 
| 800 | 
            +
                    }
         | 
| 801 | 
            +
                    else {
         | 
| 802 | 
            +
                        return Promise.resolve();
         | 
| 803 | 
            +
                    }
         | 
| 804 | 
            +
                }
         | 
| 805 | 
            +
                async handleFilesToUpload(files) {
         | 
| 806 | 
            +
                    await this.prepareFilesToUpload(files);
         | 
| 807 | 
            +
                    if (!this.autoSync) {
         | 
| 808 | 
            +
                        await this.syncFiles();
         | 
| 809 | 
            +
                    }
         | 
| 810 | 
            +
                }
         | 
| 811 | 
            +
                prepareFileToDelete(fileInfo) {
         | 
| 812 | 
            +
                    this.filesToSync.filesToDelete.push({
         | 
| 813 | 
            +
                        ...fileInfo,
         | 
| 814 | 
            +
                        status: 'info',
         | 
| 815 | 
            +
                        message: this.autoSync
         | 
| 816 | 
            +
                            ? this.t('Ready to be removed from storage')
         | 
| 817 | 
            +
                            : this.t('Preparing file to remove'),
         | 
| 818 | 
            +
                    });
         | 
| 819 | 
            +
                    const index = this.dataValue.findIndex(file => file.name === fileInfo.name);
         | 
| 820 | 
            +
                    this.splice(index);
         | 
| 821 | 
            +
                    this.redraw();
         | 
| 822 | 
            +
                }
         | 
| 823 | 
            +
                handleFileToRemove(fileInfo) {
         | 
| 824 | 
            +
                    this.prepareFileToDelete(fileInfo);
         | 
| 825 | 
            +
                    if (!this.autoSync) {
         | 
| 826 | 
            +
                        this.syncFiles();
         | 
| 827 | 
            +
                    }
         | 
| 828 | 
            +
                }
         | 
| 829 | 
            +
                async deleteFile(fileInfo) {
         | 
| 830 | 
            +
                    const { options = {} } = this.component;
         | 
| 831 | 
            +
                    if (fileInfo && (['url', 'indexeddb', 's3', 'azure', 'googledrive'].includes(this.component.storage))) {
         | 
| 832 | 
            +
                        const { fileService } = this;
         | 
| 833 | 
            +
                        if (fileService && typeof fileService.deleteFile === 'function') {
         | 
| 834 | 
            +
                            return await fileService.deleteFile(fileInfo, options);
         | 
| 835 | 
            +
                        }
         | 
| 836 | 
            +
                        else {
         | 
| 837 | 
            +
                            const formio = this.options.formio || (this.root && this.root.formio);
         | 
| 838 | 
            +
                            if (formio) {
         | 
| 839 | 
            +
                                return await formio.makeRequest('', fileInfo.url, 'delete');
         | 
| 644 840 | 
             
                            }
         | 
| 645 | 
            -
             | 
| 646 | 
            -
             | 
| 647 | 
            -
             | 
| 648 | 
            -
             | 
| 649 | 
            -
             | 
| 650 | 
            -
             | 
| 651 | 
            -
             | 
| 652 | 
            -
             | 
| 653 | 
            -
             | 
| 654 | 
            -
             | 
| 655 | 
            -
             | 
| 656 | 
            -
                                        groupPermissions = !element.component.submissionAccess ? [
         | 
| 657 | 
            -
                                            {
         | 
| 658 | 
            -
                                                type: element.component.defaultPermission,
         | 
| 659 | 
            -
                                                roles: [],
         | 
| 660 | 
            -
                                            },
         | 
| 661 | 
            -
                                        ] : element.component.submissionAccess;
         | 
| 662 | 
            -
                                        groupPermissions.forEach((permission) => {
         | 
| 663 | 
            -
                                            groupKey = ['admin', 'write', 'create'].includes(permission.type) ? element.component.key : null;
         | 
| 664 | 
            -
                                        });
         | 
| 665 | 
            -
                                    }
         | 
| 666 | 
            -
                                });
         | 
| 667 | 
            -
                                const fileKey = this.component.fileKey || 'file';
         | 
| 668 | 
            -
                                const groupResourceId = groupKey ? this.currentForm.submission.data[groupKey]._id : null;
         | 
| 669 | 
            -
                                let processedFile = null;
         | 
| 670 | 
            -
                                if (this.root.options.fileProcessor) {
         | 
| 671 | 
            -
                                    try {
         | 
| 672 | 
            -
                                        if (this.refs.fileProcessingLoader) {
         | 
| 673 | 
            -
                                            this.refs.fileProcessingLoader.style.display = 'block';
         | 
| 674 | 
            -
                                        }
         | 
| 675 | 
            -
                                        const fileProcessorHandler = fileProcessor(this.fileService, this.root.options.fileProcessor);
         | 
| 676 | 
            -
                                        processedFile = await fileProcessorHandler(file, this.component.properties);
         | 
| 677 | 
            -
                                    }
         | 
| 678 | 
            -
                                    catch (err) {
         | 
| 679 | 
            -
                                        fileUpload.status = 'error';
         | 
| 680 | 
            -
                                        fileUpload.message = this.t('File processing has been failed.');
         | 
| 681 | 
            -
                                        this.fileDropHidden = false;
         | 
| 682 | 
            -
                                        this.redraw();
         | 
| 683 | 
            -
                                        return;
         | 
| 684 | 
            -
                                    }
         | 
| 685 | 
            -
                                    finally {
         | 
| 686 | 
            -
                                        if (this.refs.fileProcessingLoader) {
         | 
| 687 | 
            -
                                            this.refs.fileProcessingLoader.style.display = 'none';
         | 
| 688 | 
            -
                                        }
         | 
| 689 | 
            -
                                    }
         | 
| 690 | 
            -
                                }
         | 
| 691 | 
            -
                                // Prep for a potential multipart upload
         | 
| 692 | 
            -
                                let count = 0;
         | 
| 693 | 
            -
                                const multipartOptions = this.component.useMultipartUpload && this.component.multipart ? {
         | 
| 694 | 
            -
                                    ...this.component.multipart,
         | 
| 695 | 
            -
                                    progressCallback: (total) => {
         | 
| 696 | 
            -
                                        count++;
         | 
| 697 | 
            -
                                        fileUpload.status = 'progress';
         | 
| 698 | 
            -
                                        fileUpload.progress = parseInt(100 * count / total);
         | 
| 699 | 
            -
                                        delete fileUpload.message;
         | 
| 700 | 
            -
                                        this.redraw();
         | 
| 701 | 
            -
                                    },
         | 
| 702 | 
            -
                                    changeMessage: (message) => {
         | 
| 703 | 
            -
                                        fileUpload.message = message;
         | 
| 704 | 
            -
                                        this.redraw();
         | 
| 705 | 
            -
                                    },
         | 
| 706 | 
            -
                                } : false;
         | 
| 707 | 
            -
                                fileUpload.message = this.t('Starting upload...');
         | 
| 708 | 
            -
                                this.redraw();
         | 
| 709 | 
            -
                                const filePromise = fileService.uploadFile(storage, processedFile || file, fileName, dir, 
         | 
| 710 | 
            -
                                // Progress callback
         | 
| 711 | 
            -
                                (evt) => {
         | 
| 712 | 
            -
                                    fileUpload.status = 'progress';
         | 
| 713 | 
            -
                                    fileUpload.progress = parseInt(100.0 * evt.loaded / evt.total);
         | 
| 714 | 
            -
                                    delete fileUpload.message;
         | 
| 715 | 
            -
                                    this.redraw();
         | 
| 716 | 
            -
                                }, url, options, fileKey, groupPermissions, groupResourceId, 
         | 
| 717 | 
            -
                                // Upload start callback
         | 
| 718 | 
            -
                                () => {
         | 
| 719 | 
            -
                                    this.emit('fileUploadingStart', filePromise);
         | 
| 720 | 
            -
                                }, (abort) => fileUpload.abort = abort, multipartOptions).then((fileInfo) => {
         | 
| 721 | 
            -
                                    const index = this.statuses.indexOf(fileUpload);
         | 
| 722 | 
            -
                                    if (index !== -1) {
         | 
| 723 | 
            -
                                        this.statuses.splice(index, 1);
         | 
| 724 | 
            -
                                    }
         | 
| 725 | 
            -
                                    fileInfo.originalName = escapedFileName;
         | 
| 726 | 
            -
                                    fileInfo.hash = fileUpload.hash;
         | 
| 727 | 
            -
                                    if (!this.hasValue()) {
         | 
| 728 | 
            -
                                        this.dataValue = [];
         | 
| 729 | 
            -
                                    }
         | 
| 730 | 
            -
                                    this.dataValue.push(fileInfo);
         | 
| 731 | 
            -
                                    _.pull(this.filesUploading, fileInfo.originalName);
         | 
| 732 | 
            -
                                    this.fileDropHidden = false;
         | 
| 733 | 
            -
                                    this.redraw();
         | 
| 734 | 
            -
                                    this.triggerChange();
         | 
| 735 | 
            -
                                    this.emit('fileUploadingEnd', filePromise);
         | 
| 736 | 
            -
                                })
         | 
| 737 | 
            -
                                    .catch((response) => {
         | 
| 738 | 
            -
                                    fileUpload.status = 'error';
         | 
| 739 | 
            -
                                    fileUpload.message = typeof response === 'string' ? response : response.toString();
         | 
| 740 | 
            -
                                    delete fileUpload.progress;
         | 
| 741 | 
            -
                                    this.fileDropHidden = false;
         | 
| 742 | 
            -
                                    _.pull(this.filesUploading, file.name);
         | 
| 743 | 
            -
                                    this.redraw();
         | 
| 744 | 
            -
                                    this.emit('fileUploadingEnd', filePromise);
         | 
| 745 | 
            -
                                });
         | 
| 841 | 
            +
                        }
         | 
| 842 | 
            +
                    }
         | 
| 843 | 
            +
                }
         | 
| 844 | 
            +
                async delete() {
         | 
| 845 | 
            +
                    if (!this.filesToSync.filesToDelete.length) {
         | 
| 846 | 
            +
                        return Promise.resolve();
         | 
| 847 | 
            +
                    }
         | 
| 848 | 
            +
                    return await Promise.all(this.filesToSync.filesToDelete.map(async (fileToSync) => {
         | 
| 849 | 
            +
                        try {
         | 
| 850 | 
            +
                            if (fileToSync.isValidationError) {
         | 
| 851 | 
            +
                                return { fileToSync };
         | 
| 746 852 | 
             
                            }
         | 
| 747 | 
            -
                             | 
| 748 | 
            -
             | 
| 853 | 
            +
                            await this.deleteFile(fileToSync);
         | 
| 854 | 
            +
                            fileToSync.status = 'success';
         | 
| 855 | 
            +
                            fileToSync.message = this.t('Succefully removed');
         | 
| 856 | 
            +
                        }
         | 
| 857 | 
            +
                        catch (response) {
         | 
| 858 | 
            +
                            fileToSync.status = 'error';
         | 
| 859 | 
            +
                            fileToSync.message = typeof response === 'string' ? response : response.toString();
         | 
| 860 | 
            +
                        }
         | 
| 861 | 
            +
                        finally {
         | 
| 862 | 
            +
                            this.redraw();
         | 
| 863 | 
            +
                        }
         | 
| 864 | 
            +
                        return { fileToSync };
         | 
| 865 | 
            +
                    }));
         | 
| 866 | 
            +
                }
         | 
| 867 | 
            +
                updateProgress(fileInfo, progressEvent) {
         | 
| 868 | 
            +
                    fileInfo.progress = parseInt(100.0 * progressEvent.loaded / progressEvent.total);
         | 
| 869 | 
            +
                    if (fileInfo.status !== 'progress') {
         | 
| 870 | 
            +
                        fileInfo.status = 'progress';
         | 
| 871 | 
            +
                        delete fileInfo.message;
         | 
| 872 | 
            +
                        this.redraw();
         | 
| 873 | 
            +
                    }
         | 
| 874 | 
            +
                    else {
         | 
| 875 | 
            +
                        const progress = Array.prototype.find.call(this.refs.progress, progressElement => progressElement.id === fileInfo.id);
         | 
| 876 | 
            +
                        progress.innerHTML = `<span class="visually-hidden">${fileInfo.progress}% ${this.t('Complete')}</span>`;
         | 
| 877 | 
            +
                        progress.style.width = `${fileInfo.progress}%`;
         | 
| 878 | 
            +
                        progress.ariaValueNow = fileInfo.progress.toString();
         | 
| 879 | 
            +
                    }
         | 
| 880 | 
            +
                }
         | 
| 881 | 
            +
                getMultipartOptions(fileToSync) {
         | 
| 882 | 
            +
                    let count = 0;
         | 
| 883 | 
            +
                    return this.component.useMultipartUpload && this.component.multipart ? {
         | 
| 884 | 
            +
                        ...this.component.multipart,
         | 
| 885 | 
            +
                        progressCallback: (total) => {
         | 
| 886 | 
            +
                            count++;
         | 
| 887 | 
            +
                            fileToSync.status = 'progress';
         | 
| 888 | 
            +
                            fileToSync.progress = parseInt(100 * count / total);
         | 
| 889 | 
            +
                            delete fileToSync.message;
         | 
| 890 | 
            +
                            this.redraw();
         | 
| 891 | 
            +
                        },
         | 
| 892 | 
            +
                        changeMessage: (message) => {
         | 
| 893 | 
            +
                            fileToSync.message = message;
         | 
| 894 | 
            +
                            this.redraw();
         | 
| 895 | 
            +
                        },
         | 
| 896 | 
            +
                    } : false;
         | 
| 897 | 
            +
                }
         | 
| 898 | 
            +
                async uploadFile(fileToSync) {
         | 
| 899 | 
            +
                    return await this.fileService.uploadFile(fileToSync.storage, fileToSync.file, fileToSync.name, fileToSync.dir, 
         | 
| 900 | 
            +
                    // Progress callback
         | 
| 901 | 
            +
                    this.updateProgress.bind(this, fileToSync), fileToSync.url, fileToSync.options, fileToSync.fileKey, fileToSync.groupPermissions, fileToSync.groupResourceId, () => { }, 
         | 
| 902 | 
            +
                    // Abort upload callback
         | 
| 903 | 
            +
                    (abort) => this.abortUploads.push({
         | 
| 904 | 
            +
                        id: fileToSync.id,
         | 
| 905 | 
            +
                        abort,
         | 
| 906 | 
            +
                    }), this.getMultipartOptions(fileToSync));
         | 
| 907 | 
            +
                }
         | 
| 908 | 
            +
                async upload() {
         | 
| 909 | 
            +
                    if (!this.filesToSync.filesToUpload.length) {
         | 
| 910 | 
            +
                        return Promise.resolve();
         | 
| 911 | 
            +
                    }
         | 
| 912 | 
            +
                    return await Promise.all(this.filesToSync.filesToUpload.map(async (fileToSync) => {
         | 
| 913 | 
            +
                        let fileInfo = null;
         | 
| 914 | 
            +
                        try {
         | 
| 915 | 
            +
                            if (fileToSync.isValidationError) {
         | 
| 916 | 
            +
                                return {
         | 
| 917 | 
            +
                                    fileToSync,
         | 
| 918 | 
            +
                                    fileInfo,
         | 
| 919 | 
            +
                                };
         | 
| 749 920 | 
             
                            }
         | 
| 750 | 
            -
             | 
| 921 | 
            +
                            fileInfo = await this.uploadFile(fileToSync);
         | 
| 922 | 
            +
                            fileToSync.status = 'success';
         | 
| 923 | 
            +
                            fileToSync.message = this.t('Succefully uploaded');
         | 
| 924 | 
            +
                            fileInfo.originalName = fileToSync.originalName;
         | 
| 925 | 
            +
                            fileInfo.hash = fileToSync.hash;
         | 
| 926 | 
            +
                        }
         | 
| 927 | 
            +
                        catch (response) {
         | 
| 928 | 
            +
                            fileToSync.status = 'error';
         | 
| 929 | 
            +
                            delete fileToSync.progress;
         | 
| 930 | 
            +
                            fileToSync.message = typeof response === 'string'
         | 
| 931 | 
            +
                                ? response
         | 
| 932 | 
            +
                                : response.type === 'abort'
         | 
| 933 | 
            +
                                    ? this.t('Request was aborted')
         | 
| 934 | 
            +
                                    : response.toString();
         | 
| 935 | 
            +
                        }
         | 
| 936 | 
            +
                        finally {
         | 
| 937 | 
            +
                            delete fileToSync.progress;
         | 
| 938 | 
            +
                            this.redraw();
         | 
| 939 | 
            +
                        }
         | 
| 940 | 
            +
                        return {
         | 
| 941 | 
            +
                            fileToSync,
         | 
| 942 | 
            +
                            fileInfo,
         | 
| 943 | 
            +
                        };
         | 
| 944 | 
            +
                    }));
         | 
| 945 | 
            +
                }
         | 
| 946 | 
            +
                async syncFiles() {
         | 
| 947 | 
            +
                    this.isSyncing = true;
         | 
| 948 | 
            +
                    this.fileDropHidden = true;
         | 
| 949 | 
            +
                    this.redraw();
         | 
| 950 | 
            +
                    try {
         | 
| 951 | 
            +
                        const [filesToDelete = [], filesToUpload = []] = await Promise.all([this.delete(), this.upload()]);
         | 
| 952 | 
            +
                        this.filesToSync.filesToDelete = filesToDelete
         | 
| 953 | 
            +
                            .filter(file => file.fileToSync?.status === 'error')
         | 
| 954 | 
            +
                            .map(file => file.fileToSync);
         | 
| 955 | 
            +
                        this.filesToSync.filesToUpload = filesToUpload
         | 
| 956 | 
            +
                            .filter(file => file.fileToSync?.status === 'error')
         | 
| 957 | 
            +
                            .map(file => file.fileToSync);
         | 
| 958 | 
            +
                        if (!this.hasValue()) {
         | 
| 959 | 
            +
                            this.dataValue = [];
         | 
| 960 | 
            +
                        }
         | 
| 961 | 
            +
                        const data = filesToUpload
         | 
| 962 | 
            +
                            .filter(file => file.fileToSync?.status === 'success')
         | 
| 963 | 
            +
                            .map(file => file.fileInfo);
         | 
| 964 | 
            +
                        this.dataValue.push(...data);
         | 
| 965 | 
            +
                        this.triggerChange();
         | 
| 966 | 
            +
                        return Promise.resolve();
         | 
| 967 | 
            +
                    }
         | 
| 968 | 
            +
                    catch (err) {
         | 
| 969 | 
            +
                        return Promise.reject();
         | 
| 970 | 
            +
                    }
         | 
| 971 | 
            +
                    finally {
         | 
| 972 | 
            +
                        this.isSyncing = false;
         | 
| 973 | 
            +
                        this.fileDropHidden = false;
         | 
| 974 | 
            +
                        this.abortUploads = [];
         | 
| 975 | 
            +
                        this.redraw();
         | 
| 751 976 | 
             
                    }
         | 
| 752 977 | 
             
                }
         | 
| 753 978 | 
             
                getFile(fileInfo) {
         | 
| @@ -783,7 +1008,21 @@ export default class FileComponent extends Field { | |
| 783 1008 | 
             
                        this.refs.fileBrowse.focus();
         | 
| 784 1009 | 
             
                    }
         | 
| 785 1010 | 
             
                }
         | 
| 786 | 
            -
                 | 
| 1011 | 
            +
                async beforeSubmit() {
         | 
| 1012 | 
            +
                    try {
         | 
| 1013 | 
            +
                        if (!this.autoSync) {
         | 
| 1014 | 
            +
                            return Promise.resolve();
         | 
| 1015 | 
            +
                        }
         | 
| 1016 | 
            +
                        await this.syncFiles();
         | 
| 1017 | 
            +
                        return this.shouldSyncFiles
         | 
| 1018 | 
            +
                            ? Promise.reject('Synchronization is failed')
         | 
| 1019 | 
            +
                            : Promise.resolve();
         | 
| 1020 | 
            +
                    }
         | 
| 1021 | 
            +
                    catch (error) {
         | 
| 1022 | 
            +
                        return Promise.reject(error.message);
         | 
| 1023 | 
            +
                    }
         | 
| 1024 | 
            +
                }
         | 
| 1025 | 
            +
                destroy(all) {
         | 
| 787 1026 | 
             
                    this.stopVideo();
         | 
| 788 1027 | 
             
                    super.destroy(all);
         | 
| 789 1028 | 
             
                }
         |