UNPKG

ngx-uploader-directive

Version:

Angular File Uploader Directive which provides two directives, which are select and file drag and drop to upload files on server.

1,209 lines (1,199 loc) 48.9 kB
import { EventEmitter, Directive, ElementRef, Input, Output, HostListener, NgModule } from '@angular/core'; import { HttpErrorResponse, HttpRequest, HttpHeaders, HttpEventType, HttpClient, HttpClientModule } from '@angular/common/http'; import { Subject, Observable } from 'rxjs'; import { mergeMap, finalize } from 'rxjs/operators'; /** * @fileoverview added by tsickle * Generated from: lib/configs/config.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** @type {?} */ const environment = { production: true }; /** * @fileoverview added by tsickle * Generated from: lib/models/ngx-uploader-directive-models.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @license * The MIT License (MIT) * Copyright (c) 2015-2018 Jan Kuri jan@bleenco.com * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /** * File Upload Options. * @record */ function IUploadOptions() { } if (false) { /** @type {?} */ IUploadOptions.prototype.requestConcurrency; /** @type {?} */ IUploadOptions.prototype.maxFilesToAddInSingleRequest; /** @type {?|undefined} */ IUploadOptions.prototype.allowedFileTypes; /** @type {?|undefined} */ IUploadOptions.prototype.maxFileUploads; /** @type {?|undefined} */ IUploadOptions.prototype.maxFileSize; /** @type {?|undefined} */ IUploadOptions.prototype.logs; } /** * Selected File Object. * @record */ function ISelectedFile() { } if (false) { /** @type {?} */ ISelectedFile.prototype.requestId; /** @type {?} */ ISelectedFile.prototype.fileIndex; /** @type {?} */ ISelectedFile.prototype.name; /** @type {?} */ ISelectedFile.prototype.type; /** @type {?} */ ISelectedFile.prototype.selectedEventType; /** @type {?|undefined} */ ISelectedFile.prototype.progress; /** @type {?|undefined} */ ISelectedFile.prototype.nativeFile; /** @type {?|undefined} */ ISelectedFile.prototype.response; } /** * File Upload Progress. * @record */ function IUploadProgress() { } if (false) { /** @type {?} */ IUploadProgress.prototype.status; /** @type {?|undefined} */ IUploadProgress.prototype.data; } /** * Upload Input events that can be emit to ngx-uploader-directive. * @record */ function IUploadInput() { } if (false) { /** @type {?} */ IUploadInput.prototype.type; /** * Input unique reference number to evalueate unique events. * Generate using Math.random(). * @type {?|undefined} */ IUploadInput.prototype.inputReferenceNumber; /** @type {?|undefined} */ IUploadInput.prototype.url; /** @type {?|undefined} */ IUploadInput.prototype.method; /** @type {?|undefined} */ IUploadInput.prototype.requestId; /** @type {?|undefined} */ IUploadInput.prototype.fieldName; /** @type {?|undefined} */ IUploadInput.prototype.fileIndex; /** @type {?|undefined} */ IUploadInput.prototype.file; /** @type {?|undefined} */ IUploadInput.prototype.data; /** @type {?|undefined} */ IUploadInput.prototype.headers; } /** * File Upload Output Events that emitted by ngx-uploader-directive. * @record */ function IUploadOutput() { } if (false) { /** @type {?} */ IUploadOutput.prototype.type; /** @type {?|undefined} */ IUploadOutput.prototype.requestId; /** @type {?|undefined} */ IUploadOutput.prototype.files; /** @type {?|undefined} */ IUploadOutput.prototype.fileSelectedEventType; /** @type {?|undefined} */ IUploadOutput.prototype.progress; /** @type {?|undefined} */ IUploadOutput.prototype.response; } /** * @fileoverview added by tsickle * Generated from: lib/services/ngx-uploader-directive.service.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ // @Injectable({ // providedIn: 'root' // }) class NgxUploaderDirectiveService { /** * @param {?=} requestConcurrency * @param {?=} maxFilesToAddInSingleRequest * @param {?=} fileTypes * @param {?=} maxFileUploads * @param {?=} maxFileSize * @param {?=} httpClient * @param {?=} logs */ constructor(requestConcurrency = Number.POSITIVE_INFINITY, maxFilesToAddInSingleRequest = Number.POSITIVE_INFINITY, fileTypes = ['*'], maxFileUploads = Number.POSITIVE_INFINITY, maxFileSize = Number.POSITIVE_INFINITY, httpClient, logs) { this.httpClient = httpClient; this.logs = logs; this.devEnv = !environment.production; this.queue = new Array(); this.MaxNumberOfRequest = 10; this.fileServiceEvents = new EventEmitter(); this.uploadScheduler = new Subject(); this.maxFilesToAddInSingleRequest = 0; this.fileTypes = fileTypes; this.maxFileUploads = maxFileUploads; this.maxFilesToAddInSingleRequest = maxFilesToAddInSingleRequest; this.maxFileSize = maxFileSize; this.subscriptions = new Array(); this.uploadScheduler .pipe(mergeMap((/** * @param {?} upload * @return {?} */ upload => this.startUpload(upload)), requestConcurrency === 0 ? this.MaxNumberOfRequest : requestConcurrency)) .subscribe((/** * @param {?} uploadOutput * @return {?} */ uploadOutput => this.fileServiceEvents.emit(uploadOutput))); } /** * Handles uploaded files * @param {?} selectedFiles Selected Files * @param {?} selectedEventType * @return {?} */ handleSelectedFiles(selectedFiles, selectedEventType) { this.queue = new Array(); this.fileServiceEvents.emit({ type: 'init', fileSelectedEventType: selectedEventType }); if (selectedFiles.length > this.maxFileUploads) { this.httpErrorResponse = new HttpErrorResponse({ status: 0, error: 'Maxium ' + this.maxFileUploads + ' files can be upload' }); this.fileServiceEvents.emit({ type: 'error', response: this.httpErrorResponse, fileSelectedEventType: selectedEventType }); return; } // verify files with allowed files and max uploads /** @type {?} */ const allowedFiles = new Array(); /** @type {?} */ const rejectedFiles = new Array(); // tslint:disable-next-line: prefer-for-of for (let checkingFileIndex = 0; checkingFileIndex < selectedFiles.length; checkingFileIndex++) { /** @type {?} */ const checkingFile = selectedFiles[checkingFileIndex]; /** @type {?} */ const queueLength = allowedFiles.length + this.queue.length + 1; if (this.isFileTypeAllowed(checkingFile.type) && this.isFileSizeAllowed(checkingFile.size)) { allowedFiles.push(checkingFile); } else { /** @type {?} */ const rejectedFile = this.convertToSelectedFile(checkingFile, checkingFileIndex, this.generateRandomeId(), selectedEventType); rejectedFiles.push(rejectedFile); } } if (rejectedFiles.length > 0) { this.httpErrorResponse = new HttpErrorResponse({ status: 0, error: 'Invalid file type or file size exceeded the limit ' + this.humanizeBytes(this.maxFileSize), statusText: 'Invalid Input' }); this.fileServiceEvents.emit({ type: 'rejected', files: rejectedFiles, fileSelectedEventType: selectedEventType, response: this.httpErrorResponse }); } if (this.logs) { console.info('Allowed Files', allowedFiles); } // Adding files to queue /** @type {?} */ let filesAddedToQueue; /** @type {?} */ const totalFilesAdded = new Array(); if (this.maxFilesToAddInSingleRequest === 0 || this.maxFilesToAddInSingleRequest === 1) { /** @type {?} */ const eventId = this.generateRandomeId(); // tslint:disable-next-line: prefer-for-of for (let fileIndex = 0; fileIndex < allowedFiles.length; fileIndex++) { /** @type {?} */ const file = allowedFiles[fileIndex]; /** @type {?} */ let selectedFile; if (this.maxFilesToAddInSingleRequest === 0) { selectedFile = this.convertToSelectedFile(file, fileIndex, eventId, selectedEventType); } else if (this.maxFilesToAddInSingleRequest === 1) { selectedFile = this.convertToSelectedFile(file, fileIndex, this.generateRandomeId(), selectedEventType); } this.queue.push(selectedFile); filesAddedToQueue = new Array(); filesAddedToQueue.push(selectedFile); totalFilesAdded.push(selectedFile); this.fileServiceEvents.emit({ type: 'addedToQueue', files: filesAddedToQueue, requestId: selectedFile.requestId, fileSelectedEventType: selectedEventType }); } } else { // generate id for max files to add in single request. /** @type {?} */ const chunkedArray = this.chunkArray(allowedFiles, this.maxFilesToAddInSingleRequest); /** @type {?} */ let fileIndex = 0; // tslint:disable-next-line: prefer-for-of for (let chukedQueueArrayIndex = 0; chukedQueueArrayIndex < chunkedArray.length; chukedQueueArrayIndex++) { /** @type {?} */ const chunkedElement = chunkedArray[chukedQueueArrayIndex]; /** @type {?} */ const eventId = this.generateRandomeId(); filesAddedToQueue = new Array(); // tslint:disable-next-line: prefer-for-of for (let chunkElementIndex = 0; chunkElementIndex < chunkedElement.length; chunkElementIndex++) { /** @type {?} */ const selectedFileElement = chunkedElement[chunkElementIndex]; /** @type {?} */ const convertdFile = this.convertToSelectedFile(selectedFileElement, fileIndex, eventId, selectedEventType); this.queue.push(convertdFile); filesAddedToQueue.push(convertdFile); totalFilesAdded.push(convertdFile); fileIndex += 1; } this.fileServiceEvents.emit({ type: 'addedToQueue', files: filesAddedToQueue, requestId: eventId, fileSelectedEventType: selectedEventType }); } } if (this.queue.length > 0) { this.fileServiceEvents.emit({ type: 'allAddedToQueue', files: totalFilesAdded, fileSelectedEventType: selectedEventType }); } if (this.logs) { console.info('Queue', this.queue); } } /** * Handles input events upload | remove | cancel * @param {?} inputEvnets Input events of file upload process * @return {?} */ handleInputEvents(inputEvnets) { return inputEvnets.subscribe((/** * @param {?} event * @return {?} */ (event) => { if (this.logs && this.devEnv) { console.info('Input event', event); } if (this.queue.length === 0) { return; } /** @type {?} */ const requestId = event.requestId; switch (event.type) { case 'uploadFile': if (!requestId) { this.httpErrorResponse = new HttpErrorResponse({ status: 0, error: 'Invalid request id.', statusText: 'Invalid Input' }); this.fileServiceEvents.emit({ type: 'error', response: this.httpErrorResponse, fileSelectedEventType: 'ALL' }); return; } this.uploadScheduler.next({ files: this.queue.filter((/** * @param {?} file * @return {?} */ (file) => { return file.requestId === event.requestId; })), event }); break; case 'uploadAll': /** @type {?} */ const groupOfRequests = this.groupByArray(this.queue.filter((/** * @param {?} file * @return {?} */ (file) => file.progress.status === 'Queue')), 'requestId'); if (this.logs) { console.info('Group of request', groupOfRequests); } for (const request in groupOfRequests) { if (groupOfRequests.hasOwnProperty(request)) { /** @type {?} */ const requestFiles = groupOfRequests[request]; if (this.logs && this.devEnv) { console.info('Requesting for id ' + request, requestFiles); } this.uploadScheduler.next({ files: requestFiles, event }); } } break; case 'cancel': if (!requestId) { this.httpErrorResponse = new HttpErrorResponse({ status: 0, error: 'Invalid request id.', statusText: 'Invalid Input' }); this.fileServiceEvents.emit({ type: 'error', response: this.httpErrorResponse, fileSelectedEventType: 'ALL' }); return; } /** @type {?} */ const subs = this.subscriptions.filter((/** * @param {?} sub * @return {?} */ sub => sub.id === requestId)); if (this.logs && this.devEnv) { console.info('subscriptions ', subs); } subs.forEach((/** * @param {?} sub * @return {?} */ sub => { if (sub.sub) { sub.sub.unsubscribe(); // tslint:disable-next-line: no-shadowed-variable /** @type {?} */ const cancelledFilesArray = this.queue.filter((/** * @param {?} file * @return {?} */ (file) => file.requestId === requestId)); if (cancelledFilesArray.length > 0) { this.queue.forEach((/** * @param {?} file * @param {?} fileIndex * @param {?} queue * @return {?} */ (file, fileIndex, queue) => { queue[fileIndex].progress.status = 'Cancelled'; })); this.fileServiceEvents.emit({ type: 'cancelled', requestId, files: cancelledFilesArray, fileSelectedEventType: cancelledFilesArray[0].selectedEventType }); } else { this.httpErrorResponse = new HttpErrorResponse({ status: 0, error: 'Files not found with request id ' + requestId }); this.fileServiceEvents.emit({ type: 'error', response: this.httpErrorResponse, fileSelectedEventType: 'ALL' }); } } })); break; case 'cancelAll': this.subscriptions.forEach((/** * @param {?} sub * @return {?} */ sub => { if (sub.sub) { sub.sub.unsubscribe(); } if (this.logs && this.devEnv) { console.info('subscriptions ', subs); } /** @type {?} */ const canceldFileArray = this.queue.filter((/** * @param {?} uploadFile * @return {?} */ (uploadFile) => uploadFile.requestId === sub.id)); if (canceldFileArray.length > 0) { this.queue.forEach((/** * @param {?} file * @param {?} fileIndex * @param {?} queue * @return {?} */ (file, fileIndex, queue) => { queue[fileIndex].progress.status = 'Cancelled'; })); this.fileServiceEvents.emit({ type: 'cancelled', files: canceldFileArray, fileSelectedEventType: canceldFileArray[0].selectedEventType }); } else { this.httpErrorResponse = new HttpErrorResponse({ status: 0, error: 'Files not found with request id ' + requestId, statusText: 'Invalid Input' }); this.fileServiceEvents.emit({ type: 'error', response: this.httpErrorResponse, fileSelectedEventType: 'ALL' }); } })); break; case 'remove': if (!requestId) { this.httpErrorResponse = new HttpErrorResponse({ status: 0, error: 'Invalid request id.', statusText: 'Invalid Input' }); this.fileServiceEvents.emit({ type: 'error', response: this.httpErrorResponse, fileSelectedEventType: 'ALL' }); return; } /** @type {?} */ const filesToRemove = this.queue.filter((/** * @param {?} file * @return {?} */ (file) => file.requestId === event.requestId)); if (filesToRemove.length > 0) { /** @type {?} */ const remainingFilesArray = this.queue.filter((/** * @param {?} file * @return {?} */ (file) => file.requestId !== event.requestId)); this.queue = remainingFilesArray; this.fileServiceEvents.emit({ type: 'removed', requestId: event.requestId, files: filesToRemove, fileSelectedEventType: 'ALL' }); } else { this.httpErrorResponse = new HttpErrorResponse({ status: 0, error: 'Files not found with request id ' + requestId, statusText: 'Invalid Input' }); this.fileServiceEvents.emit({ type: 'error', response: this.httpErrorResponse, fileSelectedEventType: 'ALL' }); } break; case 'removeAll': if (this.queue.length) { this.queue = new Array(); this.fileServiceEvents.emit({ type: 'removedAll', files: this.queue, fileSelectedEventType: 'ALL' }); } break; } // Temporary taken reference number not in use any where if (NgxUploaderDirectiveService.inputEventReferenceNumber !== event.inputReferenceNumber) { NgxUploaderDirectiveService.inputEventReferenceNumber = event.inputReferenceNumber; } })); } /** * Check for file type is valid or not * @param {?} mimeType file mime type * @return {?} */ isFileTypeAllowed(mimeType) { /** @type {?} */ const allAllowed = this.fileTypes.find((/** * @param {?} type * @return {?} */ (type) => type === '*')) !== undefined; if (allAllowed) { return true; } return this.fileTypes.find((/** * @param {?} type * @return {?} */ (type) => type === mimeType)) !== undefined; } /** * Start file upload * @param {?} upload object with files and upload input event * @return {?} */ startUpload(upload) { return new Observable((/** * @param {?} observer * @return {?} */ observer => { /** @type {?} */ const sub = this.uploadFilesHttpRequest(upload.files, upload.event) .pipe(finalize((/** * @return {?} */ () => { if (!observer.closed) { observer.complete(); } }))) .subscribe((/** * @param {?} output * @return {?} */ output => { observer.next(output); }), (/** * @param {?} err * @return {?} */ err => { observer.error(err); observer.complete(); }), (/** * @return {?} */ () => { observer.complete(); })); this.subscriptions.push({ id: upload.files[0].requestId, sub }); if (this.logs && this.devEnv) { console.info('subscriptions ', this.subscriptions); } })); } /** * Upload files to server * @param {?} files Array of files input * @param {?} event Upload inout event * @return {?} */ uploadFilesHttpRequest(files, event) { return new Observable((/** * @param {?} observer * @return {?} */ observer => { /** @type {?} */ const time = new Date().getTime(); /** @type {?} */ let speed = 0; /** @type {?} */ let eta = null; /** @type {?} */ const fileList = files; /** @type {?} */ const headers = event.headers || {}; if (this.logs && this.devEnv) { console.info('Files to Upload', fileList); } if (fileList.length > 0) { /** @type {?} */ let totalSize = 0; files.forEach((/** * @param {?} file * @param {?} index * @return {?} */ (file, index) => { totalSize += file.nativeFile.size; })); /** @type {?} */ const formData = new FormData(); if (event.data !== undefined) { Object.keys(event.data).forEach((/** * @param {?} key * @return {?} */ key => formData.append(key, event.data[key]))); } if (fileList.length > 1) { // tslint:disable-next-line: prefer-for-of for (let fileIndex = 0; fileIndex < files.length; fileIndex++) { /** @type {?} */ const element = files[fileIndex]; formData.append('file_' + (fileIndex + 1), fileList[fileIndex].nativeFile, fileList[fileIndex].name); } } else { formData.append('file', fileList[0].nativeFile, fileList[0].name); } /** @type {?} */ const cancelledFiles = this.queue.filter((/** * @param {?} file * @return {?} */ file => file.requestId === fileList[0].requestId)); if (cancelledFiles[0].progress.status === 'Cancelled') { observer.complete(); } observer.next({ type: 'start', requestId: files[0].requestId, files, fileSelectedEventType: files[0].selectedEventType }); /** @type {?} */ const req = new HttpRequest(event.method, event.url, formData, { headers: new HttpHeaders(headers), reportProgress: true }); /** @type {?} */ const httpRequestSubscription = this.httpClient.request(req).subscribe(( // tslint:disable-next-line: no-shadowed-variable /** * @param {?} data * @return {?} */ (data) => { switch (data.type) { case HttpEventType.UploadProgress: /** @type {?} */ const percentage = Math.round((data.loaded * 100) / data.total); /** @type {?} */ const diff = new Date().getTime() - time; speed = Math.round(data.loaded / diff * 1000); eta = Math.ceil((data.total - data.loaded) / speed); // console.log('Progress: ' + this.fileUploadProgress); /** @type {?} */ const fileProgress = { status: 'Uploading', data: { percentage, speed, speedHuman: `${this.humanizeBytes(speed)}/s`, startTime: null, endTime: null, eta, etaHuman: this.secondsToHuman(eta) } }; files.forEach((/** * @param {?} file * @param {?} index * @param {?} filesArray * @return {?} */ (file, index, filesArray) => { filesArray[index].progress = fileProgress; })); observer.next({ type: 'uploading', requestId: files[0].requestId, files, progress: fileProgress, fileSelectedEventType: files[0].selectedEventType }); break; case HttpEventType.Response: files[0].response = data.body; /** @type {?} */ const progress = { status: 'Done', data: { percentage: 100, speed, speedHuman: `${this.humanizeBytes(speed)}/s`, startTime: null, endTime: new Date().getTime(), eta, etaHuman: this.secondsToHuman(eta || 0) } }; files.forEach((/** * @param {?} file * @param {?} index * @param {?} filesArray * @return {?} */ (file, index, filesArray) => { filesArray[index].response = data.body; })); observer.next({ type: 'done', requestId: files[0].requestId, response: data.body, progress, fileSelectedEventType: files[0].selectedEventType, files }); observer.complete(); break; } }), (/** * @param {?} error * @return {?} */ (error) => { // console.log(error); observer.next({ type: 'error', requestId: files[0].requestId, response: error, fileSelectedEventType: files[0].selectedEventType }); observer.complete(); })); this.subscriptions.push({ id: files[0].requestId, sub: httpRequestSubscription }); } else { this.httpErrorResponse = new HttpErrorResponse({ status: 0, error: 'Files not available for upload', statusText: 'Invalid Input' }); observer.next({ type: 'error', requestId: files[0].requestId, response: this.httpErrorResponse }); observer.complete(); } })); } /** * Http Request to upload file(s). * @param {?} requestMethod Request method POST | GET * @param {?} apiUrl Url to send request * @param {?} body FormData to passwith * @param {?=} headers * @return {?} */ httpRequest(requestMethod, apiUrl, body, headers) { /** @type {?} */ const req = new HttpRequest(requestMethod, apiUrl, body, { headers, reportProgress: true }); return this.httpClient.request(req); } /** * Converting seconds to human readable * @param {?} sec Seconds * @return {?} */ secondsToHuman(sec) { return new Date(sec * 1000).toISOString().substr(11, 8); } /** * Check for max file size is allowed or not * @param {?} fileSize file size * @return {?} */ isFileSizeAllowed(fileSize) { if (!this.maxFileSize) { return true; } return fileSize <= this.maxFileSize; } /** * Generate Randome file id * @return {?} */ generateRandomeId() { return '_' + Math.random().toString(36).substr(2, 9); } /** * Humanize file Bytes * @param {?} bytes file bytes * @return {?} */ humanizeBytes(bytes) { if (bytes === 0) { return '0 Byte'; } /** @type {?} */ const k = 1024; /** @type {?} */ const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB']; /** @type {?} */ const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; } /** * Convert selected file to Selected file Interface * @param {?} file Selected File * @param {?} fileIndex File index in array * @param {?} id * @param {?} selectedEventType * @return {?} */ convertToSelectedFile(file, fileIndex, id, selectedEventType) { // if (this.logs && this.devEnv) { // console.info('Converting file to Input Selected File index: ' + fileIndex, file); // } return { fileIndex, requestId: id, name: file.name, nativeFile: file, type: file.type, selectedEventType, progress: { status: 'Queue', data: { percentage: 0, eta: 0, speed: 0, speedHuman: this.humanizeBytes(0), startTime: null, endTime: null, etaHuman: null, } } }; } /** * Make chunks of array. * @param {?} array Array to make chunks. * @param {?} chunkSize Chunk size. * @return {?} */ chunkArray(array, chunkSize) { /** @type {?} */ const chunkedArray = new Array(); /** @type {?} */ let index = 0; /** @type {?} */ const arrayLength = array.length; for (index = 0; index < arrayLength; index += chunkSize) { /** @type {?} */ const myChunk = array.slice(index, index + chunkSize); // Do something if you want with the group chunkedArray.push(myChunk); } return chunkedArray; } /** * Group by an Array. * @param {?} array Array of objects * @param {?} key key * @return {?} */ groupByArray(array, key) { return array.reduce((/** * @param {?} previousValue * @param {?} currentValue * @return {?} */ (previousValue, currentValue) => { (previousValue[currentValue[key]] = previousValue[currentValue[key]] || []).push(currentValue); return previousValue; }), {}); } } NgxUploaderDirectiveService.inputEventReferenceNumber = 0; if (false) { /** @type {?} */ NgxUploaderDirectiveService.inputEventReferenceNumber; /** * @type {?} * @private */ NgxUploaderDirectiveService.prototype.devEnv; /** @type {?} */ NgxUploaderDirectiveService.prototype.queue; /** @type {?} */ NgxUploaderDirectiveService.prototype.MaxNumberOfRequest; /** @type {?} */ NgxUploaderDirectiveService.prototype.subscriptions; /** @type {?} */ NgxUploaderDirectiveService.prototype.fileServiceEvents; /** @type {?} */ NgxUploaderDirectiveService.prototype.uploadScheduler; /** @type {?} */ NgxUploaderDirectiveService.prototype.fileTypes; /** @type {?} */ NgxUploaderDirectiveService.prototype.maxFileUploads; /** @type {?} */ NgxUploaderDirectiveService.prototype.maxFileSize; /** @type {?} */ NgxUploaderDirectiveService.prototype.requestConcurrency; /** @type {?} */ NgxUploaderDirectiveService.prototype.maxFilesToAddInSingleRequest; /** @type {?} */ NgxUploaderDirectiveService.prototype.httpErrorResponse; /** * @type {?} * @private */ NgxUploaderDirectiveService.prototype.httpClient; /** * @type {?} * @private */ NgxUploaderDirectiveService.prototype.logs; } /** * @fileoverview added by tsickle * Generated from: lib/directives/ngx-uploader-drop.directive.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class NgxUploaderDropDirective { /** * @param {?} elementRef * @param {?} httpClient */ constructor(elementRef, httpClient) { this.elementRef = elementRef; this.httpClient = httpClient; this.devEnv = !environment.production; this.stopEvent = (/** * @param {?} event * @return {?} */ (event) => { event.stopPropagation(); event.preventDefault(); }); this.uploadOutput = new EventEmitter(); } // tslint:disable-next-line: use-life-cycle-interface /** * @return {?} */ ngOnInit() { this.subscriptions = new Array(); /** @type {?} */ const concurrency = this.options.requestConcurrency; /** @type {?} */ const allowedFileTypes = this.options.allowedFileTypes; /** @type {?} */ const maxFileUploads = this.options.maxFileUploads; /** @type {?} */ const maxFileSize = this.options.maxFileSize; this.uploadService = new NgxUploaderDirectiveService(concurrency, this.options.maxFilesToAddInSingleRequest, allowedFileTypes, maxFileUploads, maxFileSize, this.httpClient, this.options.logs); // file upload element this.element = this.elementRef.nativeElement; this.element.addEventListener('drop', this.stopEvent, false); this.element.addEventListener('dragenter', this.stopEvent, false); this.element.addEventListener('dragover', this.stopEvent, false); // Adding events to subscriptions this.subscriptions.push(this.uploadService.fileServiceEvents.subscribe((/** * @param {?} event * @return {?} */ (event) => { if (event.fileSelectedEventType === 'DROP' || event.fileSelectedEventType === 'ALL') { if (this.options.logs && this.devEnv) { console.info('Output drop event', event); } if (event.type === 'error' || event.type === 'removedAll') { this.element.files = null; this.element.value = ''; } else if (event.type === 'removed' || event.type === 'rejected') { if (this.uploadService.queue.length === 0) { this.element.files = null; this.element.value = ''; } } this.uploadOutput.emit(event); } }))); if (this.uploadInput instanceof EventEmitter) { if (this.options.logs && this.devEnv) { console.info('Input drop Init'); } this.subscriptions.push(this.uploadService.handleInputEvents(this.uploadInput)); } } // tslint:disable-next-line: use-life-cycle-interface /** * @return {?} */ ngOnDestroy() { this.subscriptions.forEach((/** * @param {?} sub * @return {?} */ sub => sub.unsubscribe())); } /** * @param {?} event * @return {?} */ onDrop(event) { event.stopPropagation(); event.preventDefault(); /** @type {?} */ const outputEvent = { type: 'drop', fileSelectedEventType: 'DROP' }; this.uploadOutput.emit(outputEvent); this.uploadService.handleSelectedFiles(event.dataTransfer.files, 'DROP'); } /** * @param {?} event * @return {?} */ onDragOver(event) { if (!event) { return; } /** @type {?} */ const outputEvent = { type: 'dragOver', fileSelectedEventType: 'DROP' }; this.uploadOutput.emit(outputEvent); } /** * @param {?} event * @return {?} */ onDragLeave(event) { if (!event) { return; } /** @type {?} */ const outputEvent = { type: 'dragOut', fileSelectedEventType: 'DROP' }; this.uploadOutput.emit(outputEvent); } } NgxUploaderDropDirective.decorators = [ { type: Directive, args: [{ // tslint:disable-next-line: directive-selector selector: '[ngxFileDrop]' },] } ]; /** @nocollapse */ NgxUploaderDropDirective.ctorParameters = () => [ { type: ElementRef }, { type: HttpClient } ]; NgxUploaderDropDirective.propDecorators = { options: [{ type: Input }], uploadInput: [{ type: Input }], uploadOutput: [{ type: Output }], onDrop: [{ type: HostListener, args: ['drop', ['$event'],] }], onDragOver: [{ type: HostListener, args: ['dragover', ['$event'],] }], onDragLeave: [{ type: HostListener, args: ['dragleave', ['$event'],] }] }; if (false) { /** * @type {?} * @private */ NgxUploaderDropDirective.prototype.devEnv; /** @type {?} */ NgxUploaderDropDirective.prototype.options; /** @type {?} */ NgxUploaderDropDirective.prototype.uploadInput; /** @type {?} */ NgxUploaderDropDirective.prototype.uploadOutput; /** @type {?} */ NgxUploaderDropDirective.prototype.uploadService; /** @type {?} */ NgxUploaderDropDirective.prototype.element; /** @type {?} */ NgxUploaderDropDirective.prototype.subscriptions; /** @type {?} */ NgxUploaderDropDirective.prototype.stopEvent; /** @type {?} */ NgxUploaderDropDirective.prototype.elementRef; /** * @type {?} * @private */ NgxUploaderDropDirective.prototype.httpClient; } /** * @fileoverview added by tsickle * Generated from: lib/directives/ngx-uploader-select.directive.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class NgxUploaderSelectDirective { /** * @param {?} elementRef * @param {?} httpClient */ constructor(elementRef, httpClient) { this.elementRef = elementRef; this.httpClient = httpClient; this.devEnv = !environment.production; this.fileListener = (/** * @return {?} */ () => { // tslint:disable-next-line: no-console if (this.element.files) { // call service method to handle selected files this.uploadService.handleSelectedFiles(this.element.files, 'SELECT'); } }); this.uploadOutput = new EventEmitter(); } // tslint:disable-next-line: use-life-cycle-interface /** * @return {?} */ ngOnInit() { this.subscriptions = new Array(); /** @type {?} */ const concurrency = this.options.requestConcurrency; /** @type {?} */ const allowedFileTypes = this.options.allowedFileTypes; /** @type {?} */ const maxFileUploads = this.options.maxFileUploads; /** @type {?} */ const maxFileSize = this.options.maxFileSize; // tslint:disable-next-line: max-line-length this.uploadService = new NgxUploaderDirectiveService(concurrency, this.options.maxFilesToAddInSingleRequest, allowedFileTypes, maxFileUploads, maxFileSize, this.httpClient, this.options.logs); // file upload element this.element = this.elementRef.nativeElement; // Adding on change event listener this.element.addEventListener('change', this.fileListener, false); this.subscriptions.push(this.uploadService.fileServiceEvents.subscribe((/** * @param {?} event * @return {?} */ (event) => { if (event.fileSelectedEventType === 'SELECT' || event.fileSelectedEventType === 'ALL') { if (event.type === 'error' || event.type === 'removedAll') { this.element.files = null; this.element.value = ''; } else if (event.type === 'removed' || event.type === 'rejected') { if (this.uploadService.queue.length === 0) { this.element.files = null; this.element.value = ''; } } 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)); } } // tslint:disable-next-line: use-life-cycle-interface /** * @return {?} */ ngOnDestroy() { if (this.element) { this.element.removeEventListener('change', this.fileListener, false); this.subscriptions.forEach((/** * @param {?} sub * @return {?} */ sub => sub.unsubscribe())); } } } NgxUploaderSelectDirective.decorators = [ { type: Directive, args: [{ // tslint:disable-next-line: directive-selector selector: '[ngxFileSelect]' },] } ]; /** @nocollapse */ NgxUploaderSelectDirective.ctorParameters = () => [ { type: ElementRef }, { type: HttpClient } ]; NgxUploaderSelectDirective.propDecorators = { options: [{ type: Input }], uploadInput: [{ type: Input }], uploadOutput: [{ type: Output }] }; if (false) { /** * @type {?} * @private */ NgxUploaderSelectDirective.prototype.devEnv; /** @type {?} */ NgxUploaderSelectDirective.prototype.options; /** @type {?} */ NgxUploaderSelectDirective.prototype.uploadInput; /** @type {?} */ NgxUploaderSelectDirective.prototype.uploadOutput; /** @type {?} */ NgxUploaderSelectDirective.prototype.uploadService; /** @type {?} */ NgxUploaderSelectDirective.prototype.element; /** @type {?} */ NgxUploaderSelectDirective.prototype.subscriptions; /** @type {?} */ NgxUploaderSelectDirective.prototype.fileListener; /** @type {?} */ NgxUploaderSelectDirective.prototype.elementRef; /** * @type {?} * @private */ NgxUploaderSelectDirective.prototype.httpClient; } /** * @fileoverview added by tsickle * Generated from: lib/ngx-uploader-directive.module.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class NgxUploaderDirectiveModule { } NgxUploaderDirectiveModule.decorators = [ { type: NgModule, args: [{ declarations: [NgxUploaderDropDirective, NgxUploaderSelectDirective], imports: [], exports: [ NgxUploaderDropDirective, NgxUploaderSelectDirective, HttpClientModule ] },] } ]; /** * @fileoverview added by tsickle * Generated from: public-api.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * Generated from: ngx-uploader-directive.ts * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ export { NgxUploaderDirectiveModule, NgxUploaderDirectiveService, NgxUploaderDropDirective, NgxUploaderSelectDirective, environment }; //# sourceMappingURL=ngx-uploader-directive.js.map