134 lines
3.7 KiB
JavaScript
134 lines
3.7 KiB
JavaScript
|
|
import { FSFileData, CHUNK_SIZE } from "./FSFileData.js";
|
||
|
|
|
||
|
|
/**
|
||
|
|
* File uploader on FileServer.
|
||
|
|
* @returns {{files: Array<FSFileData>, section: string, init(): void, readonly numberOfFiles: number, readonly isUploading: boolean, readonly hasErrors: boolean, readonly allFilesUploaded: boolean, totalChunksNumber(*): number, handleSubmitFile(Event): Promise<void>, handleRetryFile(number): Promise<void>, removeFile(number): void}|boolean|this is FSFileData[]|number|boolean}
|
||
|
|
* @constructor
|
||
|
|
*/
|
||
|
|
export function FSUploader(){
|
||
|
|
|
||
|
|
return {
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Array of uploaded files.
|
||
|
|
* @type {Array<FSFileData>}
|
||
|
|
*/
|
||
|
|
files: [],
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Section that files must be uploaded.
|
||
|
|
* @type {string}
|
||
|
|
*/
|
||
|
|
section: document.querySelector("meta[name='fs-section']")?.content ?? '',
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Triggered in fs-upload.blade.php
|
||
|
|
* Refresh icons.
|
||
|
|
*
|
||
|
|
* @param {Array<FSFileData>} oldFilesArray
|
||
|
|
*/
|
||
|
|
init( oldFilesArray ){
|
||
|
|
this.$watch('files', () =>{
|
||
|
|
this.$nextTick(() => window.refreshIcons(this.$el) )
|
||
|
|
})
|
||
|
|
|
||
|
|
if( oldFilesArray !== undefined && oldFilesArray.length > 0)
|
||
|
|
this.files = oldFilesArray;
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Shortcut to files.length.
|
||
|
|
* @returns {number}
|
||
|
|
*/
|
||
|
|
get numberOfFiles(){
|
||
|
|
return this.files.length
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Look if some files are currently in upload.
|
||
|
|
* @returns {boolean}
|
||
|
|
*/
|
||
|
|
get isUploading(){
|
||
|
|
return this.files.some(
|
||
|
|
file => file.isUploading
|
||
|
|
);
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Check if some files have an error or not.
|
||
|
|
* @returns {boolean}
|
||
|
|
*/
|
||
|
|
get hasErrors(){
|
||
|
|
return this.files.some(
|
||
|
|
file => file.error
|
||
|
|
);
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Check if all files are uploaded.
|
||
|
|
* True if all files are uploaded or no one.
|
||
|
|
*
|
||
|
|
* @returns {boolean}
|
||
|
|
*/
|
||
|
|
get allFilesUploaded(){
|
||
|
|
return ( this.numberOfFiles === 0 || this.files.every(file => file.done) );
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get total chunks size of a raw file.
|
||
|
|
* @param rawFile
|
||
|
|
* @returns {number}
|
||
|
|
*/
|
||
|
|
totalChunksNumber( rawFile ){
|
||
|
|
return Math.ceil( rawFile.size / CHUNK_SIZE );
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Handle file submission.
|
||
|
|
* You can submit multiple files at once.
|
||
|
|
*
|
||
|
|
* @param {Event} e
|
||
|
|
* @returns {Promise<void>}
|
||
|
|
*/
|
||
|
|
async handleSubmitFile( e ){
|
||
|
|
|
||
|
|
const RAW_FILES_FROM_EVENT = Array.from( e.target.files );
|
||
|
|
e.target.value = ''; // Default.
|
||
|
|
|
||
|
|
for( const RAW_FILE of RAW_FILES_FROM_EVENT ){
|
||
|
|
const TOTAL_CHUNKS = this.totalChunksNumber(RAW_FILE);
|
||
|
|
let fsData = FSFileData( RAW_FILE.name, TOTAL_CHUNKS, RAW_FILE );
|
||
|
|
|
||
|
|
this.files.push( fsData );
|
||
|
|
await this.files[this.files.length - 1].upload(this.section);
|
||
|
|
}
|
||
|
|
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Retry file uploading.
|
||
|
|
*
|
||
|
|
* @param {number} index FSFileData index in this.files.
|
||
|
|
* @returns {Promise<void>}
|
||
|
|
*/
|
||
|
|
handleRetryFile( index ){
|
||
|
|
|
||
|
|
const OLDFSFILE = this.files[index];
|
||
|
|
let fsData = FSFileData(OLDFSFILE.name, this.totalChunksNumber(OLDFSFILE.rawFile), OLDFSFILE.rawFile );
|
||
|
|
this.files[index] = fsData;
|
||
|
|
|
||
|
|
this.files[index].upload(this.section);
|
||
|
|
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Remove a file.
|
||
|
|
* @param {number} index FSFileData index in this.files.
|
||
|
|
*/
|
||
|
|
handleRemoveFile( index ){
|
||
|
|
this.files.splice(index, 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|