Compare commits

..
Author SHA1 Message Date
Matthew McSparranandGitHub f577becb29 Updated docs
The README has been updated to include information on adding extra fields to uploads when uploading multiple files.
2017-12-20 10:39:37 -05:00
89 changed files with 1072 additions and 30500 deletions
+57
View File
@@ -0,0 +1,57 @@
{
"project": {
"name": "ng2-file-upload"
},
"apps": [
{
"root": "demo/src",
"outDir": "demo/dist",
"assets": [
"assets"
],
"index": "index.html",
"main": "main.ts",
"test": "../../scripts/test.ts",
"tsconfig": "tsconfig.json",
"prefix": "",
"mobile": false,
"styles": [
],
"scripts": [
],
"environmentSource": "environments/environment.ts",
"environments": {
"dev": "environments/environment.ts",
"prod": "environments/environment.prod.ts"
}
}
],
"addons": [],
"packages": [],
"e2e": {
"protractor": {
"config": "protractor.conf.js"
}
},
"test": {
"karma": {
"config": "karma.conf.js"
}
},
"defaults": {
"styleExt": "css",
"prefixInterfaces": false,
"inline": {
"style": false,
"template": false
},
"spec": {
"class": false,
"component": true,
"directive": true,
"module": false,
"pipe": true,
"service": true
}
}
}
-60
View File
@@ -1,60 +0,0 @@
{
"root": true,
"ignorePatterns": [
"**/*"
],
"plugins": [
"@nrwl/nx"
],
"overrides": [
{
"files": [
"*.ts",
"*.tsx",
"*.js",
"*.jsx"
],
"rules": {
"@nrwl/nx/enforce-module-boundaries": [
"error",
{
"enforceBuildableLibDependency": true,
"allow": [],
"depConstraints": [
{
"sourceTag": "*",
"onlyDependOnLibsWithTags": [
"*"
]
}
]
}
]
}
},
{
"files": [
"*.ts",
"*.tsx"
],
"extends": [
"plugin:@nrwl/nx/typescript"
],
"parserOptions": { "project": "./tsconfig.*?.json" },
"rules": {
"semi": "off",
"@typescript-eslint/semi": ["error"]
}
},
{
"files": [
"*.js",
"*.jsx"
],
"extends": [
"plugin:@nrwl/nx/javascript"
],
"rules": {}
}
]
}
-5
View File
@@ -1,5 +0,0 @@
{
"projects": {
"default": "ngx-file-upload"
}
}
-121
View File
@@ -1,121 +0,0 @@
name: on-release
on:
push:
tags:
- v*
env:
NX_BRANCH: ${{ github.event.number }}
NX_RUN_GROUP: ${{ github.run_id }}
NX_CLOUD_AUTH_TOKEN: ${{ secrets.NX_CLOUD_AUTH_TOKEN }}
MOZ_HEADLESS: 1
CONVENTIONAL_GITHUB_RELEASER_TOKEN: ${{ secrets.GITHUB_TOKEN }}
jobs:
# one run
one_run:
runs-on: ubuntu-latest
steps:
- name: Cancel Previous Runs
uses: styfle/cancel-workflow-action@0.9.0
with:
access_token: ${{ secrets.GITHUB_TOKEN }}
# install dependencies
install:
runs-on: ubuntu-latest
needs: one_run
steps:
- uses: actions/checkout@v2.3.4
- uses: actions/cache@v2.1.4
id: cache
with:
path: node_modules
key: node_modules-${{ hashFiles('**/package-lock.json') }}
- run: npm ci
if: steps.cache.outputs.cache-hit != 'true'
# build ng2-file-upload
build:
needs: install
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.3.4
- uses: actions/cache@v2.1.4
with:
path: node_modules
key: node_modules-${{ hashFiles('**/package-lock.json') }}
- uses: actions/cache@v2.1.4
with:
path: |
dist
key: dist-${{ github.run_id }}
- run: npx ng build --prod
# update release notes in github
update_release_draft:
needs: install
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.3.4
- uses: actions/cache@v2.1.4
with:
path: node_modules
key: node_modules-${{ hashFiles('**/package-lock.json') }}
- run: npx conventional-github-releaser -p angular
# update gh_pages
gh_pages_deploy:
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v2.3.4
- uses: actions/checkout@v2.3.4
with:
ref: 'gh-pages'
path: 'gh-pages'
- uses: actions/cache@v2.1.4
with:
path: node_modules
key: node_modules-${{ hashFiles('**/package-lock.json') }}
- uses: actions/cache@v2.1.4
with:
path: |
dist
key: dist-${{ github.run_id }}
- run: |
cd gh-pages
git config user.email gh-actions-${GITHUB_ACTOR}@github.com
git config user.name $GITHUB_ACTOR
git add -A
git commit -am "ci: gh-pages update"
continue-on-error: true
- name: push to gh-pages
uses: ad-m/github-push-action@v0.6.0
continue-on-error: true
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: 'gh-pages'
directory: 'gh-pages'
# publish to npm
npm_publish:
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v2.3.4
- uses: actions/cache@v2.1.4
with:
path: node_modules
key: node_modules-${{ hashFiles('**/package-lock.json') }}
- uses: actions/cache@v2.1.4
with:
path: |
dist
key: dist-${{ github.run_id }}
- uses: JS-DevTools/npm-publish@v1
with:
package: "dist/libs/ng2-file-upload/package.json"
token: ${{ secrets.NPM_TOKEN }}
-113
View File
@@ -1,113 +0,0 @@
name: on-pull-request-or-push
on:
pull_request:
push:
branches:
- development
env:
NX_BRANCH: ${{ github.event.number }}
NX_RUN_GROUP: ${{ github.run_id }}
NX_CLOUD_AUTH_TOKEN: ${{ secrets.NX_CLOUD_AUTH_TOKEN }}
MOZ_HEALESS: 1
SAUCE_USERNAME_PR: valorkinpr
FIREBASE_CHANNEL: ${{ fromJSON('["", "live"]')[!github.base_ref] }}
CACHE_NODE_MODULES_PATH: |
~/.npm
node_modules
CACHE_DIST_PATH: |
dist
jobs:
# one run
one_run:
runs-on: ubuntu-latest
steps:
- name: Cancel Previous Runs
uses: styfle/cancel-workflow-action@0.9.0
with:
access_token: ${{ secrets.GITHUB_TOKEN }}
# install dependencies
install:
runs-on: ubuntu-latest
needs: one_run
steps:
- uses: actions/checkout@v2.3.4
- uses: actions/cache@v2.1.4
id: cache
with:
path: ${{ env.CACHE_NODE_MODULES_PATH }}
key: node_modules-${{ hashFiles('**/package-lock.json') }}
- run: npm ci
if: steps.cache.outputs.cache-hit != 'true'
# build ng2-file-upload
build:
needs: install
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.3.4
- uses: actions/cache@v2.1.4
with:
path: ${{ env.CACHE_NODE_MODULES_PATH }}
key: node_modules-${{ hashFiles('**/package-lock.json') }}
- uses: actions/cache@v2.1.4
with:
path: ${{ env.CACHE_DIST_PATH }}
key: dist-${{ github.run_id }}
- run: npx ng build --prod
# run unit tests
unit_tests_with_coverage:
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2
with:
path: ${{ env.CACHE_NODE_MODULES_PATH }}
key: node_modules-${{ hashFiles('**/package-lock.json') }}
- uses: actions/cache@v2
with:
path: ${{ env.CACHE_DIST_PATH }}
key: dist-${{ github.run_id }}
- run: npm run test-coverage
continue-on-error: true
# run linting
linting:
runs-on: ubuntu-latest
needs: install
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2
with:
path: ${{ env.CACHE_NODE_MODULES_PATH }}
key: node_modules-${{ hashFiles('**/package-lock.json') }}
- run: npm run lint
# firebase preview
build_and_preview:
runs-on: ubuntu-latest
needs: build
outputs:
output_url: ${{ steps.firebase_hosting_preview.outputs.details_url }}
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v2
with:
path: ${{ env.CACHE_DIST_PATH }}
key: dist-${{ github.run_id }}
- uses: FirebaseExtended/action-hosting-deploy@v0
continue-on-error: true
id: firebase_hosting_preview
with:
repoToken: '${{ secrets.GITHUB_TOKEN }}'
firebaseServiceAccount: '${{ secrets.FIREBASE_SERVICE_ACCOUNT_NGX_FILE_UPLOAD }}'
projectId: ngx-file-upload
channelId: ${{ env.FIREBASE_CHANNEL }}
expires: 7d
+2 -4
View File
@@ -1,13 +1,11 @@
language: node_js
node_js:
- "10"
services:
- xvfb
- "6"
before_install:
- export CHROME_BIN=chromium-browser
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
script:
- npm run pretest
-74
View File
@@ -1,77 +1,3 @@
# [2.0.0-3](https://github.com/valor-software/ng2-file-upload/compare/v2.0.0-2...v2.0.0-3) (2021-09-07)
### Features
* **demo:** updated up to bootstrap 5 ([#1186](https://github.com/valor-software/ng2-file-upload/issues/1186)) ([02a1b2a](https://github.com/valor-software/ng2-file-upload/commit/02a1b2a53c331e2088ea05d2202be6eb2b1d051f))
# [2.0.0-2](https://github.com/valor-software/ng2-file-upload/compare/v2.0.0-1...v2.0.0-2) (2021-09-03)
# [2.0.0-1](https://github.com/valor-software/ng2-file-upload/compare/v2.0.0-0...v2.0.0-1) (2021-09-03)
### Features
* **version:** added npm versions ([#1183](https://github.com/valor-software/ng2-file-upload/issues/1183)) ([326e3ac](https://github.com/valor-software/ng2-file-upload/commit/326e3ac1a884f000f57b3fb6e30cd32f5ec4622c))
# [2.0.0-0](https://github.com/valor-software/ng2-file-upload/compare/v1.2.0...v2.0.0-0) (2021-09-03)
### Bug Fixes
* **ci:** fix xvfb service issue ([33ac156](https://github.com/valor-software/ng2-file-upload/commit/33ac156208bfcf57851210f037719107e1ca9eb9))
* **typo:** fix grammatical mistake in readme ([#1119](https://github.com/valor-software/ng2-file-upload/issues/1119)) ([8171bc8](https://github.com/valor-software/ng2-file-upload/commit/8171bc831b69692d04b650be19ff82f04ff56662))
### Features
* **package:** relaxed peer dependencies to allow ng v4 ([#713](https://github.com/valor-software/ng2-file-upload/issues/713)) ([7704e0e](https://github.com/valor-software/ng2-file-upload/commit/7704e0e970276ebcd8bfefe34bf153f82108a11e))
# [1.3.0](https://github.com/valor-software/ng2-file-upload/compare/v1.2.0...v1.3.0) (2021-08-31)
### Bug Fixes
* **ci:** fix xvfb service issue ([33ac156](https://github.com/valor-software/ng2-file-upload/commit/33ac156208bfcf57851210f037719107e1ca9eb9))
* **style:** delete extra rule ([b5917b9](https://github.com/valor-software/ng2-file-upload/commit/b5917b9fa77e63c4c1b06598abc817b8033730c3))
* **typo:** fix grammatical mistake in readme ([#1119](https://github.com/valor-software/ng2-file-upload/issues/1119)) ([8171bc8](https://github.com/valor-software/ng2-file-upload/commit/8171bc831b69692d04b650be19ff82f04ff56662))
### Features
* **bump:** added strict mode, doesn't build in dist, should be resolved ([69cd64d](https://github.com/valor-software/ng2-file-upload/commit/69cd64dc287c9bdd1c35af1062e27ce32a47e977))
* **core:** added nx ([de738f7](https://github.com/valor-software/ng2-file-upload/commit/de738f7c63d7f37e07019bc596c02e9f4320f563))
* **package:** relaxed peer dependencies to allow ng v4 ([#713](https://github.com/valor-software/ng2-file-upload/issues/713)) ([7704e0e](https://github.com/valor-software/ng2-file-upload/commit/7704e0e970276ebcd8bfefe34bf153f82108a11e))
* **upgrade:** updated up to angular 11 tests are failed ([ce9dc20](https://github.com/valor-software/ng2-file-upload/commit/ce9dc20056cc6c7cd58e502af05d7d97043c8f3a))
# [1.3.0](https://github.com/valor-software/ng2-file-upload/compare/v1.2.0...v1.3.0) (2021-08-31)
### Bug Fixes
* **ci:** fix xvfb service issue ([33ac156](https://github.com/valor-software/ng2-file-upload/commit/33ac156208bfcf57851210f037719107e1ca9eb9))
* **style:** delete extra rule ([b5917b9](https://github.com/valor-software/ng2-file-upload/commit/b5917b9fa77e63c4c1b06598abc817b8033730c3))
* **typo:** fix grammatical mistake in readme ([#1119](https://github.com/valor-software/ng2-file-upload/issues/1119)) ([8171bc8](https://github.com/valor-software/ng2-file-upload/commit/8171bc831b69692d04b650be19ff82f04ff56662))
### Features
* **bump:** added strict mode, doesn't build in dist, should be resolved ([69cd64d](https://github.com/valor-software/ng2-file-upload/commit/69cd64dc287c9bdd1c35af1062e27ce32a47e977))
* **package:** relaxed peer dependencies to allow ng v4 ([#713](https://github.com/valor-software/ng2-file-upload/issues/713)) ([7704e0e](https://github.com/valor-software/ng2-file-upload/commit/7704e0e970276ebcd8bfefe34bf153f82108a11e))
* **upgrade:** updated up to angular 11 tests are failed ([ce9dc20](https://github.com/valor-software/ng2-file-upload/commit/ce9dc20056cc6c7cd58e502af05d7d97043c8f3a))
<a name="1.3.0"></a>
# [1.3.0](https://github.com/valor-software/ng2-file-upload/compare/v1.2.0...v1.3.0) (2017-11-25)
+60 -3
View File
@@ -1,4 +1,4 @@
# ng2-file-upload [![npm version](https://badge.fury.io/js/ng2-file-upload.svg)](http://badge.fury.io/js/ng2-file-upload) [![npm downloads](https://img.shields.io/npm/dm/ng2-file-upload.svg)](https://npmjs.org/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) [![npm downloads](https://img.shields.io/npm/dm/ng2-file-upload.svg)](https://npmjs.org/ng2-file-upload)[![slack](https://ngx-slack.herokuapp.com/badge.svg)](https://ngx-slack.herokuapp.com)
Easy to use Angular2 directives for files upload ([demo](http://valor-software.github.io/ng2-file-upload/))
[![Angular 2 Style Guide](https://mgechev.github.io/angular2-style-guide/images/badge.svg)](https://github.com/mgechev/angular2-style-guide)
@@ -43,6 +43,63 @@ Easy to use Angular2 directives for files upload ([demo](http://valor-software.g
```public uploader:FileUploader = new FileUploader({url: URL}); ```
## Using ***ng2-file-upload*** with multiple uploads and other parameters
To add extra information (i.e. title, description) when uploading multiple files:
In your template:
```
<tr *ngFor="let item of uploader.queue">
<td><strong>{{ item?.file?.name }}</strong></td>
**<td><input type="text" [(ngModel)]="item.formData['title']" placeholder="Title of File"></td>**
**<td><input type="text" [(ngModel)]="item.formData['description']" placeholder="File Description"></td>**
<td nowrap>{{ item?.file?.size/1024/1024 | number:'.2' }} MB</td>
<td >
<div class="progress" style="margin-bottom: 0;">
<div class="progress-bar" role="progressbar" [ngStyle]="{ 'width': item.progress + '%' }"></div>
</div>
</td>
<td class="text-center">
<span *ngIf="item.isSuccess"><i class="glyphicon glyphicon-ok"></i></span>
<span *ngIf="item.isCancel"><i class="glyphicon glyphicon-ban-circle"></i></span>
<span *ngIf="item.isError"><i class="glyphicon glyphicon-remove"></i></span>
</td>
<td nowrap>
<button type="button" class="btn btn-success btn-xs"
(click)="item.upload()" [disabled]="item.isReady || item.isUploading || item.isSuccess">
<span class="glyphicon glyphicon-upload"></span> Upload
</button>
<button type="button" class="btn btn-warning btn-xs"
(click)="item.cancel()" [disabled]="!item.isUploading">
<span class="glyphicon glyphicon-ban-circle"></span> Cancel
</button>
<button type="button" class="btn btn-danger btn-xs"
(click)="item.remove()">
<span class="glyphicon glyphicon-trash"></span> Remove
</button>
</td>
</tr>
```
You can add inputs outside of a form, and use ```[(ngModel)]``` to add keys to the ```item``` object.
```
**<td><input type="text" [(ngModel)]="item.formData['title']" placeholder="Title of File"></td>**
**<td><input type="text" [(ngModel)]="item.formData['description']" placeholder="File Description"></td>**
```
Inside your upload component, add the following:
```
this.uploader.onBuildItemForm = (item, form) => {
form.append('title', item.formData.title);
form.append('description', item.formData.description);
console.log(item);
};
```
If you are using `Node.js` with `multer`, the extra information will not show up in the `req.files` object. You will have to pull the data from the `req.body` object.
## API for `ng2FileSelect`
### Properties
@@ -63,7 +120,7 @@ Easy to use Angular2 directives for files upload ([demo](http://valor-software.g
1. `url` - URL of File Uploader's route
2. `authToken` - Auth token that will be applied as 'Authorization' header during file send.
3. `disableMultipart` - If 'true', disable using a multipart form for file upload and instead stream the file. Some APIs (e.g. Amazon S3) may expect the file to be streamed rather than sent via a form. Defaults to false.
4. `itemAlias` - item alias (form name redefinition)
4. `itemAlias` - item alias (form name redefenition)
5. `formatDataFunction` - Function to modify the request body. 'DisableMultipart' must be 'true' for this function to be called.
6. `formatDataFunctionIsAsync` - Informs if the function sent in 'formatDataFunction' is asynchronous. Defaults to false.
7. `parametersBeforeFiles` - States if additional parameters should be appended before or after the file. Defaults to false.
@@ -77,7 +134,7 @@ Easy to use Angular2 directives for files upload ([demo](http://valor-software.g
# Troubleshooting
Please follow these guidelines when reporting bugs and feature requests:
Please follow this guidelines when reporting bugs and feature requests:
1. Use [GitHub Issues](https://github.com/valor-software/ng2-file-upload/issues) board to report bugs and feature requests (not our email address)
2. Please **always** write steps to reproduce the error. That way we can focus on fixing the bug, not scratching our heads trying to reproduce it.
-139
View File
@@ -1,139 +0,0 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"defaultProject": "ng2-file-upload-demo",
"projects": {
"ng2-file-upload": {
"root": "libs/ng2-file-upload",
"sourceRoot": "libs/ng2-file-upload/",
"projectType": "library",
"architect": {
"build": {
"builder": "@nrwl/angular:package",
"outputs": [
"dist/libs/ng2-file-upload"
],
"options": {
"tsConfig": "libs/ng2-file-upload/tsconfig.lib.json",
"project": "libs/ng2-file-upload/ng-package.json"
},
"configurations": {
"production": {
"tsConfig": "libs/ng2-file-upload/tsconfig.lib.prod.json"
}
}
},
"lint": {
"builder": "@nrwl/linter:eslint",
"options": {
"lintFilePatterns": [
"libs/ng2-file-upload/**/*.ts"
]
}
},
"test": {
"builder": "@nrwl/jest:jest",
"outputs": [
"coverage/libs/ng2-file-upload"
],
"options": {
"jestConfig": "libs/ng2-file-upload/jest.config.js",
"passWithNoTests": true
}
},
"version": {
"builder": "@nrwl/workspace:run-commands",
"outputs": [
],
"options": {
"commands": [
"ts-node ./scripts/set-version.ts",
"conventional-changelog -i CHANGELOG.md -s -p angular",
"git add -A",
"git commit -am \"chore(changelog): update [skip ci] \""
],
"parallel": false
},
"configurations": {
"production": {}
}
}
}
},
"ng2-file-upload-demo": {
"root": "apps/demo",
"sourceRoot": "apps/demo/src",
"projectType": "application",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/apps/demo",
"index": "apps/demo/src/index.html",
"main": "apps/demo/src/main.ts",
"tsConfig": "apps/demo/tsconfig.json",
"assets": [
"apps/demo/src/assets"
],
"styles": [],
"scripts": []
},
"dependsOn": [
{
"target": "build",
"projects": "dependencies"
}
],
"configurations": {
"production": {
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"fileReplacements": [
{
"replace": "apps/demo/src/environments/environment.ts",
"with": "apps/demo/src/environments/environment.prod.ts"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "ng2-file-upload-demo:build"
},
"configurations": {
"production": {
"browserTarget": "ng2-file-upload-demo:build:production"
}
}
},
"lint": {
"builder": "@nrwl/linter:eslint",
"options": {
"lintFilePatterns": [
"apps/demo/**/*.ts"
]
}
}
}
}
},
"schematics": {
"@schematics/angular:component": {
"prefix": "",
"styleext": "css"
},
"@schematics/angular:directive": {
"prefix": ""
}
}
}
-21
View File
@@ -1,21 +0,0 @@
{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts"],
"extends": [
"plugin:@nrwl/nx/angular",
"plugin:@angular-eslint/template/process-inline-templates"
],
"parserOptions": { "project": ["src/accordion/tsconfig.*?.json"] },
"rules": {
}
},
{
"files": ["*.html"],
"extends": ["plugin:@nrwl/nx/angular-template"],
"rules": {}
}
]
}
-12
View File
@@ -1,12 +0,0 @@
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
# You can see what browsers were selected by your queries by running:
# npx browserslist
> 0.5%
last 2 versions
Firefox ESR
not dead
not IE 9-11 # For IE 9-11 support, remove 'not'.
-4
View File
@@ -1,4 +0,0 @@
{
"port": 4200,
"server": { "baseDir": "./dist/apps/demo" }
}
-55
View File
@@ -1,55 +0,0 @@
import { Component } from '@angular/core';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const gettingStarted = require('html-loader!markdown-loader!../getting-started.md');
@Component({
selector: 'app',
template: `
<main class="bd-pageheader">
<div class="container">
<div class="row">
<h1>ng2-file-upload</h1>
<p>The Angular2 File Upload directives</p>
<p>
<a class="btn btn-light w-auto" href="https://github.com/valor-software/ng2-file-upload">View on GitHub</a>
</p>
</div>
<div class="row" style="padding-top: 15px">
<div class="d-flex flex-wrap">
<a href="https://npmjs.org/ng2-file-upload" class="me-2 d-flex mb-2">
<img src="https://img.shields.io/npm/v/ng2-file-upload/latest.svg" alt="npm latest version" >
</a>
<a href="https://npmjs.org/ng2-file-upload" class="me-2 d-flex mb-2">
<img src="https://img.shields.io/npm/v/ng2-file-upload/next.svg" alt="npm next version" >
</a>
<iframe src="https://ghbtns.com/github-btn.html?user=valor-software&repo=ng2-file-upload&type=star&count=true" frameborder="0" scrolling="0" width="100px" height="20px" class="me-2 mb-2"></iframe>
<iframe src="https://ghbtns.com/github-btn.html?user=valor-software&repo=ng2-file-upload&type=fork&count=true" frameborder="0" scrolling="0" width="100px" height="20px" class="mb-2"></iframe>
</div>
</div>
</div>
</main>
<div class="container">
<section id="getting-started" [innerHtml]="gettingStarted"></section>
<file-upload-section class="col-md-12"></file-upload-section>
</div>
<footer class="footer">
<div class="container">
<p class="text-muted text-center"><a href="https://github.com/valor-software/ng2-file-upload">ng2-file-upload</a> is maintained by <a href="https://github.com/valor-software">valor-software</a>.</p>
</div>
</footer>
`
})
export class AppComponent {
public gettingStarted:string = gettingStarted;
public ngAfterContentInit(): any {
setTimeout(()=>{
if (typeof PR !== 'undefined') {
// google code-prettify
PR.prettyPrint();
}
}, 150);
}
}
@@ -1,43 +0,0 @@
<section [attr.id]="name.toLowerCase()">
<div class="row">
<tabset>
<tab *ngFor="let desc of tabs" heading="{{desc.heading}}" (select)="select($event)">
<div class="card card-block p-3 border-top-0">
<simple-demo></simple-demo>
<br>
<div class="container p-0">
<div class="row" style="margin: 0px;">
<tabset class="p-0">
<tab heading="Markup">
<div class="card card-block p-3 border-top-0">
<pre class="prettyprint linenums lang-html">{{desc.html}}</pre>
</div>
</tab>
<tab heading="TypeScript">
<div class="card card-block p-3 border-top-0">
<pre class="prettyprint linenums lang-js">{{desc.ts}}</pre>
<pre class="language-typescript"><code class="language-typescript" ng-non-bindable [innerHTML]="desc.ts"></code></pre>
</div>
</tab>
<tab heading="Backend Demo">
<div class="card card-block p-3 border-top-0">
<pre class="prettyprint linenums lang-js">{{desc.js}}</pre>
</div>
</tab>
</tabset>
</div>
</div>
</div>
</tab>
</tabset>
</div>
<div class="container">
<div class="row mt-3">
<h2>API</h2>
<div class="card card-block p-3" [innerHTML]="doc"></div>
</div>
</div>
</section>
@@ -1,32 +0,0 @@
import { Component } from '@angular/core';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const doc = require('html-loader!markdown-loader!../../doc.md');
const tabDesc: Array<any> = [
{
heading: 'Simple',
// eslint-disable-next-line @typescript-eslint/no-var-requires
ts: require('!!raw-loader!./file-upload/simple-demo.ts').default,
// eslint-disable-next-line @typescript-eslint/no-var-requires
html: require('!!raw-loader!./file-upload/simple-demo.html').default,
// eslint-disable-next-line @typescript-eslint/no-var-requires
js: require('!!raw-loader!./file-upload/file-catcher.js').default
}
];
@Component({
selector: 'file-upload-section',
templateUrl: './file-upload-section.html'
})
export class FileUploadSectionComponent {
name = 'File Upload';
currentHeading = 'Simple';
doc = doc;
tabs: any = tabDesc;
select(e: any): void {
if (e.heading) {
this.currentHeading = e.heading;
}
}
}
-17
View File
@@ -1,17 +0,0 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"types": ["node"],
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
},
"angularCompilerOptions": {
"strictInjectionParameters": true,
"strictTemplates": true,
"fullTemplateTypeCheck": true
},
"files": ["src/main.ts"]
}
-7
View File
@@ -1,7 +0,0 @@
{
"extends": "./tsconfig.json",
"include": ["**/*.ts"],
"compilerOptions": {
"types": ["jest", "node"]
}
}
-20
View File
@@ -1,20 +0,0 @@
{
"extends": "../../tsconfig.base.json",
"files": [
"./src/main.ts",
"../../scripts/polyfills.ts"
],
"include": ["./src/typings.d.ts"],
"references": [
{
"path": "./tsconfig.app.json"
},
{
"path": "./tsconfig.spec.json"
},
{
"path": "./tsconfig.editor.json"
}
],
"exclude": ["**/*.spec.ts"]
}
-69
View File
@@ -1,69 +0,0 @@
/**
* This file decorates the Angular CLI with the Nx CLI to enable features such as computation caching
* and faster execution of tasks.
*
* It does this by:
*
* - Patching the Angular CLI to warn you in case you accidentally use the undecorated ng command.
* - Symlinking the ng to nx command, so all commands run through the Nx CLI
* - Updating the package.json postinstall script to give you control over this script
*
* The Nx CLI decorates the Angular CLI, so the Nx CLI is fully compatible with it.
* Every command you run should work the same when using the Nx CLI, except faster.
*
* Because of symlinking you can still type `ng build/test/lint` in the terminal. The ng command, in this case,
* will point to nx, which will perform optimizations before invoking ng. So the Angular CLI is always invoked.
* The Nx CLI simply does some optimizations before invoking the Angular CLI.
*
* To opt out of this patch:
* - Replace occurrences of nx with ng in your package.json
* - Remove the script from your postinstall script in your package.json
* - Delete and reinstall your node_modules
*/
const fs = require('fs');
const os = require('os');
const cp = require('child_process');
const isWindows = os.platform() === 'win32';
let output;
try {
output = require('@nrwl/workspace').output;
} catch (e) {
console.warn('Angular CLI could not be decorated to enable computation caching. Please ensure @nrwl/workspace is installed.');
process.exit(0);
}
/**
* Symlink of ng to nx, so you can keep using `ng build/test/lint` and still
* invoke the Nx CLI and get the benefits of computation caching.
*/
function symlinkNgCLItoNxCLI() {
try {
const ngPath = './node_modules/.bin/ng';
const nxPath = './node_modules/.bin/nx';
if (isWindows) {
/**
* This is the most reliable way to create symlink-like behavior on Windows.
* Such that it works in all shells and works with npx.
*/
['', '.cmd', '.ps1'].forEach(ext => {
if (fs.existsSync(nxPath + ext)) fs.writeFileSync(ngPath + ext, fs.readFileSync(nxPath + ext));
});
} else {
// If unix-based, symlink
cp.execSync(`ln -sf ./nx ${ngPath}`);
}
}
catch(e) {
output.error({ title: 'Unable to create a symlink from the Angular CLI to the Nx CLI:' + e.message });
throw e;
}
}
try {
symlinkNgCLItoNxCLI();
require('@nrwl/cli/lib/decorate-cli').decorateCli();
output.log({ title: 'Angular CLI has been decorated to enable computation caching.' });
} catch(e) {
output.error({ title: 'Decoration of the Angular CLI did not complete successfully' });
}
+4
View File
@@ -0,0 +1,4 @@
{
"port": 4200,
"server": { "baseDir": "./demo/dist" }
}
+43
View File
@@ -0,0 +1,43 @@
import { Component } from '@angular/core';
let gettingStarted = require('html-loader!markdown-loader!../getting-started.md');
@Component({
selector: 'app',
template: `
<main class="bd-pageheader">
<div class="container">
<h1>ng2-file-upload</h1>
<p>The Angular2 File Upload directives</p>
<a class="btn btn-primary" href="https://github.com/valor-software/ng2-file-upload">View on GitHub</a>
<div class="row">
<div class="col-lg-1"><iframe src="https://ghbtns.com/github-btn.html?user=valor-software&repo=ng2-file-upload&type=star&count=true" frameborder="0" scrolling="0" width="170px" height="20px"></iframe></div>
<div class="col-lg-1"><iframe src="https://ghbtns.com/github-btn.html?user=valor-software&repo=ng2-file-upload&type=fork&count=true" frameborder="0" scrolling="0" width="170px" height="20px"></iframe></div>
</div>
</div>
</main>
<div class="container">
<section id="getting-started" [innerHtml]="gettingStarted"></section>
<file-upload-section class="col-md-12"></file-upload-section>
</div>
<footer class="footer">
<div class="container">
<p class="text-muted text-center"><a href="https://github.com/valor-software/ng2-file-upload">ng2-file-upload</a> is maintained by <a href="https://github.com/valor-software">valor-software</a>.</p>
</div>
</footer>
`
})
export class AppComponent {
public gettingStarted:string = gettingStarted;
public ngAfterContentInit(): any {
setTimeout(()=>{
if (typeof PR !== 'undefined') {
// google code-prettify
PR.prettyPrint();
}
}, 150);
}
}
@@ -0,0 +1,40 @@
<section [attr.id]="name.toLowerCase()">
<div class="row">
<tabset>
<tab *ngFor="let desc of tabs" heading="{{desc.heading}}" (select)="select($event)">
<div class="card card-block panel panel-default panel-body">
<simple-demo></simple-demo>
<br>
<div class="row" style="margin: 0px;">
<tabset>
<tab heading="Markup">
<div class="card card-block panel panel-default panel-body">
<pre class="prettyprint linenums lang-html">{{desc.html}}</pre>
</div>
</tab>
<tab heading="TypeScript">
<div class="card card-block panel panel-default panel-body">
<pre class="prettyprint linenums lang-js">{{desc.ts}}</pre>
<pre class="language-typescript"><code class="language-typescript" ng-non-bindable [innerHTML]="desc.ts"></code></pre>
</div>
</tab>
<tab heading="Backend Demo">
<div class="card card-block panel panel-default panel-body">
<pre class="prettyprint linenums lang-js">{{desc.js}}</pre>
</div>
</tab>
</tabset>
</div>
</div>
</tab>
</tabset>
</div>
<div class="row">
<h2>API</h2>
<div class="card card-block panel panel-default panel-body" [innerHTML]="doc"></div>
</div>
</section>
@@ -0,0 +1,29 @@
import { Component } from '@angular/core';
let doc = require('html-loader!markdown-loader!../../doc.md');
let tabDesc:Array<any> = [
{
heading: 'Simple',
ts: require('!!raw-loader?lang=typescript!./file-upload/simple-demo.ts'),
html: require('!!raw-loader?lang=markup!./file-upload/simple-demo.html'),
js: require('!!raw-loader?lang=javascript!./file-upload/file-catcher.js')
}
];
@Component({
selector: 'file-upload-section',
templateUrl: './file-upload-section.html'
})
export class FileUploadSectionComponent {
public name:string = 'File Upload';
public currentHeading:string = 'Simple';
public doc:string = doc;
public tabs:any = tabDesc;
public select(e:any):void {
if (e.heading) {
this.currentHeading = e.heading;
}
}
}
@@ -2,12 +2,13 @@
.my-drop-zone { border: dotted 3px lightgray; }
.nv-file-over { border: dotted 3px red; } /* Default class applied to drop zones on over */
.another-file-over-class { border: dotted 3px green; }
html, body { height: 100%; }
</style>
<div class="container p-0">
<div class="container">
<div class="navbar">
<div class="navbar navbar-default">
<div class="navbar-header">
<a class="navbar-brand" href>Angular2 File Upload</a>
</div>
@@ -23,7 +24,7 @@
[ngClass]="{'nv-file-over': hasBaseDropZoneOver}"
(fileOver)="fileOverBase($event)"
[uploader]="uploader"
class="well my-drop-zone p-2 mb-3">
class="well my-drop-zone">
Base drop zone
</div>
@@ -31,21 +32,21 @@
[ngClass]="{'another-file-over-class': hasAnotherDropZoneOver}"
(fileOver)="fileOverAnother($event)"
[uploader]="uploader"
class="well my-drop-zone p-2 mb-3">
class="well my-drop-zone">
Another drop zone
</div>
Multiple<br>
<input class="mt-2 mb-3" type="file" ng2FileSelect [uploader]="uploader" multiple /><br/>
Multiple
<input type="file" ng2FileSelect [uploader]="uploader" multiple /><br/>
Single<br>
<input class="mt-2 mb-3" type="file" ng2FileSelect [uploader]="uploader" />
Single
<input type="file" ng2FileSelect [uploader]="uploader" />
</div>
<div class="col-md-9" style="margin-bottom: 40px">
<h3>Upload queue</h3>
<p>Queue length: {{ uploader?.queue?.length ? uploader?.queue?.length : 'Empty'}}</p>
<p>Queue length: {{ uploader?.queue?.length }}</p>
<table class="table">
<thead>
@@ -57,21 +58,21 @@
<th>Actions</th>
</tr>
</thead>
<tbody *ngIf="uploader?.queue?.length">
<tbody>
<tr *ngFor="let item of uploader.queue">
<td data-label="Name"><strong>{{ item?.file?.name }}</strong></td>
<td data-label="Size" *ngIf="uploader.options.isHTML5" nowrap>{{ item?.file?.size/1024/1024 | number:'.2' }} MB</td>
<td data-label="Progress" *ngIf="uploader.options.isHTML5">
<td><strong>{{ item?.file?.name }}</strong></td>
<td *ngIf="uploader.options.isHTML5" nowrap>{{ item?.file?.size/1024/1024 | number:'.2' }} MB</td>
<td *ngIf="uploader.options.isHTML5">
<div class="progress" style="margin-bottom: 0;">
<div class="progress-bar" role="progressbar" [ngStyle]="{ 'width': item.progress + '%' }"></div>
</div>
</td>
<td data-label="Status" class="text-center">
<td class="text-center">
<span *ngIf="item.isSuccess"><i class="glyphicon glyphicon-ok"></i></span>
<span *ngIf="item.isCancel"><i class="glyphicon glyphicon-ban-circle"></i></span>
<span *ngIf="item.isError"><i class="glyphicon glyphicon-remove"></i></span>
</td>
<td data-label="Actions" nowrap>
<td nowrap>
<button type="button" class="btn btn-success btn-xs"
(click)="item.upload()" [disabled]="item.isReady || item.isUploading || item.isSuccess">
<span class="glyphicon glyphicon-upload"></span> Upload
@@ -92,15 +93,15 @@
<div>
<div>
Queue progress:
<div class="progress mt-2 mb-3" style="">
<div class="progress" style="">
<div class="progress-bar" role="progressbar" [ngStyle]="{ 'width': uploader.progress + '%' }"></div>
</div>
</div>
<button type="button" class="btn btn-success btn-s me-2"
<button type="button" class="btn btn-success btn-s"
(click)="uploader.uploadAll()" [disabled]="!uploader.getNotUploadedItems().length">
<span class="glyphicon glyphicon-upload"></span> Upload all
</button>
<button type="button" class="btn btn-warning btn-s me-2"
<button type="button" class="btn btn-warning btn-s"
(click)="uploader.cancelAll()" [disabled]="!uploader.isUploading">
<span class="glyphicon glyphicon-ban-circle"></span> Cancel all
</button>
@@ -118,9 +119,9 @@
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header">Response</div>
<div class="card-body">
<div class="panel panel-default">
<div class="panel-heading">Response</div>
<div class="panel-body">
{{ response }}
</div>
</div>
@@ -10,18 +10,18 @@ const URL = 'https://evening-anchorage-3159.herokuapp.com/api/';
})
export class SimpleDemoComponent {
uploader: FileUploader;
hasBaseDropZoneOver: boolean;
hasAnotherDropZoneOver: boolean;
response: string;
uploader:FileUploader;
hasBaseDropZoneOver:boolean;
hasAnotherDropZoneOver:boolean;
response:string;
constructor() {
constructor (){
this.uploader = new FileUploader({
url: URL,
disableMultipart: true, // 'DisableMultipart' must be 'true' for formatDataFunction to be called.
formatDataFunctionIsAsync: true,
formatDataFunction: async item => {
return new Promise((resolve, reject) => {
formatDataFunction: async (item) => {
return new Promise( (resolve, reject) => {
resolve({
name: item._file.name,
length: item._file.size,
@@ -37,14 +37,14 @@ export class SimpleDemoComponent {
this.response = '';
this.uploader.response.subscribe(res => this.response = res );
this.uploader.response.subscribe( res => this.response = res );
}
fileOverBase(e: any): void {
public fileOverBase(e:any):void {
this.hasBaseDropZoneOver = e;
}
fileOverAnother(e: any): void {
public fileOverAnother(e:any):void {
this.hasAnotherDropZoneOver = e;
}
}
@@ -14,15 +14,6 @@
font-size: 36px;
}
td {
vertical-align: middle;
}
a, .nav-tabs a.nav-link {
text-decoration: none;
color: #6f5499;
}
.btn-group-lg > .btn, .btn-lg {
font-size: 18px;
}
@@ -31,6 +22,10 @@ section {
padding-top: 30px;
}
.bd-pageheader {
margin-top: 51px;
}
.page-header {
padding-bottom: 9px;
margin: 40px 0 20px;
@@ -42,24 +37,43 @@ section {
}
.navbar {
padding: 15px;
background-color: #f8f8f8;
border-color: #e7e7e7;
padding: 0;
}
.navbar-nav .nav-item {
margin-left: 0 !important;
}
.nav > li > a {
position: relative;
display: block;
padding: 10px 15px;
}
.nav .navbar-brand {
float: left;
height: 50px;
padding: 15px 15px;
font-size: 18px;
line-height: 20px;
margin-right: 0 !important;
}
.navbar-brand {
color: #777;
float: left;
height: 50px;
padding: 15px 15px;
font-size: 18px;
line-height: 20px;
}
.navbar-nav > li > a:focus, .navbar-default .navbar-nav > li > a:hover {
.navbar-toggler {
margin-top: 8px;
margin-right: 15px;
}
.navbar-default .navbar-nav > li > a:focus, .navbar-default .navbar-nav > li > a:hover {
color: #333;
background-color: transparent;
}
@@ -99,8 +113,14 @@ section {
margin: 10px 0;
}
.card {
border-radius: 0 0 .25rem .25rem;
.scrollable-menu .nav-link {
color: #337ab7;
font-size: 14px;
}
.scrollable-menu .nav-link:hover {
color: #23527c;
background-color: #eee;
}
@media (min-width: 992px) {
@@ -147,53 +167,6 @@ section {
padding: 0;
margin: 0;
}
table {
border: 0;
}
table caption {
font-size: 1.3em;
}
table thead {
border: none;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
table tr {
border-bottom: 3px solid #ddd;
display: block;
margin-bottom: .625em;
}
table td {
border-bottom: 1px solid #ddd;
font-size: .8em;
display: flex;
justify-content: space-between;
align-items: center;
}
table td::before {
content: attr(data-label);
font-weight: bold;
text-transform: uppercase;
}
table td:last-child {
border-bottom: 0;
}
td[data-label="Progress"] .progress {
width: 75%;
}
}
@media (max-width: 400px) {
@@ -212,6 +185,13 @@ section {
* iOS Resolution Quick Reference: http://www.iosres.com/
*/
.scrollable-menu {
height: 90vh !important;
width: 100vw;
overflow-x: hidden;
padding: 0 0 20px;
}
/**
* iPad with portrait orientation.
*/
@@ -240,22 +220,29 @@ section {
}
}
.navbar-default .navbar-toggle .icon-bar {
background-color: #888;
}
.navbar-toggle:focus {
outline: 0
}
.navbar-toggle .icon-bar {
display: block;
width: 22px;
height: 2px;
border-radius: 1px
}
.navbar-toggle .icon-bar + .icon-bar {
margin-top: 4px
}
pre {
white-space: pre-wrap; /* CSS 3 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -pre-wrap; /* Opera 4-6 */
white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
line-height: 1.42857143;
color: #333;
background-color: #f5f5f5;
border: 1px solid #ccc;
border-radius: 4px;
padding: 15px;
}
pre.prettyprint {
margin-bottom: 0;
}

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 106 KiB

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

@@ -12,7 +12,7 @@
<link rel="author" href="https://github.com/valor-software/ng2-file-upload/graphs/contributors">
<!--link to bootstrap.css-->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="assets/css/style.css">
<link rel="stylesheet" href="assets/css/prettify-angulario.css">
<style media="screen">
+1 -1
View File
@@ -1,4 +1,4 @@
import '../../../scripts/polyfills.ts';
import './polyfills.ts';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
+21
View File
@@ -0,0 +1,21 @@
// This file includes polyfills needed by Angular 2 and is loaded before
// the app. You can add your own extra polyfills to this file.
import 'ts-helpers';
import 'core-js/es6/symbol';
import 'core-js/es6/object';
import 'core-js/es6/function';
import 'core-js/es6/parse-int';
import 'core-js/es6/parse-float';
import 'core-js/es6/number';
import 'core-js/es6/math';
import 'core-js/es6/string';
import 'core-js/es6/date';
import 'core-js/es6/array';
import 'core-js/es6/regexp';
import 'core-js/es6/map';
import 'core-js/es6/set';
import 'core-js/es6/reflect';
import 'core-js/es7/reflect';
import 'zone.js/dist/zone';
import 'classlist-polyfill';
+22
View File
@@ -0,0 +1,22 @@
{
"compilerOptions": {
"declaration": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"noEmitHelpers": false,
"lib": ["es6", "dom"],
"types": [
"jasmine",
"webpack"
],
"mapRoot": "./",
"module": "es6",
"moduleResolution": "node",
"outDir": "../temp/out-tsc",
"sourceMap": true,
"target": "es5",
"typeRoots": [
"../node_modules/@types"
]
}
}
+16
View File
@@ -0,0 +1,16 @@
// Typings reference file, you can add your own global typings here
// https://www.typescriptlang.org/docs/handbook/writing-declaration-files.html
// tslint:disable
declare const System: any;
declare const ENV:string;
// google code-prettify
declare const PR:any;
// declare const require:any;
// declare const global:any;
declare module jasmine {
interface Matchers {
toHaveCssClass(expected: any): boolean;
}
}
-16
View File
@@ -1,16 +0,0 @@
{
"hosting": {
"public": "./dist/apps/demo/",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "index.html"
}
]
}
}
-5
View File
@@ -1,5 +0,0 @@
module.exports = {
projects: [
'<rootDir>/libs/ng2-file-upload'
]
};
-7
View File
@@ -1,7 +0,0 @@
const nxPreset = require('@nrwl/jest/preset');
module.exports = {
...nxPreset,
...{
coverageReporters: ['text-summary', 'json', 'lcov']
}
}
+83
View File
@@ -0,0 +1,83 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/0.13/config/configuration-file.html
const customLaunchers = require('./scripts/sauce-browsers').customLaunchers;
module.exports = function (config) {
const configuration = {
basePath: '',
frameworks: ['jasmine', '@angular/cli'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-coverage-istanbul-reporter'),
require('@angular/cli/plugins/karma')
],
files: [
{pattern: './scripts/test.ts', watched: false}
],
preprocessors: {
'./scripts/test.ts': ['@angular/cli']
},
coverageIstanbulReporter: {
reports: [ 'html', 'lcovonly' ],
fixWebpackSourcePaths: false
},
angularCli: {
config: './angular-cli.json',
environment: 'dev'
},
reporters: config.angularCli && config.angularCli.codeCoverage
? ['dots', 'coverage-istanbul']
: ['dots'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
customLaunchers: {
Chrome_travis_ci: {
base: 'Chrome',
flags: ['--no-sandbox']
}
},
mime: { 'text/x-typescript': ['ts','tsx'] },
client: { captureConsole: true }
};
if (process.env.TRAVIS) {
configuration.browsers = ['Chrome_travis_ci'];
}
if (process.env.SAUCE) {
if (!process.env.SAUCE_USERNAME || !process.env.SAUCE_ACCESS_KEY) {
console.log('Make sure the SAUCE_USERNAME and SAUCE_ACCESS_KEY environment variables are set.');
process.exit(1);
}
configuration.plugins.push(require('karma-sauce-launcher'));
configuration.reporters.push('saucelabs');
configuration.sauceLabs = {
verbose: true,
testName: 'ng2-bootstrap unit tests',
recordScreenshots: false,
username: process.env.SAUCE_USERNAME,
accessKey: process.env.SAUCE_ACCESS_KEY,
connectOptions: {
port: 5757,
logfile: 'sauce_connect.log'
},
public: 'public'
};
configuration.captureTimeout = 0;
configuration.customLaunchers = customLaunchers();
configuration.browsers = Object.keys(configuration.customLaunchers);
configuration.concurrency = 3;
configuration.browserDisconnectTolerance = 2;
configuration.browserNoActivityTimeout = 20000;
configuration.browserDisconnectTimeout = 5000;
}
config.set(configuration);
};
-21
View File
@@ -1,21 +0,0 @@
{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts"],
"extends": [
"plugin:@nrwl/nx/angular",
"plugin:@angular-eslint/template/process-inline-templates"
],
"parserOptions": { "project": ["src/accordion/tsconfig.*?.json"] },
"rules": {
}
},
{
"files": ["*.html"],
"extends": ["plugin:@nrwl/nx/angular-template"],
"rules": {}
}
]
}
-89
View File
@@ -1,89 +0,0 @@
# ng2-file-upload [![npm version](https://badge.fury.io/js/ng2-file-upload.svg)](http://badge.fury.io/js/ng2-file-upload) [![npm downloads](https://img.shields.io/npm/dm/ng2-file-upload.svg)](https://npmjs.org/ng2-file-upload)
Easy to use Angular2 directives for files upload ([demo](http://valor-software.github.io/ng2-file-upload/))
[![Angular 2 Style Guide](https://mgechev.github.io/angular2-style-guide/images/badge.svg)](https://github.com/mgechev/angular2-style-guide)
[![Build Status](https://travis-ci.org/valor-software/ng2-file-upload.svg?branch=development)](https://travis-ci.org/valor-software/ng2-file-upload)
[![Dependency Status](https://david-dm.org/valor-software/ng2-file-upload.svg)](https://david-dm.org/valor-software/ng2-file-upload)
## Quick start
1. A recommended way to install ***ng2-file-upload*** is through [npm](https://www.npmjs.com/search?q=ng2-file-upload) package manager using the following command:
`npm i ng2-file-upload --save`
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
`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).
## Using ***ng2-file-upload*** in a project
1. Install as shown in the above section.
2. Import `FileUploadModule` into the module that declares the component using ***ng2-file-upload***:
```import { FileUploadModule } from 'ng2-file-upload';```
3. Add it to `[imports]` under `@NgModule`:
```imports: [ ... FileUploadModule, ... ]```
4. Import `FileUploader` into the component:
```import { FileUploader } from 'ng2-file-upload';```
5. Create a variable for the API url:
```const URL = 'path_to_api';```
6. Initialize it:
```public uploader:FileUploader = new FileUploader({url: URL}); ```
## API for `ng2FileSelect`
### Properties
- `uploader` - (`FileUploader`) - uploader object. See using in [demo](https://github.com/valor-software/ng2-file-upload/blob/master/demo/components/file-upload/simple-demo.ts)
### Events
- `onFileSelected` - fires when files are selected and added to the uploader queue
## API for `ng2FileDrop`
### 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)
Parameters supported by this object:
1. `url` - URL of File Uploader's route
2. `authToken` - Auth token that will be applied as 'Authorization' header during file send.
3. `disableMultipart` - If 'true', disable using a multipart form for file upload and instead stream the file. Some APIs (e.g. Amazon S3) may expect the file to be streamed rather than sent via a form. Defaults to false.
4. `itemAlias` - item alias (form name redefinition)
5. `formatDataFunction` - Function to modify the request body. 'DisableMultipart' must be 'true' for this function to be called.
6. `formatDataFunctionIsAsync` - Informs if the function sent in 'formatDataFunction' is asynchronous. Defaults to false.
7. `parametersBeforeFiles` - States if additional parameters should be appended before or after the file. Defaults to false.
### Events
- `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)
- `onFileDrop` - it fires after a file has been dropped on a Drop Area; you can pass in `$event` to get the list of files that were dropped. i.e. `(onFileDrop)="dropped($event)"`
# Troubleshooting
Please follow these guidelines when reporting bugs and feature requests:
1. Use [GitHub Issues](https://github.com/valor-software/ng2-file-upload/issues) board to report bugs and feature requests (not our email address)
2. Please **always** write steps to reproduce the error. That way we can focus on fixing the bug, not scratching our heads trying to reproduce it.
Thanks for understanding!
### License
The MIT License (see the [LICENSE](https://github.com/valor-software/ng2-file-upload/blob/master/LICENSE) file for the full text)
@@ -1,28 +0,0 @@
export class FileLikeObject {
lastModifiedDate: any;
size: any;
type?: string;
name?: string;
rawFile: HTMLInputElement | File;
constructor(fileOrInput: HTMLInputElement | File) {
this.rawFile = fileOrInput;
const fakePathOrObject = fileOrInput instanceof HTMLInputElement ? fileOrInput.value : fileOrInput;
const postfix = typeof fakePathOrObject === 'string' ? 'FakePath' : 'Object';
const method = `_createFrom${postfix}`;
(this as any)[ method ](fakePathOrObject);
}
_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);
}
_createFromObject(object: { size: number, type: string, name: string }): void {
this.size = object.size;
this.type = object.type;
this.name = object.name;
}
}
@@ -1,41 +0,0 @@
import { Directive, EventEmitter, ElementRef, Input, HostListener, Output } from '@angular/core';
import { FileUploader, FileUploaderOptions } from './file-uploader.class';
@Directive({ selector: '[ng2FileSelect]' })
export class FileSelectDirective {
@Input() uploader?: FileUploader;
// eslint-disable-next-line @angular-eslint/no-output-on-prefix
@Output() onFileSelected: EventEmitter<File[]> = new EventEmitter<File[]>();
protected element: ElementRef;
constructor(element: ElementRef) {
this.element = element;
}
getOptions(): FileUploaderOptions | undefined {
return this.uploader?.options;
}
getFilters(): string {
return '';
}
isEmptyAfterSelection(): boolean {
return !!this.element.nativeElement.attributes.multiple;
}
@HostListener('change')
onChange(): void {
const files = this.element.nativeElement.files;
const options = this.getOptions();
const filters = this.getFilters();
this.uploader?.addToQueue(files, options, filters);
this.onFileSelected.emit(files);
if (this.isEmptyAfterSelection()) {
this.element.nativeElement.value = '';
}
}
}
-26
View File
@@ -1,26 +0,0 @@
module.exports = {
displayName: 'ng2-file-upload',
preset: '../../jest.preset.js',
setupFilesAfterEnv: ['<rootDir>/testing/test-setup.ts'],
globals: {
'ts-jest': {
tsconfig: '<rootDir>/tsconfig.spec.json',
astTransformers: {
before: [
'jest-preset-angular/build/InlineFilesTransformer',
'jest-preset-angular/build/StripStylesTransformer',
]
}
}
},
transform: {
'^.+\\.[tj]sx?$': 'ts-jest'
},
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
coverageDirectory: '../../coverage/libs/ng2-file-upload',
snapshotSerializers: [
'jest-preset-angular/build/AngularNoNgAttributesSnapshotSerializer.js',
'jest-preset-angular/build/AngularSnapshotSerializer.js',
'jest-preset-angular/build/HTMLCommentSerializer.js',
]
};
-7
View File
@@ -1,7 +0,0 @@
{
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
"dest": "../../dist/libs/ng2-file-upload/",
"lib": {
"entryFile": "index.ts"
}
}
-31
View File
@@ -1,31 +0,0 @@
{
"name": "ng2-file-upload",
"version": "2.0.0-3",
"description": "Angular file uploader",
"author": "Dmitriy Shekhovtsov <valorkin@gmail.com>",
"license": "MIT",
"peerDependencies": {
"@angular/core": "^11.0.0 || ^12.0.0",
"@angular/common": "^11.0.0 || ^12.0.0"
},
"sideEffects": false,
"publishConfig": {
"registry": "https://registry.npmjs.org/",
"tag": "next"
},
"repository": {
"type": "git",
"url": "git+ssh://git@github.com/valor-software/ng2-file-upload.git"
},
"bugs": {
"url": "https://github.com/valor-software/ng2-file-upload/issues"
},
"homepage": "https://github.com/valor-software/ng2-file-upload#readme",
"keywords": [
"angular",
"upload file",
"ng",
"ng2",
"angular2"
]
}
@@ -1 +0,0 @@
import 'jest-preset-angular';
-28
View File
@@ -1,28 +0,0 @@
{
"extends": "../../tsconfig.base.json",
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.lib.prod.json"
},
{
"path": "./tsconfig.spec.json"
}
],
"compilerOptions": {
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
},
"angularCompilerOptions": {
"strictInjectionParameters": true,
"strictTemplates": true,
"fullTemplateTypeCheck": true
}
}
-23
View File
@@ -1,23 +0,0 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"target": "es2015",
"declaration": true,
"declarationMap": true,
"inlineSources": true,
"types": [],
"lib": ["dom", "es2018"]
},
"angularCompilerOptions": {
"skipTemplateCodegen": true,
"strictMetadataEmit": true,
"enableResourceInlining": true
},
"include": [
"**/*.ts"
],
"exclude": [
"**/*.spec.ts"
]
}
@@ -1,10 +0,0 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.lib.json",
"compilerOptions": {
"declarationMap": false
},
"angularCompilerOptions": {
"enableIvy": false
}
}
-12
View File
@@ -1,12 +0,0 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node"]
},
"include": [
"**/*.spec.ts",
"**/*.d.ts"
]
}
-38
View File
@@ -1,38 +0,0 @@
{
"npmScope": "ng2-file-upload-demo",
"implicitDependencies": {
"angular.json": "*",
"package.json": "*",
"tsconfig.json": "*",
"tslint.json": "*",
".eslintrc.json": "*",
"nx.json": "*"
},
"projects": {
"ng2-file-upload": {
"tags": [
"lib"
]
},
"ng2-file-upload-demo": {
"tags": [],
"implicitDependencies": [
"ng2-file-upload"
]
}
},
"tasksRunnerOptions": {
"default": {
"runner": "@nrwl/workspace/tasks-runners/default",
"options": {
"cacheableOperations": [
"build",
"lint",
"test",
"e2e"
]
}
}
}
}
-28752
View File
File diff suppressed because it is too large Load Diff
+92 -78
View File
@@ -1,34 +1,39 @@
{
"name": "ng2-file-upload-base",
"version": "2.0.0-3",
"version": "1.3.0",
"private": true,
"description": "Angular file upload directives",
"scripts": {
"ng": "nx",
"start": "ng serve",
"demo.build": "ng build",
"demo.build-prod": "ng build --prod",
"build": "nx run ng2-file-upload:build",
"build-prod": "nx run ng2-file-upload:build:production",
"build.watch": "nx run ng2-file-upload:build --watch",
"test": "nx run-many --all --target=test",
"version": "nx run ng2-file-upload:version",
"lint": "nx run-many --all --target=lint",
"pretest": "run-s lint build",
"test-coverage": "nx run-many --all --target=test --codeCoverage",
"lite-server": "lite-server -c demo/bs-config.json",
"demo.serve": "run-s build link demo.build lite-server",
"demo.gh-pages": "run-s build demo.build demo.deploy",
"demo.deploy": "gh-pages -d dist/apps/ng2-file-upload",
"postinstall": "node ./decorate-angular-cli.js",
"flow.github-release": "conventional-github-releaser -p angular"
"demo.build": "ng build -prod --aot",
"demo.deploy": "gh-pages -d demo/dist",
"link": "ngm link -p src --here",
"lint": "exit 0",
"disable-lint": "tslint \"**/*.ts\" -c tslint.json --fix --type-check -t prose -e \"node_modules/**\" -e \"dist/**\" -e \"temp/**\" -e \"scripts/docs/**\"",
"flow.changelog": "conventional-changelog -i CHANGELOG.md -s -p angular",
"flow.github-release": "conventional-github-releaser -p angular",
"build": "ngm build -p src --clean",
"build.watch": "ngm build -p src --watch --skip-bundles",
"start": "ng serve --aot",
"pretest": "run-s lint build link",
"test": "ng test -sr",
"test-coverage": "ng test -sr -cc",
"version": "npm run flow.changelog && git add -A"
},
"main": "bundles/ng2-file-upload.umd.js",
"module": "index.js",
"typings": "index.d.ts",
"keywords": [
"angular",
"angular2",
"bootstrap",
"angularjs",
"twitter-bootstrap",
"file-upload",
"angular-file-upload"
],
"author": "Dmitriy Shekhovtsov <valorkin@gmail.com>",
"author": "Vyacheslav Chub <vyacheslav.chub@valor-software.com>",
"license": "MIT",
"repository": {
"type": "git",
@@ -38,64 +43,77 @@
"url": "https://github.com/valor-software/ng2-file-upload/issues"
},
"homepage": "https://github.com/valor-software/ng2-file-upload#readme",
"peerDependencies": {},
"dependencies": {},
"peerDependencies": {
"@angular/common": "^2.3.1 || >=4.0.0",
"@angular/core": "^2.3.1 || >=4.0.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.1102.13",
"@angular-devkit/build-ng-packagr": "^0.1002.0",
"@angular/animations": "~11.2.14",
"@angular/cli": "~11.2.14",
"@angular/common": "~11.2.14",
"@angular/compiler": "~11.2.14",
"@angular/compiler-cli": "~11.2.14",
"@angular/core": "~11.2.14",
"@angular/forms": "~11.2.14",
"@angular/platform-browser": "~11.2.14",
"@angular/platform-browser-dynamic": "~11.2.14",
"@angular-eslint/eslint-plugin": "4.3.0",
"@angular-eslint/eslint-plugin-template": "4.3.0",
"@angular-eslint/template-parser": "4.3.0",
"@nrwl/angular": "11.2.12",
"@nrwl/cli": "11.2.12",
"@nrwl/node": "11.2.12",
"@nrwl/eslint-plugin-nx": "11.2.12",
"@nrwl/jest": "11.2.12",
"@nrwl/linter": "11.2.12",
"@types/fs-extra": "9.0.7",
"@types/jest": "26.0.20",
"@types/node": "^12.11.1",
"@types/webpack": "^5.0.0",
"@typescript-eslint/eslint-plugin": "~4.28.3",
"@typescript-eslint/parser": "~4.28.3",
"@angular/cli": "1.0.0",
"@angular/common": "2.4.3",
"@angular/compiler": "2.4.3",
"@angular/compiler-cli": "2.4.3",
"@angular/core": "2.4.3",
"@angular/forms": "2.4.3",
"@angular/http": "2.4.3",
"@angular/language-service": "2.4.3",
"@angular/platform-browser": "2.4.3",
"@angular/platform-browser-dynamic": "2.4.3",
"@angular/router": "3.4.3",
"@angular/tsc-wrapped": "0.5.1",
"@types/jasmine": "2.5.40",
"@types/marked": "0.0.28",
"@types/node": "7.0.0",
"@types/webpack": "^2.2.1",
"bootstrap": "3.3.7",
"classlist-polyfill": "1.2.0",
"codecov": "3.8.2",
"codelyzer": "^6.0.0",
"conventional-changelog-cli": "2.1.1",
"conventional-github-releaser": "3.1.5",
"core-js": "^3.14.0",
"eslint": "7.22.0",
"eslint-config-prettier": "7.2.0",
"fs-extra": "9.1.0",
"gh-pages": "3.2.2",
"chokidar-cli": "1.2.0",
"classlist-polyfill": "1.0.3",
"codecov": "1.0.1",
"codelyzer": "~2.0.0-beta.4",
"conventional-changelog-cli": "1.2.0",
"conventional-github-releaser": "1.1.3",
"core-js": "^2.4.1",
"cpy": "5.0.0",
"cpy-cli": "1.0.1",
"del-cli": "0.2.1",
"gh-pages": "0.12.0",
"gitignore-to-glob": "0.3.0",
"google-code-prettify": "1.0.5",
"html-loader": "^1.3.2",
"jest": "26.6.3",
"jest-createspyobj": "2.0.0",
"jest-preset-angular": "8.3.2",
"markdown-loader": "^6.0.0",
"ng-packagr": "^11.2.4",
"ngx-bootstrap": "7.1.0",
"npm-run-all": "^4.1.5",
"protractor": "~7.0.0",
"raw-loader": "^4.0.2",
"rxjs": "^6.6.0",
"ts-helpers": "^1.1.2",
"ts-jest": "26.5.1",
"ts-node": "8.3.0",
"tslint": "^6.1.0",
"tslint-config-valorsoft": "^2.2.1",
"typescript": "4.1.5",
"zone.js": "~0.11.3"
"html-loader": "0.4.4",
"jasmine": "2.5.3",
"jasmine-core": "2.5.2",
"jasmine-data-provider": "2.2.0",
"jasmine-spec-reporter": "3.2.0",
"karma": "1.4.0",
"karma-chrome-launcher": "^2.0.0",
"karma-cli": "^1.0.1",
"karma-coverage-istanbul-reporter": "^1.3.0",
"karma-jasmine": "^1.0.2",
"karma-remap-istanbul": "0.4.0",
"karma-sauce-launcher": "1.1.0",
"lite-server": "2.2.2",
"lodash": "4.17.4",
"markdown-loader": "^0.1.7",
"marked": "0.3.6",
"ng2-page-scroll": "4.0.0-beta.2",
"ngm-cli": "0.4.0",
"ngx-bootstrap": "1.6.6",
"npm-run-all": "^4.0.1",
"pre-commit": "1.2.2",
"protractor": "5.0.0",
"reflect-metadata": "0.1.9",
"require-dir": "0.3.1",
"rxjs": "5.0.3",
"systemjs-builder": "0.15.34",
"ts-helpers": "^1.1.1",
"ts-node": "2.0.0",
"tslint": "4.3.1",
"tslint-config-valorsoft": "1.2.0",
"typedoc": "0.5.5",
"typescript": "2.1.5",
"wallaby-webpack": "0.0.30",
"webdriver-manager": "11.1.1",
"zone.js": "0.7.5"
},
"contributors": [
{
@@ -118,9 +136,5 @@
"email": "otelnov@gmail.com",
"url": "https://github.com/otelnov"
}
],
"dependencies": {
"@nrwl/workspace": "^12.8.0",
"tslib": "^2.0.0"
}
]
}
+1
View File
@@ -0,0 +1 @@
!**/*.js
+21
View File
@@ -0,0 +1,21 @@
// tslint:disable
/**
* @copyright Angular ng-bootstrap team
*/
beforeEach(() => {
jasmine.addMatchers({
toHaveCssClass(/*util, customEqualityTests*/) {
return {compare: buildError(false), negativeCompare: buildError(true)};
function buildError(isNot) {
return function (actual, className) {
const orNot = isNot ? 'not ' : '';
return {
pass: actual.classList.contains(className) === !isNot,
message: `Expected ${actual.outerHTML} ${orNot} to contain the CSS class "${className}"`
};
};
}
}
});
});
-5
View File
@@ -1,5 +0,0 @@
// This file includes polyfills needed by Angular 2 and is loaded before
// the app. You can add your own extra polyfills to this file.
import 'ts-helpers';
import 'zone.js/dist/zone';
import 'classlist-polyfill';
+18
View File
@@ -0,0 +1,18 @@
module.exports.customLaunchers = function customLaunchers() {
return {
sl_chrome: {base: 'SauceLabs', browserName: 'chrome'},
sl_chrome_1: {base: 'SauceLabs', browserName: 'chrome', version: 'latest-1'},
sl_firefox: {base: 'SauceLabs', browserName: 'firefox'},
sl_firefox_1: {base: 'SauceLabs', browserName: 'firefox', version: 'latest-1'},
sl_ie9: {base: 'SauceLabs', browserName: 'internet explorer', platform: 'Windows 2008', version: '9'},
'SL_IE10': {base: 'SauceLabs', browserName: 'internet explorer', platform: 'Windows 2012', version: '10'},
'SL_IE11': {base: 'SauceLabs', browserName: 'internet explorer', platform: 'Windows 8.1', version: '11'},
'SL_EDGE': {base: 'SauceLabs', browserName: 'MicrosoftEdge', platform: 'Windows 10', version: '13.10586'},
'SL_IOS9': {base: 'SauceLabs', browserName: 'iphone', platform: 'OS X 10.10', version: '9.3'},
'SL_IOS10': {base: 'SauceLabs', browserName: 'iphone', platform: 'OS X 10.10', version: '10.0'},
'SL_ANDROID4.4': {base: 'SauceLabs', browserName: 'android', platform: 'Linux', version: '4.4'},
'SL_ANDROID5': {base: 'SauceLabs', browserName: 'android', platform: 'Linux', version: '5.1'},
'SL_SAFARI9': {base: 'SauceLabs', browserName: 'safari', platform: 'OS X 10.11', version: '9.0'}
};
};
-13
View File
@@ -1,13 +0,0 @@
import { readJson, writeJson } from 'fs-extra';
const libPackage = './libs/ng2-file-upload/package.json';
const mainPackage = './package.json';
(async () => {
const version = await readJson(mainPackage).then(json => json.version);
const packageJson = await readJson(libPackage);
if (packageJson.version) {
packageJson.version = version;
}
await writeJson(libPackage, packageJson, { spaces: 2 });
})();
+37
View File
@@ -0,0 +1,37 @@
import '../demo/src/polyfills.ts';
import 'zone.js/dist/long-stack-trace-zone';
import 'zone.js/dist/proxy.js';
import 'zone.js/dist/sync-test';
import 'zone.js/dist/jasmine-patch';
import 'zone.js/dist/async-test';
import 'zone.js/dist/fake-async-test';
import { getTestBed } from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
import './matchers';
// Unfortunately there's no typing for the `__karma__` variable. Just declare it as any.
declare var __karma__: any;
declare var require: any;
// Prevent Karma from running prematurely.
__karma__.loaded = Function.prototype;
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting()
);
// Then we find all the tests.
let context = require.context('../demo/src', true, /\.spec\.ts/);
// And load the modules.
context.keys().map(context);
let context2 = require.context('../src/spec', true, /\.spec\.ts/);
context2.keys().map(context2);
// Finally, start Karma to run the tests.
__karma__.start();
+2 -2
View File
@@ -9,9 +9,9 @@ declare const ENV:string;
declare const PR:any;
// declare const global:any;
// eslint-disable-next-line @typescript-eslint/prefer-namespace-keyword
declare module jasmine {
interface Matchers<T> {
interface Matchers {
toHaveCssClass(expected: any): boolean;
}
}
@@ -4,45 +4,42 @@ import { FileUploader, FileUploaderOptions } from './file-uploader.class';
@Directive({ selector: '[ng2FileDrop]' })
export class FileDropDirective {
@Input() uploader?: FileUploader;
@Output() fileOver: EventEmitter<any> = new EventEmitter();
// eslint-disable-next-line @angular-eslint/no-output-on-prefix
@Output() onFileDrop: EventEmitter<File[]> = new EventEmitter<File[]>();
@Input() public uploader: FileUploader;
@Output() public fileOver: EventEmitter<any> = new EventEmitter();
@Output() public onFileDrop: EventEmitter<File[]> = new EventEmitter<File[]>();
protected element: ElementRef;
constructor(element: ElementRef) {
public constructor(element: ElementRef) {
this.element = element;
}
getOptions(): FileUploaderOptions | void {
return this.uploader?.options;
public getOptions(): FileUploaderOptions {
return this.uploader.options;
}
getFilters(): string {
return '';
public getFilters(): any {
return {};
}
@HostListener('drop', [ '$event' ])
onDrop(event: MouseEvent): void {
const transfer = this._getTransfer(event);
public onDrop(event: any): void {
let transfer = this._getTransfer(event);
if (!transfer) {
return;
}
const options = this.getOptions();
const filters = this.getFilters();
let options = this.getOptions();
let filters = this.getFilters();
this._preventAndStop(event);
if (options) {
this.uploader?.addToQueue(transfer.files, options, filters);
}
this.uploader.addToQueue(transfer.files, options, filters);
this.fileOver.emit(false);
this.onFileDrop.emit(transfer.files);
}
@HostListener('dragover', [ '$event' ])
onDragOver(event: MouseEvent): void {
const transfer = this._getTransfer(event);
public onDragOver(event: any): void {
let transfer = this._getTransfer(event);
if (!this._haveFiles(transfer.types)) {
return;
}
@@ -53,7 +50,7 @@ export class FileDropDirective {
}
@HostListener('dragleave', [ '$event' ])
onDragLeave(event: MouseEvent): void {
public onDragLeave(event: any): any {
if ((this as any).element) {
if (event.currentTarget === (this as any).element[ 0 ]) {
return;
@@ -68,12 +65,12 @@ export class FileDropDirective {
return event.dataTransfer ? event.dataTransfer : event.originalEvent.dataTransfer; // jQuery fix;
}
protected _preventAndStop(event: MouseEvent): void {
protected _preventAndStop(event: any): any {
event.preventDefault();
event.stopPropagation();
}
protected _haveFiles(types: any): boolean {
protected _haveFiles(types: any): any {
if (!types) {
return false;
}
@@ -2,30 +2,30 @@ import { FileLikeObject } from './file-like-object.class';
import { FileUploader, ParsedResponseHeaders, FileUploaderOptions } from './file-uploader.class';
export class FileItem {
file: FileLikeObject;
_file: File;
alias?: string;
url = '/';
method?: string;
headers: any = [];
withCredentials = true;
formData: any = [];
isReady = false;
isUploading = false;
isUploaded = false;
isSuccess = false;
isCancel = false;
isError = false;
progress = 0;
index?: number;
_xhr?: XMLHttpRequest;
_form: any;
public file: FileLikeObject;
public _file: File;
public alias: string;
public url: string = '/';
public method: string;
public headers: any = [];
public withCredentials: boolean = true;
public formData: any = [];
public isReady: boolean = false;
public isUploading: boolean = false;
public isUploaded: boolean = false;
public isSuccess: boolean = false;
public isCancel: boolean = false;
public isError: boolean = false;
public progress: number = 0;
public index: number = void 0;
public _xhr: XMLHttpRequest;
public _form: any;
protected uploader: FileUploader;
protected some: File;
protected options: FileUploaderOptions;
constructor(uploader: FileUploader, some: File, options: FileUploaderOptions) {
public constructor(uploader: FileUploader, some: File, options: FileUploaderOptions) {
this.uploader = uploader;
this.some = some;
this.options = options;
@@ -38,7 +38,7 @@ export class FileItem {
this.url = uploader.options.url;
}
upload(): void {
public upload(): void {
try {
this.uploader.uploadItem(this);
} catch (e) {
@@ -47,43 +47,43 @@ export class FileItem {
}
}
cancel(): void {
public cancel(): void {
this.uploader.cancelItem(this);
}
remove(): void {
public remove(): void {
this.uploader.removeFromQueue(this);
}
onBeforeUpload(): void {
public onBeforeUpload(): void {
return void 0;
}
onBuildForm(form: any): any {
public onBuildForm(form: any): any {
return { form };
}
onProgress(progress: number): any {
public onProgress(progress: number): any {
return { progress };
}
onSuccess(response: string, status: number, headers: ParsedResponseHeaders): any {
public onSuccess(response: string, status: number, headers: ParsedResponseHeaders): any {
return { response, status, headers };
}
onError(response: string, status: number, headers: ParsedResponseHeaders): any {
public onError(response: string, status: number, headers: ParsedResponseHeaders): any {
return { response, status, headers };
}
onCancel(response: string, status: number, headers: ParsedResponseHeaders): any {
public onCancel(response: string, status: number, headers: ParsedResponseHeaders): any {
return { response, status, headers };
}
onComplete(response: string, status: number, headers: ParsedResponseHeaders): any {
public onComplete(response: string, status: number, headers: ParsedResponseHeaders): any {
return { response, status, headers };
}
_onBeforeUpload(): void {
public _onBeforeUpload(): void {
this.isReady = true;
this.isUploading = true;
this.isUploaded = false;
@@ -94,16 +94,16 @@ export class FileItem {
this.onBeforeUpload();
}
_onBuildForm(form: any): void {
public _onBuildForm(form: any): void {
this.onBuildForm(form);
}
_onProgress(progress: number): void {
public _onProgress(progress: number): void {
this.progress = progress;
this.onProgress(progress);
}
_onSuccess(response: string, status: number, headers: ParsedResponseHeaders): void {
public _onSuccess(response: string, status: number, headers: ParsedResponseHeaders): void {
this.isReady = false;
this.isUploading = false;
this.isUploaded = true;
@@ -111,11 +111,11 @@ export class FileItem {
this.isCancel = false;
this.isError = false;
this.progress = 100;
this.index = undefined;
this.index = void 0;
this.onSuccess(response, status, headers);
}
_onError(response: string, status: number, headers: ParsedResponseHeaders): void {
public _onError(response: string, status: number, headers: ParsedResponseHeaders): void {
this.isReady = false;
this.isUploading = false;
this.isUploaded = true;
@@ -123,11 +123,11 @@ export class FileItem {
this.isCancel = false;
this.isError = true;
this.progress = 0;
this.index = undefined;
this.index = void 0;
this.onError(response, status, headers);
}
_onCancel(response: string, status: number, headers: ParsedResponseHeaders): void {
public _onCancel(response: string, status: number, headers: ParsedResponseHeaders): void {
this.isReady = false;
this.isUploading = false;
this.isUploaded = false;
@@ -135,11 +135,11 @@ export class FileItem {
this.isCancel = true;
this.isError = false;
this.progress = 0;
this.index = undefined;
this.index = void 0;
this.onCancel(response, status, headers);
}
_onComplete(response: string, status: number, headers: ParsedResponseHeaders): void {
public _onComplete(response: string, status: number, headers: ParsedResponseHeaders): void {
this.onComplete(response, status, headers);
if (this.uploader.options.removeAfterUpload) {
@@ -147,7 +147,7 @@ export class FileItem {
}
}
_prepareToUploading(): void {
public _prepareToUploading(): void {
this.index = this.index || ++this.uploader._nextIndex;
this.isReady = true;
}
+33
View File
@@ -0,0 +1,33 @@
function isElement(node: any): boolean {
return !!(node && (node.nodeName || node.prop && node.attr && node.find));
}
export class FileLikeObject {
public lastModifiedDate: any;
public size: any;
public type: string;
public name: string;
public rawFile: string;
public constructor(fileOrInput: any) {
this.rawFile = fileOrInput;
let isInput = isElement(fileOrInput);
let fakePathOrObject = isInput ? fileOrInput.value : fileOrInput;
let postfix = typeof fakePathOrObject === 'string' ? 'FakePath' : 'Object';
let method = '_createFrom' + postfix;
(this as any)[ method ](fakePathOrObject);
}
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 }): void {
this.size = object.size;
this.type = object.type;
this.name = object.name;
}
}
+41
View File
@@ -0,0 +1,41 @@
import { Directive, EventEmitter, ElementRef, Input, HostListener, Output } from '@angular/core';
import { FileUploader } from './file-uploader.class';
@Directive({ selector: '[ng2FileSelect]' })
export class FileSelectDirective {
@Input() public uploader: FileUploader;
@Output() public onFileSelected: EventEmitter<File[]> = new EventEmitter<File[]>();
protected element: ElementRef;
public constructor(element: ElementRef) {
this.element = element;
}
public getOptions(): any {
return this.uploader.options;
}
public getFilters(): any {
return {};
}
public isEmptyAfterSelection(): boolean {
return !!this.element.nativeElement.attributes.multiple;
}
@HostListener('change')
public onChange(): any {
let files = this.element.nativeElement.files;
let options = this.getOptions();
let filters = this.getFilters();
this.uploader.addToQueue(files, options, filters);
this.onFileSelected.emit(files);
if (this.isEmptyAfterSelection()) {
this.element.nativeElement.value = '';
}
}
}
@@ -1,9 +1,8 @@
import { FileLikeObject } from '../index';
import { FileLikeObject } from "../ng2-file-upload";
export class FileType {
/* MS office */
// tslint:disable-next-line:variable-name
static mime_doc: string[] = [
public static mime_doc: string[] = [
'application/msword',
'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
@@ -11,8 +10,7 @@ export class FileType {
'application/vnd.ms-word.document.macroEnabled.12',
'application/vnd.ms-word.template.macroEnabled.12'
];
// tslint:disable-next-line:variable-name
static mime_xsl: string[] = [
public static mime_xsl: string[] = [
'application/vnd.ms-excel',
'application/vnd.ms-excel',
'application/vnd.ms-excel',
@@ -23,8 +21,7 @@ export class FileType {
'application/vnd.ms-excel.addin.macroEnabled.12',
'application/vnd.ms-excel.sheet.binary.macroEnabled.12'
];
// tslint:disable-next-line:variable-name
static mime_ppt: string[] = [
public static mime_ppt: string[] = [
'application/vnd.ms-powerpoint',
'application/vnd.ms-powerpoint',
'application/vnd.ms-powerpoint',
@@ -39,8 +36,7 @@ export class FileType {
];
/* PSD */
// tslint:disable-next-line:variable-name
static mime_psd: string[] = [
public static mime_psd: string[] = [
'image/photoshop',
'image/x-photoshop',
'image/psd',
@@ -50,8 +46,7 @@ export class FileType {
];
/* Compressed files */
// tslint:disable-next-line:variable-name
static mime_compress: string[] = [
public static mime_compress: string[] = [
'application/x-gtar',
'application/x-gcompress',
'application/compress',
@@ -65,101 +60,101 @@ export class FileType {
'application/x-bzip2'
];
static getMimeClass(file: FileLikeObject): string {
public static getMimeClass(file: FileLikeObject): string {
let mimeClass = 'application';
if (file?.type && this.mime_psd.indexOf(file.type) !== -1) {
if (this.mime_psd.indexOf(file.type) !== -1) {
mimeClass = 'image';
} else if (file?.type?.match('image.*')) {
} else if (file.type.match('image.*')) {
mimeClass = 'image';
} else if (file?.type?.match('video.*')) {
} else if (file.type.match('video.*')) {
mimeClass = 'video';
} else if (file?.type?.match('audio.*')) {
} else if (file.type.match('audio.*')) {
mimeClass = 'audio';
} else if (file?.type === 'application/pdf') {
} else if (file.type === 'application/pdf') {
mimeClass = 'pdf';
} else if (file?.type && this.mime_compress.indexOf(file.type) !== -1) {
} else if (this.mime_compress.indexOf(file.type) !== -1) {
mimeClass = 'compress';
} else if (file?.type && this.mime_doc.indexOf(file.type) !== -1) {
} else if (this.mime_doc.indexOf(file.type) !== -1) {
mimeClass = 'doc';
} else if (file?.type && this.mime_xsl.indexOf(file.type) !== -1) {
} else if (this.mime_xsl.indexOf(file.type) !== -1) {
mimeClass = 'xls';
} else if (file?.type && this.mime_ppt.indexOf(file.type) !== -1) {
} else if (this.mime_ppt.indexOf(file.type) !== -1) {
mimeClass = 'ppt';
}
if (mimeClass === 'application' && file?.name) {
if (mimeClass === 'application') {
mimeClass = this.fileTypeDetection(file.name);
}
return mimeClass;
}
static fileTypeDetection(inputFilename: string): string {
const types: { [ key: string ]: string } = {
jpg: 'image',
jpeg: 'image',
tif: 'image',
psd: 'image',
bmp: 'image',
png: 'image',
nef: 'image',
tiff: 'image',
cr2: 'image',
dwg: 'image',
cdr: 'image',
ai: 'image',
indd: 'image',
pin: 'image',
cdp: 'image',
skp: 'image',
stp: 'image',
public static fileTypeDetection(inputFilename: string): string {
let types: { [ key: string ]: string } = {
'jpg': 'image',
'jpeg': 'image',
'tif': 'image',
'psd': 'image',
'bmp': 'image',
'png': 'image',
'nef': 'image',
'tiff': 'image',
'cr2': 'image',
'dwg': 'image',
'cdr': 'image',
'ai': 'image',
'indd': 'image',
'pin': 'image',
'cdp': 'image',
'skp': 'image',
'stp': 'image',
'3dm': 'image',
mp3: 'audio',
wav: 'audio',
wma: 'audio',
mod: 'audio',
m4a: 'audio',
compress: 'compress',
zip: 'compress',
rar: 'compress',
'mp3': 'audio',
'wav': 'audio',
'wma': 'audio',
'mod': 'audio',
'm4a': 'audio',
'compress': 'compress',
'zip': 'compress',
'rar': 'compress',
'7z': 'compress',
lz: 'compress',
z01: 'compress',
bz2: 'compress',
gz: 'compress',
pdf: 'pdf',
xls: 'xls',
xlsx: 'xls',
ods: 'xls',
mp4: 'video',
avi: 'video',
wmv: 'video',
mpg: 'video',
mts: 'video',
flv: 'video',
'lz': 'compress',
'z01': 'compress',
'bz2': 'compress',
'gz': 'compress',
'pdf': 'pdf',
'xls': 'xls',
'xlsx': 'xls',
'ods': 'xls',
'mp4': 'video',
'avi': 'video',
'wmv': 'video',
'mpg': 'video',
'mts': 'video',
'flv': 'video',
'3gp': 'video',
vob: 'video',
m4v: 'video',
mpeg: 'video',
m2ts: 'video',
mov: 'video',
doc: 'doc',
docx: 'doc',
eps: 'doc',
txt: 'doc',
odt: 'doc',
rtf: 'doc',
ppt: 'ppt',
pptx: 'ppt',
pps: 'ppt',
ppsx: 'ppt',
odp: 'ppt'
'vob': 'video',
'm4v': 'video',
'mpeg': 'video',
'm2ts': 'video',
'mov': 'video',
'doc': 'doc',
'docx': 'doc',
'eps': 'doc',
'txt': 'doc',
'odt': 'doc',
'rtf': 'doc',
'ppt': 'ppt',
'pptx': 'ppt',
'pps': 'ppt',
'ppsx': 'ppt',
'odp': 'ppt'
};
const chunks = inputFilename.split('.');
let chunks = inputFilename.split('.');
if (chunks.length < 2) {
return 'application';
}
const extension = chunks[ chunks.length - 1 ].toLowerCase();
let extension = chunks[ chunks.length - 1 ].toLowerCase();
if (types[ extension ] === undefined) {
return 'application';
} else {
@@ -12,12 +12,12 @@ export interface Headers {
value: string;
}
export interface ParsedResponseHeaders { [ headerFieldName: string ]: string }
export type ParsedResponseHeaders = { [ headerFieldName: string ]: string };
export interface FilterFunction {
name: string;
fn(item: FileLikeObject, options?: FileUploaderOptions): boolean;
}
export type FilterFunction = {
name: string,
fn: (item?: FileLikeObject, options?: FileUploaderOptions) => boolean
};
export interface FileUploaderOptions {
allowedMimeType?: string[];
@@ -31,64 +31,62 @@ export interface FileUploaderOptions {
maxFileSize?: number;
queueLimit?: number;
removeAfterUpload?: boolean;
url: string;
url?: string;
disableMultipart?: boolean;
itemAlias?: string;
authTokenHeader?: string;
additionalParameter?: { [ key: string ]: any };
parametersBeforeFiles?: boolean;
// eslint-disable-next-line @typescript-eslint/ban-types
formatDataFunction?: Function;
formatDataFunctionIsAsync?: boolean;
}
export class FileUploader {
authToken?: string;
isUploading = false;
queue: FileItem[] = [];
progress = 0;
_nextIndex = 0;
autoUpload: any;
authTokenHeader?: string;
response: EventEmitter<any>;
public authToken: string;
public isUploading: boolean = false;
public queue: FileItem[] = [];
public progress: number = 0;
public _nextIndex: number = 0;
public autoUpload: any;
public authTokenHeader: string;
public response: EventEmitter<any>;
options: FileUploaderOptions = {
public options: FileUploaderOptions = {
autoUpload: false,
isHTML5: true,
filters: [],
removeAfterUpload: false,
disableMultipart: false,
formatDataFunction: (item: FileItem) => item._file,
formatDataFunctionIsAsync: false,
url: ''
formatDataFunctionIsAsync: false
};
protected _failFilterIndex?: number;
protected _failFilterIndex: number;
constructor(options: FileUploaderOptions) {
public constructor(options: FileUploaderOptions) {
this.setOptions(options);
this.response = new EventEmitter<string>();
this.response = new EventEmitter<any>();
}
setOptions(options: FileUploaderOptions): void {
public setOptions(options: FileUploaderOptions): void {
this.options = Object.assign(this.options, options);
this.authToken = this.options.authToken;
this.authTokenHeader = this.options.authTokenHeader || 'Authorization';
this.autoUpload = this.options.autoUpload;
this.options.filters?.unshift({ name: 'queueLimit', fn: this._queueLimitFilter });
this.options.filters.unshift({ name: 'queueLimit', fn: this._queueLimitFilter });
if (this.options.maxFileSize) {
this.options.filters?.unshift({ name: 'fileSize', fn: this._fileSizeFilter });
this.options.filters.unshift({ name: 'fileSize', fn: this._fileSizeFilter });
}
if (this.options.allowedFileType) {
this.options.filters?.unshift({ name: 'fileType', fn: this._fileTypeFilter });
this.options.filters.unshift({ name: 'fileType', fn: this._fileTypeFilter });
}
if (this.options.allowedMimeType) {
this.options.filters?.unshift({ name: 'mimeType', fn: this._mimeTypeFilter });
this.options.filters.unshift({ name: 'mimeType', fn: this._mimeTypeFilter });
}
for (let i = 0; i < this.queue.length; i++) {
@@ -96,31 +94,28 @@ export class FileUploader {
}
}
addToQueue(files: File[], _options?: FileUploaderOptions, filters?: [] | string): void {
let options = _options;
const list: File[] = [];
for (const file of files) {
public addToQueue(files: File[], options?: FileUploaderOptions, filters?: FilterFunction[] | string): void {
let list: File[] = [];
for (let file of files) {
list.push(file);
}
const arrayOfFilters = this._getFilters(filters);
const count = this.queue.length;
const addedFileItems: FileItem[] = [];
let arrayOfFilters = this._getFilters(filters);
let count = this.queue.length;
let addedFileItems: FileItem[] = [];
list.map((some: File) => {
if (!options) {
options = this.options;
}
const temp = new FileLikeObject(some);
let temp = new FileLikeObject(some);
if (this._isValidFile(temp, arrayOfFilters, options)) {
const fileItem = new FileItem(this, some, options);
let fileItem = new FileItem(this, some, options);
addedFileItems.push(fileItem);
this.queue.push(fileItem);
this._onAfterAddingFile(fileItem);
} else {
if (this._failFilterIndex) {
const filter = arrayOfFilters[ this._failFilterIndex ];
this._onWhenAddingFileFailed(temp, filter, options);
}
let filter = arrayOfFilters[ this._failFilterIndex ];
this._onWhenAddingFileFailed(temp, filter, options);
}
});
if (this.queue.length !== count) {
@@ -133,9 +128,9 @@ export class FileUploader {
}
}
removeFromQueue(value: FileItem): void {
const index = this.getIndexOfItem(value);
const item = this.queue[ index ];
public removeFromQueue(value: FileItem): void {
let index = this.getIndexOfItem(value);
let item = this.queue[ index ];
if (item.isUploading) {
item.cancel();
}
@@ -143,17 +138,17 @@ export class FileUploader {
this.progress = this._getTotalProgress();
}
clearQueue(): void {
public clearQueue(): void {
while (this.queue.length) {
this.queue[ 0 ].remove();
}
this.progress = 0;
}
uploadItem(value: FileItem): void {
const index = this.getIndexOfItem(value);
const item = this.queue[ index ];
const transport = this.options.isHTML5 ? '_xhrTransport' : '_iframeTransport';
public uploadItem(value: FileItem): void {
let index = this.getIndexOfItem(value);
let item = this.queue[ index ];
let transport = this.options.isHTML5 ? '_xhrTransport' : '_iframeTransport';
item._prepareToUploading();
if (this.isUploading) {
return;
@@ -162,17 +157,17 @@ export class FileUploader {
(this as any)[ transport ](item);
}
cancelItem(value: FileItem): void {
const index = this.getIndexOfItem(value);
const item = this.queue[ index ];
const prop = this.options.isHTML5 ? item._xhr : item._form;
public cancelItem(value: FileItem): void {
let index = this.getIndexOfItem(value);
let item = this.queue[ index ];
let prop = this.options.isHTML5 ? item._xhr : item._form;
if (item && item.isUploading) {
prop.abort();
}
}
uploadAll(): void {
const items = this.getNotUploadedItems().filter((item: FileItem) => !item.isUploading);
public uploadAll(): void {
let items = this.getNotUploadedItems().filter((item: FileItem) => !item.isUploading);
if (!items.length) {
return;
}
@@ -180,107 +175,110 @@ export class FileUploader {
items[ 0 ].upload();
}
cancelAll(): void {
const items = this.getNotUploadedItems();
public cancelAll(): void {
let items = this.getNotUploadedItems();
items.map((item: FileItem) => item.cancel());
}
isFile(value: any): boolean {
public isFile(value: any): boolean {
return isFile(value);
}
isFileLikeObject(value: any): boolean {
public isFileLikeObject(value: any): boolean {
return value instanceof FileLikeObject;
}
getIndexOfItem(value: any): number {
public getIndexOfItem(value: any): number {
return typeof value === 'number' ? value : this.queue.indexOf(value);
}
getNotUploadedItems(): any[] {
public getNotUploadedItems(): any[] {
return this.queue.filter((item: FileItem) => !item.isUploaded);
}
getReadyItems(): any[] {
public getReadyItems(): any[] {
return this.queue
.filter((item: FileItem) => (item.isReady && !item.isUploading))
.sort((item1: any, item2: any) => item1.index - item2.index);
}
onAfterAddingAll(fileItems: any): any {
return { fileItems };
}
onBuildItemForm(fileItem: FileItem, form: any): any {
return { fileItem, form };
}
onAfterAddingFile(fileItem: FileItem): any {
return { fileItem };
}
onWhenAddingFileFailed(item: FileLikeObject, filter: any, options: any): any {
return { item, filter, options };
}
onBeforeUploadItem(fileItem: FileItem): any {
return { fileItem };
}
onProgressItem(fileItem: FileItem, progress: any): any {
return { fileItem, progress };
}
onProgressAll(progress: any): any {
return { progress };
}
onSuccessItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): any {
return { item, response, status, headers };
}
onErrorItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): any {
return { item, response, status, headers };
}
onCancelItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): any {
return { item, response, status, headers };
}
onCompleteItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): any {
return { item, response, status, headers };
}
onCompleteAll(): any {
public destroy(): void {
return void 0;
}
_mimeTypeFilter(item: FileLikeObject): boolean {
return !(item?.type && this.options.allowedMimeType && this.options.allowedMimeType?.indexOf(item.type) === -1);
public onAfterAddingAll(fileItems: any): any {
return { fileItems };
}
_fileSizeFilter(item: FileLikeObject): boolean {
public onBuildItemForm(fileItem: FileItem, form: any): any {
return { fileItem, form };
}
public onAfterAddingFile(fileItem: FileItem): any {
return { fileItem };
}
public onWhenAddingFileFailed(item: FileLikeObject, filter: any, options: any): any {
return { item, filter, options };
}
public onBeforeUploadItem(fileItem: FileItem): any {
return { fileItem };
}
public onProgressItem(fileItem: FileItem, progress: any): any {
return { fileItem, progress };
}
public onProgressAll(progress: any): any {
return { progress };
}
public onSuccessItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): any {
return { item, response, status, headers };
}
public onErrorItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): any {
return { item, response, status, headers };
}
public onCancelItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): any {
return { item, response, status, headers };
}
public onCompleteItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): any {
return { item, response, status, headers };
}
public onCompleteAll(): any {
return void 0;
}
public _mimeTypeFilter(item: FileLikeObject): boolean {
return !(this.options.allowedMimeType && this.options.allowedMimeType.indexOf(item.type) === -1);
}
public _fileSizeFilter(item: FileLikeObject): boolean {
return !(this.options.maxFileSize && item.size > this.options.maxFileSize);
}
_fileTypeFilter(item: FileLikeObject): boolean {
public _fileTypeFilter(item: FileLikeObject): boolean {
return !(this.options.allowedFileType &&
this.options.allowedFileType.indexOf(FileType.getMimeClass(item)) === -1);
}
_onErrorItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): void {
public _onErrorItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): void {
item._onError(response, status, headers);
this.onErrorItem(item, response, status, headers);
}
_onCompleteItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): void {
public _onCompleteItem(item: FileItem, response: string, status: number, headers: ParsedResponseHeaders): void {
item._onComplete(response, status, headers);
this.onCompleteItem(item, response, status, headers);
const nextItem = this.getReadyItems()[ 0 ];
let nextItem = this.getReadyItems()[ 0 ];
this.isUploading = false;
if (nextItem) {
nextItem.upload();
return;
}
this.onCompleteAll();
@@ -291,18 +289,15 @@ export class FileUploader {
protected _headersGetter(parsedHeaders: ParsedResponseHeaders): any {
return (name: any): any => {
if (name) {
return parsedHeaders[ name.toLowerCase() ] || undefined;
return parsedHeaders[ name.toLowerCase() ] || void 0;
}
return parsedHeaders;
};
}
protected _xhrTransport(item: FileItem): any {
// tslint:disable-next-line:no-this-assignment
// eslint-disable-next-line @typescript-eslint/no-this-alias
const that = this;
const xhr = item._xhr = new XMLHttpRequest();
let that = this;
let xhr = item._xhr = new XMLHttpRequest();
let sendable: any;
this._onBeforeUploadItem(item);
@@ -312,6 +307,7 @@ export class FileUploader {
if (!this.options.disableMultipart) {
sendable = new FormData();
this._onBuildItemForm(item, sendable);
const appendFile = () => sendable.append(item.alias, item._file, item.file.name);
if (!this.options.parametersBeforeFiles) {
appendFile();
@@ -320,70 +316,66 @@ export class FileUploader {
// For AWS, Additional Parameters must come BEFORE Files
if (this.options.additionalParameter !== undefined) {
Object.keys(this.options.additionalParameter).forEach((key: string) => {
let paramVal = this.options.additionalParameter?.[ key ];
let paramVal = this.options.additionalParameter[ key ];
// Allow an additional parameter to include the filename
if (typeof paramVal === 'string' && paramVal.indexOf('{{file_name}}') >= 0 && item.file?.name) {
if (typeof paramVal === 'string' && paramVal.indexOf('{{file_name}}') >= 0) {
paramVal = paramVal.replace('{{file_name}}', item.file.name);
}
sendable.append(key, paramVal);
});
}
if (appendFile && this.options.parametersBeforeFiles) {
if (this.options.parametersBeforeFiles) {
appendFile();
}
} else {
if (this.options.formatDataFunction) {
sendable = this.options.formatDataFunction(item);
}
sendable = this.options.formatDataFunction(item);
}
xhr.upload.onprogress = (event: any) => {
const progress = Math.round(event.lengthComputable ? event.loaded * 100 / event.total : 0);
let progress = Math.round(event.lengthComputable ? event.loaded * 100 / event.total : 0);
this._onProgressItem(item, progress);
};
xhr.onload = () => {
const headers = this._parseHeaders(xhr.getAllResponseHeaders());
const response = this._transformResponse(xhr.response, headers);
const gist = this._isSuccessCode(xhr.status) ? 'Success' : 'Error';
const method = `_on${gist}Item`;
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 = () => {
const headers = this._parseHeaders(xhr.getAllResponseHeaders());
const response = this._transformResponse(xhr.response, headers);
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 = () => {
const headers = this._parseHeaders(xhr.getAllResponseHeaders());
const response = this._transformResponse(xhr.response, headers);
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);
};
if (item.method && item.url) {
xhr.open(item.method, item.url, true);
}
xhr.open(item.method, item.url, true);
xhr.withCredentials = item.withCredentials;
if (this.options.headers) {
for (const header of this.options.headers) {
for (let header of this.options.headers) {
xhr.setRequestHeader(header.name, header.value);
}
}
if (item.headers.length) {
for (const header of item.headers) {
for (let header of item.headers) {
xhr.setRequestHeader(header.name, header.value);
}
}
if (this.authToken && this.authTokenHeader) {
if (this.authToken) {
xhr.setRequestHeader(this.authTokenHeader, this.authToken);
}
xhr.onreadystatechange = function () {
if (xhr.readyState == XMLHttpRequest.DONE) {
that.response.emit(xhr.responseText);
that.response.emit(xhr.responseText)
}
};
}
if (this.options.formatDataFunctionIsAsync) {
sendable.then(
(result: any) => xhr.send(JSON.stringify(result))
@@ -394,32 +386,30 @@ export class FileUploader {
this._render();
}
protected _getTotalProgress(value = 0): number {
protected _getTotalProgress(value: number = 0): number {
if (this.options.removeAfterUpload) {
return value;
}
const notUploaded = this.getNotUploadedItems().length;
const uploaded = notUploaded ? this.queue.length - notUploaded : this.queue.length;
const ratio = 100 / this.queue.length;
const current = value * ratio / 100;
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);
}
protected _getFilters(filters?: FilterFunction[] | string): FilterFunction[] | [] {
protected _getFilters(filters: FilterFunction[] | string): FilterFunction[] {
if (!filters) {
return this.options?.filters || [];
return this.options.filters;
}
if (Array.isArray(filters)) {
return filters;
}
if (typeof filters === 'string') {
const names = filters.match(/[^\s,]+/g);
return this.options?.filters || []
.filter((filter: any) => names?.indexOf(filter.name) !== -1);
let names = filters.match(/[^\s,]+/g);
return this.options.filters
.filter((filter: any) => names.indexOf(filter.name) !== -1);
}
return this.options?.filters || [];
return this.options.filters;
}
protected _render(): any {
@@ -432,12 +422,8 @@ export class FileUploader {
protected _isValidFile(file: FileLikeObject, filters: FilterFunction[], options: FileUploaderOptions): boolean {
this._failFilterIndex = -1;
return !filters.length ? true : filters.every((filter: FilterFunction) => {
if (this._failFilterIndex) {
this._failFilterIndex++;
}
this._failFilterIndex++;
return filter.fn.call(this, file, options);
});
}
@@ -451,7 +437,7 @@ export class FileUploader {
}
protected _parseHeaders(headers: string): ParsedResponseHeaders {
const parsed: any = {};
let parsed: any = {};
let key: any;
let val: any;
let i: any;
@@ -466,7 +452,6 @@ export class FileUploader {
parsed[ key ] = parsed[ key ] ? parsed[ key ] + ', ' + val : val;
}
});
return parsed;
}
@@ -493,7 +478,7 @@ export class FileUploader {
}
protected _onProgressItem(item: FileItem, progress: any): void {
const total = this._getTotalProgress(progress);
let total = this._getTotalProgress(progress);
this.progress = total;
item._onProgress(progress);
this.onProgressItem(item, progress);
@@ -1,8 +1,7 @@
export * from './file-upload/file-select.directive';
export * from './file-upload/file-drop.directive';
export * from './file-upload/file-uploader.class';
export * from './file-upload/file-item.class';
export * from './file-upload/file-like-object.class';
export * from './file-upload/file-like-object.class';
export { FileUploadModule } from './file-upload/file-upload.module';
export { FileSelectDirective } from './file-upload/file-select.directive';
+1
View File
@@ -0,0 +1 @@
export * from './index';
+8
View File
@@ -0,0 +1,8 @@
{
"name": "ng2-file-upload",
"version": "1.3.0",
"peerDependencies": {
"@angular/common": "*",
"@angular/core": "*"
}
}
@@ -2,9 +2,9 @@ import { Component, DebugElement } from '@angular/core';
import { By } from '@angular/platform-browser';
import { inject, ComponentFixture, TestBed } from '@angular/core/testing';
import { FileUploader } from '../../file-upload/file-uploader.class';
import { FileUploadModule } from '../../file-upload/file-upload.module';
import { FileDropDirective } from '../../file-upload/file-drop.directive';
import { FileUploader } from '../file-upload/file-uploader.class';
import { FileUploadModule } from '../file-upload/file-upload.module';
import { FileDropDirective } from '../file-upload/file-drop.directive';
@Component({
selector: 'container',
@@ -57,15 +57,13 @@ describe('Directive: FileDropDirective', () => {
const options = fileDropDirective.getOptions();
// Check url set through binding
expect(options.url).toBe(hostComponent.url);
// Check default options
expect(options).toBeTruthy();
if (options) {
expect(options.url).toBe(hostComponent.url);
expect(options.autoUpload).toBeFalsy();
expect(options.isHTML5).toBeTruthy();
expect(options.removeAfterUpload).toBeFalsy();
expect(options.disableMultipart).toBeFalsy();
}
expect(options.autoUpload).toBeFalsy();
expect(options.isHTML5).toBeTruthy();
expect(options.removeAfterUpload).toBeFalsy();
expect(options.disableMultipart).toBeFalsy();
});
it('can get filters', () => {
@@ -95,8 +93,9 @@ describe('Directive: FileDropDirective', () => {
fileDropDirective.onDrop(getFakeEventData());
const uploadedFiles = getFakeEventData().dataTransfer.files;
const expectedArguments = [ uploadedFiles, fileDropDirective.getOptions(), fileDropDirective.getFilters() ];
expect(fileDropDirective.uploader.addToQueue).toHaveBeenCalledWith(uploadedFiles, fileDropDirective.getOptions(), fileDropDirective.getFilters());
expect(fileDropDirective.uploader.addToQueue).toHaveBeenCalledWith(...expectedArguments);
expect(fileOverData).toBeFalsy();
expect(fileDropData).toEqual(uploadedFiles);
});
@@ -144,5 +143,5 @@ function getFakeEventData(): any {
},
preventDefault: () => undefined,
stopPropagation: () => undefined
};
}
}
@@ -2,9 +2,9 @@ import { TestBed, ComponentFixture } from '@angular/core/testing';
import { Component, DebugElement } from '@angular/core';
import { By } from '@angular/platform-browser';
import { FileUploadModule } from '../../file-upload/file-upload.module';
import { FileSelectDirective } from '../../file-upload/file-select.directive';
import { FileUploader } from '../../file-upload/file-uploader.class';
import { FileUploadModule } from '../file-upload/file-upload.module';
import { FileSelectDirective } from '../file-upload/file-select.directive';
import { FileUploader } from '../file-upload/file-uploader.class';
@Component({
selector: 'container',
@@ -54,18 +54,15 @@ describe('Directive: FileSelectDirective', () => {
it('can get uploader options', () => {
const options = fileSelectDirective.getOptions();
expect(options).toBeTruthy();
if (options) {
// Check url set through binding
expect(options.url).toBe(hostComponent.url);
// Check default options
expect(options.autoUpload).toBeFalsy();
expect(options.isHTML5).toBeTruthy();
expect(options.removeAfterUpload).toBeFalsy();
expect(options.disableMultipart).toBeFalsy();
}
// Check url set through binding
expect(options.url).toBe(hostComponent.url);
// Check default options
expect(options.autoUpload).toBeFalsy();
expect(options.isHTML5).toBeTruthy();
expect(options.removeAfterUpload).toBeFalsy();
expect(options.disableMultipart).toBeFalsy();
});
it('can get filters', () => {
@@ -94,6 +91,9 @@ describe('Directive: FileSelectDirective', () => {
fileSelectDirective.onChange();
expect(fileSelectDirective.uploader.addToQueue).toHaveBeenCalledWith(directiveElement.nativeElement.files, fileSelectDirective.getOptions(), fileSelectDirective.getFilters());
const expectedArguments = [ directiveElement.nativeElement.files,
fileSelectDirective.getOptions(),
fileSelectDirective.getFilters() ];
expect(fileSelectDirective.uploader.addToQueue).toHaveBeenCalledWith(...expectedArguments);
});
});
+37
View File
@@ -0,0 +1,37 @@
{
"compilerOptions": {
"outDir": "../dist",
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"sourceMap": false,
"noEmitHelpers": false,
"noImplicitAny": true,
"declaration": true,
"skipLibCheck": true,
"stripInternal": true,
"noUnusedLocals": false,
"noUnusedParameters": false,
"lib": ["dom", "es6"],
"types": [
"jasmine",
"webpack"
],
"typeRoots": [
"../node_modules/@types"
]
},
"exclude": [
"node_modules"
],
"files": [
"../scripts/typings.d.ts",
"./ng2-file-upload.ts",
"./index.ts"
],
"angularCompilerOptions": {
"genDir": "../temp/factories"
}
}
-27
View File
@@ -1,27 +0,0 @@
{
"compileOnSave": false,
"compilerOptions": {
"rootDir": ".",
"sourceMap": true,
"declaration": false,
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"importHelpers": true,
"target": "es2015",
"module": "esnext",
"lib": [
"es2017",
"dom"
],
"skipLibCheck": true,
"skipDefaultLibCheck": true,
"baseUrl": ".",
"paths": {
"ng2-file-upload": [
"libs/ng2-file-upload/index.ts"
]
}
},
"exclude": []
}