mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-12 17:04:57 +00:00
* upgrade to HttpClient * upgrade to Renderer2 * upgrade Document reference * remove useless test with deprecated ReflectiveInjector * upgrade to latest typescript * upgrade libs * upgrade package scripts * remove rxjs blacklists and duplicate rules * add rxjs compat to help with migration * fix breaking changes * fix breaking changes in material * fix breaking changes (material 6) * upgrade rxjs, ngx-translate and flex layout * update unit tests * restore providers * upgrade deprecated Observable.error * rebase fix first configuration problems * fix style issues commented * fix core build * fix lib template errors * move lib test execution in angular.json * ignore * karma conf files * fix import statement test * single run option * update packages reporter * restore report * increase timeout * improve karma conf test configuration * fix test issues about lint * fix test analytics * fix process service test * content service fix test * fix logout directive test * fix core test * fix build * update node-sass to latest * update angular cli dependencies * improve build script create directorites and move files only if previous command succeded * upgrade individual libs to 6.0 * remove old webpack files * revert sass change * fix type issues fix style issues * fix tslint demo shell issue * fix peerdependencies * fix test e2e BC * package upate * fix style import issue * extract-text-webpack-plugin beta * fix test dist build command * remove alpha js-api * fix tslint issue add banner tslint rule * upload service fix * change BC script * fix test dist script * increase demo shell timeout test * verbose copy * path absolute * fix script bc * fix copy part * fix path warning fix monaco editor * remove duplicate header * remove unused import * fix align and check ago tests * add missing import * fix notification button selector * [ANGULAR6] fixed core tests * fix CS test * fix cs test step 2 * increase travis_wait for dist * fix attachment PS * fix checklist test * use pdf min
263 lines
8.4 KiB
TypeScript
263 lines
8.4 KiB
TypeScript
/*!
|
|
* @license
|
|
* Copyright 2016 Alfresco Software, Ltd.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
/* tslint:disable:no-input-rename */
|
|
|
|
import { Directive, ElementRef, HostListener, Input, NgZone, OnDestroy, OnInit, Renderer2 } from '@angular/core';
|
|
import { FileInfo, FileUtils } from '../utils/file-utils';
|
|
|
|
@Directive({
|
|
selector: '[adf-upload]'
|
|
})
|
|
export class UploadDirective implements OnInit, OnDestroy {
|
|
|
|
/** Enables/disables uploading. */
|
|
@Input('adf-upload')
|
|
enabled: boolean = true;
|
|
|
|
/** Data to upload. */
|
|
@Input('adf-upload-data')
|
|
data: any;
|
|
|
|
/** Upload mode. Can be "drop" (receives dropped files) or "click"
|
|
* (clicking opens a file dialog). Both modes can be active at once.
|
|
*/
|
|
@Input()
|
|
mode: string[] = ['drop']; // click|drop
|
|
|
|
/** Toggles multiple file uploads. */
|
|
@Input()
|
|
multiple: boolean;
|
|
|
|
/** (Click mode only) MIME type filter for files to accept. */
|
|
@Input()
|
|
accept: string;
|
|
|
|
/** (Click mode only) Toggles uploading of directories. */
|
|
@Input()
|
|
directory: boolean;
|
|
|
|
isDragging: boolean = false;
|
|
|
|
private cssClassName: string = 'adf-upload__dragging';
|
|
private upload: HTMLInputElement;
|
|
private element: HTMLElement;
|
|
|
|
constructor(private el: ElementRef, private renderer: Renderer2, private ngZone: NgZone) {
|
|
this.element = el.nativeElement;
|
|
}
|
|
|
|
ngOnInit() {
|
|
if (this.isClickMode() && this.renderer) {
|
|
let inputUpload = this.renderer.createElement('input');
|
|
this.upload = this.el.nativeElement.parentElement.appendChild(inputUpload);
|
|
|
|
this.upload.type = 'file';
|
|
this.upload.style.display = 'none';
|
|
this.upload.addEventListener('change', e => this.onSelectFiles(e));
|
|
|
|
if (this.multiple) {
|
|
this.upload.setAttribute('multiple', '');
|
|
}
|
|
|
|
if (this.accept) {
|
|
this.upload.setAttribute('accept', this.accept);
|
|
}
|
|
|
|
if (this.directory) {
|
|
this.upload.setAttribute('webkitdirectory', '');
|
|
}
|
|
}
|
|
|
|
if (this.isDropMode()) {
|
|
this.ngZone.runOutsideAngular(() => {
|
|
this.element.addEventListener('dragenter', this.onDragEnter.bind(this));
|
|
this.element.addEventListener('dragover', this.onDragOver.bind(this));
|
|
this.element.addEventListener('dragleave', this.onDragLeave.bind(this));
|
|
this.element.addEventListener('drop', this.onDrop.bind(this));
|
|
});
|
|
}
|
|
}
|
|
|
|
ngOnDestroy() {
|
|
this.element.removeEventListener('dragenter', this.onDragEnter);
|
|
this.element.removeEventListener('dragover', this.onDragOver);
|
|
this.element.removeEventListener('dragleave', this.onDragLeave);
|
|
this.element.removeEventListener('drop', this.onDrop);
|
|
}
|
|
|
|
@HostListener('click', ['$event'])
|
|
onClick(event: Event) {
|
|
if (this.isClickMode() && this.upload) {
|
|
event.preventDefault();
|
|
this.upload.click();
|
|
}
|
|
}
|
|
|
|
onDragEnter(event: Event) {
|
|
if (this.isDropMode()) {
|
|
this.element.classList.add(this.cssClassName);
|
|
this.isDragging = true;
|
|
}
|
|
}
|
|
|
|
onDragOver(event: Event) {
|
|
event.preventDefault();
|
|
if (this.isDropMode()) {
|
|
this.element.classList.add(this.cssClassName);
|
|
this.isDragging = true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
onDragLeave(event) {
|
|
if (this.isDropMode()) {
|
|
this.element.classList.remove(this.cssClassName);
|
|
this.isDragging = false;
|
|
}
|
|
}
|
|
|
|
onDrop(event: Event) {
|
|
if (this.isDropMode()) {
|
|
|
|
event.stopPropagation();
|
|
event.preventDefault();
|
|
|
|
this.element.classList.remove(this.cssClassName);
|
|
this.isDragging = false;
|
|
|
|
const dataTranfer = this.getDataTransfer(event);
|
|
if (dataTranfer) {
|
|
this.getFilesDropped(dataTranfer).then(files => {
|
|
this.onUploadFiles(files);
|
|
});
|
|
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
onUploadFiles(files: FileInfo[]) {
|
|
if (this.enabled && files.length > 0) {
|
|
let e = new CustomEvent('upload-files', {
|
|
detail: {
|
|
sender: this,
|
|
data: this.data,
|
|
files: files
|
|
},
|
|
bubbles: true
|
|
});
|
|
|
|
this.el.nativeElement.dispatchEvent(e);
|
|
}
|
|
}
|
|
|
|
protected hasMode(mode: string): boolean {
|
|
return this.enabled && mode && this.mode && this.mode.indexOf(mode) > -1;
|
|
}
|
|
|
|
protected isDropMode(): boolean {
|
|
return this.hasMode('drop');
|
|
}
|
|
|
|
protected isClickMode(): boolean {
|
|
return this.hasMode('click');
|
|
}
|
|
|
|
getDataTransfer(event: Event | any): DataTransfer {
|
|
if (event && event.dataTransfer) {
|
|
return event.dataTransfer;
|
|
}
|
|
if (event && event.originalEvent && event.originalEvent.dataTransfer) {
|
|
return event.originalEvent.dataTransfer;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Extract files from the DataTransfer object used to hold the data that is being dragged during a drag and drop operation.
|
|
* @param dataTransfer DataTransfer object
|
|
*/
|
|
getFilesDropped(dataTransfer: DataTransfer): Promise<FileInfo[]> {
|
|
return new Promise(resolve => {
|
|
const iterations = [];
|
|
|
|
if (dataTransfer) {
|
|
const items = dataTransfer.items;
|
|
if (items) {
|
|
for (let i = 0; i < items.length; i++) {
|
|
if (typeof items[i].webkitGetAsEntry !== 'undefined') {
|
|
let item = items[i].webkitGetAsEntry();
|
|
if (item) {
|
|
if (item.isFile) {
|
|
iterations.push(Promise.resolve(<FileInfo> {
|
|
entry: item,
|
|
file: items[i].getAsFile(),
|
|
relativeFolder: '/'
|
|
}));
|
|
} else if (item.isDirectory) {
|
|
iterations.push(new Promise(resolveFolder => {
|
|
FileUtils.flattern(item).then(files => resolveFolder(files));
|
|
}));
|
|
}
|
|
}
|
|
} else {
|
|
iterations.push(Promise.resolve(<FileInfo> {
|
|
entry: null,
|
|
file: items[i].getAsFile(),
|
|
relativeFolder: '/'
|
|
}));
|
|
}
|
|
}
|
|
} else {
|
|
// safari or FF
|
|
let files = FileUtils
|
|
.toFileArray(dataTransfer.files)
|
|
.map(file => <FileInfo> {
|
|
entry: null,
|
|
file: file,
|
|
relativeFolder: '/'
|
|
});
|
|
|
|
iterations.push(Promise.resolve(files));
|
|
}
|
|
}
|
|
|
|
Promise.all(iterations).then(result => {
|
|
resolve(result.reduce((a, b) => a.concat(b), []));
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Invoked when user selects files or folders by means of File Dialog
|
|
* @param e DOM event
|
|
*/
|
|
onSelectFiles(e: any): void {
|
|
if (this.isClickMode()) {
|
|
const input = (<HTMLInputElement> e.currentTarget);
|
|
const files = FileUtils.toFileArray(input.files);
|
|
this.onUploadFiles(files.map(file => <FileInfo> {
|
|
entry: null,
|
|
file: file,
|
|
relativeFolder: '/'
|
|
}));
|
|
e.target.value = '';
|
|
}
|
|
}
|
|
}
|