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
# ignore build and dist for now
/build
/bundles
/demo-build
/dist
/coverage
/ts
# ignore incline compiling
/demo/**/*.js
/demo/**/*.d.ts
/demo/**/*.js.map

View File

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

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

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({
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<any> = new EventEmitter();
@Directive({selector: '[ng2FileDrop]'})
export class FileDropDirective {
@Input() public uploader:FileUploader;
@Output() public 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;
}
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 === (<any>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();
}
}*/
}

View File

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

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

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
@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<any> = [FileSelect];

View File

@@ -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<any> = [];
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;
(<any>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<any> {
return this.queue.filter((item:any) => !item.isUploaded);
}
public getReadyItems() {
public getReadyItems():Array<any> {
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';
(<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) {
/*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();
}
}

View File

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

View File

@@ -1,10 +1,8 @@
/// <reference path="../../tsd.d.ts" />
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<any> = [
];
let tabsContent:string = ``;
tabDesc.forEach(desc => {
tabDesc.forEach((desc:any) => {
tabsContent += `
<tab heading="${desc.heading}" (select)="select($event)">
<div class="card card-block panel panel-default panel-body">
@@ -70,12 +68,12 @@ tabDesc.forEach(desc => {
</div>
</section>
`,
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;
}

View File

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

View File

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

View File

@@ -34,11 +34,5 @@
Loading...
</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>
</html>

View File

@@ -1,9 +1,8 @@
/// <reference path="../tsd.d.ts" />
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);

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');
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']);

View File

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

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-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
]
};

View File

@@ -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": [
{

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": {
"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"
}

View File

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

View File

@@ -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 '<pre><code>' + out + '\n</code></pre>';
return `<pre><code>${out}\n</code></pre>`;
}
var classMap = this.options.langPrefix + lang;
return '<pre class="' + classMap + '"><code class="' + classMap + '">' + out + '\n</code></pre>\n';
return `<pre class="${classMap}"><code class="${classMap}">${out}\n</code></pre>\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);
}