chore(build): ng2 style guide applied,

- build process updated
- systemjs bundler added

BREAKING CHANGES:
- directives and selectors renamed to ng2FileSelect and ng2FileDrop
This commit is contained in:
Dmitriy Shekhovtsov
2016-05-11 18:40:47 +03:00
parent 13c5c35864
commit aee69d8b80
30 changed files with 743 additions and 740 deletions

107
.config/bundle-system.js Executable file
View File

@@ -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);
}

200
.eslintrc
View File

@@ -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
}
}

6
.eslintrc.json Normal file
View File

@@ -0,0 +1,6 @@
{
"extends": "./node_modules/eslint-config-valorsoft/.eslintrc.json",
"env": {
"node": true
}
}

6
.gitignore vendored
View File

@@ -10,9 +10,13 @@ npm-debug.log
.idea .idea
# ignore build and dist for now # ignore build and dist for now
/build /bundles
/demo-build
/dist /dist
/coverage
/ts
# ignore incline compiling
/demo/**/*.js /demo/**/*.js
/demo/**/*.d.ts /demo/**/*.d.ts
/demo/**/*.js.map /demo/**/*.js.map

View File

@@ -1,13 +1,24 @@
.idea .idea
demo
build
gulp-tasks gulp-tasks
logs logs
tsd.d.ts # typings
typings typings
/node_modules # testing
karma.conf.js
test.bundle.js
coverage
# demo build
demo
demo-build
webpack.config.js webpack.config.js
#typescript sources
*.ts
*.js.map
!*.d.ts
/components/**/*.ts
!/components/**/*.d.ts

View File

@@ -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) # 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/)) 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) [![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) [![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). 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. `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 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). [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 ### 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) - `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 `ng2-file-drop`
### Properties ### Properties

View File

@@ -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: `<input type="file" ng2FileSelect [uploader]="uploader" />`,
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<ContainerComponent>) => {
expect(fixture).not.toBeNull();
}));
});

View File

@@ -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({ @Directive({selector: '[ng2FileDrop]'})
selector: '[ng2-file-drop]', export class FileDropDirective {
properties: ['uploader'], @Input() public uploader:FileUploader;
events: ['fileOver'], @Output() public fileOver:EventEmitter<any> = new EventEmitter();
host: {
'(drop)': 'onDrop($event)',
'(dragover)': 'onDragOver($event)',
'(dragleave)': 'onDragLeave($event)'
}
})
export class FileDrop {
public uploader:FileUploader;
private fileOver:EventEmitter<any> = new EventEmitter();
constructor(private element:ElementRef) { private element:ElementRef;
public constructor(element:ElementRef) {
this.element = element;
} }
getOptions() { public getOptions():any {
return this.uploader.options; 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); let transfer = this._getTransfer(event);
if (!transfer) { if (!transfer) {
return; return;
@@ -36,10 +31,11 @@ export class FileDrop {
let filters = this.getFilters(); let filters = this.getFilters();
this._preventAndStop(event); this._preventAndStop(event);
this.uploader.addToQueue(transfer.files, options, filters); 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); let transfer = this._getTransfer(event);
if (!this._haveFiles(transfer.types)) { if (!this._haveFiles(transfer.types)) {
return; return;
@@ -47,16 +43,17 @@ export class FileDrop {
transfer.dropEffect = 'copy'; transfer.dropEffect = 'copy';
this._preventAndStop(event); this._preventAndStop(event);
this.fileOver.next(true); this.fileOver.emit(true);
} }
onDragLeave(event:any):any { @HostListener('dragleave', ['$event'])
if (event.currentTarget === (<any>this).element[0]) { public onDragLeave(event:any):any {
if (event.currentTarget === (this as any).element[0]) {
return; return;
} }
this._preventAndStop(event); this._preventAndStop(event);
this.fileOver.next(false); this.fileOver.emit(false);
} }
private _getTransfer(event:any):any { private _getTransfer(event:any):any {
@@ -81,12 +78,12 @@ export class FileDrop {
return false; return false;
} }
} }
/*
_addOverClass(item:any):any { _addOverClass(item:any):any {
item.addOverClass(); item.addOverClass();
} }
_removeOverClass(item:any):any { _removeOverClass(item:any):any {
item.removeOverClass(); item.removeOverClass();
} }*/
} }

View File

@@ -1,5 +1,5 @@
import {FileLikeObject} from './file-like-object'; import {FileLikeObject} from './file-like-object.class';
import {FileUploader} from './file-uploader'; import {FileUploader} from './file-uploader.class';
export class FileItem { export class FileItem {
public file:FileLikeObject; public file:FileLikeObject;
@@ -17,15 +17,22 @@ export class FileItem {
public isCancel:boolean = false; public isCancel:boolean = false;
public isError:boolean = false; public isError:boolean = false;
public progress:number = 0; 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 = new FileLikeObject(some);
this._file = some; this._file = some;
this.url = uploader.url; this.url = uploader.url;
} }
public upload() { public upload():void {
try { try {
this.uploader.uploadItem(this); this.uploader.uploadItem(this);
} catch (e) { } catch (e) {
@@ -34,33 +41,39 @@ export class FileItem {
} }
} }
public cancel() { public cancel():void {
this.uploader.cancelItem(this); this.uploader.cancelItem(this);
} }
public remove() { public remove():void {
this.uploader.removeFromQueue(this); 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.isReady = true;
this.isUploading = true; this.isUploading = true;
this.isUploaded = false; this.isUploaded = false;
@@ -71,12 +84,12 @@ export class FileItem {
this.onBeforeUpload(); this.onBeforeUpload();
} }
private _onProgress(progress:number) { public _onProgress(progress:number):void {
this.progress = progress; this.progress = progress;
this.onProgress(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.isReady = false;
this.isUploading = false; this.isUploading = false;
this.isUploaded = true; this.isUploaded = true;
@@ -84,11 +97,11 @@ export class FileItem {
this.isCancel = false; this.isCancel = false;
this.isError = false; this.isError = false;
this.progress = 100; this.progress = 100;
this.index = null; this.index = void 0;
this.onSuccess(response, status, headers); 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.isReady = false;
this.isUploading = false; this.isUploading = false;
this.isUploaded = true; this.isUploaded = true;
@@ -96,11 +109,11 @@ export class FileItem {
this.isCancel = false; this.isCancel = false;
this.isError = true; this.isError = true;
this.progress = 0; this.progress = 0;
this.index = null; this.index = void 0;
this.onError(response, status, headers); 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.isReady = false;
this.isUploading = false; this.isUploading = false;
this.isUploaded = false; this.isUploaded = false;
@@ -108,11 +121,11 @@ export class FileItem {
this.isCancel = true; this.isCancel = true;
this.isError = false; this.isError = false;
this.progress = 0; this.progress = 0;
this.index = null; this.index = void 0;
this.onCancel(response, status, headers); 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); this.onComplete(response, status, headers);
if (this.uploader.removeAfterUpload) { if (this.uploader.removeAfterUpload) {
@@ -120,7 +133,7 @@ export class FileItem {
} }
} }
private _prepareToUploading() { public _prepareToUploading():void {
this.index = this.index || ++this.uploader._nextIndex; this.index = this.index || ++this.uploader._nextIndex;
this.isReady = true; this.isReady = true;
} }

View File

@@ -1,4 +1,4 @@
function isElement(node:any) { function isElement(node:any):boolean {
return !!(node && (node.nodeName || node.prop && node.attr && node.find)); return !!(node && (node.nodeName || node.prop && node.attr && node.find));
} }
@@ -8,22 +8,22 @@ export class FileLikeObject {
public type:string; public type:string;
public name:string; public name:string;
constructor(fileOrInput:any) { public constructor(fileOrInput:any) {
let isInput = isElement(fileOrInput); let isInput = isElement(fileOrInput);
let fakePathOrObject = isInput ? fileOrInput.value : fileOrInput; let fakePathOrObject = isInput ? fileOrInput.value : fileOrInput;
let postfix = typeof fakePathOrObject === 'string' ? 'FakePath' : 'Object'; let postfix = typeof fakePathOrObject === 'string' ? 'FakePath' : 'Object';
let method = '_createFrom' + postfix; let method = '_createFrom' + postfix;
(<any>this)[method](fakePathOrObject); (this as any)[method](fakePathOrObject);
} }
public _createFromFakePath(path:string) { public _createFromFakePath(path:string):void {
this.lastModifiedDate = null; this.lastModifiedDate = void 0;
this.size = null; this.size = void 0;
this.type = 'like/' + path.slice(path.lastIndexOf('.') + 1).toLowerCase(); this.type = 'like/' + path.slice(path.lastIndexOf('.') + 1).toLowerCase();
this.name = path.slice(path.lastIndexOf('/') + path.lastIndexOf('\\') + 2); 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.lastModifiedDate = copy(object.lastModifiedDate);
this.size = object.size; this.size = object.size;
this.type = object.type; this.type = object.type;

View File

@@ -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 // todo: filters
@Directive({ @Directive({selector: '[ng2FileSelect]'})
selector: '[ng2-file-select]', export class FileSelectDirective {
properties: ['uploader'], @Input() public uploader:FileUploader;
host: {
'(change)': 'onChange()'
}
})
export class FileSelect {
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; return this.uploader.options;
} }
public getFilters() { public getFilters():any {
return void 0;
} }
public isEmptyAfterSelection():boolean { public isEmptyAfterSelection():boolean {
return !!this.element.nativeElement.attributes.multiple; 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.uploader.isHTML5 ? this.element.nativeElement[0].files : this.element.nativeElement[0];
let files = this.element.nativeElement.files; let files = this.element.nativeElement.files;
let options = this.getOptions(); let options = this.getOptions();
@@ -45,5 +43,3 @@ export class FileSelect {
} }
} }
} }
export const fileUpload:Array<any> = [FileSelect];

View File

@@ -1,14 +1,11 @@
import {FileLikeObject} from './file-like-object'; import {FileLikeObject} from './file-like-object.class';
import {FileItem} from './file-item'; import {FileItem} from './file-item.class';
function isFile(value:any):boolean {
function isFile(value:any) {
return (File && value instanceof File); return (File && value instanceof File);
} }
// function isFileLikeObject(value:any) {
function isFileLikeObject(value:any) { // return value instanceof FileLikeObject;
return value instanceof FileLikeObject; // }
}
export class FileUploader { export class FileUploader {
public url:string; public url:string;
public authToken:string; public authToken:string;
@@ -19,11 +16,12 @@ export class FileUploader {
public isHTML5:boolean = true; public isHTML5:boolean = true;
public removeAfterUpload:boolean = false; public removeAfterUpload:boolean = false;
public queueLimit:number; public queueLimit:number;
public _nextIndex = 0; public _nextIndex:number = 0;
public filters:Array<any> = []; public filters:Array<any> = [];
public options:any;
private _failFilterIndex:number; private _failFilterIndex:number;
constructor(public options:any) { public constructor(options:any) {
// Object.assign(this, options); // Object.assign(this, options);
this.url = options.url; this.url = options.url;
this.authToken = options.authToken; this.authToken = options.authToken;
@@ -31,19 +29,16 @@ export class FileUploader {
this.filters.unshift({name: 'folder', fn: this._folderFilter}); 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[] = []; let list:any[] = [];
for (let file of files) { for (let file of files) {
list.push(file); list.push(file);
} }
let arrayOfFilters = this._getFilters(filters); let arrayOfFilters = this._getFilters(filters);
let count = this.queue.length; let count = this.queue.length;
let addedFileItems:any[] = []; let addedFileItems:any[] = [];
list.map((some:any) => {
list.map(some => {
let temp = new FileLikeObject(some); let temp = new FileLikeObject(some);
if (this._isValidFile(temp, arrayOfFilters, options)) { if (this._isValidFile(temp, arrayOfFilters, options)) {
let fileItem = new FileItem(this, some, options); let fileItem = new FileItem(this, some, options);
addedFileItems.push(fileItem); addedFileItems.push(fileItem);
@@ -54,101 +49,92 @@ export class FileUploader {
this._onWhenAddingFileFailed(temp, filter, options); this._onWhenAddingFileFailed(temp, filter, options);
} }
}); });
if (this.queue.length !== count) { if (this.queue.length !== count) {
this._onAfterAddingAll(addedFileItems); this._onAfterAddingAll(addedFileItems);
this.progress = this._getTotalProgress(); this.progress = this._getTotalProgress();
} }
this._render(); this._render();
if (this.autoUpload) { if (this.autoUpload) {
this.uploadAll(); this.uploadAll();
} }
} }
public removeFromQueue(value:any) { public removeFromQueue(value:any):void {
let index = this.getIndexOfItem(value); let index = this.getIndexOfItem(value);
let item = this.queue[index]; let item = this.queue[index];
if (item.isUploading) { if (item.isUploading) {
item.cancel(); item.cancel();
} }
this.queue.splice(index, 1); this.queue.splice(index, 1);
this.progress = this._getTotalProgress(); this.progress = this._getTotalProgress();
} }
public clearQueue() { public clearQueue():void {
while (this.queue.length) { while (this.queue.length) {
this.queue[0].remove(); this.queue[0].remove();
} }
this.progress = 0; this.progress = 0;
} }
public uploadItem(value:FileItem) { public uploadItem(value:FileItem):void {
let index = this.getIndexOfItem(value); let index = this.getIndexOfItem(value);
let item = this.queue[index]; let item = this.queue[index];
let transport = this.isHTML5 ? '_xhrTransport' : '_iframeTransport'; let transport = this.isHTML5 ? '_xhrTransport' : '_iframeTransport';
item._prepareToUploading(); item._prepareToUploading();
if (this.isUploading) { if (this.isUploading) {
return; return;
} }
this.isUploading = true; this.isUploading = true;
(<any>this)[transport](item); (this as any)[transport](item);
} }
public cancelItem(value:any) { public cancelItem(value:any):void {
let index = this.getIndexOfItem(value); let index = this.getIndexOfItem(value);
let item = this.queue[index]; let item = this.queue[index];
let prop = this.isHTML5 ? '_xhr' : '_form'; let prop = this.isHTML5 ? '_xhr' : '_form';
if (item && item.isUploading) { if (item && item.isUploading) {
item[prop].abort(); item[prop].abort();
} }
} }
public uploadAll() { public uploadAll():void {
let items = this.getNotUploadedItems().filter(item => !item.isUploading); let items = this.getNotUploadedItems().filter((item:any) => !item.isUploading);
if (!items.length) { if (!items.length) {
return; return;
} }
items.map((item:any) => item._prepareToUploading());
items.map(item => item._prepareToUploading());
items[0].upload(); items[0].upload();
} }
public cancelAll() { public cancelAll():void {
let items = this.getNotUploadedItems(); let items = this.getNotUploadedItems();
items.map(item => item.cancel()); items.map((item:any) => item.cancel());
} }
public isFile(value:any):boolean {
public isFile(value:any) {
return isFile(value); return isFile(value);
} }
public isFileLikeObject(value:any) { public isFileLikeObject(value:any):boolean {
return value instanceof FileLikeObject; return value instanceof FileLikeObject;
} }
public getIndexOfItem(value:any) { public getIndexOfItem(value:any):number {
return typeof value === 'number' ? value : this.queue.indexOf(value); return typeof value === 'number' ? value : this.queue.indexOf(value);
} }
public getNotUploadedItems() { public getNotUploadedItems():Array<any> {
return this.queue.filter(item => !item.isUploaded); return this.queue.filter((item:any) => !item.isUploaded);
} }
public getReadyItems() { public getReadyItems():Array<any> {
return this.queue return this.queue
.filter(item => (item.isReady && !item.isUploading)) .filter((item:any) => (item.isReady && !item.isUploading))
.sort((item1, item2) => item1.index - item2.index); .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) => {
forEach(this._directives[key], (object) => { forEach(this._directives[key], (object) => {
object.destroy(); 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) { if (this.removeAfterUpload) {
return value; return value;
} }
let notUploaded = this.getNotUploadedItems().length; let notUploaded = this.getNotUploadedItems().length;
let uploaded = notUploaded ? this.queue.length - notUploaded : this.queue.length; let uploaded = notUploaded ? this.queue.length - notUploaded : this.queue.length;
let ratio = 100 / this.queue.length; let ratio = 100 / this.queue.length;
let current = value * ratio / 100; let current = value * ratio / 100;
return Math.round(uploaded * ratio + current); return Math.round(uploaded * ratio + current);
} }
private _getFilters(filters:any) { private _getFilters(filters:any):any {
if (!filters) { if (!filters) {
return this.filters; return this.filters;
} }
if (Array.isArray(filters)) { if (Array.isArray(filters)) {
return filters; return filters;
} }
let names = filters.match(/[^\s,]+/g); let names = filters.match(/[^\s,]+/g);
return this.filters 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: ? // todo: ?
} }
private _folderFilter(item:any) { private _folderFilter(item:any):boolean {
return !!(item.size || item.type); return !!(item.size || item.type);
} }
private _queueLimitFilter() { private _queueLimitFilter():boolean {
return this.queue.length < this.queueLimit; 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; this._failFilterIndex = -1;
return !filters.length ? true : filters.every((filter:any) => { return !filters.length ? true : filters.every((filter:any) => {
this._failFilterIndex++; 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; return (status >= 200 && status < 300) || status === 304;
} }
/* tslint:disable */
private _transformResponse(response:any, headers:any):any { private _transformResponse(response:any, headers:any):any {
// todo: ? // todo: ?
/*var headersGetter = this._headersGetter(headers); /*var headersGetter = this._headersGetter(headers);
@@ -248,121 +322,48 @@ export class FileUploader {
});*/ });*/
return response; return response;
} }
/* tslint:enable */
private _parseHeaders(headers:any) { private _parseHeaders(headers:any):any {
let parsed:any = {}, key:any, val:any, i:any; let parsed:any = {};
let key:any;
let val:any;
let i:any;
if (!headers) { if (!headers) {
return parsed; return parsed;
} }
headers.split('\n').map((line:any) => { headers.split('\n').map((line:any) => {
i = line.indexOf(':'); i = line.indexOf(':');
key = line.slice(0, i).trim().toLowerCase(); key = line.slice(0, i).trim().toLowerCase();
val = line.slice(i + 1).trim(); val = line.slice(i + 1).trim();
if (key) { if (key) {
parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val; parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val;
} }
}); });
return parsed; return parsed;
} }
private _headersGetter(parsedHeaders:any) { /*private _iframeTransport(item: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';
(<any>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) {
// todo: implement it later // 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); this.onWhenAddingFileFailed(item, filter, options);
} }
private _onAfterAddingFile(item:any) { private _onAfterAddingFile(item:any):void {
this.onAfterAddingFile(item); this.onAfterAddingFile(item);
} }
private _onAfterAddingAll(items:any) { private _onAfterAddingAll(items:any):void {
this.onAfterAddingAll(items); this.onAfterAddingAll(items);
} }
private _onBeforeUploadItem(item:any) { private _onBeforeUploadItem(item:any):void {
item._onBeforeUpload(); item._onBeforeUpload();
this.onBeforeUploadItem(item); this.onBeforeUploadItem(item);
} }
private _onProgressItem(item:any, progress:any) { private _onProgressItem(item:any, progress:any):void {
let total = this._getTotalProgress(progress); let total = this._getTotalProgress(progress);
this.progress = total; this.progress = total;
item._onProgress(progress); item._onProgress(progress);
@@ -370,36 +371,14 @@ export class FileUploader {
this.onProgressAll(total); this.onProgressAll(total);
this._render(); this._render();
} }
/* tslint:disable */
private _onSuccessItem(item:any, response:any, status:any, headers:any) { private _onSuccessItem(item:any, response:any, status:any, headers:any):void {
item._onSuccess(response, status, headers); item._onSuccess(response, status, headers);
this.onSuccessItem(item, response, status, headers); this.onSuccessItem(item, response, status, headers);
} }
/* tslint:enable */
public _onErrorItem(item:any, response:any, status:any, headers:any) { private _onCancelItem(item:any, response:any, status:any, headers:any):void {
item._onError(response, status, headers);
this.onErrorItem(item, response, status, headers);
}
private _onCancelItem(item:any, response:any, status:any, headers:any) {
item._onCancel(response, status, headers); item._onCancel(response, status, headers);
this.onCancelItem(item, 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();
}
} }

View File

@@ -1,32 +1,17 @@
### Usage ### Usage
```typescript ```typescript
import {FileSelect, FileDrop, FileUploader} from 'ng2-file-upload'; import {FileSelectDirective, FileDropDirective, FileUploader} from 'ng2-file-upload/ng2-file-upload';
``` ```
### Annotations ### Annotations
```typescript ```typescript
// class FileSelect // class FileSelectDirective
@Directive({ @Directive({ selector: '[ng2FileSelect]' })
selector: '[ng2-file-select]',
properties: ['uploader'],
host: {
'(change)': 'onChange()'
}
})
``` ```
```typescript ```typescript
// class FileDrop // class FileDropDirective
@Directive({ @Directive({ selector: '[ng2FileDrop]' })
selector: '[ng2-file-drop]',
properties: ['uploader'],
events: ['fileOver'],
host: {
'(drop)': 'onDrop($event)',
'(dragover)': 'onDragOver($event)',
'(dragleave)': 'onDragLeave($event)'
}
})
``` ```
## FileSelect API ## FileSelect API
@@ -48,6 +33,6 @@ import {FileSelect, FileDrop, FileUploader} from 'ng2-file-upload';
### Events ### 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 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) [html demo](https://github.com/valor-software/ng2-file-upload/blob/master/demo/components/file-upload/simple-demo.html)

View File

@@ -1,10 +1,8 @@
/// <reference path="../../tsd.d.ts" />
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {CORE_DIRECTIVES} from '@angular/common'; import {CORE_DIRECTIVES} from '@angular/common';
import {TAB_DIRECTIVES} from 'ng2-bootstrap/ng2-bootstrap'; 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 name = 'File Upload';
let doc = require('../../components/file-upload/readme.md'); let doc = require('../../components/file-upload/readme.md');
@@ -19,7 +17,7 @@ let tabDesc:Array<any> = [
]; ];
let tabsContent:string = ``; let tabsContent:string = ``;
tabDesc.forEach(desc => { tabDesc.forEach((desc:any) => {
tabsContent += ` tabsContent += `
<tab heading="${desc.heading}" (select)="select($event)"> <tab heading="${desc.heading}" (select)="select($event)">
<div class="card card-block panel panel-default panel-body"> <div class="card card-block panel panel-default panel-body">
@@ -70,12 +68,12 @@ tabDesc.forEach(desc => {
</div> </div>
</section> </section>
`, `,
directives: [SimpleDemo, TAB_DIRECTIVES, CORE_DIRECTIVES] directives: [SimpleDemoComponent, TAB_DIRECTIVES, CORE_DIRECTIVES]
}) })
export class FileUploadSection { export class FileUploadSectionComponent {
private currentHeading:string = 'Simple'; public currentHeading:string = 'Simple';
private select(e:any) { public select(e:any):void {
if (e.heading) { if (e.heading) {
this.currentHeading = e.heading; this.currentHeading = e.heading;
} }

View File

@@ -1,3 +1,4 @@
/*eslint-disable*/
var express = require('express'); var express = require('express');
var multer = require('multer'); var multer = require('multer');
var fs = require('fs'); var fs = require('fs');

View File

@@ -20,7 +20,7 @@
<h3>Select files</h3> <h3>Select files</h3>
<div ng2-file-drop <div ng2FileDrop
[ngClass]="{'nv-file-over': hasBaseDropZoneOver}" [ngClass]="{'nv-file-over': hasBaseDropZoneOver}"
(fileOver)="fileOverBase($event)" (fileOver)="fileOverBase($event)"
[uploader]="uploader" [uploader]="uploader"
@@ -28,7 +28,7 @@
Base drop zone Base drop zone
</div> </div>
<div ng2-file-drop <div ng2FileDrop
[ngClass]="{'another-file-over-class': hasAnotherDropZoneOver}" [ngClass]="{'another-file-over-class': hasAnotherDropZoneOver}"
(fileOver)="fileOverAnother($event)" (fileOver)="fileOverAnother($event)"
[uploader]="uploader" [uploader]="uploader"
@@ -37,10 +37,10 @@
</div> </div>
Multiple Multiple
<input type="file" ng2-file-select [uploader]="uploader" multiple /><br/> <input type="file" ng2FileSelect [uploader]="uploader" multiple /><br/>
Single Single
<input type="file" ng2-file-select [uploader]="uploader" /> <input type="file" ng2FileSelect [uploader]="uploader" />
</div> </div>
<div class="col-md-9" style="margin-bottom: 40px"> <div class="col-md-9" style="margin-bottom: 40px">

View File

@@ -1,5 +1,3 @@
/// <reference path="../../../tsd.d.ts" />
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {CORE_DIRECTIVES, FORM_DIRECTIVES, NgClass, NgStyle} from '@angular/common'; import {CORE_DIRECTIVES, FORM_DIRECTIVES, NgClass, NgStyle} from '@angular/common';
import {FILE_UPLOAD_DIRECTIVES, FileUploader} from '../../../ng2-file-upload'; import {FILE_UPLOAD_DIRECTIVES, FileUploader} from '../../../ng2-file-upload';
@@ -15,16 +13,16 @@ const URL = 'https://evening-anchorage-3159.herokuapp.com/api/';
template: template, template: template,
directives: [FILE_UPLOAD_DIRECTIVES, NgClass, NgStyle, CORE_DIRECTIVES, FORM_DIRECTIVES] directives: [FILE_UPLOAD_DIRECTIVES, NgClass, NgStyle, CORE_DIRECTIVES, FORM_DIRECTIVES]
}) })
export class SimpleDemo { export class SimpleDemoComponent {
private uploader:FileUploader = new FileUploader({url: URL}); public uploader:FileUploader = new FileUploader({url: URL});
private hasBaseDropZoneOver:boolean = false; public hasBaseDropZoneOver:boolean = false;
private hasAnotherDropZoneOver:boolean = false; public hasAnotherDropZoneOver:boolean = false;
private fileOverBase(e:any) { public fileOverBase(e:any):void {
this.hasBaseDropZoneOver = e; this.hasBaseDropZoneOver = e;
} }
private fileOverAnother(e:any) { public fileOverAnother(e:any):void {
this.hasAnotherDropZoneOver = e; this.hasAnotherDropZoneOver = e;
} }
} }

View File

@@ -34,11 +34,5 @@
Loading... Loading...
</app> </app>
<!-- Angular2 files -->
<script src="/build/angular2.js"></script>
<!-- Angular2 file upload script -->
<script src="/build/angular2-file-upload.js"></script>
<!-- App script -->
<script src="/build/angular2-file-upload-demo.js"></script>
</body> </body>
</html> </html>

View File

@@ -1,9 +1,8 @@
/// <reference path="../tsd.d.ts" />
import {bootstrap} from '@angular/platform-browser-dynamic'; import {bootstrap} from '@angular/platform-browser-dynamic';
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {NgClass} from '@angular/common'; 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'); let gettingStarted = require('./getting-started.md');
@@ -36,10 +35,10 @@ let gettingStarted = require('./getting-started.md');
`, `,
directives: [ directives: [
NgClass, NgClass,
FileUploadSection FileUploadSectionComponent
] ]
}) })
export class Demo { export class DemoComponent {
} }
bootstrap(Demo); bootstrap(DemoComponent);

26
es6-object.d.ts vendored
View File

@@ -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;

View File

@@ -1,23 +1,18 @@
var gulp = require('gulp'); 'use strict';
var esLint = require('gulp-eslint');
var tslint = require('gulp-tslint');
var paths = gulp.paths; const gulp = require('gulp');
const tslint = require('gulp-tslint');
const paths = gulp.paths;
gulp.task('eslint', function() { gulp.task('tslint', () =>
return gulp.src(paths.jssrc) gulp
.pipe(esLint({useEslintrc: true})) .src(paths.tssrc)
.pipe(esLint.format()) .pipe(tslint())
.pipe(esLint.failOnError()); .pipe(tslint.report('prose', {
}); emitError: true,
summarizeFailureOutput: true,
reportLimit: 50
}))
);
gulp.task('tslint', function() { gulp.task('lint', ['tslint']);
return gulp.src(paths.tssrc)
.pipe(tslint())
.pipe(tslint.report('verbose', {
emitError: true,
reportLimit: 0
}));
});
gulp.task('lint', ['tslint', 'eslint']);

View File

@@ -1,29 +1,18 @@
var gulp = require('gulp'); 'use strict';
const gulp = require('gulp');
gulp.paths = { gulp.paths = {
tssrc: [ tssrc: [
'**/*.ts', '**/*.ts',
'!**/*.d.ts',
'!node_modules/**/*', '!node_modules/**/*',
'!dist/**/*', '!bundles/**/*',
'!typings/**/*', '!typings/**/*']
'!**/*.{ts,coffee}.js'],
jssrc: [
'*.js',
'gulp-tasks/*.js',
'!ng2-file-upload.js',
'!angular2-file-upload.js',
'!node_modules',
'!**/*.{ts,coffee}.js']
}; };
require('require-dir')('./gulp-tasks'); require('require-dir')('./gulp-tasks');
var clean = require('gulp-clean'); gulp.task('default', () => {
gulp.task('clean', function () {
return gulp.src('dist', {read: false})
.pipe(clean());
});
gulp.task('default', function () {
gulp.start('lint'); gulp.start('lint');
}); });

101
karma.conf.js Normal file
View File

@@ -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);
}

View File

@@ -1,8 +1,14 @@
export * from './components/file-upload/file-select'; export * from './components/file-upload/file-select.directive';
export * from './components/file-upload/file-drop'; export * from './components/file-upload/file-drop.directive';
export * from './components/file-upload/file-uploader'; export * from './components/file-upload/file-uploader.class';
import {FileSelect} from './components/file-upload/file-select'; import {FileSelectDirective} from './components/file-upload/file-select.directive';
import {FileDrop} from './components/file-upload/file-drop'; 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
]
};

View File

@@ -1,13 +1,32 @@
{ {
"name": "ng2-file-upload", "name": "ng2-file-upload",
"version": "1.0.0-beta.1", "version": "1.0.1",
"description": "angular2 file upload directives", "description": "angular2 file upload directives",
"scripts": { "scripts": {
"deploy": "NODE_ENV=production webpack -p --progress --color --optimize-minimize --optimize-dedupe --optimize-occurence-order", "flow.install:typings": "./node_modules/.bin/typings install",
"prepublish": "gulp clean && ./node_modules/.bin/typings install && tsc", "flow.compile": "npm run flow.install:typings && npm run flow.compile:common && npm run flow.compile:system ",
"server": "webpack-dev-server --hot --inline --colors --display-error-details --display-cached", "flow.compile:common": "./node_modules/.bin/tsc",
"start": "npm run server", "flow.compile:system": "./.config/bundle-system.js",
"test": "gulp lint" "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", "main": "ng2-file-upload.js",
"typings": "ng2-file-upload.d.ts", "typings": "ng2-file-upload.d.ts",
@@ -27,8 +46,7 @@
"url": "https://github.com/valor-software/ng2-file-upload/issues" "url": "https://github.com/valor-software/ng2-file-upload/issues"
}, },
"homepage": "https://github.com/valor-software/ng2-file-upload#readme", "homepage": "https://github.com/valor-software/ng2-file-upload#readme",
"dependencies": { "dependencies": {},
},
"peerDependencies": { "peerDependencies": {
"@angular/common": "^2.0.0-rc.1", "@angular/common": "^2.0.0-rc.1",
"@angular/core": "^2.0.0-rc.1" "@angular/core": "^2.0.0-rc.1"
@@ -39,39 +57,59 @@
"@angular/core": "^2.0.0-rc.1", "@angular/core": "^2.0.0-rc.1",
"@angular/platform-browser": "^2.0.0-rc.1", "@angular/platform-browser": "^2.0.0-rc.1",
"@angular/platform-browser-dynamic": "^2.0.0-rc.1", "@angular/platform-browser-dynamic": "^2.0.0-rc.1",
"async": "1.5.2",
"bootstrap": "3.3.6", "bootstrap": "3.3.6",
"clean-webpack-plugin": "0.1.9", "codecov": "1.0.1",
"compression-webpack-plugin": "0.3.1", "compression-webpack-plugin": "0.3.1",
"es6-promise": "^3.1.2", "conventional-changelog-cli": "1.2.0",
"es6-shim": "^0.35.0", "conventional-github-releaser": "1.1.2",
"eslint": "1.10.3", "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", "exports-loader": "0.6.3",
"file-loader": "0.8.5", "file-loader": "0.8.5",
"gh-pages": "0.11.0",
"gulp": "3.9.1", "gulp": "3.9.1",
"gulp-clean": "0.3.2",
"gulp-eslint": "1.1.1",
"gulp-size": "2.1.0", "gulp-size": "2.1.0",
"gulp-tsc": "1.1.5",
"gulp-tslint": "5.0.0", "gulp-tslint": "5.0.0",
"html-loader": "0.4.3", "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", "markdown-loader": "0.1.7",
"marked": "0.3.5", "marked": "0.3.5",
"moment": "2.13.0",
"ng2-bootstrap": "1.0.16", "ng2-bootstrap": "1.0.16",
"pre-commit": "1.1.2", "phantomjs-polyfill": "0.0.2",
"prismjs": "valorkin/prism", "phantomjs-prebuilt": "2.1.7",
"pre-commit": "1.1.3",
"prismjs": "1.4.1",
"prismjs-loader": "0.0.2", "prismjs-loader": "0.0.2",
"raw-loader": "0.5.1", "raw-loader": "0.5.1",
"reflect-metadata": "0.1.2", "reflect-metadata": "0.1.2",
"require-dir": "0.3.0", "require-dir": "0.3.0",
"rxjs": "5.0.0-beta.6", "rxjs": "5.0.0-beta.6",
"source-map-loader": "0.1.5",
"systemjs-builder": "0.15.16",
"ts-loader": "0.8.2", "ts-loader": "0.8.2",
"tslint": "3.9.0", "tslint-config-valorsoft": "1.0.3",
"typescript": "1.8.10", "typescript": "1.8.10",
"typings": "^0.8.1", "typings": "0.8.1",
"webpack": "1.13.0", "webpack": "1.13.0",
"webpack-dev-server": "1.14.1", "webpack-dev-server": "1.14.1",
"zone.js": "^0.6.12" "zone.js": "0.6.12"
}, },
"contributors": [ "contributors": [
{ {

47
test.bundle.js Normal file
View File

@@ -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);

1
tsd.d.ts vendored
View File

@@ -1 +0,0 @@
/// <reference path="es6-object.d.ts"/>

View File

@@ -1,56 +1,4 @@
{ {
"rules": { "extends": "tslint-config-valorsoft",
"class-name": true, "rulesDirectory": "./node_modules/codelyzer"
"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"
]
}
} }

View File

@@ -1,9 +1,12 @@
{ {
"dependencies": { "dependencies": {
"moment": "registry:npm/moment#2.10.5+20160211003958",
"webpack": "registry:npm/webpack#1.12.9+20160219013405" "webpack": "registry:npm/webpack#1.12.9+20160219013405"
}, },
"devDependencies": {}, "devDependencies": {},
"ambientDependencies": { "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"
} }
} }

View File

@@ -1,35 +1,35 @@
var path = require('path'); /* eslint global-require: 0 */
var marked = require('marked'); 'use strict';
var webpack = require('webpack');
var Clean = require('clean-webpack-plugin'); const path = require('path');
var CompressionPlugin = require('compression-webpack-plugin'); 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 hack
marked.Renderer.prototype.code = function (code, lang) { marked.Renderer.prototype.code = function renderCode(code, lang) {
var out = this.options.highlight(code, lang); const out = this.options.highlight(code, lang);
const classMap = this.options.langPrefix + lang;
if (!lang) { if (!lang) {
return '<pre><code>' + out + '\n</code></pre>'; return `<pre><code>${out}\n</code></pre>`;
} }
return `<pre class="${classMap}"><code class="${classMap}">${out}\n</code></pre>\n`;
var classMap = this.options.langPrefix + lang;
return '<pre class="' + classMap + '"><code class="' + classMap + '">' + out + '\n</code></pre>\n';
}; };
/*eslint no-process-env:0, camelcase:0*/ /*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'; const config = {
//var absSrc = path.join(__dirname, src);
var dest = '/build';
var absDest = path.join(__dirname, dest);
var config = {
// isProduction ? 'source-map' : 'evale', // isProduction ? 'source-map' : 'evale',
devtool: 'source-map', devtool,
debug: true, debug: false,
cache: true,
verbose: true, verbose: true,
displayErrorDetails: true, displayErrorDetails: true,
@@ -40,9 +40,9 @@ var config = {
}, },
resolve: { resolve: {
cache: false,
root: __dirname, root: __dirname,
extensions: ['', '.ts', '.js', '.json'], extensions: ['', '.ts', '.js', '.json']
alias: {}
}, },
entry: { entry: {
@@ -55,8 +55,8 @@ var config = {
'@angular/common', '@angular/common',
'@angular/core' '@angular/core'
], ],
'angular2-file-upload': ['ng2-file-upload'], 'angular2-bootstrap': ['ng2-file-upload'],
'angular2-file-upload-demo': 'demo' 'angular2-bootstrap-demo': 'demo'
}, },
output: { output: {
@@ -71,23 +71,20 @@ var config = {
inline: true, inline: true,
colors: true, colors: true,
historyApiFallback: true, historyApiFallback: true,
proxy: { contentBase: dest,
'*/api/*': 'http://localhost:3000/' //publicPath: dest,
}, outputPath: dest,
contentBase: src, watchOptions: {aggregateTimeout: 300, poll: 1000}
publicPath: dest
}, },
markdownLoader: { markdownLoader: {
langPrefix: 'language-', langPrefix: 'language-',
highlight: function (code, lang) { highlight(code, lang) {
var language = !lang || lang === 'html' ? 'markup' : lang; const language = !lang || lang === 'html' ? 'markup' : lang;
if (!global.Prism) { const Prism = global.Prism || reqPrism;
global.Prism = require('prismjs');
}
var Prism = global.Prism;
if (!Prism.languages[language]) { if (!Prism.languages[language]) {
require('prismjs/components/prism-' + language + '.js'); require(`prismjs/components/prism-${language}.js`);
} }
return Prism.highlight(code, Prism.languages[language]); return Prism.highlight(code, Prism.languages[language]);
} }
@@ -96,77 +93,65 @@ var config = {
loaders: [ loaders: [
// support markdown // support markdown
{test: /\.md$/, loader: 'html?minimize=false!markdown'}, {test: /\.md$/, loader: 'html?minimize=false!markdown'},
// Support for *.json files. // Support for *.json files.
{test: /\.json$/, loader: 'json'}, {test: /\.json$/, loader: 'json'},
// Support for CSS as raw text // Support for CSS as raw text
{test: /\.css$/, loader: 'raw'}, {test: /\.css$/, loader: 'raw'},
// support for .html as raw text // support for .html as raw text
{test: /\.html$/, loader: 'raw'}, {test: /\.html$/, loader: 'raw'},
// Support for .ts files. // Support for .ts files.
{ {
test: /\.ts$/, test: /\.ts$/,
loader: 'ts', loader: 'ts',
query: { query: {
ignoreDiagnostics: [ compilerOptions: {
6053, removeComments: true,
// TS2305 -> Module 'ng' has no exported member noEmitHelpers: false
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
]
}, },
exclude: [ exclude: [/\.(spec|e2e)\.ts$/]
/\.min\.js$/,
/\.spec\.ts$/,
/\.e2e\.ts$/,
/web_modules/,
/test/
]
} }
], ],
noParse: [ noParse: [
/rtts_assert\/src\/rtts_assert/, /rtts_assert\/src\/rtts_assert/,
/reflect-metadata/ /reflect-metadata/,
/zone\.js\/dist\/zone-microtask/
] ]
}, },
plugins: [ plugins: [
new Clean(['build']), //new Clean([dest]),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurenceOrderPlugin(true),
new webpack.optimize.CommonsChunkPlugin({ new webpack.optimize.CommonsChunkPlugin({
name: 'angular2', name: 'angular2',
minChunks: Infinity, minChunks: Infinity,
filename: 'angular2.js' filename: 'angular2.js'
}), }),
new webpack.optimize.DedupePlugin({ // static assets
__isProduction: isProduction new CopyWebpackPlugin([{from: 'demo/favicon.ico', to: 'favicon.ico'}]),
}), new CopyWebpackPlugin([{from: 'demo/assets', to: 'assets'}]),
new webpack.optimize.OccurenceOrderPlugin(), // generating html
new webpack.optimize.DedupePlugin() new HtmlWebpackPlugin({template: 'demo/index.html'})
], ],
pushPlugins: function () { pushPlugins() {
if (!isProduction) { if (!isProduction) {
return; return;
} }
const plugins = [
this.plugins.push.apply(this.plugins, [
//production only //production only
new webpack.optimize.UglifyJsPlugin({ new webpack.optimize.UglifyJsPlugin({
beautify: false,
mangle: false,
comments: false,
compress: { compress: {
warnings: false, screw_ie8: true
drop_debugger: false //warnings: false,
}, //drop_debugger: false
output: { }
comments: false //verbose: true,
}, //beautify: false,
beautify: false //quote_style: 3
}), }),
new CompressionPlugin({ new CompressionPlugin({
asset: '{file}.gz', asset: '{file}.gz',
@@ -175,10 +160,19 @@ var config = {
threshold: 10240, threshold: 10240,
minRatio: 0.8 minRatio: 0.8
}) })
]); ];
this
.plugins
.push
.apply(plugins);
} }
}; };
config.pushPlugins(); config.pushPlugins();
module.exports = config; module.exports = config;
function root(partialPath) {
return path.join(__dirname, partialPath);
}