From 23903557708125ee02561acdedec5cb9f6c13e07 Mon Sep 17 00:00:00 2001 From: Jaykumar Prajapati Date: Fri, 1 May 2020 22:02:01 +0530 Subject: [PATCH] multiple event emit solved by adding emit type of emitter --- .../directives/ngx-uploader-drop.directive.ts | 22 ++- .../ngx-uploader-select.directive.ts | 23 ++- .../models/ngx-uploader-directive-models.ts | 7 +- .../src/lib/ngx-uploader-directive.service.ts | 132 ++++++++++-------- src/app/app.component.html | 4 +- src/app/app.component.ts | 15 +- 6 files changed, 123 insertions(+), 80 deletions(-) diff --git a/projects/ngx-uploader-directive/src/lib/directives/ngx-uploader-drop.directive.ts b/projects/ngx-uploader-directive/src/lib/directives/ngx-uploader-drop.directive.ts index 9da959e..b6c42ae 100644 --- a/projects/ngx-uploader-directive/src/lib/directives/ngx-uploader-drop.directive.ts +++ b/projects/ngx-uploader-directive/src/lib/directives/ngx-uploader-drop.directive.ts @@ -22,6 +22,7 @@ */ // tslint:disable: max-line-length +// tslint:disable: no-console import { Directive, Input, EventEmitter, Output, ElementRef, HostListener } from '@angular/core'; import { IUploadOptions, IUploadInput, IUploadOutput } from '../models/ngx-uploader-directive-models'; import { Subscription } from 'rxjs'; @@ -35,6 +36,8 @@ import { NgxUploaderDirectiveService } from '../ngx-uploader-directive.service'; export class NgxUploaderDropDirective { + private devEnv = true; + @Input() options: IUploadOptions; @Input() uploadInput: EventEmitter; @Output() uploadOutput: EventEmitter; @@ -70,12 +73,19 @@ export class NgxUploaderDropDirective { // Adding events to subscriptions this.subscriptions.push( this.uploadService.fileServiceEvents.subscribe((event: IUploadOutput) => { - this.uploadOutput.emit(event); + if (event.fileSelectedEventType === 'DROP' || event.fileSelectedEventType === 'ALL') { + if (this.options.logs && this.devEnv) { + console.info('Output drop event', event); + } + this.uploadOutput.emit(event); + } }) ); if (this.uploadInput instanceof EventEmitter) { - // console.log('Input emit'); + if (this.options.logs && this.devEnv) { + console.info('Input drop Init'); + } this.subscriptions.push(this.uploadService.handleInputEvents(this.uploadInput)); } } @@ -95,9 +105,9 @@ export class NgxUploaderDropDirective { event.stopPropagation(); event.preventDefault(); - const outputEvent: IUploadOutput = { type: 'drop' }; + const outputEvent: IUploadOutput = { type: 'drop', fileSelectedEventType: 'DROP' }; this.uploadOutput.emit(outputEvent); - this.uploadService.handleSelectedFiles(event.dataTransfer.files); + this.uploadService.handleSelectedFiles(event.dataTransfer.files, 'DROP'); } @HostListener('dragover', ['$event']) @@ -106,7 +116,7 @@ export class NgxUploaderDropDirective { return; } - const outputEvent: IUploadOutput = { type: 'dragOver' }; + const outputEvent: IUploadOutput = { type: 'dragOver', fileSelectedEventType: 'DROP' }; this.uploadOutput.emit(outputEvent); } @@ -116,7 +126,7 @@ export class NgxUploaderDropDirective { return; } - const outputEvent: IUploadOutput = { type: 'dragOut' }; + const outputEvent: IUploadOutput = { type: 'dragOut', fileSelectedEventType: 'DROP' }; this.uploadOutput.emit(outputEvent); } diff --git a/projects/ngx-uploader-directive/src/lib/directives/ngx-uploader-select.directive.ts b/projects/ngx-uploader-directive/src/lib/directives/ngx-uploader-select.directive.ts index dce01b5..535de04 100644 --- a/projects/ngx-uploader-directive/src/lib/directives/ngx-uploader-select.directive.ts +++ b/projects/ngx-uploader-directive/src/lib/directives/ngx-uploader-select.directive.ts @@ -21,6 +21,8 @@ * SOFTWARE. */ +// tslint:disable: max-line-length +// tslint:disable: no-console import { Directive, Input, EventEmitter, Output, ElementRef } from '@angular/core'; import { IUploadOptions, IUploadInput, IUploadOutput } from '../models/ngx-uploader-directive-models'; import { Subscription } from 'rxjs'; @@ -34,8 +36,10 @@ import { NgxUploaderDirectiveService } from '../ngx-uploader-directive.service'; export class NgxUploaderSelectDirective { + private devEnv = true; + @Input() options: IUploadOptions; - @Input() uploadInput: EventEmitter; + @Input() uploadInput: EventEmitter; @Output() uploadOutput: EventEmitter; uploadService: NgxUploaderDirectiveService; @@ -66,14 +70,21 @@ export class NgxUploaderSelectDirective { // Adding on change event listener this.element.addEventListener('change', this.fileListener, false); - // Adding events to subscriptions this.subscriptions.push( this.uploadService.fileServiceEvents.subscribe((event: IUploadOutput) => { - this.uploadOutput.emit(event); + if (event.fileSelectedEventType === 'SELECT' || event.fileSelectedEventType === 'ALL') { + if (this.options.logs && this.devEnv) { + console.info('Output select event', event); + } + this.uploadOutput.emit(event); + } }) ); if (this.uploadInput instanceof EventEmitter) { + if (this.options.logs && this.devEnv) { + console.info('Input select Init'); + } this.subscriptions.push(this.uploadService.handleInputEvents(this.uploadInput)); } } @@ -88,10 +99,12 @@ export class NgxUploaderSelectDirective { fileListener = () => { // tslint:disable-next-line: no-console - console.info('file listener', this.element.files); + if (this.options.logs && this.devEnv) { + console.info('File changes', this.element.files); + } if (this.element.files) { // call service method to handle selected files - this.uploadService.handleSelectedFiles(this.element.files); + this.uploadService.handleSelectedFiles(this.element.files, 'SELECT'); } } diff --git a/projects/ngx-uploader-directive/src/lib/models/ngx-uploader-directive-models.ts b/projects/ngx-uploader-directive/src/lib/models/ngx-uploader-directive-models.ts index 7bd7bf4..781517e 100644 --- a/projects/ngx-uploader-directive/src/lib/models/ngx-uploader-directive-models.ts +++ b/projects/ngx-uploader-directive/src/lib/models/ngx-uploader-directive-models.ts @@ -41,6 +41,7 @@ export interface ISelectedFile { fileIndex: number; // file index of selected files. name: string; // Name of file. type: string; // Type of file. + selectedEventType: 'DROP' | 'SELECT'; // Type of selection of file. progress?: IUploadProgress; // File upload Progress. nativeFile?: File; // Native File. formData?: FormData; // Form data to upload with file. @@ -73,10 +74,9 @@ export interface IUploadInput { id?: string; // Input id of file to upload. fieldName?: string; // Input field name. fileIndex?: number; // Input file index to upload. - file?: ISelectedFile; // Input selected file. + file?: ISelectedFile; // Input array selected file. formData?: FormData; // Input form data to pass with file. headers?: { [key: string]: string }; // Input headers to pass with upload request. - withHeaders?: boolean; // Input upload with credentials. } /** @@ -86,7 +86,8 @@ export interface IUploadOutput { type: 'init' | 'addedToQueue' | 'allAddedToQueue' | 'uploading' | 'done' | 'start' | 'cancelled' | 'dragOver' | 'dragOut' | 'drop' | 'removed' | 'removedAll' | 'rejected' | 'error'; // Output events. id?: string; // id of selected file. - file?: ISelectedFile; // selected file. + file?: ISelectedFile; // array selected file. + fileSelectedEventType?: 'DROP' | 'SELECT' | 'ALL'; // Type of selection of file. progress?: IUploadProgress; // Progress response?: any; // File upload api response. } \ No newline at end of file diff --git a/projects/ngx-uploader-directive/src/lib/ngx-uploader-directive.service.ts b/projects/ngx-uploader-directive/src/lib/ngx-uploader-directive.service.ts index dfae978..404eb70 100644 --- a/projects/ngx-uploader-directive/src/lib/ngx-uploader-directive.service.ts +++ b/projects/ngx-uploader-directive/src/lib/ngx-uploader-directive.service.ts @@ -21,11 +21,12 @@ * SOFTWARE. */ +// tslint:disable: max-line-length // tslint:disable: no-console import { Injectable, EventEmitter } from '@angular/core'; import { ISelectedFile, IUploadOutput, IUploadInput, IUploadProgress } from './models/ngx-uploader-directive-models'; -import { Observable, Subscription } from 'rxjs'; -import { finalize } from 'rxjs/operators'; +import { Observable, Subscription, Subject } from 'rxjs'; +import { finalize, mergeMap } from 'rxjs/operators'; import { HttpRequest, HttpClient, HttpEventType, HttpHandler, HttpHeaders } from '@angular/common/http'; // @Injectable({ @@ -34,9 +35,13 @@ import { HttpRequest, HttpClient, HttpEventType, HttpHandler, HttpHeaders } from export class NgxUploaderDirectiveService { - queue: Array; + public static queue: Array = new Array(); + + private devEnv = true; + subscriptions: Array<{ id: string, sub: Subscription }>; fileServiceEvents: EventEmitter; + uploadScheduler: Subject<{ files: Array, event: IUploadInput }>; fileTypes: Array; maxFileUploads: number; maxFileSize: number; @@ -52,25 +57,31 @@ export class NgxUploaderDirectiveService { private httpClient: HttpClient, private logs?: boolean, ) { - this.queue = new Array(); this.fileServiceEvents = new EventEmitter(); + this.uploadScheduler = new Subject(); this.requestConcurrency = requestConcurrency; this.fileTypes = fileTypes; this.maxFileUploads = maxFileUploads; this.maxFileSize = maxFileSize; this.subscriptions = new Array<{ id: string, sub: Subscription }>(); + + this.uploadScheduler + .pipe( + mergeMap(upload => this.startUpload(upload), requestConcurrency) + ) + .subscribe(uploadOutput => this.fileServiceEvents.emit(uploadOutput)); } /** * Handles uploaded files * @param selectedFiles Selected Files */ - handleSelectedFiles(selectedFiles: FileList) { + handleSelectedFiles(selectedFiles: FileList, selectedEventType: 'DROP' | 'SELECT') { - this.queue = new Array(); - this.fileServiceEvents.emit({ type: 'init' }); + NgxUploaderDirectiveService.queue = new Array(); + this.fileServiceEvents.emit({ type: 'init', fileSelectedEventType: selectedEventType }); - if (this.logs) { + if (this.logs && this.devEnv) { console.info('Handling selected files', selectedFiles); } @@ -79,13 +90,13 @@ export class NgxUploaderDirectiveService { // tslint:disable-next-line: prefer-for-of for (let checkingFileIndex = 0; checkingFileIndex < selectedFiles.length; checkingFileIndex++) { const checkingFile = selectedFiles[checkingFileIndex]; - const queueLength = allowedFiles.length + this.queue.length + 1; + const queueLength = allowedFiles.length + NgxUploaderDirectiveService.queue.length + 1; if (this.isFileTypeAllowed(checkingFile.type) && queueLength <= this.maxFileUploads && this.isFileSizeAllowed(checkingFile.size)) { allowedFiles.push(checkingFile); } else { - const rejectedFile: ISelectedFile = this.convertToSelectedFile(checkingFile, checkingFileIndex); - this.fileServiceEvents.emit({ type: 'rejected', file: rejectedFile, id: rejectedFile.id }); + const rejectedFile: ISelectedFile = this.convertToSelectedFile(checkingFile, checkingFileIndex, selectedEventType); + this.fileServiceEvents.emit({ type: 'rejected', file: rejectedFile, id: rejectedFile.id, fileSelectedEventType: selectedEventType }); } } @@ -97,20 +108,20 @@ export class NgxUploaderDirectiveService { // tslint:disable-next-line: prefer-for-of for (let fileIndex = 0; fileIndex < allowedFiles.length; fileIndex++) { const file = allowedFiles[fileIndex]; - if (this.logs) { + if (this.logs && this.devEnv) { console.info('Adding files to queue file index: ' + fileIndex, file); } - const selectedFile: ISelectedFile = this.convertToSelectedFile(file, fileIndex); - this.queue.push(selectedFile); - this.fileServiceEvents.emit({ type: 'addedToQueue', file: selectedFile, id: selectedFile.id }); + const selectedFile: ISelectedFile = this.convertToSelectedFile(file, fileIndex, selectedEventType); + NgxUploaderDirectiveService.queue.push(selectedFile); + this.fileServiceEvents.emit({ type: 'addedToQueue', file: selectedFile, id: selectedFile.id, fileSelectedEventType: selectedEventType }); } - if (this.queue.length > 0) { - this.fileServiceEvents.emit({ type: 'allAddedToQueue' }); + if (NgxUploaderDirectiveService.queue.length > 0) { + this.fileServiceEvents.emit({ type: 'allAddedToQueue', fileSelectedEventType: selectedEventType }); } if (this.logs) { - console.info('Queue', this.queue); + console.info('Queue', NgxUploaderDirectiveService.queue); } } @@ -120,33 +131,25 @@ export class NgxUploaderDirectiveService { */ handleInputEvents(inputEvnets: EventEmitter): Subscription { return inputEvnets.subscribe((event: IUploadInput) => { - if (this.logs) { - console.info('Input Event', event); + if (this.logs && this.devEnv) { + console.info('Input event', event); } + switch (event.type) { case 'uploadFile': - const fileIndex = this.queue.findIndex(file => file === event.file); + const fileIndex = NgxUploaderDirectiveService.queue.findIndex(file => file === event.file); if (fileIndex !== -1 && event.file) { - this.startUpload({ files: this.queue, event }).subscribe( - (uploadResponse) => { - this.fileServiceEvents.emit(uploadResponse); - }, - (uploadError) => { - this.fileServiceEvents.emit(uploadError); - } - ); + this.uploadScheduler.next({ + files: NgxUploaderDirectiveService.queue.filter((file) => { + return file.fileIndex === fileIndex; + }), event + }); } + break; case 'uploadAll': - this.startUpload({ files: this.queue, event }).subscribe( - (uploadResponse) => { - this.fileServiceEvents.emit(uploadResponse); - }, - (uploadError) => { - this.fileServiceEvents.emit(uploadError); - } - ); + this.uploadScheduler.next({ files: NgxUploaderDirectiveService.queue, event }); break; case 'cancel': @@ -159,10 +162,10 @@ export class NgxUploaderDirectiveService { if (sub.sub) { sub.sub.unsubscribe(); // tslint:disable-next-line: no-shadowed-variable - const fileIndex = this.queue.findIndex(file => file.id === id); + const fileIndex = NgxUploaderDirectiveService.queue.findIndex(file => file.id === id); if (fileIndex !== -1) { - this.queue[fileIndex].progress.status = 'Cancelled'; - this.fileServiceEvents.emit({ type: 'cancelled', file: this.queue[fileIndex], id: this.queue[fileIndex].id }); + NgxUploaderDirectiveService.queue[fileIndex].progress.status = 'Cancelled'; + this.fileServiceEvents.emit({ type: 'cancelled', file: NgxUploaderDirectiveService.queue[fileIndex], id: NgxUploaderDirectiveService.queue[fileIndex].id, fileSelectedEventType: NgxUploaderDirectiveService.queue[fileIndex].selectedEventType }); } } }); @@ -174,10 +177,10 @@ export class NgxUploaderDirectiveService { sub.sub.unsubscribe(); } - const file = this.queue.find(uploadFile => uploadFile.id === sub.id); + const file = NgxUploaderDirectiveService.queue.find(uploadFile => uploadFile.id === sub.id); if (file) { file.progress.status = 'Cancelled'; - this.fileServiceEvents.emit({ type: 'cancelled' }); + this.fileServiceEvents.emit({ type: 'cancelled', fileSelectedEventType: NgxUploaderDirectiveService.queue[fileIndex].selectedEventType }); } }); break; @@ -187,19 +190,19 @@ export class NgxUploaderDirectiveService { return; } - const removeFileIndex = this.queue.findIndex(file => file.id === event.id); + const removeFileIndex = NgxUploaderDirectiveService.queue.findIndex(file => file.id === event.id); if (removeFileIndex !== -1) { - const file = this.queue[removeFileIndex]; - this.queue.splice(removeFileIndex, 1); - this.fileServiceEvents.emit({ type: 'removed', file, id: event.id }); + const file = NgxUploaderDirectiveService.queue[removeFileIndex]; + NgxUploaderDirectiveService.queue.splice(removeFileIndex, 1); + this.fileServiceEvents.emit({ type: 'removed', file, id: event.id, fileSelectedEventType: NgxUploaderDirectiveService.queue[fileIndex].selectedEventType }); } break; case 'removeAll': - if (this.queue.length) { - this.queue = new Array(); - this.fileServiceEvents.emit({ type: 'removedAll' }); + if (NgxUploaderDirectiveService.queue.length) { + NgxUploaderDirectiveService.queue = new Array(); + this.fileServiceEvents.emit({ type: 'removedAll', fileSelectedEventType: 'ALL' }); } break; } @@ -238,6 +241,8 @@ export class NgxUploaderDirectiveService { }, () => { observer.complete(); }); + + // this.subscriptions.push({ id: upload.files[0].id, sub }); }); } @@ -256,7 +261,7 @@ export class NgxUploaderDirectiveService { const fileList = files; const headers = event.headers || {}; - if (this.logs) { + if (this.logs && this.devEnv) { console.info('Files to Upload', files); console.info('Files upload with input event', event); } @@ -303,12 +308,24 @@ export class NgxUploaderDirectiveService { } }; - observer.next({ type: 'uploading', file: files[0], progress: fileProgress }); + observer.next({ type: 'uploading', progress: fileProgress, fileSelectedEventType: files[0].selectedEventType }); break; case HttpEventType.Response: files[0].response = data.body; - observer.next({ type: 'done', file: files[0], response: data.body }); + const progress: IUploadProgress = { + status: 'Done', + data: { + percentage: 100, + speed, + speedHuman: `${this.humanizeBytes(speed)}/s`, + startTime: null, + endTime: new Date().getTime(), + eta, + etaHuman: this.secondsToHuman(eta || 0) + } + }; + observer.next({ type: 'done', response: data.body, progress, fileSelectedEventType: files[0].selectedEventType }); observer.complete(); break; } @@ -316,7 +333,7 @@ export class NgxUploaderDirectiveService { }, (error) => { console.log(error); - observer.next({ type: 'error', file: files[0], response: error }); + observer.next({ type: 'error', response: error, fileSelectedEventType: files[0].selectedEventType }); observer.complete(); } ); @@ -388,10 +405,10 @@ export class NgxUploaderDirectiveService { * @param file Selected File * @param fileIndex File index in array */ - convertToSelectedFile(file: File, fileIndex: number): ISelectedFile { - // if (this.logs) { - // console.info('Converting file to Input Selected File index: ' + fileIndex, file); - // } + convertToSelectedFile(file: File, fileIndex: number, selectedEventType: 'DROP' | 'SELECT'): ISelectedFile { + if (this.logs && this.devEnv) { + console.info('Converting file to Input Selected File index: ' + fileIndex, file); + } return { fileIndex, @@ -399,6 +416,7 @@ export class NgxUploaderDirectiveService { name: file.name, nativeFile: file, type: file.type, + selectedEventType, progress: { status: 'Queue', data: { diff --git a/src/app/app.component.html b/src/app/app.component.html index ea94872..b02b12b 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -30,8 +30,8 @@

Drag & Drop

or choose file(s) - + \ No newline at end of file diff --git a/src/app/app.component.ts b/src/app/app.component.ts index d91651e..9e0f0ab 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -15,7 +15,7 @@ export class AppComponent { files: Array; uploadInput: EventEmitter; dragOver: boolean; - uploadUrl = 'upload url'; + uploadUrl = 'http://192.168.0.224:8099/api/blocklists/uploadblockednumberfile'; /** * Default Constructor @@ -28,19 +28,19 @@ export class AppComponent { } onUploadOutput(output: IUploadOutput): void { - console.log(output); + // console.log(output); switch (output.type) { case 'init': this.files = new Array(); break; case 'allAddedToQueue': // uncomment this if you want to auto upload files when added - // startUpload(); + // this.startUpload(); break; case 'addedToQueue': if (typeof output.file !== 'undefined') { this.files.push(output.file); - console.log(this.files); + // console.log(this.files); } break; case 'uploading': @@ -75,18 +75,19 @@ export class AppComponent { type: 'uploadAll', url: this.uploadUrl, method: 'POST', - formData: this.formData + formData: this.formData, + headers: { Authorization: 'bearer ' + 'aetklsndfl' } }; this.uploadInput.emit(event); } cancelUpload(id: string): void { - this.uploadInput.emit({ type: 'cancel', id: id }); + this.uploadInput.emit({ type: 'cancel', id }); } removeFile(id: string): void { - this.uploadInput.emit({ type: 'remove', id: id }); + this.uploadInput.emit({ type: 'remove', id }); } removeAllFiles(): void {