import { Component , EventEmitter , Inject , Input , OnDestroy , Output , ViewEncapsulation } from '@angular/core' ; import { HttpEvent , HttpEventType } from '@angular/common/http' ; import { TranslateService } from '@ngx-translate/core' ; import { WINDOW } from '../../utilities' ; import { ObPopUpService } from '../../pop-up/pop-up.service' ; import { ObEUploadEventType , ObIFile , ObIFileList , ObIUploadEvent } from '../file-upload.model' ; import { ObFileUploadService } from '../file-upload.service' ; @ Component ( { selector : 'ob-progress' , templateUrl : './progress.component.html' , styleUrls : [ './progress.component.scss' ] , encapsulation : ViewEncapsulation . None , host : { class : 'ob-progress' } } ) export class ObProgressComponent implements OnDestroy { @ Output ( ) readonly uploadEvent = new EventEmitter < ObIUploadEvent > ( ) ; @ Input ( ) singleRequest : boolean ; @ Input ( ) uploadUrl : string ; uploadedFiles : ObIFileList = { } as ObIFileList ; private readonly window : Window ; constructor ( private readonly fileUploadService , private readonly popup , private readonly translate , @ Inject ( WINDOW ) window ) { this . window = window ; } @ Input ( ) set files ( files ) { this . window . setTimeout ( ( ) => this . uploadFiles ( files ) ) ; } ngOnDestroy ( ) { this . uploadedFiles . files ?. forEach ( file => file . subscription . unsubscribe ( ) ) ; } cancelUpload ( file ) { if ( ! file . completed && this . popup . confirm ( this . translate . instant ( 'i18n.oblique.file-upload.remove' ) ) ) { this . uploadedFiles . files [ file . index ] ?. subscription . unsubscribe ( ) ; this . uploadedFiles . files . splice ( file . index , 1 ) ; this . uploadedFiles . fileCount -- ; this . uploadEvent . emit ( { type : ObEUploadEventType . CANCELED , files : this . arrayifyFiles ( file . binary ) } ) ; this . isUploadComplete ( ) ; } } retryUpload ( file ) { if ( file . hasError ) { if ( this . singleRequest ) { this . uploadFilesTogether ( file . binary as File [ ] ) ; } else { this . uploadSingleFile ( this . convertToObIFile ( file . binary , file . index ) ) ; } } } private uploadFiles ( files ) { this . uploadedFiles . fileCount = files . length ; if ( this . singleRequest ) { this . uploadFilesTogether ( files ) ; } else { this . uploadFilesIndividually ( files ) ; } } private uploadFilesIndividually ( files ) { this . uploadedFiles . files = files . map ( ( file , index ) => this . convertToObIFile ( file , index ) ) ; this . uploadedFiles . files . forEach ( file => this . uploadSingleFile ( file ) ) ; } private uploadSingleFile ( file ) { this . uploadedFiles . files [ file . index ] . subscription = this . fileUploadService . upload ( this . uploadUrl , file . binary as File ) . subscribe ( event => { this . updateFileProgress ( event , file . index ) ; } ) ; } private isUploadComplete ( ) { if ( ! this . uploadedFiles . files . some ( file => ! file . completed ) ) { const completedFiles = this . uploadedFiles . files . reduce ( ( files , file ) => [ ... files , ... this . arrayifyFiles ( file . binary ) ] , [ ] ) ; this . uploadEvent . emit ( { type : ObEUploadEventType . UPLOADED , files : completedFiles } ) ; this . fileUploadService . notifyUploadComplete ( ) ; this . window . setTimeout ( ( ) => { this . uploadedFiles . fileCount = 0 ; this . uploadedFiles . files . length = 0 ; } , 1000 ) ; } } private uploadFilesTogether ( files ) { this . uploadedFiles . files = [ this . convertToObIFile ( files , 0 ) ] ; this . uploadedFiles . files [ 0 ] . subscription = this . fileUploadService . multiUpload ( this . uploadUrl , files ) . subscribe ( event => { this . updateFileProgress ( event , 0 ) ; } ) ; } private updateFileProgress ( event , index ) { if ( event . type !== HttpEventType . User ) { this . uploadedFiles . files [ index ] . progress = event . type === HttpEventType . UploadProgress ? Math . round ( ( event . loaded / event . total ) * 100 ) : 100 ; } else { this . uploadEvent . emit ( { type : ObEUploadEventType . ERRORED , files : ( event as { type : HttpEventType ; files : File [ ] ; } ) . files } ) ; } this . uploadedFiles . files [ index ] . completed = event . type === HttpEventType . Response ; this . uploadedFiles . files [ index ] . hasError = event . type === HttpEventType . User ; this . isUploadComplete ( ) ; } private convertToObIFile ( file , index ) { return { index , name : ( file as File ) . name , completed : false , progress : 0 , hasError : false , binary : file , subscription : undefined } ; } private arrayifyFiles ( binary ) { return binary instanceof Array ? binary : [ binary ] ; } }