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