@vaadin/upload 25.2.7 → 25.3.0-alpha10
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/custom-elements.json +637 -204
- package/package.json +11 -11
- package/src/vaadin-upload-button.js +4 -10
- package/src/vaadin-upload-drop-zone.js +1 -0
- package/src/vaadin-upload-file-list-mixin.d.ts +1 -0
- package/src/vaadin-upload-file-list-mixin.js +10 -103
- package/src/vaadin-upload-file-list.js +1 -0
- package/src/vaadin-upload-file-mixin.js +0 -9
- package/src/vaadin-upload-file.js +8 -5
- package/src/vaadin-upload-helpers.js +143 -0
- package/src/vaadin-upload-icon.js +1 -0
- package/src/vaadin-upload-internal-manager.js +174 -0
- package/src/vaadin-upload-manager.d.ts +1 -6
- package/src/vaadin-upload-manager.js +85 -32
- package/src/vaadin-upload-mixin.d.ts +4 -44
- package/src/vaadin-upload-mixin.js +361 -577
- package/src/vaadin-upload.js +1 -0
- package/web-types.json +6 -16
- package/web-types.lit.json +1 -1
|
@@ -228,11 +228,15 @@ export class UploadManager extends EventTarget {
|
|
|
228
228
|
validFiles.push(file);
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
-
this
|
|
231
|
+
this._setFiles(validFiles);
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
-
|
|
235
|
-
|
|
234
|
+
/**
|
|
235
|
+
* Internal setter - bypasses validation for internal use only.
|
|
236
|
+
* @param {Array<UploadFile>} value
|
|
237
|
+
* @private
|
|
238
|
+
*/
|
|
239
|
+
_setFiles(value) {
|
|
236
240
|
this.#files = value;
|
|
237
241
|
this.#updateMaxFilesReached();
|
|
238
242
|
this.#notifyFilesChanged();
|
|
@@ -286,7 +290,7 @@ export class UploadManager extends EventTarget {
|
|
|
286
290
|
files = [files];
|
|
287
291
|
}
|
|
288
292
|
// Only upload files that are managed by this instance and not already complete
|
|
289
|
-
files.filter((file) => this
|
|
293
|
+
files.filter((file) => this._isFileManaged(file) && !file.complete).forEach((file) => this._queueFileUpload(file));
|
|
290
294
|
}
|
|
291
295
|
|
|
292
296
|
/**
|
|
@@ -310,7 +314,19 @@ export class UploadManager extends EventTarget {
|
|
|
310
314
|
* @param {UploadFile} file - The file to remove
|
|
311
315
|
*/
|
|
312
316
|
removeFile(file) {
|
|
313
|
-
this
|
|
317
|
+
this._removeFile(file);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Whether the given file is managed by this instance: only managed files
|
|
322
|
+
* are uploaded by `uploadFiles`, and an upload is canceled if its file is
|
|
323
|
+
* no longer managed after the `upload-before` or `upload-request` event.
|
|
324
|
+
* @param {UploadFile} file
|
|
325
|
+
* @returns {boolean}
|
|
326
|
+
* @private
|
|
327
|
+
*/
|
|
328
|
+
_isFileManaged(file) {
|
|
329
|
+
return this.#files.includes(file);
|
|
314
330
|
}
|
|
315
331
|
|
|
316
332
|
// ============ Private methods ============
|
|
@@ -376,14 +392,20 @@ export class UploadManager extends EventTarget {
|
|
|
376
392
|
file.loaded = 0;
|
|
377
393
|
file.held = true;
|
|
378
394
|
file.formDataName = this.formDataName;
|
|
379
|
-
this
|
|
395
|
+
this._setFiles([file, ...this.#files]);
|
|
380
396
|
|
|
381
397
|
if (!this.noAuto) {
|
|
382
|
-
this
|
|
398
|
+
this._queueFileUpload(file);
|
|
383
399
|
}
|
|
384
400
|
}
|
|
385
401
|
|
|
386
|
-
|
|
402
|
+
/**
|
|
403
|
+
* Remove a file from the list and the upload queue, aborting its active
|
|
404
|
+
* upload if any.
|
|
405
|
+
* @param {UploadFile} file
|
|
406
|
+
* @private
|
|
407
|
+
*/
|
|
408
|
+
_removeFile(file) {
|
|
387
409
|
this.#uploadQueue = this.#uploadQueue.filter((f) => f !== file);
|
|
388
410
|
|
|
389
411
|
// If the file is actively uploading (not held) and not already aborted, abort the XHR
|
|
@@ -394,7 +416,7 @@ export class UploadManager extends EventTarget {
|
|
|
394
416
|
|
|
395
417
|
const fileIndex = this.#files.indexOf(file);
|
|
396
418
|
if (fileIndex >= 0) {
|
|
397
|
-
this
|
|
419
|
+
this._setFiles(this.#files.filter((f) => f !== file));
|
|
398
420
|
|
|
399
421
|
this.dispatchEvent(
|
|
400
422
|
new CustomEvent('file-remove', {
|
|
@@ -404,7 +426,13 @@ export class UploadManager extends EventTarget {
|
|
|
404
426
|
}
|
|
405
427
|
}
|
|
406
428
|
|
|
407
|
-
|
|
429
|
+
/**
|
|
430
|
+
* Queue an upload of the given file, resetting its upload state. A file
|
|
431
|
+
* that is already uploading or queued is ignored.
|
|
432
|
+
* @param {UploadFile} file
|
|
433
|
+
* @private
|
|
434
|
+
*/
|
|
435
|
+
_queueFileUpload(file) {
|
|
408
436
|
if (file.uploading) {
|
|
409
437
|
return;
|
|
410
438
|
}
|
|
@@ -414,8 +442,7 @@ export class UploadManager extends EventTarget {
|
|
|
414
442
|
return;
|
|
415
443
|
}
|
|
416
444
|
|
|
417
|
-
file
|
|
418
|
-
file.progress = 0;
|
|
445
|
+
this._resetFileProgress(file);
|
|
419
446
|
file.held = true;
|
|
420
447
|
file.uploading = file.indeterminate = true;
|
|
421
448
|
file.complete = file.abort = file.errorKey = false;
|
|
@@ -423,10 +450,24 @@ export class UploadManager extends EventTarget {
|
|
|
423
450
|
this.#notifyFilesChanged();
|
|
424
451
|
|
|
425
452
|
this.#uploadQueue.push(file);
|
|
426
|
-
this
|
|
453
|
+
this._processUploadQueue();
|
|
427
454
|
}
|
|
428
455
|
|
|
429
|
-
|
|
456
|
+
/**
|
|
457
|
+
* Reset the progress properties of a file when it is queued for upload.
|
|
458
|
+
* @param {UploadFile} file
|
|
459
|
+
* @private
|
|
460
|
+
*/
|
|
461
|
+
_resetFileProgress(file) {
|
|
462
|
+
file.loaded = 0;
|
|
463
|
+
file.progress = 0;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Start uploads for queued files if there is capacity for them.
|
|
468
|
+
* @private
|
|
469
|
+
*/
|
|
470
|
+
_processUploadQueue() {
|
|
430
471
|
while (this.#uploadQueue.length > 0 && this.#activeUploads < this.maxConcurrentUploads) {
|
|
431
472
|
const nextFile = this.#uploadQueue.shift();
|
|
432
473
|
if (nextFile) {
|
|
@@ -484,7 +525,7 @@ export class UploadManager extends EventTarget {
|
|
|
484
525
|
clearTimeout(stalledId);
|
|
485
526
|
this.#activeUploads -= 1;
|
|
486
527
|
this.#cleanupXhr(xhr);
|
|
487
|
-
this
|
|
528
|
+
this._processUploadQueue();
|
|
488
529
|
};
|
|
489
530
|
|
|
490
531
|
xhr.ontimeout = () => {
|
|
@@ -494,7 +535,7 @@ export class UploadManager extends EventTarget {
|
|
|
494
535
|
file.status = '';
|
|
495
536
|
|
|
496
537
|
this.#activeUploads -= 1;
|
|
497
|
-
this
|
|
538
|
+
this._processUploadQueue();
|
|
498
539
|
this.#cleanupXhr(xhr);
|
|
499
540
|
|
|
500
541
|
this.dispatchEvent(new CustomEvent('upload-error', { detail: { file, xhr } }));
|
|
@@ -507,7 +548,7 @@ export class UploadManager extends EventTarget {
|
|
|
507
548
|
file.indeterminate = file.uploading = false;
|
|
508
549
|
|
|
509
550
|
this.#activeUploads -= 1;
|
|
510
|
-
this
|
|
551
|
+
this._processUploadQueue();
|
|
511
552
|
this.#cleanupXhr(xhr);
|
|
512
553
|
|
|
513
554
|
// Return early if already handled (abort or timeout)
|
|
@@ -540,8 +581,7 @@ export class UploadManager extends EventTarget {
|
|
|
540
581
|
const eventName = file.errorKey ? 'upload-error' : 'upload-success';
|
|
541
582
|
this.dispatchEvent(new CustomEvent(eventName, { detail: { file, xhr } }));
|
|
542
583
|
|
|
543
|
-
|
|
544
|
-
file.xhr = null;
|
|
584
|
+
this._clearFileXhr(file);
|
|
545
585
|
|
|
546
586
|
this.#notifyFilesChanged();
|
|
547
587
|
}
|
|
@@ -560,18 +600,18 @@ export class UploadManager extends EventTarget {
|
|
|
560
600
|
}),
|
|
561
601
|
);
|
|
562
602
|
if (!evt) {
|
|
563
|
-
this
|
|
603
|
+
this._holdFile(file);
|
|
564
604
|
return;
|
|
565
605
|
}
|
|
566
606
|
|
|
567
607
|
// Check if file was removed during upload-before handler
|
|
568
608
|
// If file.abort is true, onabort already decremented #activeUploads
|
|
569
|
-
if (!this
|
|
609
|
+
if (!this._isFileManaged(file)) {
|
|
570
610
|
if (!file.abort) {
|
|
571
611
|
this.#activeUploads -= 1;
|
|
572
612
|
}
|
|
573
613
|
this.#cleanupXhr(xhr);
|
|
574
|
-
this
|
|
614
|
+
this._processUploadQueue();
|
|
575
615
|
return;
|
|
576
616
|
}
|
|
577
617
|
|
|
@@ -616,18 +656,18 @@ export class UploadManager extends EventTarget {
|
|
|
616
656
|
}),
|
|
617
657
|
);
|
|
618
658
|
if (!uploadEvt) {
|
|
619
|
-
this
|
|
659
|
+
this._holdFile(file);
|
|
620
660
|
return;
|
|
621
661
|
}
|
|
622
662
|
|
|
623
663
|
// Check if file was removed during upload-request handler
|
|
624
664
|
// If file.abort is true, onabort already decremented #activeUploads
|
|
625
|
-
if (!this
|
|
665
|
+
if (!this._isFileManaged(file)) {
|
|
626
666
|
if (!file.abort) {
|
|
627
667
|
this.#activeUploads -= 1;
|
|
628
668
|
}
|
|
629
669
|
this.#cleanupXhr(xhr);
|
|
630
|
-
this
|
|
670
|
+
this._processUploadQueue();
|
|
631
671
|
return;
|
|
632
672
|
}
|
|
633
673
|
|
|
@@ -640,7 +680,7 @@ export class UploadManager extends EventTarget {
|
|
|
640
680
|
file.errorKey = e.message || 'sendFailed';
|
|
641
681
|
this.#cleanupXhr(xhr);
|
|
642
682
|
this.#notifyFilesChanged();
|
|
643
|
-
this
|
|
683
|
+
this._processUploadQueue();
|
|
644
684
|
}
|
|
645
685
|
}
|
|
646
686
|
|
|
@@ -653,15 +693,28 @@ export class UploadManager extends EventTarget {
|
|
|
653
693
|
}
|
|
654
694
|
|
|
655
695
|
/**
|
|
656
|
-
* Reset file state
|
|
696
|
+
* Reset the file state and free its upload slot when its `upload-before`
|
|
697
|
+
* or `upload-request` event is prevented.
|
|
698
|
+
* @param {UploadFile} file
|
|
699
|
+
* @private
|
|
657
700
|
*/
|
|
658
|
-
|
|
701
|
+
_holdFile(file) {
|
|
659
702
|
this.#activeUploads -= 1;
|
|
660
703
|
file.uploading = false;
|
|
661
704
|
file.indeterminate = false;
|
|
662
705
|
file.held = true;
|
|
663
706
|
this.#notifyFilesChanged();
|
|
664
|
-
this
|
|
707
|
+
this._processUploadQueue();
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
/**
|
|
711
|
+
* Clear the file's reference to the request once the upload has finished,
|
|
712
|
+
* to allow garbage collection.
|
|
713
|
+
* @param {UploadFile} file
|
|
714
|
+
* @private
|
|
715
|
+
*/
|
|
716
|
+
_clearFileXhr(file) {
|
|
717
|
+
file.xhr = null;
|
|
665
718
|
}
|
|
666
719
|
|
|
667
720
|
/**
|
|
@@ -701,12 +754,12 @@ export class UploadManager extends EventTarget {
|
|
|
701
754
|
}),
|
|
702
755
|
);
|
|
703
756
|
if (evt) {
|
|
704
|
-
// Reset uploading flag so
|
|
757
|
+
// Reset uploading flag so _queueFileUpload doesn't early-return
|
|
705
758
|
// This allows retrying queued files that haven't started yet
|
|
706
759
|
file.uploading = false;
|
|
707
760
|
// Remove from queue if present (for queued files being retried)
|
|
708
761
|
this.#uploadQueue = this.#uploadQueue.filter((f) => f !== file);
|
|
709
|
-
this
|
|
762
|
+
this._queueFileUpload(file);
|
|
710
763
|
}
|
|
711
764
|
}
|
|
712
765
|
|
|
@@ -722,7 +775,7 @@ export class UploadManager extends EventTarget {
|
|
|
722
775
|
if (file.xhr) {
|
|
723
776
|
file.xhr.abort();
|
|
724
777
|
}
|
|
725
|
-
this
|
|
778
|
+
this._removeFile(file);
|
|
726
779
|
}
|
|
727
780
|
}
|
|
728
781
|
|
|
@@ -5,27 +5,18 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import type { Constructor } from '@open-wc/dedupe-mixin';
|
|
7
7
|
import type { I18nMixinClass } from '@vaadin/component-base/src/i18n-mixin.js';
|
|
8
|
+
import type { UploadFileListI18n } from './vaadin-upload-file-list-mixin.js';
|
|
9
|
+
import type { UploadFile as UploadManagerFile } from './vaadin-upload-manager.js';
|
|
8
10
|
|
|
9
|
-
export interface UploadFile extends
|
|
10
|
-
uploadTarget: string;
|
|
11
|
-
elapsed: number;
|
|
11
|
+
export interface UploadFile extends UploadManagerFile {
|
|
12
12
|
elapsedStr: string;
|
|
13
|
-
remaining: number;
|
|
14
13
|
remainingStr: string;
|
|
15
|
-
progress: number;
|
|
16
|
-
speed: number;
|
|
17
14
|
totalStr: string;
|
|
18
|
-
loaded: number;
|
|
19
15
|
loadedStr: string;
|
|
20
|
-
status: string;
|
|
21
16
|
error: string;
|
|
22
|
-
abort?: boolean;
|
|
23
|
-
complete?: boolean;
|
|
24
|
-
held?: boolean;
|
|
25
|
-
uploading?: boolean;
|
|
26
17
|
}
|
|
27
18
|
|
|
28
|
-
export interface UploadI18n {
|
|
19
|
+
export interface UploadI18n extends UploadFileListI18n {
|
|
29
20
|
dropFiles?: {
|
|
30
21
|
one?: string;
|
|
31
22
|
many?: string;
|
|
@@ -34,37 +25,6 @@ export interface UploadI18n {
|
|
|
34
25
|
one?: string;
|
|
35
26
|
many?: string;
|
|
36
27
|
};
|
|
37
|
-
error?: {
|
|
38
|
-
tooManyFiles?: string;
|
|
39
|
-
fileIsTooBig?: string;
|
|
40
|
-
incorrectFileType?: string;
|
|
41
|
-
};
|
|
42
|
-
uploading?: {
|
|
43
|
-
status?: {
|
|
44
|
-
connecting?: string;
|
|
45
|
-
stalled?: string;
|
|
46
|
-
processing?: string;
|
|
47
|
-
held?: string;
|
|
48
|
-
};
|
|
49
|
-
remainingTime?: {
|
|
50
|
-
prefix?: string;
|
|
51
|
-
unknown?: string;
|
|
52
|
-
};
|
|
53
|
-
error?: {
|
|
54
|
-
serverUnavailable?: string;
|
|
55
|
-
unexpectedServerError?: string;
|
|
56
|
-
forbidden?: string;
|
|
57
|
-
fileTooLarge?: string;
|
|
58
|
-
};
|
|
59
|
-
};
|
|
60
|
-
units?: {
|
|
61
|
-
size?: string[];
|
|
62
|
-
sizeBase?: number;
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
formatSize?(bytes: number): string;
|
|
66
|
-
|
|
67
|
-
formatTime?(seconds: number, units: number[]): string;
|
|
68
28
|
}
|
|
69
29
|
|
|
70
30
|
export type UploadMethod = 'POST' | 'PUT';
|