mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
improved uploading of files (#1730)
* improved uploading of files - new core/UploadDirective to allow dropping files to any html element - enhanced file dropping for DataTable rows (disabled by default) - enhanced file dropping for DocumentList rows (disabled by default) - upload drop area now handles file uploads for child elements (i.e. rows in the document list) * fix unit tests * unit tests and code cleanup * #1732, fix upload of folders
This commit is contained in:
committed by
Mario Romano
parent
f3de023ab3
commit
3fee3b5002
@@ -128,7 +128,7 @@ export class UploadButtonComponent {
|
||||
let directoryName = this.getDirectoryName(directoryPath);
|
||||
let absolutePath = this.currentFolderPath + this.getDirectoryPath(directoryPath);
|
||||
|
||||
this.uploadService.createFolder(absolutePath, directoryName)
|
||||
this.uploadService.createFolder(absolutePath, directoryName, this.rootFolderId)
|
||||
.subscribe(
|
||||
res => {
|
||||
let relativeDir = this.currentFolderPath + '/' + directoryPath;
|
||||
|
@@ -4,8 +4,7 @@
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.input-focus {
|
||||
.file-draggable__input-focus {
|
||||
color: #2196F3;
|
||||
margin-left: 3px;
|
||||
border: 3px dashed #2196F3;
|
||||
border: 1px dashed #2196F3;
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@
|
||||
(onFilesDropped)="onFilesDropped($event)"
|
||||
(onFilesEntityDropped)="onFilesEntityDropped($event)"
|
||||
(onFolderEntityDropped)="onFolderEntityDropped($event)"
|
||||
(upload-files)="onUploadFiles($event)"
|
||||
dropzone="" webkitdropzone="*" #droparea>
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
|
@@ -72,16 +72,35 @@ export class UploadDragAreaComponent {
|
||||
this.uploadService.setOptions(formFields, this.versioning);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles 'upload-files' events raised by child components.
|
||||
* @param e DOM event
|
||||
*/
|
||||
onUploadFiles(e: CustomEvent) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
let files = e.detail.files;
|
||||
if (files && files.length > 0) {
|
||||
if (e.detail.data.obj.entry.isFolder) {
|
||||
let id = e.detail.data.obj.entry.id;
|
||||
this.onFilesDropped(files, id, '/');
|
||||
} else {
|
||||
this.onFilesDropped(files);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method called when files are dropped in the drag area.
|
||||
*
|
||||
* @param {File[]} files - files dropped in the drag area.
|
||||
*/
|
||||
onFilesDropped(files: File[]): void {
|
||||
onFilesDropped(files: File[], rootId?: string, directory?: string): void {
|
||||
if (files.length) {
|
||||
if (this.checkValidity(files)) {
|
||||
this.uploadService.addToQueue(files);
|
||||
this.uploadService.uploadFilesInTheQueue(this.rootFolderId, this.currentFolderPath, this.onSuccess);
|
||||
this.uploadService.uploadFilesInTheQueue(rootId || this.rootFolderId, directory || this.currentFolderPath, this.onSuccess);
|
||||
let latestFilesAdded = this.uploadService.getQueue();
|
||||
if (this.showNotificationBar) {
|
||||
this.showUndoNotificationBar(latestFilesAdded);
|
||||
@@ -132,7 +151,7 @@ export class UploadDragAreaComponent {
|
||||
let relativePath = folder.fullPath.replace(folder.name, '');
|
||||
relativePath = this.currentFolderPath + relativePath;
|
||||
|
||||
this.uploadService.createFolder(relativePath, folder.name)
|
||||
this.uploadService.createFolder(relativePath, folder.name, this.rootFolderId)
|
||||
.subscribe(
|
||||
message => {
|
||||
this.onSuccess.emit({
|
||||
|
@@ -19,7 +19,7 @@ import { FileDraggableDirective } from '../directives/file-draggable.directive';
|
||||
|
||||
describe('FileDraggableDirective', () => {
|
||||
|
||||
let component;
|
||||
let component: FileDraggableDirective;
|
||||
|
||||
beforeEach( () => {
|
||||
component = new FileDraggableDirective();
|
||||
@@ -51,7 +51,7 @@ describe('FileDraggableDirective', () => {
|
||||
done();
|
||||
});
|
||||
|
||||
component._onDropFiles(fakeEvent);
|
||||
component.onDropFiles(fakeEvent);
|
||||
});
|
||||
|
||||
it('should emit onFilesDropped event when a file is dragged not with Chrome' , (done) => {
|
||||
@@ -70,7 +70,7 @@ describe('FileDraggableDirective', () => {
|
||||
done();
|
||||
});
|
||||
|
||||
component._onDropFiles(fakeEvent);
|
||||
component.onDropFiles(fakeEvent);
|
||||
});
|
||||
|
||||
it('should emit onFilesDropped event when a file is dragged with Chrome', (done) => {
|
||||
@@ -90,7 +90,7 @@ describe('FileDraggableDirective', () => {
|
||||
done();
|
||||
});
|
||||
|
||||
component._onDropFiles(fakeEvent);
|
||||
component.onDropFiles(fakeEvent);
|
||||
});
|
||||
|
||||
it('should take the focus when the drag enter is called', () => {
|
||||
@@ -98,7 +98,7 @@ describe('FileDraggableDirective', () => {
|
||||
spyOn(mockEvent, 'preventDefault');
|
||||
|
||||
expect(component.getInputFocus()).toBe(false);
|
||||
component._onDragEnter(mockEvent);
|
||||
component.onDragEnter(mockEvent);
|
||||
expect(component.getInputFocus()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Directive, EventEmitter, Output } from '@angular/core';
|
||||
import { Directive, HostListener, HostBinding, EventEmitter, Output } from '@angular/core';
|
||||
|
||||
/**
|
||||
* [file-draggable]
|
||||
@@ -29,17 +29,12 @@ import { Directive, EventEmitter, Output } from '@angular/core';
|
||||
* @returns {FileDraggableDirective} .
|
||||
*/
|
||||
@Directive({
|
||||
selector: '[file-draggable]',
|
||||
host: {
|
||||
'(drop)': '_onDropFiles($event)',
|
||||
'(dragenter)': '_onDragEnter($event)',
|
||||
'(dragleave)': '_onDragLeave($event)',
|
||||
'(dragover)': '_onDragOver($event)',
|
||||
'[class.input-focus]': '_inputFocusClass'
|
||||
}
|
||||
selector: '[file-draggable]'
|
||||
})
|
||||
export class FileDraggableDirective {
|
||||
|
||||
files: File [];
|
||||
|
||||
@Output()
|
||||
onFilesDropped: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
@@ -49,41 +44,39 @@ export class FileDraggableDirective {
|
||||
@Output()
|
||||
onFolderEntityDropped: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
files: File [];
|
||||
|
||||
private _inputFocusClass: boolean = false;
|
||||
|
||||
constructor() {
|
||||
}
|
||||
@HostBinding('class.file-draggable__input-focus')
|
||||
inputFocusClass: boolean = false;
|
||||
|
||||
/**
|
||||
* Method called when files is dropped in the drag and drop area.
|
||||
*
|
||||
* @param {$event} $event - DOM $event.
|
||||
* @param event DOM event.
|
||||
*/
|
||||
_onDropFiles($event: any): void {
|
||||
this._preventDefault($event);
|
||||
@HostListener('drop', ['$event'])
|
||||
onDropFiles(event: any): void {
|
||||
if (!event.defaultPrevented) {
|
||||
this.preventDefault(event);
|
||||
|
||||
let items = $event.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) {
|
||||
this._traverseFileTree(item);
|
||||
let items = event.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) {
|
||||
this.traverseFileTree(item);
|
||||
}
|
||||
} else {
|
||||
let files = event.dataTransfer.files;
|
||||
this.onFilesDropped.emit(files);
|
||||
}
|
||||
} else {
|
||||
let files = $event.dataTransfer.files;
|
||||
this.onFilesDropped.emit(files);
|
||||
}
|
||||
} else {
|
||||
// safari or FF
|
||||
let files = event.dataTransfer.files;
|
||||
this.onFilesDropped.emit(files);
|
||||
}
|
||||
} else {
|
||||
// safari or FF
|
||||
let files = $event.dataTransfer.files;
|
||||
this.onFilesDropped.emit(files);
|
||||
}
|
||||
|
||||
this._inputFocusClass = false;
|
||||
this.inputFocusClass = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,7 +84,7 @@ export class FileDraggableDirective {
|
||||
*
|
||||
* @param {Object} item - can contains files or folders.
|
||||
*/
|
||||
private _traverseFileTree(item: any): void {
|
||||
private traverseFileTree(item: any): void {
|
||||
if (item.isFile) {
|
||||
let self = this;
|
||||
self.onFilesEntityDropped.emit(item);
|
||||
@@ -105,44 +98,50 @@ export class FileDraggableDirective {
|
||||
/**
|
||||
* Change the style of the drag area when a file drag in.
|
||||
*
|
||||
* @param {$event} $event - DOM $event.
|
||||
* @param {event} event - DOM event.
|
||||
*/
|
||||
_onDragEnter($event: Event): void {
|
||||
this._preventDefault($event);
|
||||
|
||||
this._inputFocusClass = true;
|
||||
@HostListener('dragenter', ['$event'])
|
||||
onDragEnter(event: Event): void {
|
||||
if (!event.defaultPrevented) {
|
||||
this.preventDefault(event);
|
||||
this.inputFocusClass = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the style of the drag area when a file drag out.
|
||||
*
|
||||
* @param {$event} $event - DOM $event.
|
||||
* @param {event} event - DOM event.
|
||||
*/
|
||||
_onDragLeave($event: Event): void {
|
||||
this._preventDefault($event);
|
||||
|
||||
this._inputFocusClass = false;
|
||||
@HostListener('dragleave', ['$event'])
|
||||
onDragLeave(event: Event): void {
|
||||
if (!event.defaultPrevented) {
|
||||
this.preventDefault(event);
|
||||
this.inputFocusClass = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the style of the drag area when a file is over the drag area.
|
||||
*
|
||||
* @param $event
|
||||
* @private
|
||||
* @param event
|
||||
*/
|
||||
_onDragOver($event: Event): void {
|
||||
this._preventDefault($event);
|
||||
this._inputFocusClass = true;
|
||||
@HostListener('dragover', ['$event'])
|
||||
onDragOver(event: Event): void {
|
||||
if (!event.defaultPrevented) {
|
||||
this.preventDefault(event);
|
||||
this.inputFocusClass = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent default and stop propagation of the DOM event.
|
||||
*
|
||||
* @param {$event} $event - DOM $event.
|
||||
* @param {event} $event - DOM event.
|
||||
*/
|
||||
_preventDefault($event: Event): void {
|
||||
$event.stopPropagation();
|
||||
$event.preventDefault();
|
||||
preventDefault(event: Event): void {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,6 +149,6 @@ export class FileDraggableDirective {
|
||||
* @returns {boolean}
|
||||
*/
|
||||
getInputFocus () {
|
||||
return this._inputFocusClass;
|
||||
return this.inputFocusClass;
|
||||
}
|
||||
}
|
||||
|
@@ -162,17 +162,14 @@ export class UploadService {
|
||||
* Create a folder
|
||||
* @param name - the folder name
|
||||
*/
|
||||
createFolder(relativePath: string, name: string) {
|
||||
return Observable.fromPromise(this.callApiCreateFolder(relativePath, name))
|
||||
.map(res => {
|
||||
return res;
|
||||
})
|
||||
createFolder(relativePath: string, name: string, parentId?: string) {
|
||||
return Observable.fromPromise(this.callApiCreateFolder(relativePath, name, parentId))
|
||||
.do(data => this.logService.info('Node data', data)) // eyeball results in the console
|
||||
.catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
callApiCreateFolder(relativePath: string, name: string): Promise<MinimalNodeEntity> {
|
||||
return this.apiService.getInstance().nodes.createFolder(name, relativePath);
|
||||
callApiCreateFolder(relativePath: string, name: string, parentId?: string): Promise<MinimalNodeEntity> {
|
||||
return this.apiService.getInstance().nodes.createFolder(name, relativePath, parentId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user