From 8db149ffe506ae7c6d308015ddd2cd80abffb797 Mon Sep 17 00:00:00 2001 From: Rick Blokdijk Date: Sat, 23 Jan 2016 00:04:40 +0100 Subject: [PATCH 01/19] Update file-item.ts See: https://github.com/valor-software/ng2-file-upload/issues/29 Fixed by updating progress inside zone.run() --- components/file-upload/file-item.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/components/file-upload/file-item.ts b/components/file-upload/file-item.ts index 2fe79d8..55ff1e6 100644 --- a/components/file-upload/file-item.ts +++ b/components/file-upload/file-item.ts @@ -1,3 +1,4 @@ +import {NgZone} from 'angular2/core'; import {FileLikeObject} from './file-like-object'; import {FileUploader} from './file-uploader'; @@ -18,11 +19,13 @@ export class FileItem { public isError:boolean = false; public progress:number = 0; public index:number = null; + private _zone:NgZone; constructor(private uploader:FileUploader, private some:any, private options:any) { this.file = new FileLikeObject(some); this._file = some; this.url = uploader.url; + this._zone = new NgZone({ enableLongStackTrace: false }); } public upload() { @@ -72,7 +75,9 @@ export class FileItem { } private _onProgress(progress:number) { - this.progress = progress; + this._zone.run(() => { + this.progress = progress; + }); this.onProgress(progress); } -- 2.43.0 From a122d6703d79550f3e2c5a420abfbb73dd9aed59 Mon Sep 17 00:00:00 2001 From: Ben Sgroi Date: Fri, 12 Feb 2016 11:14:59 -0800 Subject: [PATCH 02/19] Effective default queue limit of 0 If you don't set the queueLimit manually, then it's undefined, so the queueLimitFilter never allows any files by default. I modified the filter to ignore the queueLimit if it's undefined. --- components/file-upload/file-uploader.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/file-upload/file-uploader.ts b/components/file-upload/file-uploader.ts index e0ce563..820c613 100644 --- a/components/file-upload/file-uploader.ts +++ b/components/file-upload/file-uploader.ts @@ -225,7 +225,7 @@ export class FileUploader { } private _queueLimitFilter() { - return this.queue.length < this.queueLimit; + return this.queueLimit === undefined || this.queue.length < this.queueLimit; } private _isValidFile(file:any, filters:any, options:any) { -- 2.43.0 From a9e093ed2b020a7500d75062a18509d8fb838fb4 Mon Sep 17 00:00:00 2001 From: Sylvain Dumont Date: Wed, 17 Feb 2016 23:57:09 +0100 Subject: [PATCH 03/19] expose autoUpload --- components/file-upload/file-uploader.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/components/file-upload/file-uploader.ts b/components/file-upload/file-uploader.ts index e0ce563..2ec1789 100644 --- a/components/file-upload/file-uploader.ts +++ b/components/file-upload/file-uploader.ts @@ -27,6 +27,7 @@ export class FileUploader { // Object.assign(this, options); this.url = options.url; this.authToken = options.authToken; + this.autoUpload = options.autoUpload; this.filters.unshift({name: 'queueLimit', fn: this._queueLimitFilter}); this.filters.unshift({name: 'folder', fn: this._folderFilter}); } -- 2.43.0 From 6db3c7e1603fa40fdfe91759f8462dad701d5344 Mon Sep 17 00:00:00 2001 From: Ibrahim Islam Date: Sat, 2 Apr 2016 16:46:09 +0600 Subject: [PATCH 04/19] exposes an event for file drop Emits an event passing in raw `File` dropped --- components/file-upload/file-drop.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/components/file-upload/file-drop.ts b/components/file-upload/file-drop.ts index 50d4a05..fe7db82 100644 --- a/components/file-upload/file-drop.ts +++ b/components/file-upload/file-drop.ts @@ -5,7 +5,7 @@ import { FileUploader } from './file-uploader'; @Directive({ selector: '[ng2-file-drop]', properties: ['uploader'], - events: ['fileOver'], + events: ['fileOver','onFileDrop'], host: { '(drop)': 'onDrop($event)', '(dragover)': 'onDragOver($event)', @@ -15,6 +15,7 @@ import { FileUploader } from './file-uploader'; export class FileDrop { public uploader:FileUploader; private fileOver:EventEmitter = new EventEmitter(); + private onFileDrop:EventEmitter = new EventEmitter(); constructor(private element:ElementRef) { } @@ -36,6 +37,7 @@ export class FileDrop { let filters = this.getFilters(); this._preventAndStop(event); this.uploader.addToQueue(transfer.files, options, filters); + this.onFileDrop.emit(transfer.files[0]); this.fileOver.next(false); } -- 2.43.0 From 80cb9d5891705a693c7490de81bfe402aefa5763 Mon Sep 17 00:00:00 2001 From: Joaquim Rodolfo Galli Date: Wed, 4 May 2016 18:41:59 -0400 Subject: [PATCH 05/19] Adicionado a biblioteca do angular2 RC.0.1 --- .travis.yml | 20 +++++++++ components/file-upload/file-drop.ts | 2 +- components/file-upload/file-select.ts | 2 +- demo/components/file-upload-section.ts | 4 +- demo/components/file-upload/simple-demo.html | 2 +- demo/components/file-upload/simple-demo.ts | 4 +- demo/index.ts | 12 +++-- gulpfile.js | 1 + ng2-file-upload.ts | 2 + package.json | 47 +++++++++++++------- tsconfig.json | 13 +++--- typings.json | 9 ++++ webpack.config.js | 8 ++-- 13 files changed, 87 insertions(+), 39 deletions(-) create mode 100644 .travis.yml create mode 100644 typings.json diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..100c80f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,20 @@ +language: node_js +node_js: + - "5" + - "4" + +before_install: +- npm install -g npm@latest + +script: +- npm test +- npm run deploy + +addons: + firefox: "42.0" + apt: + sources: + - ubuntu-toolchain-r-test + # required by node-gyp to build some packages + packages: + - g++-4.8 diff --git a/components/file-upload/file-drop.ts b/components/file-upload/file-drop.ts index 50d4a05..2de4812 100644 --- a/components/file-upload/file-drop.ts +++ b/components/file-upload/file-drop.ts @@ -1,4 +1,4 @@ -import { Directive, EventEmitter, ElementRef } from 'angular2/core'; +import { Directive, EventEmitter, ElementRef } from '@angular/core'; import { FileUploader } from './file-uploader'; diff --git a/components/file-upload/file-select.ts b/components/file-upload/file-select.ts index 66ca229..0fb75de 100644 --- a/components/file-upload/file-select.ts +++ b/components/file-upload/file-select.ts @@ -1,4 +1,4 @@ -import { Directive, ElementRef } from 'angular2/core'; +import { Directive, ElementRef } from '@angular/core'; import {FileUploader} from './file-uploader'; diff --git a/demo/components/file-upload-section.ts b/demo/components/file-upload-section.ts index 81a2c49..5c3fe76 100644 --- a/demo/components/file-upload-section.ts +++ b/demo/components/file-upload-section.ts @@ -1,7 +1,7 @@ /// -import {Component, View} from 'angular2/core'; -import {CORE_DIRECTIVES} from 'angular2/common'; +import {Component} from '@angular/core'; +import {CORE_DIRECTIVES} from '@angular/common'; import {TAB_DIRECTIVES} from 'ng2-bootstrap/ng2-bootstrap'; import {SimpleDemo} from './file-upload/simple-demo'; diff --git a/demo/components/file-upload/simple-demo.html b/demo/components/file-upload/simple-demo.html index 135f1e2..f59cb7a 100644 --- a/demo/components/file-upload/simple-demo.html +++ b/demo/components/file-upload/simple-demo.html @@ -59,7 +59,7 @@ - + {{ item?.file?.name }} {{ item?.file?.size/1024/1024 | number:'.2' }} MB diff --git a/demo/components/file-upload/simple-demo.ts b/demo/components/file-upload/simple-demo.ts index cddc043..3d031c5 100644 --- a/demo/components/file-upload/simple-demo.ts +++ b/demo/components/file-upload/simple-demo.ts @@ -1,7 +1,7 @@ /// -import {Component} from 'angular2/core'; -import {CORE_DIRECTIVES, FORM_DIRECTIVES, NgClass, NgStyle} from 'angular2/common'; +import {Component} from '@angular/core'; +import {CORE_DIRECTIVES, FORM_DIRECTIVES, NgClass, NgStyle} from '@angular/common'; import {FILE_UPLOAD_DIRECTIVES, FileUploader} from '../../../ng2-file-upload'; // webpack html imports diff --git a/demo/index.ts b/demo/index.ts index 3a70956..7bf13c0 100644 --- a/demo/index.ts +++ b/demo/index.ts @@ -1,16 +1,14 @@ -/// -import {bootstrap} from 'angular2/platform/browser'; -import {Component, View} from 'angular2/core'; -import {NgClass} from 'angular2/common'; +/// +import {bootstrap} from '@angular/platform-browser-dynamic'; +import {Component} from '@angular/core'; +import {NgClass} from '@angular/common'; import {FileUploadSection} from './components/file-upload-section'; let gettingStarted = require('./getting-started.md'); @Component({ - selector: 'app' -}) -@View({ + selector: 'app', template: `
diff --git a/gulpfile.js b/gulpfile.js index 2eb78a8..654d545 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -26,4 +26,5 @@ gulp.task('clean', function () { gulp.task('default', function () { gulp.start('lint'); + }); diff --git a/ng2-file-upload.ts b/ng2-file-upload.ts index 74d20a4..b6a0e8d 100644 --- a/ng2-file-upload.ts +++ b/ng2-file-upload.ts @@ -1,3 +1,5 @@ +/// + export * from './components/file-upload/file-select'; export * from './components/file-upload/file-drop'; export * from './components/file-upload/file-uploader'; diff --git a/package.json b/package.json index ab9a231..3eb5920 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "prepublish": "gulp clean && tsc", "server": "webpack-dev-server --hot --inline --colors --display-error-details --display-cached", "start": "npm run server", - "test": "gulp lint" + "test": "gulp lint", + "postinstall": "typings install" }, "main": "ng2-file-upload.js", "typings": "ng2-file-upload.d.ts", @@ -27,16 +28,25 @@ "url": "https://github.com/valor-software/ng2-file-upload/issues" }, "homepage": "https://github.com/valor-software/ng2-file-upload#readme", - "dependencies": {}, + "dependencies": { + }, + "peerDependencies": { + "@angular/common": "^2.0.0-rc.1", + "@angular/compiler": "^2.0.0-rc.1", + "@angular/core": "^2.0.0-rc.1", + "@angular/platform-browser": "^2.0.0-rc.1", + "@angular/platform-browser-dynamic": "^2.0.0-rc.1" +}, "devDependencies": { - "angular2": "2.0.0-beta.0", - "reflect-metadata": "0.1.2", - "rxjs": "5.0.0-beta.0", - "zone.js": "0.6.10", - "es6-shim": "0.33.13", + "@angular/common": "2.0.0-rc.1", + "@angular/compiler": "2.0.0-rc.1", + "@angular/core": "2.0.0-rc.1", + "@angular/platform-browser": "2.0.0-rc.1", + "@angular/platform-browser-dynamic": "2.0.0-rc.1", "bootstrap": "3.3.6", - "clean-webpack-plugin": "0.1.8", - "compression-webpack-plugin": "0.3.1", + "clean-webpack-plugin": "0.1.9", + "es6-promise": "^3.1.2", + "es6-shim": "^0.35.0", "eslint": "1.10.3", "exports-loader": "0.6.3", "file-loader": "0.8.5", @@ -44,23 +54,26 @@ "gulp-clean": "0.3.2", "gulp-eslint": "1.1.1", "gulp-size": "2.1.0", - "gulp-tsc": "1.1.4", - "gulp-tslint": "4.3.5", + "gulp-tsc": "1.1.5", + "gulp-tslint": "5.0.0", "html-loader": "0.4.3", "markdown-loader": "0.1.7", "marked": "0.3.5", - "moment": "2.11.2", - "ng2-bootstrap": "1.0.11", + "moment": "2.13.0", + "ng2-bootstrap": "^1.0.15", "pre-commit": "1.1.2", "prismjs": "valorkin/prism", "prismjs-loader": "0.0.2", "raw-loader": "0.5.1", + "reflect-metadata": "0.1.2", "require-dir": "0.3.0", + "rxjs": "^5.0.0-beta.6", "ts-loader": "0.8.2", - "tslint": "3.7.1", - "typescript": "1.8.9", - "webpack": "1.12.15", - "webpack-dev-server": "1.14.0" + "tslint": "3.9.0", + "typescript": "1.8.10", + "webpack": "1.13.0", + "webpack-dev-server": "1.14.1", + "zone.js": "^0.6.12" }, "contributors": [ { diff --git a/tsconfig.json b/tsconfig.json index f320393..30fe802 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,14 +1,15 @@ { - "version": "1.7.5", + "version": "1.7.6", "compilerOptions": { "target": "es5", "module": "commonjs", - "sourceMap": true, + "moduleResolution": "node", + "sourceMap": false, "declaration": true, - "removeComments": true, + "removeComments": false, "emitDecoratorMetadata": true, "experimentalDecorators": true, - "listFiles": false, + "listFiles": true, "noLib": false, "noImplicitAny": true }, @@ -16,6 +17,8 @@ "node_modules" ], "files": [ - "ng2-file-upload.ts" + "ng2-file-upload.ts", + "./typings/browser.d.ts", + "./ng2-file-upload.ts" ] } diff --git a/typings.json b/typings.json new file mode 100644 index 0000000..5fa43da --- /dev/null +++ b/typings.json @@ -0,0 +1,9 @@ +{ + "dependencies": { + "webpack": "registry:npm/webpack#1.12.9+20160219013405" + }, + "devDependencies": {}, + "ambientDependencies": { + "es6-shim": "registry:dt/es6-shim#0.31.2+20160317120654" + } +} diff --git a/webpack.config.js b/webpack.config.js index b98b7c1..8ee6d46 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -48,10 +48,12 @@ var config = { entry: { angular2: [ // Angular 2 Deps - 'zone.js/dist/zone-microtask', + 'es6-shim', + 'es6-promise', + 'zone.js', 'reflect-metadata', - 'angular2/common', - 'angular2/core' + '@angular/common', + '@angular/core' ], 'angular2-file-upload': ['ng2-file-upload'], 'angular2-file-upload-demo': 'demo' -- 2.43.0 From 7a18833df47a83157c06054fea7ae9740639b630 Mon Sep 17 00:00:00 2001 From: Joaquim Rodolfo Galli Date: Wed, 4 May 2016 18:42:37 -0400 Subject: [PATCH 06/19] Adicionado a biblioteca do angular2 RC.0.1 --- gulpfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gulpfile.js b/gulpfile.js index 654d545..cbeaead 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -26,5 +26,5 @@ gulp.task('clean', function () { gulp.task('default', function () { gulp.start('lint'); - }); + -- 2.43.0 From 434c67e2a82912cbe754cadb8398871d241cad05 Mon Sep 17 00:00:00 2001 From: Joaquim Rodolfo Galli Date: Fri, 6 May 2016 16:39:49 -0400 Subject: [PATCH 07/19] Changed the NG2-bootstrap version for RC.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3eb5920..949ce34 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "markdown-loader": "0.1.7", "marked": "0.3.5", "moment": "2.13.0", - "ng2-bootstrap": "^1.0.15", + "ng2-bootstrap": "git://github.com/valor-software/ng2-bootstrap.git#development", "pre-commit": "1.1.2", "prismjs": "valorkin/prism", "prismjs-loader": "0.0.2", -- 2.43.0 From b966cbdc6dfb86eda2d08fdfa58f163da41172b4 Mon Sep 17 00:00:00 2001 From: Joaquim Rodolfo Galli Date: Fri, 6 May 2016 17:00:53 -0400 Subject: [PATCH 08/19] Changed package.json, remove postinstall: `typings install` --- package.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 949ce34..e97ef07 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,7 @@ "prepublish": "gulp clean && tsc", "server": "webpack-dev-server --hot --inline --colors --display-error-details --display-cached", "start": "npm run server", - "test": "gulp lint", - "postinstall": "typings install" + "test": "gulp lint" }, "main": "ng2-file-upload.js", "typings": "ng2-file-upload.d.ts", @@ -67,7 +66,7 @@ "raw-loader": "0.5.1", "reflect-metadata": "0.1.2", "require-dir": "0.3.0", - "rxjs": "^5.0.0-beta.6", + "rxjs": "5.0.0-beta.6", "ts-loader": "0.8.2", "tslint": "3.9.0", "typescript": "1.8.10", -- 2.43.0 From 13c5c358648b4a7e8db8cc7fd0cf13396962c6c4 Mon Sep 17 00:00:00 2001 From: Carlos Iriarte Date: Sat, 7 May 2016 10:39:03 -0600 Subject: [PATCH 09/19] feat(package): upgrade to angular 2.0.0-rc.1 (#176) * Upgrade to angular 2.0.0-rc.1 * Add a simple .travis.yml closes #180 * Upgrade to ng2-bootstrap 1.0.16 * Install typings on prepublish * (chore) Fix rxjs dependency, moved it to dev dep * (chore) Upgrade to node 6. Keep mandatory deps. --- .travis.yml | 16 ++++++++ components/file-upload/file-drop.ts | 2 +- components/file-upload/file-select.ts | 2 +- demo/components/file-upload-section.ts | 4 +- demo/components/file-upload/simple-demo.html | 2 +- demo/components/file-upload/simple-demo.ts | 4 +- demo/index.ts | 10 ++--- package.json | 43 ++++++++++++-------- tsconfig.json | 15 +++---- typings.json | 9 ++++ webpack.config.js | 8 ++-- 11 files changed, 76 insertions(+), 39 deletions(-) create mode 100644 .travis.yml create mode 100644 typings.json diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..1dce4ba --- /dev/null +++ b/.travis.yml @@ -0,0 +1,16 @@ +language: node_js +node_js: + - "6" + +script: +- npm test +- npm run deploy + +addons: + firefox: "42.0" + apt: + sources: + - ubuntu-toolchain-r-test + # required by node-gyp to build some packages + packages: + - g++-4.8 \ No newline at end of file diff --git a/components/file-upload/file-drop.ts b/components/file-upload/file-drop.ts index 50d4a05..2de4812 100644 --- a/components/file-upload/file-drop.ts +++ b/components/file-upload/file-drop.ts @@ -1,4 +1,4 @@ -import { Directive, EventEmitter, ElementRef } from 'angular2/core'; +import { Directive, EventEmitter, ElementRef } from '@angular/core'; import { FileUploader } from './file-uploader'; diff --git a/components/file-upload/file-select.ts b/components/file-upload/file-select.ts index 66ca229..0fb75de 100644 --- a/components/file-upload/file-select.ts +++ b/components/file-upload/file-select.ts @@ -1,4 +1,4 @@ -import { Directive, ElementRef } from 'angular2/core'; +import { Directive, ElementRef } from '@angular/core'; import {FileUploader} from './file-uploader'; diff --git a/demo/components/file-upload-section.ts b/demo/components/file-upload-section.ts index 81a2c49..5c3fe76 100644 --- a/demo/components/file-upload-section.ts +++ b/demo/components/file-upload-section.ts @@ -1,7 +1,7 @@ /// -import {Component, View} from 'angular2/core'; -import {CORE_DIRECTIVES} from 'angular2/common'; +import {Component} from '@angular/core'; +import {CORE_DIRECTIVES} from '@angular/common'; import {TAB_DIRECTIVES} from 'ng2-bootstrap/ng2-bootstrap'; import {SimpleDemo} from './file-upload/simple-demo'; diff --git a/demo/components/file-upload/simple-demo.html b/demo/components/file-upload/simple-demo.html index 135f1e2..f59cb7a 100644 --- a/demo/components/file-upload/simple-demo.html +++ b/demo/components/file-upload/simple-demo.html @@ -59,7 +59,7 @@ - + {{ item?.file?.name }} {{ item?.file?.size/1024/1024 | number:'.2' }} MB diff --git a/demo/components/file-upload/simple-demo.ts b/demo/components/file-upload/simple-demo.ts index cddc043..3d031c5 100644 --- a/demo/components/file-upload/simple-demo.ts +++ b/demo/components/file-upload/simple-demo.ts @@ -1,7 +1,7 @@ /// -import {Component} from 'angular2/core'; -import {CORE_DIRECTIVES, FORM_DIRECTIVES, NgClass, NgStyle} from 'angular2/common'; +import {Component} from '@angular/core'; +import {CORE_DIRECTIVES, FORM_DIRECTIVES, NgClass, NgStyle} from '@angular/common'; import {FILE_UPLOAD_DIRECTIVES, FileUploader} from '../../../ng2-file-upload'; // webpack html imports diff --git a/demo/index.ts b/demo/index.ts index 3a70956..6de7dee 100644 --- a/demo/index.ts +++ b/demo/index.ts @@ -1,16 +1,14 @@ /// -import {bootstrap} from 'angular2/platform/browser'; -import {Component, View} from 'angular2/core'; -import {NgClass} from 'angular2/common'; +import {bootstrap} from '@angular/platform-browser-dynamic'; +import {Component} from '@angular/core'; +import {NgClass} from '@angular/common'; import {FileUploadSection} from './components/file-upload-section'; let gettingStarted = require('./getting-started.md'); @Component({ - selector: 'app' -}) -@View({ + selector: 'app', template: `
diff --git a/package.json b/package.json index ab9a231..5fcfa7a 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "angular2 file upload directives", "scripts": { "deploy": "NODE_ENV=production webpack -p --progress --color --optimize-minimize --optimize-dedupe --optimize-occurence-order", - "prepublish": "gulp clean && tsc", + "prepublish": "gulp clean && ./node_modules/.bin/typings install && tsc", "server": "webpack-dev-server --hot --inline --colors --display-error-details --display-cached", "start": "npm run server", "test": "gulp lint" @@ -27,16 +27,23 @@ "url": "https://github.com/valor-software/ng2-file-upload/issues" }, "homepage": "https://github.com/valor-software/ng2-file-upload#readme", - "dependencies": {}, + "dependencies": { + }, + "peerDependencies": { + "@angular/common": "^2.0.0-rc.1", + "@angular/core": "^2.0.0-rc.1" + }, "devDependencies": { - "angular2": "2.0.0-beta.0", - "reflect-metadata": "0.1.2", - "rxjs": "5.0.0-beta.0", - "zone.js": "0.6.10", - "es6-shim": "0.33.13", + "@angular/common": "^2.0.0-rc.1", + "@angular/compiler": "^2.0.0-rc.1", + "@angular/core": "^2.0.0-rc.1", + "@angular/platform-browser": "^2.0.0-rc.1", + "@angular/platform-browser-dynamic": "^2.0.0-rc.1", "bootstrap": "3.3.6", - "clean-webpack-plugin": "0.1.8", + "clean-webpack-plugin": "0.1.9", "compression-webpack-plugin": "0.3.1", + "es6-promise": "^3.1.2", + "es6-shim": "^0.35.0", "eslint": "1.10.3", "exports-loader": "0.6.3", "file-loader": "0.8.5", @@ -44,23 +51,27 @@ "gulp-clean": "0.3.2", "gulp-eslint": "1.1.1", "gulp-size": "2.1.0", - "gulp-tsc": "1.1.4", - "gulp-tslint": "4.3.5", + "gulp-tsc": "1.1.5", + "gulp-tslint": "5.0.0", "html-loader": "0.4.3", "markdown-loader": "0.1.7", "marked": "0.3.5", - "moment": "2.11.2", - "ng2-bootstrap": "1.0.11", + "moment": "2.13.0", + "ng2-bootstrap": "1.0.16", "pre-commit": "1.1.2", "prismjs": "valorkin/prism", "prismjs-loader": "0.0.2", "raw-loader": "0.5.1", + "reflect-metadata": "0.1.2", "require-dir": "0.3.0", + "rxjs": "5.0.0-beta.6", "ts-loader": "0.8.2", - "tslint": "3.7.1", - "typescript": "1.8.9", - "webpack": "1.12.15", - "webpack-dev-server": "1.14.0" + "tslint": "3.9.0", + "typescript": "1.8.10", + "typings": "^0.8.1", + "webpack": "1.13.0", + "webpack-dev-server": "1.14.1", + "zone.js": "^0.6.12" }, "contributors": [ { diff --git a/tsconfig.json b/tsconfig.json index f320393..69720d0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,21 +1,22 @@ { - "version": "1.7.5", "compilerOptions": { "target": "es5", "module": "commonjs", - "sourceMap": true, + "moduleResolution": "node", + "sourceMap": false, "declaration": true, - "removeComments": true, + "removeComments": false, "emitDecoratorMetadata": true, "experimentalDecorators": true, + "noImplicitAny": true, "listFiles": false, - "noLib": false, - "noImplicitAny": true + "noLib": false }, "exclude": [ "node_modules" ], "files": [ - "ng2-file-upload.ts" + "./typings/browser.d.ts", + "./ng2-file-upload.ts" ] -} +} \ No newline at end of file diff --git a/typings.json b/typings.json new file mode 100644 index 0000000..8279f82 --- /dev/null +++ b/typings.json @@ -0,0 +1,9 @@ +{ + "dependencies": { + "webpack": "registry:npm/webpack#1.12.9+20160219013405" + }, + "devDependencies": {}, + "ambientDependencies": { + "es6-shim": "registry:dt/es6-shim#0.31.2+20160317120654" + } +} \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index b98b7c1..8ee6d46 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -48,10 +48,12 @@ var config = { entry: { angular2: [ // Angular 2 Deps - 'zone.js/dist/zone-microtask', + 'es6-shim', + 'es6-promise', + 'zone.js', 'reflect-metadata', - 'angular2/common', - 'angular2/core' + '@angular/common', + '@angular/core' ], 'angular2-file-upload': ['ng2-file-upload'], 'angular2-file-upload-demo': 'demo' -- 2.43.0 From aee69d8b80f9e88b22af6da5841352307bc2b42e Mon Sep 17 00:00:00 2001 From: Dmitriy Shekhovtsov Date: Wed, 11 May 2016 18:40:47 +0300 Subject: [PATCH 10/19] chore(build): ng2 style guide applied, - build process updated - systemjs bundler added BREAKING CHANGES: - directives and selectors renamed to ng2FileSelect and ng2FileDrop --- .config/bundle-system.js | 107 ++++++ .eslintrc | 200 ----------- .eslintrc.json | 6 + .gitignore | 6 +- .npmignore | 19 +- README.md | 8 +- .../file-upload/file-drop.directive.spec.ts | 21 ++ .../{file-drop.ts => file-drop.directive.ts} | 51 ++- .../{file-item.ts => file-item.class.ts} | 59 +-- ...ke-object.ts => file-like-object.class.ts} | 14 +- ...ile-select.ts => file-select.directive.ts} | 30 +- ...ile-uploader.ts => file-uploader.class.ts} | 339 ++++++++---------- components/file-upload/readme.md | 27 +- demo/components/file-upload-section.ts | 14 +- demo/components/file-upload/file-catcher.js | 1 + demo/components/file-upload/simple-demo.html | 8 +- demo/components/file-upload/simple-demo.ts | 14 +- demo/index.html | 6 - demo/index.ts | 9 +- es6-object.d.ts | 26 -- gulp-tasks/lint.js | 35 +- gulpfile.js | 25 +- karma.conf.js | 101 ++++++ ng2-file-upload.ts | 18 +- package.json | 80 +++-- test.bundle.js | 47 +++ tsd.d.ts | 1 - tslint.json | 56 +-- typings.json | 7 +- webpack.config.js | 148 ++++---- 30 files changed, 743 insertions(+), 740 deletions(-) create mode 100755 .config/bundle-system.js delete mode 100644 .eslintrc create mode 100644 .eslintrc.json create mode 100644 components/file-upload/file-drop.directive.spec.ts rename components/file-upload/{file-drop.ts => file-drop.directive.ts} (57%) rename components/file-upload/{file-item.ts => file-item.class.ts} (59%) rename components/file-upload/{file-like-object.ts => file-like-object.class.ts} (76%) rename components/file-upload/{file-select.ts => file-select.directive.ts} (61%) rename components/file-upload/{file-uploader.ts => file-uploader.class.ts} (71%) delete mode 100644 es6-object.d.ts create mode 100644 karma.conf.js create mode 100644 test.bundle.js delete mode 100644 tsd.d.ts diff --git a/.config/bundle-system.js b/.config/bundle-system.js new file mode 100755 index 0000000..9c8cc53 --- /dev/null +++ b/.config/bundle-system.js @@ -0,0 +1,107 @@ +#!/usr/bin/env node +'use strict'; + +/*eslint no-console: 0, no-sync: 0*/ + +// System.js bundler +// simple and yet reusable system.js bundler +// bundles, minifies and gzips + +const fs = require('fs'); +const del = require('del'); +const path = require('path'); +const zlib = require('zlib'); +const async = require('async'); +const Builder = require('systemjs-builder'); + +const pkg = require('../package.json'); +const name = pkg.name; +const targetFolder = path.resolve('./bundles'); + +async.waterfall([ + cleanBundlesFolder, + getSystemJsBundleConfig, + buildSystemJs({minify: false, sourceMaps: true, mangle: false}), + getSystemJsBundleConfig, + buildSystemJs({minify: true, sourceMaps: true, mangle: false}), + gzipSystemJsBundle +], err => { + if (err) { + throw err; + } +}); + +function getSystemJsBundleConfig(cb) { + const config = { + baseURL: '..', + transpiler: 'typescript', + typescriptOptions: { + module: 'cjs' + }, + map: { + typescript: path.resolve('node_modules/typescript/lib/typescript.js'), + '@angular/core': path.resolve('node_modules/@angular/core/index.js'), + '@angular/common': path.resolve('node_modules/@angular/common/index.js'), + '@angular/compiler': path.resolve('node_modules/@angular/compiler/index.js'), + '@angular/platform-browser': path.resolve('node_modules/@angular/platform-browser/index.js'), + '@angular/platform-browser-dynamic': path.resolve('node_modules/@angular/platform-browser-dynamic/'), + rxjs: path.resolve('node_modules/rxjs') + }, + paths: { + '*': '*.js' + } + }; + + config.meta = ['@angular/common','@angular/compiler','@angular/core', + '@angular/platform-browser','@angular/platform-browser-dynamic', 'rxjs'].reduce((memo, currentValue) => { + memo[path.resolve(`node_modules/${currentValue}/*`)] = {build: false}; + return memo; + }, {}); + config.meta.moment = {build: false}; + return cb(null, config); +} + +function cleanBundlesFolder(cb) { + return del(targetFolder) + .then(paths => { + console.log('Deleted files and folders:\n', paths.join('\n')); + cb(); + }); +} + +function buildSystemJs(options) { + return (config, cb) => { + const minPostFix = options && options.minify ? '.min' : ''; + const fileName = `${name}${minPostFix}.js`; + const dest = path.resolve(__dirname, targetFolder, fileName); + const builder = new Builder(); + + console.log('Bundling system.js file:', fileName, options); + builder.config(config); + return builder + .bundle([name, name].join('/'), dest, options) + .then(() => cb()) + .catch(cb); + }; +} + +function gzipSystemJsBundle(cb) { + const files = fs + .readdirSync(path.resolve(targetFolder)) + .map(file => path.resolve(targetFolder, file)) + .filter(file => fs.statSync(file).isFile()) + .filter(file => path.extname(file) !== 'gz'); + + return async.eachSeries(files, (file, gzipcb) => { + process.nextTick(() => { + console.log('Gzipping ', file); + const gzip = zlib.createGzip({level: 9}); + const inp = fs.createReadStream(file); + const out = fs.createWriteStream(`${file}.gz`); + + inp.on('end', () => gzipcb()); + inp.on('error', err => gzipcb(err)); + return inp.pipe(gzip).pipe(out); + }); + }, cb); +} diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 1025ddc..0000000 --- a/.eslintrc +++ /dev/null @@ -1,200 +0,0 @@ -{ - "env": { - "browser": 2, - "node": 2, - "mocha": 2, - "es6": 2 - }, - "ecmaFeatures": { - "modules": true - }, - "globals": { - "_": 2, - "$": 2, - "angular": 2, - "jQuery": 2 - }, - "rules": { - // Possible Errors - "comma-dangle": 2, - // no-comma-dangle - (deprecated) - "no-cond-assign": [2, "always"], - "no-console": 2, - "no-constant-condition": 2, - "no-control-regex": 2, - "no-debugger": 2, - "no-dupe-keys": 2, - "no-dupe-args": 2, - "no-duplicate-case": 2, - "no-empty-character-class": 2, - // no-empty-class - (deprecated) - "no-empty": 2, - "no-ex-assign": 2, - "no-extra-boolean-cast": 2, - "no-extra-parens": 2, - "no-extra-semi": 2, - "no-func-assign": 2, - "no-inner-declarations": 2, - "no-invalid-regexp": 2, - "no-irregular-whitespace": 2, - "no-negated-in-lhs": 2, - "no-obj-calls": 2, - "no-regex-spaces": 2, - "no-sparse-arrays": 2, - "no-unreachable": 2, - "use-isnan": 2, - "valid-jsdoc": 2, - "valid-typeof": 2, - "no-unexpected-multiline": 2, - - // Best Practices - // not sure - "accessor-pairs": [2, {"getWithoutSet": false, "setWithoutGet": true}], - "block-scoped-var": 2, - "complexity": [2, 6], - "consistent-return": 2, - "curly": 2, - "default-case": 2, - "dot-notation": 2, - // not good for chain calls, but not for properties - "dot-location": [2, "property"], - "eqeqeq": 2, - "guard-for-in": 2, - "no-alert": 2, - "no-caller": 2, - "no-div-regex": 2, - "no-else-return": 2, - "no-empty-label": 2, - "no-eq-null": 2, - "no-eval": 2, - "no-extend-native": 2, - "no-extra-bind": 2, - "no-fallthrough": 2, - "no-floating-decimal": 2, - "no-implied-eval": 2, - "no-iterator": 2, - "no-labels": 2, - "no-lone-blocks": 2, - "no-loop-func": 2, - "no-multi-spaces": 2, - "no-multi-str": 2, - "no-native-reassign": 2, - "no-new": 2, - "no-new-func": 2, - "no-new-wrappers": 2, - "no-octal": 2, - "no-octal-escape": 2, - "no-param-reassign": 2, - "no-process-env": 2, - "no-proto": 2, - "no-redeclare": 2, - "no-return-assign": 2, - "no-script-url": 2, - "no-self-compare": 2, - "no-sequences": 2, - "no-throw-literal": 2, - "no-unused-expressions": 2, - "no-void": 2, - "no-warning-comments": [1, { "terms": ["todo", "fixme"], "location": "anywhere" }], - "no-with": 2, - "radix": 2, - "vars-on-top": 0, - "wrap-iife": [2, "inside"], - "yoda": [2, "never"], - - // Strict Mode - "strict": [2, "global"], - - // Variables - "no-catch-shadow": 2, - "no-delete-var": 2, - "no-label-var": 2, - "no-shadow": 2, - "no-shadow-restricted-names": 2, - "no-undef": 2, - "no-undef-init": 2, - "no-undefined": 2, - "no-unused-vars": 2, - "no-use-before-define": [2, "nofunc"], - - // Node.js - "handle-callback-err": [2, "^.*(e|E)rr" ], - "no-mixed-requires": [2, true], - "no-new-require": 2, - "no-path-concat": 2, - "no-process-exit": 2, - "no-sync": 2, - - // Stylistic Issues - "array-bracket-spacing": [2, "never"], - "brace-style": [2, "1tbs", { "allowSingleLine": true }], - "camelcase": 2, - "comma-spacing": [2, {"before": false, "after": true}], - "comma-style": [2, "last"], - "computed-property-spacing": [2, "never"], - "consistent-this": [2, "self"], - // not sure - "eol-last": 0, - "func-names": 0, - "func-style": [2, "declaration"], - "indent": [2, 2], - "key-spacing": [2, { "beforeColon": false, "afterColon": true}], - "max-nested-callbacks": [2, 3], - "new-cap": [2, {"newIsCap": true, "capIsNew": true, "capIsNewExceptions":[ - "ObjectId", - "Object", - "Function", - "Number", - "String", - "Boolean", - "Date", - "Array", - "Symbol", - "RegExp" - ]}], - "new-parens": 2, - "newline-after-var": 0, - "no-array-constructor": 2, - "no-inline-comments": 2, - "no-lonely-if": 2, - "no-mixed-spaces-and-tabs": 2, - "no-multiple-empty-lines": [2, {"max": 1}], - "no-nested-ternary": 2, - "no-new-object": 2, - "no-spaced-func": 2, - "no-ternary": 0, - "no-trailing-spaces": 2, - "no-underscore-dangle": 2, - "no-unneeded-ternary": 2, - "object-curly-spacing": [2, "never"], - "one-var": [2, { - "var": "never", // Exactly one var declaration per function - "let": "never", // Exactly one let declaration per block - "const": "never" // Exactly one declarator per const declaration per block - }], - "operator-assignment": [1, "always"], - "operator-linebreak": [2, "after"], - "padded-blocks": [2, "never"], - "quote-props": [2, "as-needed"], - "quotes": [2, "single", "avoid-escape"], - "semi": [2, "always"], - "semi-spacing": 2, - // "sort-vars": [1, { "ignoreCase": true }], - "space-after-keywords": [2, "always" ], - "space-before-blocks": [2, "always"], - "space-in-parens": [2, "never"], - "space-infix-ops": 2, - "space-return-throw-case": 2, - "space-unary-ops": [2, { "words": true, "nonwords": false }], - "spaced-comment": 0, - "wrap-regexp": 0, - - // Legacy - "max-len": [1, 120, 4], - // todo: apply max-params - "max-params": [0, 3], - // todo: apply max-statements - "max-statements": [2, 30], - "no-bitwise": 2 - } -} diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..f8afe99 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,6 @@ +{ + "extends": "./node_modules/eslint-config-valorsoft/.eslintrc.json", + "env": { + "node": true + } +} diff --git a/.gitignore b/.gitignore index 3fb66f9..9a947e2 100644 --- a/.gitignore +++ b/.gitignore @@ -10,9 +10,13 @@ npm-debug.log .idea # ignore build and dist for now -/build +/bundles +/demo-build /dist +/coverage +/ts +# ignore incline compiling /demo/**/*.js /demo/**/*.d.ts /demo/**/*.js.map diff --git a/.npmignore b/.npmignore index bd753f7..8f189f2 100644 --- a/.npmignore +++ b/.npmignore @@ -1,13 +1,24 @@ .idea -demo -build gulp-tasks logs -tsd.d.ts +# typings typings -/node_modules +# testing +karma.conf.js +test.bundle.js +coverage +# demo build +demo +demo-build webpack.config.js +#typescript sources +*.ts +*.js.map +!*.d.ts +/components/**/*.ts +!/components/**/*.d.ts + diff --git a/README.md b/README.md index 8373a11..74da75e 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # ng2-file-upload [![npm version](https://badge.fury.io/js/ng2-file-upload.svg)](http://badge.fury.io/js/ng2-file-upload) Easy to use Angular2 directives for files upload ([demo](http://valor-software.github.io/ng2-file-upload/)) -Follow me at [twitter](https://twitter.com/valorkin) to be notified about new releases. +Follow me [![twitter](https://img.shields.io/twitter/follow/valorkin.svg?style=social&label=%20valorkin)](https://twitter.com/valorkin) to be notified about new releases. [![Code Climate](https://codeclimate.com/github/valor-software/ng2-file-upload/badges/gpa.svg)](https://codeclimate.com/github/valor-software/ng2-file-upload) [![Join the chat at https://gitter.im/valor-software/ng2-bootstrap](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/valor-software/ng2-bootstrap?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) @@ -17,9 +17,9 @@ Follow me at [twitter](https://twitter.com/valorkin) to be notified about new re Alternatively, you can [download it in a ZIP file](https://github.com/valor-software/ng2-file-upload/archive/master.zip). -2. Currently `ng2-file-upload` contains two directives: `ng2-file-select` and `ng2-file-drop`. `ng2-file-select` is used for 'file-input' field of form and +2. Currently `ng2-file-upload` contains two directives: `ng2-file-select` and `ng2-file-drop`. `ng2-file-select` is used for 'file-input' field of form and `ng2-file-drop` is used for area that will be used for dropping of file or files. - + 3. More information regarding using of ***ng2-file-upload*** is located in [demo](http://valor-software.github.io/ng2-file-upload/) and [demo sources](https://github.com/valor-software/ng2-file-upload/tree/master/demo). @@ -28,7 +28,7 @@ Follow me at [twitter](https://twitter.com/valorkin) to be notified about new re ### Properties - `uploader` - (`FileUploader`) - uploader object. See using in [demo](https://github.com/valor-software/ng2-file-upload/blob/master/demo/components/file-upload/simple-demo.ts) - + ## API for `ng2-file-drop` ### Properties diff --git a/components/file-upload/file-drop.directive.spec.ts b/components/file-upload/file-drop.directive.spec.ts new file mode 100644 index 0000000..264e409 --- /dev/null +++ b/components/file-upload/file-drop.directive.spec.ts @@ -0,0 +1,21 @@ +import {Component} from '@angular/core'; +import {it, inject, beforeEachProviders} from '@angular/core/testing'; +import {ComponentFixture} from '@angular/compiler/testing'; +import {FileUploader} from './file-uploader.class'; +import {FileSelectDirective} from './file-select.directive'; +@Component({ + selector: 'container', + template: ``, + directives: [FileSelectDirective] +}) +export class ContainerComponent { + public uploader:FileUploader = new FileUploader({url: 'localhost:3000'}); +} +describe('Directive: FileSelectDirective', () => { + beforeEachProviders(() => [ + ContainerComponent + ]); + it('should be fine', inject([ContainerComponent], (fixture:ComponentFixture) => { + expect(fixture).not.toBeNull(); + })); +}); diff --git a/components/file-upload/file-drop.ts b/components/file-upload/file-drop.directive.ts similarity index 57% rename from components/file-upload/file-drop.ts rename to components/file-upload/file-drop.directive.ts index 2de4812..14ed93f 100644 --- a/components/file-upload/file-drop.ts +++ b/components/file-upload/file-drop.directive.ts @@ -1,32 +1,27 @@ -import { Directive, EventEmitter, ElementRef } from '@angular/core'; +import { Directive, EventEmitter, ElementRef, HostListener, Input, Output } from '@angular/core'; -import { FileUploader } from './file-uploader'; +import { FileUploader } from './file-uploader.class'; -@Directive({ - selector: '[ng2-file-drop]', - properties: ['uploader'], - events: ['fileOver'], - host: { - '(drop)': 'onDrop($event)', - '(dragover)': 'onDragOver($event)', - '(dragleave)': 'onDragLeave($event)' - } -}) -export class FileDrop { - public uploader:FileUploader; - private fileOver:EventEmitter = new EventEmitter(); +@Directive({selector: '[ng2FileDrop]'}) +export class FileDropDirective { + @Input() public uploader:FileUploader; + @Output() public fileOver:EventEmitter = new EventEmitter(); - constructor(private element:ElementRef) { + private element:ElementRef; + public constructor(element:ElementRef) { + this.element = element; } - getOptions() { + public getOptions():any { return this.uploader.options; } - getFilters() { + public getFilters():any { + return {}; } - onDrop(event:any) { + @HostListener('drop', ['$event']) + public onDrop(event:any):void { let transfer = this._getTransfer(event); if (!transfer) { return; @@ -36,10 +31,11 @@ export class FileDrop { let filters = this.getFilters(); this._preventAndStop(event); this.uploader.addToQueue(transfer.files, options, filters); - this.fileOver.next(false); + this.fileOver.emit(false); } - onDragOver(event:any) { + @HostListener('dragover', ['$event']) + public onDragOver(event:any):void { let transfer = this._getTransfer(event); if (!this._haveFiles(transfer.types)) { return; @@ -47,16 +43,17 @@ export class FileDrop { transfer.dropEffect = 'copy'; this._preventAndStop(event); - this.fileOver.next(true); + this.fileOver.emit(true); } - onDragLeave(event:any):any { - if (event.currentTarget === (this).element[0]) { + @HostListener('dragleave', ['$event']) + public onDragLeave(event:any):any { + if (event.currentTarget === (this as any).element[0]) { return; } this._preventAndStop(event); - this.fileOver.next(false); + this.fileOver.emit(false); } private _getTransfer(event:any):any { @@ -81,12 +78,12 @@ export class FileDrop { return false; } } - +/* _addOverClass(item:any):any { item.addOverClass(); } _removeOverClass(item:any):any { item.removeOverClass(); - } + }*/ } diff --git a/components/file-upload/file-item.ts b/components/file-upload/file-item.class.ts similarity index 59% rename from components/file-upload/file-item.ts rename to components/file-upload/file-item.class.ts index 2fe79d8..97cef1d 100644 --- a/components/file-upload/file-item.ts +++ b/components/file-upload/file-item.class.ts @@ -1,5 +1,5 @@ -import {FileLikeObject} from './file-like-object'; -import {FileUploader} from './file-uploader'; +import {FileLikeObject} from './file-like-object.class'; +import {FileUploader} from './file-uploader.class'; export class FileItem { public file:FileLikeObject; @@ -17,15 +17,22 @@ export class FileItem { public isCancel:boolean = false; public isError:boolean = false; public progress:number = 0; - public index:number = null; + public index:number = void 0; - constructor(private uploader:FileUploader, private some:any, private options:any) { + private uploader:FileUploader; + private some:any; + private options:any; + + public constructor(uploader:FileUploader, some:any, options:any) { + this.uploader = uploader; + this.some = some; + this.options = options; this.file = new FileLikeObject(some); this._file = some; this.url = uploader.url; } - public upload() { + public upload():void { try { this.uploader.uploadItem(this); } catch (e) { @@ -34,33 +41,39 @@ export class FileItem { } } - public cancel() { + public cancel():void { this.uploader.cancelItem(this); } - public remove() { + public remove():void { this.uploader.removeFromQueue(this); } - public onBeforeUpload() { + public onBeforeUpload():void { + return void 0; } - public onProgress(progress:number) { + public onProgress(progress:number):any { + return {progress}; } - public onSuccess(response:any, status:any, headers:any) { + public onSuccess(response:any, status:any, headers:any):any { + return {response,status,headers}; } - public onError(response:any, status:any, headers:any) { + public onError(response:any, status:any, headers:any):any { + return {response,status,headers}; } - public onCancel(response:any, status:any, headers:any) { + public onCancel(response:any, status:any, headers:any):any { + return {response,status,headers}; } - public onComplete(response:any, status:any, headers:any) { + public onComplete(response:any, status:any, headers:any):any { + return {response,status,headers}; } - private _onBeforeUpload() { + public _onBeforeUpload():void { this.isReady = true; this.isUploading = true; this.isUploaded = false; @@ -71,12 +84,12 @@ export class FileItem { this.onBeforeUpload(); } - private _onProgress(progress:number) { + public _onProgress(progress:number):void { this.progress = progress; this.onProgress(progress); } - private _onSuccess(response:any, status:any, headers:any) { + public _onSuccess(response:any, status:any, headers:any):void { this.isReady = false; this.isUploading = false; this.isUploaded = true; @@ -84,11 +97,11 @@ export class FileItem { this.isCancel = false; this.isError = false; this.progress = 100; - this.index = null; + this.index = void 0; this.onSuccess(response, status, headers); } - private _onError(response:any, status:any, headers:any) { + public _onError(response:any, status:any, headers:any):void { this.isReady = false; this.isUploading = false; this.isUploaded = true; @@ -96,11 +109,11 @@ export class FileItem { this.isCancel = false; this.isError = true; this.progress = 0; - this.index = null; + this.index = void 0; this.onError(response, status, headers); } - private _onCancel(response:any, status:any, headers:any) { + public _onCancel(response:any, status:any, headers:any):void { this.isReady = false; this.isUploading = false; this.isUploaded = false; @@ -108,11 +121,11 @@ export class FileItem { this.isCancel = true; this.isError = false; this.progress = 0; - this.index = null; + this.index = void 0; this.onCancel(response, status, headers); } - private _onComplete(response:any, status:any, headers:any) { + public _onComplete(response:any, status:any, headers:any):void { this.onComplete(response, status, headers); if (this.uploader.removeAfterUpload) { @@ -120,7 +133,7 @@ export class FileItem { } } - private _prepareToUploading() { + public _prepareToUploading():void { this.index = this.index || ++this.uploader._nextIndex; this.isReady = true; } diff --git a/components/file-upload/file-like-object.ts b/components/file-upload/file-like-object.class.ts similarity index 76% rename from components/file-upload/file-like-object.ts rename to components/file-upload/file-like-object.class.ts index 9e824ab..2d0ccf7 100644 --- a/components/file-upload/file-like-object.ts +++ b/components/file-upload/file-like-object.class.ts @@ -1,4 +1,4 @@ -function isElement(node:any) { +function isElement(node:any):boolean { return !!(node && (node.nodeName || node.prop && node.attr && node.find)); } @@ -8,22 +8,22 @@ export class FileLikeObject { public type:string; public name:string; - constructor(fileOrInput:any) { + public constructor(fileOrInput:any) { let isInput = isElement(fileOrInput); let fakePathOrObject = isInput ? fileOrInput.value : fileOrInput; let postfix = typeof fakePathOrObject === 'string' ? 'FakePath' : 'Object'; let method = '_createFrom' + postfix; - (this)[method](fakePathOrObject); + (this as any)[method](fakePathOrObject); } - public _createFromFakePath(path:string) { - this.lastModifiedDate = null; - this.size = null; + public _createFromFakePath(path:string):void { + this.lastModifiedDate = void 0; + this.size = void 0; this.type = 'like/' + path.slice(path.lastIndexOf('.') + 1).toLowerCase(); this.name = path.slice(path.lastIndexOf('/') + path.lastIndexOf('\\') + 2); } - public _createFromObject(object:{size: number, type: string, name: string}) { + public _createFromObject(object:{size: number, type: string, name: string}):void { // this.lastModifiedDate = copy(object.lastModifiedDate); this.size = object.size; this.type = object.type; diff --git a/components/file-upload/file-select.ts b/components/file-upload/file-select.directive.ts similarity index 61% rename from components/file-upload/file-select.ts rename to components/file-upload/file-select.directive.ts index 0fb75de..250bf2c 100644 --- a/components/file-upload/file-select.ts +++ b/components/file-upload/file-select.directive.ts @@ -1,34 +1,32 @@ -import { Directive, ElementRef } from '@angular/core'; +import { Directive, ElementRef, Input, HostListener } from '@angular/core'; -import {FileUploader} from './file-uploader'; +import {FileUploader} from './file-uploader.class'; // todo: filters -@Directive({ - selector: '[ng2-file-select]', - properties: ['uploader'], - host: { - '(change)': 'onChange()' - } -}) -export class FileSelect { - public uploader:FileUploader; +@Directive({selector: '[ng2FileSelect]'}) +export class FileSelectDirective { + @Input() public uploader:FileUploader; - constructor(private element:ElementRef) { + private element:ElementRef; + public constructor(element:ElementRef) { + this.element = element; } - public getOptions() { + public getOptions():any { return this.uploader.options; } - public getFilters() { + public getFilters():any { + return void 0; } public isEmptyAfterSelection():boolean { return !!this.element.nativeElement.attributes.multiple; } - onChange() { + @HostListener('change') + public onChange():any { // let files = this.uploader.isHTML5 ? this.element.nativeElement[0].files : this.element.nativeElement[0]; let files = this.element.nativeElement.files; let options = this.getOptions(); @@ -45,5 +43,3 @@ export class FileSelect { } } } - -export const fileUpload:Array = [FileSelect]; diff --git a/components/file-upload/file-uploader.ts b/components/file-upload/file-uploader.class.ts similarity index 71% rename from components/file-upload/file-uploader.ts rename to components/file-upload/file-uploader.class.ts index e0ce563..45cf2cd 100644 --- a/components/file-upload/file-uploader.ts +++ b/components/file-upload/file-uploader.class.ts @@ -1,14 +1,11 @@ -import {FileLikeObject} from './file-like-object'; -import {FileItem} from './file-item'; - -function isFile(value:any) { +import {FileLikeObject} from './file-like-object.class'; +import {FileItem} from './file-item.class'; +function isFile(value:any):boolean { return (File && value instanceof File); } - -function isFileLikeObject(value:any) { - return value instanceof FileLikeObject; -} - +// function isFileLikeObject(value:any) { +// return value instanceof FileLikeObject; +// } export class FileUploader { public url:string; public authToken:string; @@ -19,11 +16,12 @@ export class FileUploader { public isHTML5:boolean = true; public removeAfterUpload:boolean = false; public queueLimit:number; - public _nextIndex = 0; + public _nextIndex:number = 0; public filters:Array = []; + public options:any; private _failFilterIndex:number; - constructor(public options:any) { + public constructor(options:any) { // Object.assign(this, options); this.url = options.url; this.authToken = options.authToken; @@ -31,19 +29,16 @@ export class FileUploader { this.filters.unshift({name: 'folder', fn: this._folderFilter}); } - public addToQueue(files:any[], options:any, filters:any) { + public addToQueue(files:any[], options:any, filters:any):void { let list:any[] = []; for (let file of files) { list.push(file); } - let arrayOfFilters = this._getFilters(filters); let count = this.queue.length; let addedFileItems:any[] = []; - - list.map(some => { + list.map((some:any) => { let temp = new FileLikeObject(some); - if (this._isValidFile(temp, arrayOfFilters, options)) { let fileItem = new FileItem(this, some, options); addedFileItems.push(fileItem); @@ -54,101 +49,92 @@ export class FileUploader { this._onWhenAddingFileFailed(temp, filter, options); } }); - if (this.queue.length !== count) { this._onAfterAddingAll(addedFileItems); this.progress = this._getTotalProgress(); } - this._render(); - if (this.autoUpload) { this.uploadAll(); } } - public removeFromQueue(value:any) { + public removeFromQueue(value:any):void { let index = this.getIndexOfItem(value); let item = this.queue[index]; if (item.isUploading) { item.cancel(); } - this.queue.splice(index, 1); this.progress = this._getTotalProgress(); } - public clearQueue() { + public clearQueue():void { while (this.queue.length) { this.queue[0].remove(); } - this.progress = 0; } - public uploadItem(value:FileItem) { + public uploadItem(value:FileItem):void { let index = this.getIndexOfItem(value); let item = this.queue[index]; let transport = this.isHTML5 ? '_xhrTransport' : '_iframeTransport'; - item._prepareToUploading(); if (this.isUploading) { return; } - this.isUploading = true; - (this)[transport](item); + (this as any)[transport](item); } - public cancelItem(value:any) { + public cancelItem(value:any):void { let index = this.getIndexOfItem(value); let item = this.queue[index]; let prop = this.isHTML5 ? '_xhr' : '_form'; - if (item && item.isUploading) { item[prop].abort(); } } - public uploadAll() { - let items = this.getNotUploadedItems().filter(item => !item.isUploading); + public uploadAll():void { + let items = this.getNotUploadedItems().filter((item:any) => !item.isUploading); if (!items.length) { return; } - - items.map(item => item._prepareToUploading()); + items.map((item:any) => item._prepareToUploading()); items[0].upload(); } - public cancelAll() { + public cancelAll():void { let items = this.getNotUploadedItems(); - items.map(item => item.cancel()); + items.map((item:any) => item.cancel()); } - - public isFile(value:any) { + public isFile(value:any):boolean { return isFile(value); } - public isFileLikeObject(value:any) { + public isFileLikeObject(value:any):boolean { return value instanceof FileLikeObject; } - public getIndexOfItem(value:any) { + public getIndexOfItem(value:any):number { return typeof value === 'number' ? value : this.queue.indexOf(value); } - public getNotUploadedItems() { - return this.queue.filter(item => !item.isUploaded); + public getNotUploadedItems():Array { + return this.queue.filter((item:any) => !item.isUploaded); } - public getReadyItems() { + public getReadyItems():Array { return this.queue - .filter(item => (item.isReady && !item.isUploading)) - .sort((item1, item2) => item1.index - item2.index); + .filter((item:any) => (item.isReady && !item.isUploading)) + .sort((item1:any, item2:any) => item1.index - item2.index); } - public destroy() { + public destroy():void { + return void 0; /*forEach(this._directives, (key) => { forEach(this._directives[key], (object) => { object.destroy(); @@ -156,79 +142,166 @@ export class FileUploader { });*/ } - public onAfterAddingAll(fileItems:any) { + public onAfterAddingAll(fileItems:any):any { + return {fileItems}; } - public onAfterAddingFile(fileItem:any) { + public onAfterAddingFile(fileItem:any):any { + return {fileItem}; } - public onWhenAddingFileFailed(item:any, filter:any, options:any) { + public onWhenAddingFileFailed(item:any, filter:any, options:any):any { + return {item, filter, options}; } - public onBeforeUploadItem(fileItem:any) { + public onBeforeUploadItem(fileItem:any):any { + return {fileItem}; } - public onProgressItem(fileItem:any, progress:any) { + public onProgressItem(fileItem:any, progress:any):any { + return {fileItem, progress}; } - public onProgressAll(progress:any) { + public onProgressAll(progress:any):any { + return {progress}; } - public onSuccessItem(item:any, response:any, status:any, headers:any) { + public onSuccessItem(item:any, response:any, status:any, headers:any):any { + return {item, response, status, headers}; } - public onErrorItem(item:any, response:any, status:any, headers:any) { + public onErrorItem(item:any, response:any, status:any, headers:any):any { + return {item, response, status, headers}; } - public onCancelItem(item:any, response:any, status:any, headers:any) { + public onCancelItem(item:any, response:any, status:any, headers:any):any { + return {item, response, status, headers}; } - public onCompleteItem(item:any, response:any, status:any, headers:any) { + public onCompleteItem(item:any, response:any, status:any, headers:any):any { + return {item, response, status, headers}; } - public onCompleteAll() { + public onCompleteAll():any { + return void 0; } - private _getTotalProgress(value = 0) { + public _onErrorItem(item:any, response:any, status:any, headers:any):void { + item._onError(response, status, headers); + this.onErrorItem(item, response, status, headers); + } + + public _onCompleteItem(item:any, response:any, status:any, headers:any):void { + item._onComplete(response, status, headers); + this.onCompleteItem(item, response, status, headers); + let nextItem = this.getReadyItems()[0]; + this.isUploading = false; + if (nextItem) { + nextItem.upload(); + return; + } + this.onCompleteAll(); + this.progress = this._getTotalProgress(); + this._render(); + } + + protected _headersGetter(parsedHeaders:any):any { + return (name:any) => { + if (name) { + return parsedHeaders[name.toLowerCase()] || void 0; + } + return parsedHeaders; + }; + } + + protected _xhrTransport(item:any):any { + let xhr = item._xhr = new XMLHttpRequest(); + let form = new FormData(); + this._onBeforeUploadItem(item); + // todo + /*item.formData.map(obj => { + obj.map((value, key) => { + form.append(key, value); + }); + });*/ + if (typeof item._file.size !== 'number') { + throw new TypeError('The file specified is no longer valid'); + } + form.append(item.alias, item._file, item.file.name); + xhr.upload.onprogress = (event:any) => { + let progress = Math.round(event.lengthComputable ? event.loaded * 100 / event.total : 0); + this._onProgressItem(item, progress); + }; + xhr.onload = () => { + let headers = this._parseHeaders(xhr.getAllResponseHeaders()); + let response = this._transformResponse(xhr.response, headers); + let gist = this._isSuccessCode(xhr.status) ? 'Success' : 'Error'; + let method = '_on' + gist + 'Item'; + (this as any)[method](item, response, xhr.status, headers); + this._onCompleteItem(item, response, xhr.status, headers); + }; + xhr.onerror = () => { + let headers = this._parseHeaders(xhr.getAllResponseHeaders()); + let response = this._transformResponse(xhr.response, headers); + this._onErrorItem(item, response, xhr.status, headers); + this._onCompleteItem(item, response, xhr.status, headers); + }; + xhr.onabort = () => { + let headers = this._parseHeaders(xhr.getAllResponseHeaders()); + let response = this._transformResponse(xhr.response, headers); + this._onCancelItem(item, response, xhr.status, headers); + this._onCompleteItem(item, response, xhr.status, headers); + }; + xhr.open(item.method, item.url, true); + xhr.withCredentials = item.withCredentials; + // todo + /*item.headers.map((value, name) => { + xhr.setRequestHeader(name, value); + });*/ + if (this.authToken) { + xhr.setRequestHeader('Authorization', this.authToken); + } + xhr.send(form); + this._render(); + } + + private _getTotalProgress(value:number = 0):number { if (this.removeAfterUpload) { return value; } - let notUploaded = this.getNotUploadedItems().length; let uploaded = notUploaded ? this.queue.length - notUploaded : this.queue.length; let ratio = 100 / this.queue.length; let current = value * ratio / 100; - return Math.round(uploaded * ratio + current); } - private _getFilters(filters:any) { + private _getFilters(filters:any):any { if (!filters) { return this.filters; } - if (Array.isArray(filters)) { return filters; } - let names = filters.match(/[^\s,]+/g); return this.filters - .filter(filter => names.indexOf(filter.name) !== -1); + .filter((filter:any) => names.indexOf(filter.name) !== -1); } - private _render() { + private _render():any { + return void 0; // todo: ? } - private _folderFilter(item:any) { + private _folderFilter(item:any):boolean { return !!(item.size || item.type); } - private _queueLimitFilter() { + private _queueLimitFilter():boolean { return this.queue.length < this.queueLimit; } - private _isValidFile(file:any, filters:any, options:any) { + private _isValidFile(file:any, filters:any, options:any):boolean { this._failFilterIndex = -1; return !filters.length ? true : filters.every((filter:any) => { this._failFilterIndex++; @@ -236,10 +309,11 @@ export class FileUploader { }); } - private _isSuccessCode(status:any) { + private _isSuccessCode(status:any):boolean { return (status >= 200 && status < 300) || status === 304; } + /* tslint:disable */ private _transformResponse(response:any, headers:any):any { // todo: ? /*var headersGetter = this._headersGetter(headers); @@ -248,121 +322,48 @@ export class FileUploader { });*/ return response; } - - private _parseHeaders(headers:any) { - let parsed:any = {}, key:any, val:any, i:any; - + /* tslint:enable */ + private _parseHeaders(headers:any):any { + let parsed:any = {}; + let key:any; + let val:any; + let i:any; if (!headers) { return parsed; } - headers.split('\n').map((line:any) => { i = line.indexOf(':'); key = line.slice(0, i).trim().toLowerCase(); val = line.slice(i + 1).trim(); - if (key) { parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val; } }); - return parsed; } - private _headersGetter(parsedHeaders:any) { - return (name:any) => { - if (name) { - return parsedHeaders[name.toLowerCase()] || null; - } - return parsedHeaders; - }; - } - - _xhrTransport(item:any) { - let xhr = item._xhr = new XMLHttpRequest(); - let form = new FormData(); - - this._onBeforeUploadItem(item); - - // todo - /*item.formData.map(obj => { - obj.map((value, key) => { - form.append(key, value); - }); - });*/ - - if (typeof item._file.size !== 'number') { - throw new TypeError('The file specified is no longer valid'); - } - - form.append(item.alias, item._file, item.file.name); - - xhr.upload.onprogress = (event) => { - let progress = Math.round(event.lengthComputable ? event.loaded * 100 / event.total : 0); - this._onProgressItem(item, progress); - }; - - xhr.onload = () => { - let headers = this._parseHeaders(xhr.getAllResponseHeaders()); - let response = this._transformResponse(xhr.response, headers); - let gist = this._isSuccessCode(xhr.status) ? 'Success' : 'Error'; - let method = '_on' + gist + 'Item'; - (this)[method](item, response, xhr.status, headers); - this._onCompleteItem(item, response, xhr.status, headers); - }; - - xhr.onerror = () => { - let headers = this._parseHeaders(xhr.getAllResponseHeaders()); - let response = this._transformResponse(xhr.response, headers); - this._onErrorItem(item, response, xhr.status, headers); - this._onCompleteItem(item, response, xhr.status, headers); - }; - - xhr.onabort = () => { - let headers = this._parseHeaders(xhr.getAllResponseHeaders()); - let response = this._transformResponse(xhr.response, headers); - this._onCancelItem(item, response, xhr.status, headers); - this._onCompleteItem(item, response, xhr.status, headers); - }; - - xhr.open(item.method, item.url, true); - xhr.withCredentials = item.withCredentials; - - // todo - /*item.headers.map((value, name) => { - xhr.setRequestHeader(name, value); - });*/ - - if (this.authToken) { - xhr.setRequestHeader('Authorization', this.authToken); - } - - xhr.send(form); - this._render(); - } - - private _iframeTransport(item:any) { + /*private _iframeTransport(item:any) { // todo: implement it later - } + }*/ - private _onWhenAddingFileFailed(item:any, filter:any, options:any) { + private _onWhenAddingFileFailed(item:any, filter:any, options:any):void { this.onWhenAddingFileFailed(item, filter, options); } - private _onAfterAddingFile(item:any) { + private _onAfterAddingFile(item:any):void { this.onAfterAddingFile(item); } - private _onAfterAddingAll(items:any) { + private _onAfterAddingAll(items:any):void { this.onAfterAddingAll(items); } - private _onBeforeUploadItem(item:any) { + private _onBeforeUploadItem(item:any):void { item._onBeforeUpload(); this.onBeforeUploadItem(item); } - private _onProgressItem(item:any, progress:any) { + private _onProgressItem(item:any, progress:any):void { let total = this._getTotalProgress(progress); this.progress = total; item._onProgress(progress); @@ -370,36 +371,14 @@ export class FileUploader { this.onProgressAll(total); this._render(); } - - private _onSuccessItem(item:any, response:any, status:any, headers:any) { + /* tslint:disable */ + private _onSuccessItem(item:any, response:any, status:any, headers:any):void { item._onSuccess(response, status, headers); this.onSuccessItem(item, response, status, headers); } - - public _onErrorItem(item:any, response:any, status:any, headers:any) { - item._onError(response, status, headers); - this.onErrorItem(item, response, status, headers); - } - - private _onCancelItem(item:any, response:any, status:any, headers:any) { + /* tslint:enable */ + private _onCancelItem(item:any, response:any, status:any, headers:any):void { item._onCancel(response, status, headers); this.onCancelItem(item, response, status, headers); } - - public _onCompleteItem(item:any, response:any, status:any, headers:any) { - item._onComplete(response, status, headers); - this.onCompleteItem(item, response, status, headers); - - let nextItem = this.getReadyItems()[0]; - this.isUploading = false; - - if (nextItem) { - nextItem.upload(); - return; - } - - this.onCompleteAll(); - this.progress = this._getTotalProgress(); - this._render(); - } } diff --git a/components/file-upload/readme.md b/components/file-upload/readme.md index 37f84be..62b9b18 100644 --- a/components/file-upload/readme.md +++ b/components/file-upload/readme.md @@ -1,32 +1,17 @@ ### Usage ```typescript -import {FileSelect, FileDrop, FileUploader} from 'ng2-file-upload'; +import {FileSelectDirective, FileDropDirective, FileUploader} from 'ng2-file-upload/ng2-file-upload'; ``` ### Annotations ```typescript -// class FileSelect -@Directive({ - selector: '[ng2-file-select]', - properties: ['uploader'], - host: { - '(change)': 'onChange()' - } -}) +// class FileSelectDirective +@Directive({ selector: '[ng2FileSelect]' }) ``` ```typescript -// class FileDrop -@Directive({ - selector: '[ng2-file-drop]', - properties: ['uploader'], - events: ['fileOver'], - host: { - '(drop)': 'onDrop($event)', - '(dragover)': 'onDragOver($event)', - '(dragleave)': 'onDragLeave($event)' - } -}) +// class FileDropDirective +@Directive({ selector: '[ng2FileDrop]' }) ``` ## FileSelect API @@ -48,6 +33,6 @@ import {FileSelect, FileDrop, FileUploader} from 'ng2-file-upload'; ### Events - - `file-over` - it fires during 'over' and 'out' events for Drop Area; returns `boolean`: `true` if file is over Drop Area, `false` in case of out. + - `fileOver` - it fires during 'over' and 'out' events for Drop Area; returns `boolean`: `true` if file is over Drop Area, `false` in case of out. See using in [ts demo](https://github.com/valor-software/ng2-file-upload/blob/master/demo/components/file-upload/simple-demo.ts) and [html demo](https://github.com/valor-software/ng2-file-upload/blob/master/demo/components/file-upload/simple-demo.html) diff --git a/demo/components/file-upload-section.ts b/demo/components/file-upload-section.ts index 5c3fe76..eb4d586 100644 --- a/demo/components/file-upload-section.ts +++ b/demo/components/file-upload-section.ts @@ -1,10 +1,8 @@ -/// - import {Component} from '@angular/core'; import {CORE_DIRECTIVES} from '@angular/common'; import {TAB_DIRECTIVES} from 'ng2-bootstrap/ng2-bootstrap'; -import {SimpleDemo} from './file-upload/simple-demo'; +import {SimpleDemoComponent} from './file-upload/simple-demo'; let name = 'File Upload'; let doc = require('../../components/file-upload/readme.md'); @@ -19,7 +17,7 @@ let tabDesc:Array = [ ]; let tabsContent:string = ``; -tabDesc.forEach(desc => { +tabDesc.forEach((desc:any) => { tabsContent += `
@@ -70,12 +68,12 @@ tabDesc.forEach(desc => {
`, - directives: [SimpleDemo, TAB_DIRECTIVES, CORE_DIRECTIVES] + directives: [SimpleDemoComponent, TAB_DIRECTIVES, CORE_DIRECTIVES] }) -export class FileUploadSection { - private currentHeading:string = 'Simple'; +export class FileUploadSectionComponent { + public currentHeading:string = 'Simple'; - private select(e:any) { + public select(e:any):void { if (e.heading) { this.currentHeading = e.heading; } diff --git a/demo/components/file-upload/file-catcher.js b/demo/components/file-upload/file-catcher.js index ff858e8..960ce2d 100644 --- a/demo/components/file-upload/file-catcher.js +++ b/demo/components/file-upload/file-catcher.js @@ -1,3 +1,4 @@ +/*eslint-disable*/ var express = require('express'); var multer = require('multer'); var fs = require('fs'); diff --git a/demo/components/file-upload/simple-demo.html b/demo/components/file-upload/simple-demo.html index f59cb7a..d0e4c81 100644 --- a/demo/components/file-upload/simple-demo.html +++ b/demo/components/file-upload/simple-demo.html @@ -20,7 +20,7 @@

Select files

-
-
Multiple -
+
Single - +
diff --git a/demo/components/file-upload/simple-demo.ts b/demo/components/file-upload/simple-demo.ts index 3d031c5..cd0bf52 100644 --- a/demo/components/file-upload/simple-demo.ts +++ b/demo/components/file-upload/simple-demo.ts @@ -1,5 +1,3 @@ -/// - import {Component} from '@angular/core'; import {CORE_DIRECTIVES, FORM_DIRECTIVES, NgClass, NgStyle} from '@angular/common'; import {FILE_UPLOAD_DIRECTIVES, FileUploader} from '../../../ng2-file-upload'; @@ -15,16 +13,16 @@ const URL = 'https://evening-anchorage-3159.herokuapp.com/api/'; template: template, directives: [FILE_UPLOAD_DIRECTIVES, NgClass, NgStyle, CORE_DIRECTIVES, FORM_DIRECTIVES] }) -export class SimpleDemo { - private uploader:FileUploader = new FileUploader({url: URL}); - private hasBaseDropZoneOver:boolean = false; - private hasAnotherDropZoneOver:boolean = false; +export class SimpleDemoComponent { + public uploader:FileUploader = new FileUploader({url: URL}); + public hasBaseDropZoneOver:boolean = false; + public hasAnotherDropZoneOver:boolean = false; - private fileOverBase(e:any) { + public fileOverBase(e:any):void { this.hasBaseDropZoneOver = e; } - private fileOverAnother(e:any) { + public fileOverAnother(e:any):void { this.hasAnotherDropZoneOver = e; } } diff --git a/demo/index.html b/demo/index.html index beae0ac..e110fd9 100644 --- a/demo/index.html +++ b/demo/index.html @@ -34,11 +34,5 @@ Loading... - - - - - - diff --git a/demo/index.ts b/demo/index.ts index 6de7dee..2ee024c 100644 --- a/demo/index.ts +++ b/demo/index.ts @@ -1,9 +1,8 @@ -/// import {bootstrap} from '@angular/platform-browser-dynamic'; import {Component} from '@angular/core'; import {NgClass} from '@angular/common'; -import {FileUploadSection} from './components/file-upload-section'; +import {FileUploadSectionComponent} from './components/file-upload-section'; let gettingStarted = require('./getting-started.md'); @@ -36,10 +35,10 @@ let gettingStarted = require('./getting-started.md'); `, directives: [ NgClass, - FileUploadSection + FileUploadSectionComponent ] }) -export class Demo { +export class DemoComponent { } -bootstrap(Demo); +bootstrap(DemoComponent); diff --git a/es6-object.d.ts b/es6-object.d.ts deleted file mode 100644 index bede479..0000000 --- a/es6-object.d.ts +++ /dev/null @@ -1,26 +0,0 @@ -interface ObjectConstructor { - /** - * Copy the values of all of the enumerable own properties from one or more source objects to a - * target object. Returns the target object. - * @param target The target object to copy to. - * @param sources One or more source objects to copy properties from. - */ - assign(target: any, ...sources: any[]): any; - - /** - * Returns true if the values are the same value, false otherwise. - * @param value1 The first value. - * @param value2 The second value. - */ - is(value1: any, value2: any): boolean; - - /** - * Sets the prototype of a specified object o to object proto or null. Returns the object o. - * @param o The object to change its prototype. - * @param proto The value of the new prototype or null. - * @remarks Requires `__proto__` support. - */ - setPrototypeOf(o: any, proto: any): any; -} - -declare function require(path:string): any; diff --git a/gulp-tasks/lint.js b/gulp-tasks/lint.js index 1371ed5..de91156 100644 --- a/gulp-tasks/lint.js +++ b/gulp-tasks/lint.js @@ -1,23 +1,18 @@ -var gulp = require('gulp'); -var esLint = require('gulp-eslint'); -var tslint = require('gulp-tslint'); +'use strict'; -var paths = gulp.paths; +const gulp = require('gulp'); +const tslint = require('gulp-tslint'); +const paths = gulp.paths; -gulp.task('eslint', function() { - return gulp.src(paths.jssrc) - .pipe(esLint({useEslintrc: true})) - .pipe(esLint.format()) - .pipe(esLint.failOnError()); -}); +gulp.task('tslint', () => +gulp + .src(paths.tssrc) + .pipe(tslint()) + .pipe(tslint.report('prose', { + emitError: true, + summarizeFailureOutput: true, + reportLimit: 50 + })) +); -gulp.task('tslint', function() { - return gulp.src(paths.tssrc) - .pipe(tslint()) - .pipe(tslint.report('verbose', { - emitError: true, - reportLimit: 0 - })); -}); - -gulp.task('lint', ['tslint', 'eslint']); +gulp.task('lint', ['tslint']); diff --git a/gulpfile.js b/gulpfile.js index 2eb78a8..a902fca 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,29 +1,18 @@ -var gulp = require('gulp'); +'use strict'; + +const gulp = require('gulp'); gulp.paths = { tssrc: [ '**/*.ts', + '!**/*.d.ts', '!node_modules/**/*', - '!dist/**/*', - '!typings/**/*', - '!**/*.{ts,coffee}.js'], - jssrc: [ - '*.js', - 'gulp-tasks/*.js', - '!ng2-file-upload.js', - '!angular2-file-upload.js', - '!node_modules', - '!**/*.{ts,coffee}.js'] + '!bundles/**/*', + '!typings/**/*'] }; require('require-dir')('./gulp-tasks'); -var clean = require('gulp-clean'); -gulp.task('clean', function () { - return gulp.src('dist', {read: false}) - .pipe(clean()); -}); - -gulp.task('default', function () { +gulp.task('default', () => { gulp.start('lint'); }); diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 0000000..31fec66 --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,101 @@ +'use strict'; + +const path = require('path'); +const cwd = process.cwd(); + +module.exports = config => { + config.set({ + // base path that will be used to resolve all patterns (eg. files, exclude) + basePath: '', + + // frameworks to use + // available frameworks: https://npmjs.org/browse/keyword/karma-adapter + frameworks: ['jasmine'], + + // list of files / patterns to load in the browser + files: [ + {pattern: 'test.bundle.js', watched: false} + ], + + // list of files to exclude + exclude: [], + + // preprocess matching files before serving them to the browser + // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor + preprocessors: { + 'test.bundle.js': ['coverage', 'webpack', 'sourcemap'] + }, + + webpack: { + resolve: { + root: [path.resolve(cwd)], + modulesDirectories: ['node_modules', 'demo', 'components', 'test', '.'], + extensions: ['', '.ts', '.js', '.css'] + }, + module: { + loaders: [ + {test: /\.ts$/, loader: 'ts-loader', exclude: [/node_modules/]} + ], + postLoaders: [ + // instrument only testing sources with Istanbul + { + test: /\.(js|ts)$/, + include: root('components'), + loader: 'istanbul-instrumenter-loader', + exclude: [ + /\.e2e\.ts$/, + /node_modules/ + ] + } + ] + }, + stats: { + colors: true, + reasons: true + }, + watch: true, + debug: true + }, + + coverageReporter: { + dir: 'coverage/', + reporters: [ + {type: 'text'}, + {type: 'json'}, + {type: 'html'} + ] + }, + webpackServer: {noInfo: true}, + + // test results reporter to use + // possible values: 'dots', 'progress' + // available reporters: https://npmjs.org/browse/keyword/karma-reporter + reporters: ['spec', 'coverage'], + + // web server port + port: 9876, + + // enable / disable colors in the output (reporters and logs) + colors: true, + + // level of logging + // possible values: config.LOG_DISABLE || config.LOG_ERROR || + // config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG + logLevel: config.LOG_INFO, + + // enable / disable watching file and executing tests whenever any file changes + autoWatch: false, + + // start these browsers + // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher + browsers: ['PhantomJS'], + + // Continuous Integration mode + // if true, Karma captures browsers, runs the tests and exits + singleRun: true + }); +}; + +function root(partialPath) { + return path.join(__dirname, partialPath); +} diff --git a/ng2-file-upload.ts b/ng2-file-upload.ts index 74d20a4..353f03c 100644 --- a/ng2-file-upload.ts +++ b/ng2-file-upload.ts @@ -1,8 +1,14 @@ -export * from './components/file-upload/file-select'; -export * from './components/file-upload/file-drop'; -export * from './components/file-upload/file-uploader'; +export * from './components/file-upload/file-select.directive'; +export * from './components/file-upload/file-drop.directive'; +export * from './components/file-upload/file-uploader.class'; -import {FileSelect} from './components/file-upload/file-select'; -import {FileDrop} from './components/file-upload/file-drop'; +import {FileSelectDirective} from './components/file-upload/file-select.directive'; +import {FileDropDirective} from './components/file-upload/file-drop.directive'; -export const FILE_UPLOAD_DIRECTIVES:[any] = [FileSelect, FileDrop]; +export const FILE_UPLOAD_DIRECTIVES:[any] = [FileSelectDirective, FileDropDirective]; + +export default { + directives: [ + FILE_UPLOAD_DIRECTIVES + ] +}; diff --git a/package.json b/package.json index 5fcfa7a..1510712 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,32 @@ { "name": "ng2-file-upload", - "version": "1.0.0-beta.1", + "version": "1.0.1", "description": "angular2 file upload directives", "scripts": { - "deploy": "NODE_ENV=production webpack -p --progress --color --optimize-minimize --optimize-dedupe --optimize-occurence-order", - "prepublish": "gulp clean && ./node_modules/.bin/typings install && tsc", - "server": "webpack-dev-server --hot --inline --colors --display-error-details --display-cached", - "start": "npm run server", - "test": "gulp lint" + "flow.install:typings": "./node_modules/.bin/typings install", + "flow.compile": "npm run flow.install:typings && npm run flow.compile:common && npm run flow.compile:system ", + "flow.compile:common": "./node_modules/.bin/tsc", + "flow.compile:system": "./.config/bundle-system.js", + "flow.copy:src": "./node_modules/.bin/cpy ng2-file-upload.ts \"components/*.ts\" ts --parents", + "flow.clean": "./node_modules/.bin/del bundles coverage demo-build typings \"components/**/*.+(js|d.ts|js.map)\" dist \"ng2-file-upload.+(js|d.ts|js.map)\"", + "flow.deploy:gh-pages": "npm run flow.build:prod && ./node_modules/.bin/gh-pages -d demo-build", + "flow.eslint": "./node_modules/.bin/eslint --ignore-path .gitignore --ext js --fix . .config", + "flow.tslint": "./node_modules/.bin/gulp lint", + "flow.lint": "npm run flow.eslint && npm run flow.tslint", + "flow.changelog": "./node_modules/.bin/conventional-changelog -i CHANGELOG.md -s -p angular -v", + "flow.github-release": "conventional-github-releaser -p angular", + "flow.build:prod": "NODE_ENV=production ./node_modules/.bin/webpack --progress --color", + "flow.build:dev": "./node_modules/.bin/webpack --progress --color", + "flow.serve:dev": "./node_modules/.bin/webpack-dev-server --hot --inline --colors --display-error-details --display-cached", + "flow.serve:prod": "NODE_ENV=production ./node_modules/.bin/webpack-dev-server --hot --inline --colors --display-error-details --display-cached", + "prepublish": "npm run flow.clean && npm run flow.compile", + "postpublish": "npm run flow.deploy:gh-pages", + "start": "npm run flow.serve:dev", + "pretest": "npm run flow.lint", + "test": "NODE_ENV=test ./node_modules/.bin/karma start", + "preversion": "npm test", + "version": "npm run flow.changelog && git add -A", + "postversion": "git push origin development && git push --tags" }, "main": "ng2-file-upload.js", "typings": "ng2-file-upload.d.ts", @@ -27,8 +46,7 @@ "url": "https://github.com/valor-software/ng2-file-upload/issues" }, "homepage": "https://github.com/valor-software/ng2-file-upload#readme", - "dependencies": { - }, + "dependencies": {}, "peerDependencies": { "@angular/common": "^2.0.0-rc.1", "@angular/core": "^2.0.0-rc.1" @@ -39,39 +57,59 @@ "@angular/core": "^2.0.0-rc.1", "@angular/platform-browser": "^2.0.0-rc.1", "@angular/platform-browser-dynamic": "^2.0.0-rc.1", + "async": "1.5.2", "bootstrap": "3.3.6", - "clean-webpack-plugin": "0.1.9", + "codecov": "1.0.1", "compression-webpack-plugin": "0.3.1", - "es6-promise": "^3.1.2", - "es6-shim": "^0.35.0", - "eslint": "1.10.3", + "conventional-changelog-cli": "1.2.0", + "conventional-github-releaser": "1.1.2", + "copy-webpack-plugin": "2.1.3", + "cpy-cli": "1.0.0", + "del-cli": "0.2.0", + "es6-promise": "3.1.2", + "es6-shim": "0.35.0", + "es7-reflect-metadata": "1.6.0", + "eslint-config-valorsoft": "0.0.10", "exports-loader": "0.6.3", "file-loader": "0.8.5", + "gh-pages": "0.11.0", "gulp": "3.9.1", - "gulp-clean": "0.3.2", - "gulp-eslint": "1.1.1", "gulp-size": "2.1.0", - "gulp-tsc": "1.1.5", "gulp-tslint": "5.0.0", "html-loader": "0.4.3", + "html-webpack-plugin": "2.16.1", + "istanbul-instrumenter-loader": "0.2.0", + "jasmine": "2.4.1", + "karma": "0.13.22", + "karma-chrome-launcher": "1.0.1", + "karma-coverage": "1.0.0", + "karma-jasmine": "1.0.2", + "karma-phantomjs-launcher": "1.0.0", + "karma-sourcemap-loader": "0.3.7", + "karma-spec-reporter": "0.0.26", + "karma-webpack": "1.7.0", + "lite-server": "2.2.0", "markdown-loader": "0.1.7", "marked": "0.3.5", - "moment": "2.13.0", "ng2-bootstrap": "1.0.16", - "pre-commit": "1.1.2", - "prismjs": "valorkin/prism", + "phantomjs-polyfill": "0.0.2", + "phantomjs-prebuilt": "2.1.7", + "pre-commit": "1.1.3", + "prismjs": "1.4.1", "prismjs-loader": "0.0.2", "raw-loader": "0.5.1", "reflect-metadata": "0.1.2", "require-dir": "0.3.0", "rxjs": "5.0.0-beta.6", + "source-map-loader": "0.1.5", + "systemjs-builder": "0.15.16", "ts-loader": "0.8.2", - "tslint": "3.9.0", + "tslint-config-valorsoft": "1.0.3", "typescript": "1.8.10", - "typings": "^0.8.1", + "typings": "0.8.1", "webpack": "1.13.0", "webpack-dev-server": "1.14.1", - "zone.js": "^0.6.12" + "zone.js": "0.6.12" }, "contributors": [ { diff --git a/test.bundle.js b/test.bundle.js new file mode 100644 index 0000000..9ade857 --- /dev/null +++ b/test.bundle.js @@ -0,0 +1,47 @@ +'use strict'; + +/* eslint vars-on-top:0 no-var:0 */ +// @AngularClass +/* + * When testing with webpack and ES6, we have to do some extra + * things get testing to work right. Because we are gonna write test + * in ES6 to, we have to compile those as well. That's handled in + * karma.conf.js with the karma-webpack plugin. This is the entry + * file for webpack test. Just like webpack will create a bundle.js + * file for our client, when we run test, it well compile and bundle them + * all here! Crazy huh. So we need to do some setup + */ +Error.stackTraceLimit = Infinity; +require('phantomjs-polyfill'); +require('es6-promise'); +require('es6-shim'); +require('es7-reflect-metadata/dist/browser'); + +// require('zone.js'); +require('zone.js/dist/zone.js'); +require('zone.js/dist/long-stack-trace-zone.js'); +require('zone.js/dist/jasmine-patch.js'); +require('zone.js/dist/async-test.js'); + +var testing = require('@angular/core/testing'); +var browser = require('@angular/platform-browser-dynamic/testing'); + +testing.setBaseTestProviders( + browser.TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS, + browser.TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS); + +/* + Ok, this is kinda crazy. We can use the the context method on + require that webpack created in order to tell webpack + what files we actually want to require or import. + Below, context will be an function/object with file names as keys. + using that regex we are saying look in ./src/app and ./test then find + any file that ends with spec.js and get its path. By passing in true + we say do this recursively + */ +var testContext = require.context('./components', true, /\.spec\.ts/); + +// get all the files, for each file, call the context function +// that will require the file and load it up here. Context will +// loop and require those spec files here +testContext.keys().forEach(testContext); diff --git a/tsd.d.ts b/tsd.d.ts deleted file mode 100644 index 8c3121c..0000000 --- a/tsd.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/tslint.json b/tslint.json index 262192e..ea3f776 100644 --- a/tslint.json +++ b/tslint.json @@ -1,56 +1,4 @@ { - "rules": { - "class-name": true, - "comment-format": [true, "check-space"], - "curly": true, - "eofline": true, - "forin": true, - "indent": [true, "spaces"], - "label-position": true, - "label-undefined": true, - "max-line-length": [false, 140], - "no-arg": true, - "no-bitwise": true, - "no-console": [true, - "debug", - "info", - "time", - "timeEnd", - "trace" - ], - "no-construct": true, - "no-debugger": true, - "no-duplicate-key": true, - "no-duplicate-variable": true, - "no-empty": false, - "no-eval": true, - "no-shadowed-variable": true, - "no-string-literal": true, - "no-switch-case-fall-through": true, - "trailing-comma": false, - "no-trailing-whitespace": true, - "no-unused-expression": true, - "no-unused-variable": false, - "no-unreachable": true, - "no-use-before-declare": true, - "no-var-keyword": true, - "one-line": [true, - "check-open-brace", - "check-catch", - "check-else", - "check-whitespace" - ], - "quotemark": [true, "single"], - "radix": true, - "semicolon": true, - "object-literal-sort-keys": false, - "triple-equals": [true, "allow-null-check"], - "variable-name": false, - "whitespace": [true, - "check-branch", - "check-decl", - "check-operator", - "check-separator" - ] - } + "extends": "tslint-config-valorsoft", + "rulesDirectory": "./node_modules/codelyzer" } diff --git a/typings.json b/typings.json index 8279f82..592b524 100644 --- a/typings.json +++ b/typings.json @@ -1,9 +1,12 @@ { "dependencies": { + "moment": "registry:npm/moment#2.10.5+20160211003958", "webpack": "registry:npm/webpack#1.12.9+20160219013405" }, "devDependencies": {}, "ambientDependencies": { - "es6-shim": "registry:dt/es6-shim#0.31.2+20160317120654" + "es6-shim": "registry:dt/es6-shim#0.31.2+20160317120654", + "jasmine": "registry:dt/jasmine#2.2.0+20160317120654", + "require": "registry:dt/require#2.1.20+20160316155526" } -} \ No newline at end of file +} diff --git a/webpack.config.js b/webpack.config.js index 8ee6d46..2bb2843 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,35 +1,35 @@ -var path = require('path'); -var marked = require('marked'); -var webpack = require('webpack'); +/* eslint global-require: 0 */ +'use strict'; -var Clean = require('clean-webpack-plugin'); -var CompressionPlugin = require('compression-webpack-plugin'); +const path = require('path'); +const marked = require('marked'); +const webpack = require('webpack'); +const reqPrism = require('prismjs'); +const CompressionPlugin = require('compression-webpack-plugin'); +const CopyWebpackPlugin = require('copy-webpack-plugin'); +const HtmlWebpackPlugin = require('html-webpack-plugin'); // marked renderer hack -marked.Renderer.prototype.code = function (code, lang) { - var out = this.options.highlight(code, lang); +marked.Renderer.prototype.code = function renderCode(code, lang) { + const out = this.options.highlight(code, lang); + const classMap = this.options.langPrefix + lang; if (!lang) { - return '
' + out + '\n
'; + return `
${out}\n
`; } - - var classMap = this.options.langPrefix + lang; - return '
' + out + '\n
\n'; + return `
${out}\n
\n`; }; /*eslint no-process-env:0, camelcase:0*/ -var isProduction = (process.env.NODE_ENV || 'development') === 'production'; +const isProduction = (process.env.NODE_ENV || 'development') === 'production'; +const devtool = process.env.NODE_ENV === 'test' ? 'inline-source-map' : 'source-map'; +const dest = 'demo-build'; +const absDest = root(dest); -var src = 'demo'; -//var absSrc = path.join(__dirname, src); -var dest = '/build'; -var absDest = path.join(__dirname, dest); - -var config = { +const config = { // isProduction ? 'source-map' : 'evale', - devtool: 'source-map', - debug: true, - cache: true, + devtool, + debug: false, verbose: true, displayErrorDetails: true, @@ -40,9 +40,9 @@ var config = { }, resolve: { + cache: false, root: __dirname, - extensions: ['', '.ts', '.js', '.json'], - alias: {} + extensions: ['', '.ts', '.js', '.json'] }, entry: { @@ -55,8 +55,8 @@ var config = { '@angular/common', '@angular/core' ], - 'angular2-file-upload': ['ng2-file-upload'], - 'angular2-file-upload-demo': 'demo' + 'angular2-bootstrap': ['ng2-file-upload'], + 'angular2-bootstrap-demo': 'demo' }, output: { @@ -71,23 +71,20 @@ var config = { inline: true, colors: true, historyApiFallback: true, - proxy: { - '*/api/*': 'http://localhost:3000/' - }, - contentBase: src, - publicPath: dest + contentBase: dest, + //publicPath: dest, + outputPath: dest, + watchOptions: {aggregateTimeout: 300, poll: 1000} }, markdownLoader: { langPrefix: 'language-', - highlight: function (code, lang) { - var language = !lang || lang === 'html' ? 'markup' : lang; - if (!global.Prism) { - global.Prism = require('prismjs'); - } - var Prism = global.Prism; + highlight(code, lang) { + const language = !lang || lang === 'html' ? 'markup' : lang; + const Prism = global.Prism || reqPrism; + if (!Prism.languages[language]) { - require('prismjs/components/prism-' + language + '.js'); + require(`prismjs/components/prism-${language}.js`); } return Prism.highlight(code, Prism.languages[language]); } @@ -96,77 +93,65 @@ var config = { loaders: [ // support markdown {test: /\.md$/, loader: 'html?minimize=false!markdown'}, - // Support for *.json files. {test: /\.json$/, loader: 'json'}, - // Support for CSS as raw text {test: /\.css$/, loader: 'raw'}, - // support for .html as raw text {test: /\.html$/, loader: 'raw'}, - // Support for .ts files. { test: /\.ts$/, loader: 'ts', query: { - ignoreDiagnostics: [ - 6053, - // TS2305 -> Module 'ng' has no exported member - 2305, - // TS2307 -> Cannot find external module - 2307, - // TS2300 -> Duplicate identifier - 2300, - // TS2309 -> An export assignment cannot be used in a module with other exported elements. - 2309 - ] + compilerOptions: { + removeComments: true, + noEmitHelpers: false + } }, - exclude: [ - /\.min\.js$/, - /\.spec\.ts$/, - /\.e2e\.ts$/, - /web_modules/, - /test/ - ] + exclude: [/\.(spec|e2e)\.ts$/] } ], noParse: [ /rtts_assert\/src\/rtts_assert/, - /reflect-metadata/ + /reflect-metadata/, + /zone\.js\/dist\/zone-microtask/ ] }, plugins: [ - new Clean(['build']), + //new Clean([dest]), + new webpack.optimize.DedupePlugin(), + new webpack.optimize.OccurenceOrderPlugin(true), new webpack.optimize.CommonsChunkPlugin({ name: 'angular2', minChunks: Infinity, filename: 'angular2.js' }), - new webpack.optimize.DedupePlugin({ - __isProduction: isProduction - }), - new webpack.optimize.OccurenceOrderPlugin(), - new webpack.optimize.DedupePlugin() + // static assets + new CopyWebpackPlugin([{from: 'demo/favicon.ico', to: 'favicon.ico'}]), + new CopyWebpackPlugin([{from: 'demo/assets', to: 'assets'}]), + // generating html + new HtmlWebpackPlugin({template: 'demo/index.html'}) ], - pushPlugins: function () { + pushPlugins() { if (!isProduction) { return; } - - this.plugins.push.apply(this.plugins, [ + const plugins = [ //production only new webpack.optimize.UglifyJsPlugin({ + beautify: false, + mangle: false, + comments: false, compress: { - warnings: false, - drop_debugger: false - }, - output: { - comments: false - }, - beautify: false + screw_ie8: true + //warnings: false, + //drop_debugger: false + } + //verbose: true, + //beautify: false, + //quote_style: 3 }), new CompressionPlugin({ asset: '{file}.gz', @@ -175,10 +160,19 @@ var config = { threshold: 10240, minRatio: 0.8 }) - ]); + ]; + + this + .plugins + .push + .apply(plugins); } }; config.pushPlugins(); module.exports = config; + +function root(partialPath) { + return path.join(__dirname, partialPath); +} -- 2.43.0 From d2f60894bbfcb8af63505f40ea66a3d4c9ebdc65 Mon Sep 17 00:00:00 2001 From: Dmitriy Shekhovtsov Date: Wed, 11 May 2016 19:11:31 +0300 Subject: [PATCH 11/19] chore(package): prismjs loader updated --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 1510712..04c5625 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "flow.tslint": "./node_modules/.bin/gulp lint", "flow.lint": "npm run flow.eslint && npm run flow.tslint", "flow.changelog": "./node_modules/.bin/conventional-changelog -i CHANGELOG.md -s -p angular -v", - "flow.github-release": "conventional-github-releaser -p angular", + "flow.github-release": "./node_modules/.bin/conventional-github-releaser -p angular", "flow.build:prod": "NODE_ENV=production ./node_modules/.bin/webpack --progress --color", "flow.build:dev": "./node_modules/.bin/webpack --progress --color", "flow.serve:dev": "./node_modules/.bin/webpack-dev-server --hot --inline --colors --display-error-details --display-cached", @@ -26,7 +26,7 @@ "test": "NODE_ENV=test ./node_modules/.bin/karma start", "preversion": "npm test", "version": "npm run flow.changelog && git add -A", - "postversion": "git push origin development && git push --tags" + "postversion": "git push origin master && git push --tags" }, "main": "ng2-file-upload.js", "typings": "ng2-file-upload.d.ts", @@ -69,7 +69,7 @@ "es6-promise": "3.1.2", "es6-shim": "0.35.0", "es7-reflect-metadata": "1.6.0", - "eslint-config-valorsoft": "0.0.10", + "eslint-config-valorsoft": "0.0.11", "exports-loader": "0.6.3", "file-loader": "0.8.5", "gh-pages": "0.11.0", @@ -96,7 +96,7 @@ "phantomjs-prebuilt": "2.1.7", "pre-commit": "1.1.3", "prismjs": "1.4.1", - "prismjs-loader": "0.0.2", + "prismjs-loader": "0.0.3", "raw-loader": "0.5.1", "reflect-metadata": "0.1.2", "require-dir": "0.3.0", -- 2.43.0 From d938aa1c396a5a9145edf6fcdf30931cf4188246 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vojt=C4=9Bch=20Kal=C3=A1b?= Date: Tue, 23 Feb 2016 09:02:45 +0100 Subject: [PATCH 12/19] # This is a combination of 3 commits. # The first commit's message is: feat(uploader): huge uploader update - creted uploader options - added `file type` support - added headers to xhr - rename FileUploaderSettings => FileUploaderOptionsInterface - added public methods set Options - created filter from set options - added demo component # The 2nd commit message will be skipped: # rename FileUploaderSettings => FileUploaderOptionsInterface # The 3rd commit message will be skipped: # added public method setOptions --- components/file-upload/file-item.class.ts | 4 +- components/file-upload/file-type.ts | 158 ++++++++++++++++++ components/file-upload/file-uploader.class.ts | 123 ++++++++++---- .../file-upload/zs-file-demo/demo.html | 3 + .../file-upload/zs-file-demo/demo.ts | 124 ++++++++++++++ 5 files changed, 377 insertions(+), 35 deletions(-) create mode 100644 components/file-upload/file-type.ts create mode 100644 demo/components/file-upload/zs-file-demo/demo.html create mode 100644 demo/components/file-upload/zs-file-demo/demo.ts diff --git a/components/file-upload/file-item.class.ts b/components/file-upload/file-item.class.ts index aa06890..1151510 100644 --- a/components/file-upload/file-item.class.ts +++ b/components/file-upload/file-item.class.ts @@ -32,7 +32,7 @@ export class FileItem { this.options = options; this.file = new FileLikeObject(some); this._file = some; - this.url = uploader.url; + this.url = uploader.options.url; this._zone = new NgZone({ enableLongStackTrace: false }); } @@ -134,7 +134,7 @@ export class FileItem { public _onComplete(response:any, status:any, headers:any):void { this.onComplete(response, status, headers); - if (this.uploader.removeAfterUpload) { + if (this.uploader.options.removeAfterUpload) { this.remove(); } } diff --git a/components/file-upload/file-type.ts b/components/file-upload/file-type.ts new file mode 100644 index 0000000..e256953 --- /dev/null +++ b/components/file-upload/file-type.ts @@ -0,0 +1,158 @@ +export class FileType { + /* MS office */ + static mime_doc = [ + 'application/msword', + 'application/msword', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', + 'application/vnd.ms-word.document.macroEnabled.12', + 'application/vnd.ms-word.template.macroEnabled.12' + ]; + static mime_xsl = [ + 'application/vnd.ms-excel', + 'application/vnd.ms-excel', + 'application/vnd.ms-excel', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', + 'application/vnd.ms-excel.sheet.macroEnabled.12', + 'application/vnd.ms-excel.template.macroEnabled.12', + 'application/vnd.ms-excel.addin.macroEnabled.12', + 'application/vnd.ms-excel.sheet.binary.macroEnabled.12' + ]; + static mime_ppt = [ + 'application/vnd.ms-powerpoint', + 'application/vnd.ms-powerpoint', + 'application/vnd.ms-powerpoint', + 'application/vnd.ms-powerpoint', + 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'application/vnd.openxmlformats-officedocument.presentationml.template', + 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', + 'application/vnd.ms-powerpoint.addin.macroEnabled.12', + 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', + 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', + 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12' + ]; + + /* PSD */ + static mime_psd = [ + 'image/photoshop', + 'image/x-photoshop', + 'image/psd', + 'application/photoshop', + 'application/psd', + 'zz-application/zz-winassoc-psd' + ]; + + /* Compressed files */ + static mime_compress = [ + 'application/x-gtar', + 'application/x-gcompress', + 'application/compress', + 'application/x-tar', + 'application/x-rar-compressed', + 'application/octet-stream' + ]; + + static getMimeClass(file) { + let mimeClass = 'application'; + if (this.mime_psd.indexOf(file.type) !== -1) { + mimeClass = 'image'; + } else if (file.type.match('image.*')) { + mimeClass = 'image'; + } else if (file.type.match('video.*')) { + mimeClass = 'video'; + } else if (file.type.match('audio.*')) { + mimeClass = 'audio'; + } else if (file.type === 'application/pdf') { + mimeClass = 'pdf'; + } else if (this.mime_compress.indexOf(file.type) !== -1) { + mimeClass = 'compress'; + } else if (this.mime_doc.indexOf(file.type) !== -1) { + mimeClass = 'doc'; + } else if (this.mime_xsl.indexOf(file.type) !== -1) { + mimeClass = 'xls'; + } else if (this.mime_ppt.indexOf(file.type) !== -1) { + mimeClass = 'ppt'; + } + if (mimeClass === 'application') { + mimeClass = this.fileTypeDetection(file.name); + } + + + return mimeClass; + } + + + static fileTypeDetection(inputFilename) { + let types = { + 'jpg': 'image', + 'jpeg': 'image', + 'tif': 'image', + 'psd': 'image', + 'bmp': 'image', + 'png': 'image', + 'nef': 'image', + 'tiff': 'image', + 'cr2': 'image', + 'dwg': 'image', + 'cdr': 'image', + 'ai': 'image', + 'indd': 'image', + 'pin': 'image', + 'cdp': 'image', + 'skp': 'image', + 'stp': 'image', + '3dm': 'image', + 'mp3': 'audio', + 'wav': 'audio', + 'wma': 'audio', + 'mod': 'audio', + 'm4a': 'audio', + 'compress': 'compress', + 'rar': 'compress', + '7z': 'compress', + 'lz': 'compress', + 'z01': 'compress', + 'pdf': 'pdf', + 'xls': 'xls', + 'xlsx': 'xls', + 'ods': 'xls', + 'mp4': 'video', + 'avi': 'video', + 'wmv': 'video', + 'mpg': 'video', + 'mts': 'video', + 'flv': 'video', + '3gp': 'video', + 'vob': 'video', + 'm4v': 'video', + 'mpeg': 'video', + 'm2ts': 'video', + 'mov': 'video', + 'doc': 'doc', + 'docx': 'doc', + 'eps': 'doc', + 'rtf': 'doc', + 'txt': 'doc', + 'odt': 'doc', + 'rtf': 'doc', + 'ppt': 'ppt', + 'pptx': 'ppt', + 'pps': 'ppt', + 'ppsx': 'ppt', + 'odp': 'ppt' + }; + + let chunks = inputFilename.split('.'); + if (chunks.length < 2) { + return 'application'; + } + let extension = chunks[chunks.length - 1].toLowerCase(); + if (types[extension] === undefined) { + return 'application'; + } else { + return types[extension]; + } + } + +} diff --git a/components/file-upload/file-uploader.class.ts b/components/file-upload/file-uploader.class.ts index 54365e4..8349148 100644 --- a/components/file-upload/file-uploader.class.ts +++ b/components/file-upload/file-uploader.class.ts @@ -1,44 +1,85 @@ import {FileLikeObject} from './file-like-object.class'; import {FileItem} from './file-item.class'; -function isFile(value:any):boolean { +import {FileType} from './file-type'; +function isFile(value: any) { return (File && value instanceof File); } // function isFileLikeObject(value:any) { -// return value instanceof FileLikeObject; -// } -export class FileUploader { - public url:string; - public authToken:string; - public isUploading:boolean = false; - public queue:Array = []; - public progress:number = 0; - public autoUpload:boolean = false; - public isHTML5:boolean = true; - public removeAfterUpload:boolean = false; - public queueLimit:number; - public _nextIndex:number = 0; - public filters:Array = []; - public options:any; - private _failFilterIndex:number; +export interface Headers { + name: string; + value: string; +} - public constructor(options:any) { - // Object.assign(this, options); - this.url = options.url; - this.authToken = options.authToken; - this.autoUpload = options.autoUpload; - this.filters.unshift({name: 'queueLimit', fn: this._queueLimitFilter}); - this.filters.unshift({name: 'folder', fn: this._folderFilter}); +export interface FileUploaderOptionsInterface { + allowedMimeType?: Array; + allowedFileType?: Array; + autoUpload?:boolean; + isHTML5?:boolean; + filters?:Array; + headers?: Array; + maxFileSize?: number; + queueLimit?:number; + removeAfterUpload?:boolean; + url?:string; +} + +export class FileUploader { + + public authToken: string; + public isUploading: boolean = false; + public queue: Array = []; + public progress: number = 0; + public _nextIndex:number = 0; + public options:any; + private _failFilterIndex: number; + + public options: FileUploaderOptionsInterface = { + autoUpload: false, + isHTML5: true, + filters: [], + removeAfterUpload: false, + }; + + + constructor() { } - public addToQueue(files:any[], options:any, filters:any):void { - let list:any[] = []; + public setOptions(options: any) { + this.options = Object.assign(this.options, options); + + this.authToken = options.authToken; + this.autoUpload = options.autoUpload; + this.options.filters.unshift({name: 'queueLimit', fn: this._queueLimitFilter}); + + if (this.options.maxFileSize) { + this.options.filters.unshift({name: 'fileSize', fn: this._fileSizeFilter}); + } + + if (this.options.allowedFileType) { + this.options.filters.unshift({name: 'fileType', fn: this._fileTypeFilter}); + } + + if (this.options.allowedMimeType) { + this.options.filters.unshift({name: 'mimeType', fn: this._mimeTypeFilter}); + } + + // this.options.filters.unshift({name: 'folder', fn: this._folderFilter}); + } + + + public addToQueue(files: any[], options?: any, filters?: any) { + let list: any[] = []; for (let file of files) { list.push(file); } let arrayOfFilters = this._getFilters(filters); let count = this.queue.length; - let addedFileItems:any[] = []; + let addedFileItems: any[] = []; list.map((some:any) => { + if (!options) { + options = this.options; + } + let temp = new FileLikeObject(some); if (this._isValidFile(temp, arrayOfFilters, options)) { let fileItem = new FileItem(this, some, options); @@ -55,7 +96,7 @@ export class FileUploader { this.progress = this._getTotalProgress(); } this._render(); - if (this.autoUpload) { + if (this.options.autoUpload) { this.uploadAll(); } } @@ -80,7 +121,7 @@ export class FileUploader { public uploadItem(value:FileItem):void { let index = this.getIndexOfItem(value); let item = this.queue[index]; - let transport = this.isHTML5 ? '_xhrTransport' : '_iframeTransport'; + let transport = this.options.isHTML5 ? '_xhrTransport' : '_iframeTransport'; item._prepareToUploading(); if (this.isUploading) { return; @@ -92,7 +133,7 @@ export class FileUploader { public cancelItem(value:any):void { let index = this.getIndexOfItem(value); let item = this.queue[index]; - let prop = this.isHTML5 ? '_xhr' : '_form'; + let prop = this.options.isHTML5 ? '_xhr' : '_form'; if (item && item.isUploading) { item[prop].abort(); } @@ -175,8 +216,19 @@ export class FileUploader { return {item, response, status, headers}; } - public onCancelItem(item:any, response:any, status:any, headers:any):any { - return {item, response, status, headers}; + private _mimeTypeFilter(item: any) { + return !(this.options.allowedMimeType && this.options.allowedMimeType.indexOf(item.type) === -1); + } + + private _fileSizeFilter(item: any) { + return !(this.options.maxFileSize && item.size > this.options.maxFileSize); + } + + private _fileTypeFilter(item: any) { + return !(this.options.allowedFileType && + this.options.allowedFileType.indexOf(FileType.getMimeClass(item)) === -1); + } + } public onCompleteItem(item:any, response:any, status:any, headers:any):any { @@ -207,7 +259,7 @@ export class FileUploader { } protected _headersGetter(parsedHeaders:any):any { - return (name:any) => { + return (name: any) => { if (name) { return parsedHeaders[name.toLowerCase()] || void 0; } @@ -259,6 +311,11 @@ export class FileUploader { /*item.headers.map((value, name) => { xhr.setRequestHeader(name, value); });*/ + if (this.options.headers) { + for (let header of this.options.headers) { + xhr.setRequestHeader(header.name, header.value); + } + } if (this.authToken) { xhr.setRequestHeader('Authorization', this.authToken); } diff --git a/demo/components/file-upload/zs-file-demo/demo.html b/demo/components/file-upload/zs-file-demo/demo.html new file mode 100644 index 0000000..6984b24 --- /dev/null +++ b/demo/components/file-upload/zs-file-demo/demo.html @@ -0,0 +1,3 @@ + diff --git a/demo/components/file-upload/zs-file-demo/demo.ts b/demo/components/file-upload/zs-file-demo/demo.ts new file mode 100644 index 0000000..e4140c0 --- /dev/null +++ b/demo/components/file-upload/zs-file-demo/demo.ts @@ -0,0 +1,124 @@ +import {Component, EventEmitter, ElementRef, Renderer, Input} from 'angular2/core'; +import {FileUploader, FileUploaderOptionsInterface} from '../../../../ng2-file-upload'; + +@Component({ + selector: 'demo-file-upload', + providers: [FileUploader], + directives: [], + pipes: [], + host: { + '(drop)': 'onDrop($event)', + '(dragover)': 'onDragOver($event)', + '(dragleave)': 'onDragLeave($event)', + '[class.hover]': 'isHover' + }, + template: require('./demo.html'), + styles: [':host {border:1px solid black; padding:59px;display: block;}' + + '.hover {border: 3px solid green; backgroud: black;}'] +}) +export class DemoFileUpload { + + @Input() url: string; + @Input() queueLimit: number; + @Input() maxFileSize: number; + @Input() autoUpload: boolean; + @Input() allowedMimeType: Array; + @Input() allowedFileType: Array; + @Input() headers: Array; + + private inputs = ['allowedMimeType', + 'allowedFileType', + 'autoUpload', + 'isHTML5', + 'headers', + 'maxFileSize', + 'queueLimit', + 'removeAfterUpload', + 'url', + ]; + + private uploaderOptions: FileUploaderOptionsInterface = {}; + + private isHover: boolean = false; + private multiple: boolean = true; + + constructor(private element: ElementRef, + private fileUploadService: FileUploader, + private renderer: Renderer) { + } + + ngOnInit() { + for (let input of this.inputs) { + if (this[input]) { + this.uploaderOptions[input] = this[input]; + } + } + this.fileUploadService.setOptions(this.uploaderOptions); + + this.multiple = (!this.queueLimit || this.queueLimit > 1); + } + + + onDrop(event: any) { + this._preventAndStop(event); + this.isHover = false; + + let transfer = this._getTransfer(event); + if (!transfer) { + return; + } + this.fileUploadService.addToQueue(transfer.files); + } + + onDragOver(event: any) { + this._preventAndStop(event); + + if (this.isHover) { + return; + } + + let transfer = this._getTransfer(event); + if (!this._haveFiles(transfer.types)) { + return; + } + this.isHover = true; + } + + onDragLeave(event: any): any { + this._preventAndStop(event); + if (event.currentTarget === (this).element[0]) { + return; + } + this.isHover = false; + } + + onChange($event) { + this.fileUploadService.addToQueue($event.srcElement.files); + } + + + private _getTransfer(event: any): any { + return event.dataTransfer ? event.dataTransfer : event.originalEvent.dataTransfer; + } + + private _preventAndStop(event: any): any { + event.preventDefault(); + event.stopPropagation(); + } + + private _haveFiles(types: any): any { + if (!types) { + return false; + } + + if (types.indexOf) { + return types.indexOf('Files') !== -1; + } else if (types.contains) { + return types.contains('Files'); + } else { + return false; + } + } + + +} -- 2.43.0 From ef6091c670d3260ede3430d98c7863e861dcd609 Mon Sep 17 00:00:00 2001 From: Dmitriy Shekhovtsov Date: Thu, 12 May 2016 15:15:03 +0300 Subject: [PATCH 13/19] fix(upload): merge fix and get filters fix --- components/file-upload/file-type.class.ts | 154 +++++++++++++++++ components/file-upload/file-type.ts | 158 ------------------ components/file-upload/file-uploader.class.ts | 111 ++++++------ .../file-upload/zs-file-demo/demo.ts | 74 ++++---- 4 files changed, 250 insertions(+), 247 deletions(-) create mode 100644 components/file-upload/file-type.class.ts delete mode 100644 components/file-upload/file-type.ts diff --git a/components/file-upload/file-type.class.ts b/components/file-upload/file-type.class.ts new file mode 100644 index 0000000..ea16a18 --- /dev/null +++ b/components/file-upload/file-type.class.ts @@ -0,0 +1,154 @@ +export class FileType { + /* MS office */ + public static mime_doc:string[] = [ + 'application/msword', + 'application/msword', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', + 'application/vnd.ms-word.document.macroEnabled.12', + 'application/vnd.ms-word.template.macroEnabled.12' + ]; + public static mime_xsl:string[] = [ + 'application/vnd.ms-excel', + 'application/vnd.ms-excel', + 'application/vnd.ms-excel', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', + 'application/vnd.ms-excel.sheet.macroEnabled.12', + 'application/vnd.ms-excel.template.macroEnabled.12', + 'application/vnd.ms-excel.addin.macroEnabled.12', + 'application/vnd.ms-excel.sheet.binary.macroEnabled.12' + ]; + public static mime_ppt:string[] = [ + 'application/vnd.ms-powerpoint', + 'application/vnd.ms-powerpoint', + 'application/vnd.ms-powerpoint', + 'application/vnd.ms-powerpoint', + 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'application/vnd.openxmlformats-officedocument.presentationml.template', + 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', + 'application/vnd.ms-powerpoint.addin.macroEnabled.12', + 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', + 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', + 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12' + ]; + + /* PSD */ + public static mime_psd:string[] = [ + 'image/photoshop', + 'image/x-photoshop', + 'image/psd', + 'application/photoshop', + 'application/psd', + 'zz-application/zz-winassoc-psd' + ]; + + /* Compressed files */ + public static mime_compress:string[] = [ + 'application/x-gtar', + 'application/x-gcompress', + 'application/compress', + 'application/x-tar', + 'application/x-rar-compressed', + 'application/octet-stream' + ]; + + public static getMimeClass(file:any):string { + let mimeClass = 'application'; + if (this.mime_psd.indexOf(file.type) !== -1) { + mimeClass = 'image'; + } else if (file.type.match('image.*')) { + mimeClass = 'image'; + } else if (file.type.match('video.*')) { + mimeClass = 'video'; + } else if (file.type.match('audio.*')) { + mimeClass = 'audio'; + } else if (file.type === 'application/pdf') { + mimeClass = 'pdf'; + } else if (this.mime_compress.indexOf(file.type) !== -1) { + mimeClass = 'compress'; + } else if (this.mime_doc.indexOf(file.type) !== -1) { + mimeClass = 'doc'; + } else if (this.mime_xsl.indexOf(file.type) !== -1) { + mimeClass = 'xls'; + } else if (this.mime_ppt.indexOf(file.type) !== -1) { + mimeClass = 'ppt'; + } + if (mimeClass === 'application') { + mimeClass = this.fileTypeDetection(file.name); + } + + return mimeClass; + } + + public static fileTypeDetection(inputFilename:string):string { + let types:{[key:string]:string} = { + 'jpg': 'image', + 'jpeg': 'image', + 'tif': 'image', + 'psd': 'image', + 'bmp': 'image', + 'png': 'image', + 'nef': 'image', + 'tiff': 'image', + 'cr2': 'image', + 'dwg': 'image', + 'cdr': 'image', + 'ai': 'image', + 'indd': 'image', + 'pin': 'image', + 'cdp': 'image', + 'skp': 'image', + 'stp': 'image', + '3dm': 'image', + 'mp3': 'audio', + 'wav': 'audio', + 'wma': 'audio', + 'mod': 'audio', + 'm4a': 'audio', + 'compress': 'compress', + 'rar': 'compress', + '7z': 'compress', + 'lz': 'compress', + 'z01': 'compress', + 'pdf': 'pdf', + 'xls': 'xls', + 'xlsx': 'xls', + 'ods': 'xls', + 'mp4': 'video', + 'avi': 'video', + 'wmv': 'video', + 'mpg': 'video', + 'mts': 'video', + 'flv': 'video', + '3gp': 'video', + 'vob': 'video', + 'm4v': 'video', + 'mpeg': 'video', + 'm2ts': 'video', + 'mov': 'video', + 'doc': 'doc', + 'docx': 'doc', + 'eps': 'doc', + 'txt': 'doc', + 'odt': 'doc', + 'rtf': 'doc', + 'ppt': 'ppt', + 'pptx': 'ppt', + 'pps': 'ppt', + 'ppsx': 'ppt', + 'odp': 'ppt' + }; + + let chunks = inputFilename.split('.'); + if (chunks.length < 2) { + return 'application'; + } + let extension = chunks[chunks.length - 1].toLowerCase(); + if (types[extension] === undefined) { + return 'application'; + } else { + return types[extension]; + } + } +} diff --git a/components/file-upload/file-type.ts b/components/file-upload/file-type.ts deleted file mode 100644 index e256953..0000000 --- a/components/file-upload/file-type.ts +++ /dev/null @@ -1,158 +0,0 @@ -export class FileType { - /* MS office */ - static mime_doc = [ - 'application/msword', - 'application/msword', - 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', - 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', - 'application/vnd.ms-word.document.macroEnabled.12', - 'application/vnd.ms-word.template.macroEnabled.12' - ]; - static mime_xsl = [ - 'application/vnd.ms-excel', - 'application/vnd.ms-excel', - 'application/vnd.ms-excel', - 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', - 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', - 'application/vnd.ms-excel.sheet.macroEnabled.12', - 'application/vnd.ms-excel.template.macroEnabled.12', - 'application/vnd.ms-excel.addin.macroEnabled.12', - 'application/vnd.ms-excel.sheet.binary.macroEnabled.12' - ]; - static mime_ppt = [ - 'application/vnd.ms-powerpoint', - 'application/vnd.ms-powerpoint', - 'application/vnd.ms-powerpoint', - 'application/vnd.ms-powerpoint', - 'application/vnd.openxmlformats-officedocument.presentationml.presentation', - 'application/vnd.openxmlformats-officedocument.presentationml.template', - 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', - 'application/vnd.ms-powerpoint.addin.macroEnabled.12', - 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', - 'application/vnd.ms-powerpoint.presentation.macroEnabled.12', - 'application/vnd.ms-powerpoint.slideshow.macroEnabled.12' - ]; - - /* PSD */ - static mime_psd = [ - 'image/photoshop', - 'image/x-photoshop', - 'image/psd', - 'application/photoshop', - 'application/psd', - 'zz-application/zz-winassoc-psd' - ]; - - /* Compressed files */ - static mime_compress = [ - 'application/x-gtar', - 'application/x-gcompress', - 'application/compress', - 'application/x-tar', - 'application/x-rar-compressed', - 'application/octet-stream' - ]; - - static getMimeClass(file) { - let mimeClass = 'application'; - if (this.mime_psd.indexOf(file.type) !== -1) { - mimeClass = 'image'; - } else if (file.type.match('image.*')) { - mimeClass = 'image'; - } else if (file.type.match('video.*')) { - mimeClass = 'video'; - } else if (file.type.match('audio.*')) { - mimeClass = 'audio'; - } else if (file.type === 'application/pdf') { - mimeClass = 'pdf'; - } else if (this.mime_compress.indexOf(file.type) !== -1) { - mimeClass = 'compress'; - } else if (this.mime_doc.indexOf(file.type) !== -1) { - mimeClass = 'doc'; - } else if (this.mime_xsl.indexOf(file.type) !== -1) { - mimeClass = 'xls'; - } else if (this.mime_ppt.indexOf(file.type) !== -1) { - mimeClass = 'ppt'; - } - if (mimeClass === 'application') { - mimeClass = this.fileTypeDetection(file.name); - } - - - return mimeClass; - } - - - static fileTypeDetection(inputFilename) { - let types = { - 'jpg': 'image', - 'jpeg': 'image', - 'tif': 'image', - 'psd': 'image', - 'bmp': 'image', - 'png': 'image', - 'nef': 'image', - 'tiff': 'image', - 'cr2': 'image', - 'dwg': 'image', - 'cdr': 'image', - 'ai': 'image', - 'indd': 'image', - 'pin': 'image', - 'cdp': 'image', - 'skp': 'image', - 'stp': 'image', - '3dm': 'image', - 'mp3': 'audio', - 'wav': 'audio', - 'wma': 'audio', - 'mod': 'audio', - 'm4a': 'audio', - 'compress': 'compress', - 'rar': 'compress', - '7z': 'compress', - 'lz': 'compress', - 'z01': 'compress', - 'pdf': 'pdf', - 'xls': 'xls', - 'xlsx': 'xls', - 'ods': 'xls', - 'mp4': 'video', - 'avi': 'video', - 'wmv': 'video', - 'mpg': 'video', - 'mts': 'video', - 'flv': 'video', - '3gp': 'video', - 'vob': 'video', - 'm4v': 'video', - 'mpeg': 'video', - 'm2ts': 'video', - 'mov': 'video', - 'doc': 'doc', - 'docx': 'doc', - 'eps': 'doc', - 'rtf': 'doc', - 'txt': 'doc', - 'odt': 'doc', - 'rtf': 'doc', - 'ppt': 'ppt', - 'pptx': 'ppt', - 'pps': 'ppt', - 'ppsx': 'ppt', - 'odp': 'ppt' - }; - - let chunks = inputFilename.split('.'); - if (chunks.length < 2) { - return 'application'; - } - let extension = chunks[chunks.length - 1].toLowerCase(); - if (types[extension] === undefined) { - return 'application'; - } else { - return types[extension]; - } - } - -} diff --git a/components/file-upload/file-uploader.class.ts b/components/file-upload/file-uploader.class.ts index 8349148..76448c6 100644 --- a/components/file-upload/file-uploader.class.ts +++ b/components/file-upload/file-uploader.class.ts @@ -1,23 +1,24 @@ import {FileLikeObject} from './file-like-object.class'; import {FileItem} from './file-item.class'; -import {FileType} from './file-type'; -function isFile(value: any) { +import {FileType} from './file-type.class'; + +function isFile(value:any):boolean { return (File && value instanceof File); } // function isFileLikeObject(value:any) { export interface Headers { - name: string; - value: string; + name:string; + value:string; } -export interface FileUploaderOptionsInterface { - allowedMimeType?: Array; - allowedFileType?: Array; +export interface FileUploaderOptions { + allowedMimeType?:Array; + allowedFileType?:Array; autoUpload?:boolean; isHTML5?:boolean; filters?:Array; - headers?: Array; - maxFileSize?: number; + headers?:Array; + maxFileSize?:number; queueLimit?:number; removeAfterUpload?:boolean; url?:string; @@ -25,26 +26,27 @@ export interface FileUploaderOptionsInterface { export class FileUploader { - public authToken: string; - public isUploading: boolean = false; - public queue: Array = []; - public progress: number = 0; + public authToken:string; + public isUploading:boolean = false; + public queue:Array = []; + public progress:number = 0; public _nextIndex:number = 0; - public options:any; - private _failFilterIndex: number; + public autoUpload:any; - public options: FileUploaderOptionsInterface = { + public options:FileUploaderOptions = { autoUpload: false, isHTML5: true, filters: [], - removeAfterUpload: false, + removeAfterUpload: false }; + private _failFilterIndex:number; - constructor() { + public constructor(options:any) { + this.setOptions(options); } - public setOptions(options: any) { + public setOptions(options:any):void { this.options = Object.assign(this.options, options); this.authToken = options.authToken; @@ -66,19 +68,18 @@ export class FileUploader { // this.options.filters.unshift({name: 'folder', fn: this._folderFilter}); } - - public addToQueue(files: any[], options?: any, filters?: any) { - let list: any[] = []; + public addToQueue(files:any[], options?:any, filters?:any):void { + let list:any[] = []; for (let file of files) { list.push(file); } let arrayOfFilters = this._getFilters(filters); let count = this.queue.length; - let addedFileItems: any[] = []; + let addedFileItems:any[] = []; list.map((some:any) => { - if (!options) { - options = this.options; - } + if (!options) { + options = this.options; + } let temp = new FileLikeObject(some); if (this._isValidFile(temp, arrayOfFilters, options)) { @@ -216,19 +217,8 @@ export class FileUploader { return {item, response, status, headers}; } - private _mimeTypeFilter(item: any) { - return !(this.options.allowedMimeType && this.options.allowedMimeType.indexOf(item.type) === -1); - } - - private _fileSizeFilter(item: any) { - return !(this.options.maxFileSize && item.size > this.options.maxFileSize); - } - - private _fileTypeFilter(item: any) { - return !(this.options.allowedFileType && - this.options.allowedFileType.indexOf(FileType.getMimeClass(item)) === -1); - } - + public onCancelItem(item:any, response:any, status:any, headers:any):any { + return {item, response, status, headers}; } public onCompleteItem(item:any, response:any, status:any, headers:any):any { @@ -239,6 +229,19 @@ export class FileUploader { return void 0; } + public _mimeTypeFilter(item:any):boolean { + return !(this.options.allowedMimeType && this.options.allowedMimeType.indexOf(item.type) === -1); + } + + public _fileSizeFilter(item:any):boolean { + return !(this.options.maxFileSize && item.size > this.options.maxFileSize); + } + + public _fileTypeFilter(item:any):boolean { + return !(this.options.allowedFileType && + this.options.allowedFileType.indexOf(FileType.getMimeClass(item)) === -1); + } + public _onErrorItem(item:any, response:any, status:any, headers:any):void { item._onError(response, status, headers); this.onErrorItem(item, response, status, headers); @@ -259,7 +262,7 @@ export class FileUploader { } protected _headersGetter(parsedHeaders:any):any { - return (name: any) => { + return (name:any) => { if (name) { return parsedHeaders[name.toLowerCase()] || void 0; } @@ -324,7 +327,7 @@ export class FileUploader { } private _getTotalProgress(value:number = 0):number { - if (this.removeAfterUpload) { + if (this.options.removeAfterUpload) { return value; } let notUploaded = this.getNotUploadedItems().length; @@ -336,14 +339,17 @@ export class FileUploader { private _getFilters(filters:any):any { if (!filters) { - return this.filters; + return this.options.filters; } if (Array.isArray(filters)) { return filters; } - let names = filters.match(/[^\s,]+/g); - return this.filters - .filter((filter:any) => names.indexOf(filter.name) !== -1); + if (typeof filters === 'string') { + let names = filters.match(/[^\s,]+/g); + return this.options.filters + .filter((filter:any) => names.indexOf(filter.name) !== -1); + } + return this.options.filters; } private _render():any { @@ -351,12 +357,12 @@ export class FileUploader { // todo: ? } - private _folderFilter(item:any):boolean { - return !!(item.size || item.type); - } + // private _folderFilter(item:any):boolean { + // return !!(item.size || item.type); + // } private _queueLimitFilter():boolean { - return this.queueLimit === undefined || this.queue.length < this.queueLimit; + return this.options.queueLimit === undefined || this.queue.length < this.options.queueLimit; } private _isValidFile(file:any, filters:any, options:any):boolean { @@ -380,6 +386,7 @@ export class FileUploader { });*/ return response; } + /* tslint:enable */ private _parseHeaders(headers:any):any { let parsed:any = {}; @@ -401,8 +408,8 @@ export class FileUploader { } /*private _iframeTransport(item:any) { - // todo: implement it later - }*/ + // todo: implement it later + }*/ private _onWhenAddingFileFailed(item:any, filter:any, options:any):void { this.onWhenAddingFileFailed(item, filter, options); @@ -429,11 +436,13 @@ export class FileUploader { this.onProgressAll(total); this._render(); } + /* tslint:disable */ private _onSuccessItem(item:any, response:any, status:any, headers:any):void { item._onSuccess(response, status, headers); this.onSuccessItem(item, response, status, headers); } + /* tslint:enable */ private _onCancelItem(item:any, response:any, status:any, headers:any):void { item._onCancel(response, status, headers); diff --git a/demo/components/file-upload/zs-file-demo/demo.ts b/demo/components/file-upload/zs-file-demo/demo.ts index e4140c0..be81a98 100644 --- a/demo/components/file-upload/zs-file-demo/demo.ts +++ b/demo/components/file-upload/zs-file-demo/demo.ts @@ -1,32 +1,26 @@ -import {Component, EventEmitter, ElementRef, Renderer, Input} from 'angular2/core'; -import {FileUploader, FileUploaderOptionsInterface} from '../../../../ng2-file-upload'; +import {Component, ElementRef, Renderer, Input, HostListener, HostBinding, OnInit} from '@angular/core'; +import {FileUploader, FileUploaderOptions} from '../../../../ng2-file-upload'; @Component({ selector: 'demo-file-upload', providers: [FileUploader], - directives: [], - pipes: [], - host: { - '(drop)': 'onDrop($event)', - '(dragover)': 'onDragOver($event)', - '(dragleave)': 'onDragLeave($event)', - '[class.hover]': 'isHover' - }, template: require('./demo.html'), styles: [':host {border:1px solid black; padding:59px;display: block;}' + '.hover {border: 3px solid green; backgroud: black;}'] }) -export class DemoFileUpload { +export class DemoFileUploadComponent implements OnInit { - @Input() url: string; - @Input() queueLimit: number; - @Input() maxFileSize: number; - @Input() autoUpload: boolean; - @Input() allowedMimeType: Array; - @Input() allowedFileType: Array; - @Input() headers: Array; + @Input() public url:string; + @Input() public queueLimit:number; + @Input() public maxFileSize:number; + @Input() public autoUpload:boolean; + @Input() public allowedMimeType:Array; + @Input() public allowedFileType:Array; + @Input() public headers:Array; - private inputs = ['allowedMimeType', + @HostBinding('class.hover') private isHover:boolean = false; + + private inputs:string[] = ['allowedMimeType', 'allowedFileType', 'autoUpload', 'isHTML5', @@ -34,20 +28,24 @@ export class DemoFileUpload { 'maxFileSize', 'queueLimit', 'removeAfterUpload', - 'url', + 'url' ]; - private uploaderOptions: FileUploaderOptionsInterface = {}; + private uploaderOptions:FileUploaderOptions = {}; - private isHover: boolean = false; - private multiple: boolean = true; + private multiple:boolean = true; - constructor(private element: ElementRef, - private fileUploadService: FileUploader, - private renderer: Renderer) { + private element:ElementRef; + private fileUploadService:FileUploader; + private renderer:Renderer; + + public constructor(element:ElementRef, fileUploadService:FileUploader, renderer:Renderer) { + this.element = element; + this.fileUploadService = fileUploadService; + this.renderer = renderer; } - ngOnInit() { + public ngOnInit():any { for (let input of this.inputs) { if (this[input]) { this.uploaderOptions[input] = this[input]; @@ -58,8 +56,8 @@ export class DemoFileUpload { this.multiple = (!this.queueLimit || this.queueLimit > 1); } - - onDrop(event: any) { + @HostListener('drop', ['$event']) + public onDrop(event:any):void { this._preventAndStop(event); this.isHover = false; @@ -70,7 +68,8 @@ export class DemoFileUpload { this.fileUploadService.addToQueue(transfer.files); } - onDragOver(event: any) { + @HostListener('dragover', ['$event']) + public onDragOver(event:any):void { this._preventAndStop(event); if (this.isHover) { @@ -84,29 +83,29 @@ export class DemoFileUpload { this.isHover = true; } - onDragLeave(event: any): any { + @HostListener('dragleave', ['$event']) + public onDragLeave(event:any):void { this._preventAndStop(event); - if (event.currentTarget === (this).element[0]) { + if (event.currentTarget === (this as any).element[0]) { return; } this.isHover = false; } - onChange($event) { + public onChange($event:any):void { this.fileUploadService.addToQueue($event.srcElement.files); } - - private _getTransfer(event: any): any { + private _getTransfer(event:any):any { return event.dataTransfer ? event.dataTransfer : event.originalEvent.dataTransfer; } - private _preventAndStop(event: any): any { + private _preventAndStop(event:any):any { event.preventDefault(); event.stopPropagation(); } - private _haveFiles(types: any): any { + private _haveFiles(types:any):any { if (!types) { return false; } @@ -120,5 +119,4 @@ export class DemoFileUpload { } } - } -- 2.43.0 From 3dd2c0e952cffcdbec9ea3df7e1ca9b5fcd1ffa1 Mon Sep 17 00:00:00 2001 From: Dmitriy Shekhovtsov Date: Thu, 12 May 2016 15:50:50 +0300 Subject: [PATCH 14/19] Merge of onBuildForm --- components/file-upload/file-item.class.ts | 8 ++++++++ components/file-upload/file-uploader.class.ts | 11 +++++++++++ 2 files changed, 19 insertions(+) diff --git a/components/file-upload/file-item.class.ts b/components/file-upload/file-item.class.ts index 1151510..d8db025 100644 --- a/components/file-upload/file-item.class.ts +++ b/components/file-upload/file-item.class.ts @@ -57,6 +57,10 @@ export class FileItem { return void 0; } + public onBuildForm(form:any):any { + return {form}; + } + public onProgress(progress:number):any { return {progress}; } @@ -88,6 +92,10 @@ export class FileItem { this.onBeforeUpload(); } + public _onBuildForm(form:any):void { + this.onBuildForm(form); + } + public _onProgress(progress:number):void { this._zone.run(() => { this.progress = progress; diff --git a/components/file-upload/file-uploader.class.ts b/components/file-upload/file-uploader.class.ts index 76448c6..b014b2d 100644 --- a/components/file-upload/file-uploader.class.ts +++ b/components/file-upload/file-uploader.class.ts @@ -189,6 +189,10 @@ export class FileUploader { return {fileItems}; } + public onBuildItemForm(fileItem:any, form:any):any { + return {fileItem, form}; + } + public onAfterAddingFile(fileItem:any):any { return {fileItem}; } @@ -283,6 +287,8 @@ export class FileUploader { if (typeof item._file.size !== 'number') { throw new TypeError('The file specified is no longer valid'); } + this._onBuildItemForm(item, form); + form.append(item.alias, item._file, item.file.name); xhr.upload.onprogress = (event:any) => { let progress = Math.round(event.lengthComputable ? event.loaded * 100 / event.total : 0); @@ -428,6 +434,11 @@ export class FileUploader { this.onBeforeUploadItem(item); } + private _onBuildItemForm(item:any, form:any):void { + item._onBuildForm(form); + this.onBuildItemForm(item, form); + } + private _onProgressItem(item:any, progress:any):void { let total = this._getTotalProgress(progress); this.progress = total; -- 2.43.0 From 9461806f214245cc0aeb31463bc165cc8a3f134b Mon Sep 17 00:00:00 2001 From: Dmitriy Shekhovtsov Date: Thu, 12 May 2016 15:56:35 +0300 Subject: [PATCH 15/19] chore(onFileDrop): emit all dropped files --- components/file-upload/file-drop.directive.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/file-upload/file-drop.directive.ts b/components/file-upload/file-drop.directive.ts index e659868..28225eb 100644 --- a/components/file-upload/file-drop.directive.ts +++ b/components/file-upload/file-drop.directive.ts @@ -6,7 +6,7 @@ import { FileUploader } from './file-uploader.class'; export class FileDropDirective { @Input() public uploader:FileUploader; @Output() public fileOver:EventEmitter = new EventEmitter(); - @Output() public onFileDrop:EventEmitter = new EventEmitter(); + @Output() public onFileDrop:EventEmitter = new EventEmitter(); private element:ElementRef; public constructor(element:ElementRef) { @@ -33,7 +33,7 @@ export class FileDropDirective { this._preventAndStop(event); this.uploader.addToQueue(transfer.files, options, filters); this.fileOver.emit(false); - this.onFileDrop.emit(transfer.files[0]); + this.onFileDrop.emit(transfer.files); } @HostListener('dragover', ['$event']) -- 2.43.0 From 04fc2c9470bd1d35297820843ad6344abc3c53b5 Mon Sep 17 00:00:00 2001 From: Dmitriy Shekhovtsov Date: Thu, 12 May 2016 16:03:44 +0300 Subject: [PATCH 16/19] chore(ci): added code cov report --- .travis.yml | 26 ++++++++++++++++---------- README.md | 2 ++ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1dce4ba..ce4e7cd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,16 +1,22 @@ language: node_js node_js: - - "6" + - "6" script: -- npm test -- npm run deploy + - npm run flow.install:typings + - npm test + +after_success: + - ./node_modules/.bin/codecov + - npm run deploy addons: - firefox: "42.0" - apt: - sources: - - ubuntu-toolchain-r-test - # required by node-gyp to build some packages - packages: - - g++-4.8 \ No newline at end of file + # sauce labs tunel connector (read more https://docs.travis-ci.com/user/sauce-connect/ ) + sauce_connect: true + firefox: "42.0" + apt: + sources: + - ubuntu-toolchain-r-test + # required by node-gyp to build some packages + packages: + - g++-4.8 diff --git a/README.md b/README.md index 74da75e..d520c55 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ Easy to use Angular2 directives for files upload ([demo](http://valor-software.g Follow me [![twitter](https://img.shields.io/twitter/follow/valorkin.svg?style=social&label=%20valorkin)](https://twitter.com/valorkin) to be notified about new releases. +[![Angular 2 Style Guide](https://mgechev.github.io/angular2-style-guide/images/badge.svg)](https://github.com/mgechev/angular2-style-guide) +[![Build Status](https://travis-ci.org/valor-software/ng2-file-upload.svg?branch=master)](https://travis-ci.org/valor-software/ng2-file-upload) [![Code Climate](https://codeclimate.com/github/valor-software/ng2-file-upload/badges/gpa.svg)](https://codeclimate.com/github/valor-software/ng2-file-upload) [![Join the chat at https://gitter.im/valor-software/ng2-bootstrap](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/valor-software/ng2-bootstrap?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Dependency Status](https://david-dm.org/valor-software/ng2-file-upload.svg)](https://david-dm.org/valor-software/ng2-file-upload) -- 2.43.0 From f634d218d8703e19d8c069fafd2929ae64d5cedd Mon Sep 17 00:00:00 2001 From: Dmitriy Shekhovtsov Date: Thu, 12 May 2016 16:04:22 +0300 Subject: [PATCH 17/19] 1.0.2 --- CHANGELOG.md | 26 ++++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..a3dfb1b --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,26 @@ + +## 1.0.2 (2016-05-12) + + +### Bug Fixes + +* **upload:** merge fix and get filters fix ([ef6091c](https://github.com/valor-software/ng2-file-upload/commit/ef6091c)) + + +### Chores + +* **build:** ng2 style guide applied, ([aee69d8](https://github.com/valor-software/ng2-file-upload/commit/aee69d8)) + + +### Features + +* **package:** upgrade to angular 2.0.0-rc.1 ([#176](https://github.com/valor-software/ng2-file-upload/issues/176)) ([13c5c35](https://github.com/valor-software/ng2-file-upload/commit/13c5c35)), closes [#180](https://github.com/valor-software/ng2-file-upload/issues/180) + + +### BREAKING CHANGES + +* build: S: +- directives and selectors renamed to ng2FileSelect and ng2FileDrop + + + diff --git a/package.json b/package.json index 04c5625..95a66e5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ng2-file-upload", - "version": "1.0.1", + "version": "1.0.2", "description": "angular2 file upload directives", "scripts": { "flow.install:typings": "./node_modules/.bin/typings install", -- 2.43.0 From d7512dbb1e2b475d3e16ac008a18090ff02c026d Mon Sep 17 00:00:00 2001 From: Dmitriy Shekhovtsov Date: Thu, 12 May 2016 16:07:31 +0300 Subject: [PATCH 18/19] chore(ci): travis build fixed --- .travis.yml | 1 - CHANGELOG.md | 3 +-- README.md | 6 +++--- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index ce4e7cd..56eb9da 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,6 @@ script: after_success: - ./node_modules/.bin/codecov - - npm run deploy addons: # sauce labs tunel connector (read more https://docs.travis-ci.com/user/sauce-connect/ ) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3dfb1b..2c748c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ ### Chores -* **build:** ng2 style guide applied, ([aee69d8](https://github.com/valor-software/ng2-file-upload/commit/aee69d8)) +* **build:** ng2 style guide applied ([aee69d8](https://github.com/valor-software/ng2-file-upload/commit/aee69d8)) ### Features @@ -19,7 +19,6 @@ ### BREAKING CHANGES -* build: S: - directives and selectors renamed to ng2FileSelect and ng2FileDrop diff --git a/README.md b/README.md index d520c55..c4ced13 100644 --- a/README.md +++ b/README.md @@ -25,13 +25,13 @@ Follow me [![twitter](https://img.shields.io/twitter/follow/valorkin.svg?style=s 3. More information regarding using of ***ng2-file-upload*** is located in [demo](http://valor-software.github.io/ng2-file-upload/) and [demo sources](https://github.com/valor-software/ng2-file-upload/tree/master/demo). -## API for `ng2-file-select` +## API for `ng2FileSelect` ### Properties - `uploader` - (`FileUploader`) - uploader object. See using in [demo](https://github.com/valor-software/ng2-file-upload/blob/master/demo/components/file-upload/simple-demo.ts) -## API for `ng2-file-drop` +## API for `ng2FileDrop` ### Properties @@ -44,7 +44,7 @@ Follow me [![twitter](https://img.shields.io/twitter/follow/valorkin.svg?style=s ### Events - - `file-over` - it fires during 'over' and 'out' events for Drop Area; returns `boolean`: `true` if file is over Drop Area, `false` in case of out. + - `fileOver` - it fires during 'over' and 'out' events for Drop Area; returns `boolean`: `true` if file is over Drop Area, `false` in case of out. See using in [ts demo](https://github.com/valor-software/ng2-file-upload/blob/master/demo/components/file-upload/simple-demo.ts) and [html demo](https://github.com/valor-software/ng2-file-upload/blob/master/demo/components/file-upload/simple-demo.html) -- 2.43.0 From 85d996ea370a668ddb9b68de5e99d68e1cfba223 Mon Sep 17 00:00:00 2001 From: Dmitriy Shekhovtsov Date: Thu, 12 May 2016 16:07:58 +0300 Subject: [PATCH 19/19] 1.0.3 --- CHANGELOG.md | 5 +++++ package.json | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c748c6..84ccfb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ + +## [1.0.3](https://github.com/valor-software/ng2-file-upload/compare/v1.0.2...v1.0.3) (2016-05-12) + + + ## 1.0.2 (2016-05-12) diff --git a/package.json b/package.json index 95a66e5..2459e91 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ng2-file-upload", - "version": "1.0.2", + "version": "1.0.3", "description": "angular2 file upload directives", "scripts": { "flow.install:typings": "./node_modules/.bin/typings install", -- 2.43.0