[ADF-1188] Upload related components, unify interfaces, deprecate disableWithNoPermission (#2216)

* Deprecate enabled input property in UploadDragAreaComponent

* Refactoring about disabled property

* using adf-node-permission directive, deprecating disableWithNoPermission

* Parent component access from directive

* Upliad drag area component uses the directive also

* Usage of property instead of helper method in the NodePermissionSubjects

* Fix small issues

* Update readme files
This commit is contained in:
Popovics András
2017-08-16 15:44:04 +02:00
committed by Mario Romano
parent 9cd188aa4f
commit ac55704220
12 changed files with 494 additions and 218 deletions

View File

@@ -92,7 +92,7 @@ npm install ng2-alfresco-upload
| parentId | string | empty | The ID of the root. It can be the nodeId if you are using the upload for the Content Service or taskId/processId for the Process Service. |
| versioning | boolean | false | Versioning false is the default uploader behaviour and it renames the file using an integer suffix if there is a name clash. Versioning true to indicate that a major version should be created |
| staticTitle | string | (predefined) | define the text of the upload button |
| disableWithNoPermission | boolean | false | If the value is true and the user doesn't have the permission to delete the node the button will be disabled |
| **(deprecated)** disableWithNoPermission ***use node permission directive from core instead*** | boolean | false | If the value is true and the user doesn't have the permission to delete the node the button will be disabled |
| tooltip | string | | Custom tooltip |
### Events
@@ -171,7 +171,8 @@ export class AppComponent {
| Name | Type | Default | Description |
| --- | --- | --- | --- |
| enabled | boolean | true | Toggle component enabled state |
| disabled | boolean | false | Toggle component disabled state |
| **(deprecated)** enabled | boolean | true | Toggle component enabled state |
| **(deprecated)** showNotificationBar | boolean | true | Hide/show notification bar. **Deprecated in 1.6.0: use UploadService events and NotificationService api instead.** |
| rootFolderId | string | '-root-' | The ID of the root folder node. |
| **(deprecated)** currentFolderPath | string | '/' | define the path where the files are uploaded. **Deprecated in 1.6.0: use rootFolderId instead.** |

View File

@@ -15,31 +15,47 @@
* limitations under the License.
*/
import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
import { Component, EventEmitter, forwardRef, Input, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core';
import { MinimalNodeEntryEntity } from 'alfresco-js-api';
import { AlfrescoApiService, AlfrescoTranslationService, FileModel, FileUtils, LogService, NotificationService, UploadService } from 'ng2-alfresco-core';
import {
AlfrescoApiService,
AlfrescoTranslationService,
EXTENDIBLE_COMPONENT,
FileModel,
FileUtils,
LogService,
NodePermissionSubject,
NotificationService,
UploadService
} from 'ng2-alfresco-core';
import { Observable, Subject } from 'rxjs/Rx';
import { PermissionModel } from '../models/permissions.model';
@Component({
selector: 'adf-upload-button, alfresco-upload-button',
templateUrl: './upload-button.component.html',
styleUrls: ['./upload-button.component.css']
styleUrls: ['./upload-button.component.css'],
providers: [
{ provide: EXTENDIBLE_COMPONENT, useExisting: forwardRef(() => UploadButtonComponent)}
]
})
export class UploadButtonComponent implements OnInit, OnChanges {
export class UploadButtonComponent implements OnInit, OnChanges, NodePermissionSubject {
/** @deprecated Deprecated in 1.6.0, you can use UploadService events and NotificationService api instead. */
@Input()
showNotificationBar: boolean = true;
/** @deprecated Deprecated in 1.6.0, this property is not used for couple of releases already. */
@Input()
currentFolderPath: string = '/';
/** @deprecated Deprecated in 1.8.0, use the button with combination of adf-node-permission directive */
@Input()
disableWithNoPermission: boolean = false;
@Input()
disabled: boolean = false;
/**
* @deprecated Deprecated in 1.6.0, you can use UploadService events and NotificationService api instead.
*
* @type {boolean}
* @memberof UploadButtonComponent
*/
@Input()
showNotificationBar: boolean = true;
@Input()
uploadFolders: boolean = false;
@@ -58,21 +74,9 @@ export class UploadButtonComponent implements OnInit, OnChanges {
@Input()
tooltip: string = null;
/**
* @deprecated Deprecated in 1.6.0, this property is not used for couple of releases already.
*
* @type {string}
* @memberof UploadDragAreaComponent
*/
@Input()
currentFolderPath: string = '/';
@Input()
rootFolderId: string = '-root-';
@Input()
disableWithNoPermission: boolean = false;
@Output()
onSuccess = new EventEmitter();
@@ -117,6 +121,7 @@ export class UploadButtonComponent implements OnInit, OnChanges {
return this.disabled ? true : undefined;
}
/** @deprecated Deprecated in 1.8.0, use the button with combination of adf-node-permission directive */
isDisableWithNoPermission(): boolean {
return !this.hasPermission && this.disableWithNoPermission ? true : undefined;
}

View File

@@ -1,4 +1,4 @@
<div [file-draggable]="enabled" id="UploadBorder" class="upload-border"
<div [file-draggable]="isDroppable()" id="UploadBorder" class="upload-border"
(onFilesDropped)="onFilesDropped($event)"
(onFilesEntityDropped)="onFilesEntityDropped($event)"
(onFolderEntityDropped)="onFolderEntityDropped($event)"

View File

@@ -23,40 +23,38 @@ import { TranslationMock } from '../assets/translation.service.mock';
import { FileDraggableDirective } from '../directives/file-draggable.directive';
import { UploadDragAreaComponent } from './upload-drag-area.component';
let fakeShareDataRow = {
obj: {
entry: {
createdAt: '2017-06-04T04:32:15.597Z',
path: {
name: '/Company Home/User Homes/Test',
isComplete: true,
elements: [
{
id: '94acfc73-7014-4475-9bd9-93a2162f0f8c',
name: 'Company Home'
},
{
id: '55052317-7e59-4058-8e07-769f41e615e1',
name: 'User Homes'
},
{
id: '70e1cc6a-6918-468a-b84a-1048093b06fd',
name: 'Test'
}
]
},
isFolder: true,
name: 'pippo',
id: '7462d28e-bd43-4b91-9e7b-0d71598680ac',
nodeType: 'cm:folder',
allowableOperations: [
'delete',
'update',
'create'
]
function getFakeShareDataRow(allowableOperations = ['delete', 'update', 'create']) {
return {
obj: {
entry: {
createdAt: '2017-06-04T04:32:15.597Z',
path: {
name: '/Company Home/User Homes/Test',
isComplete: true,
elements: [
{
id: '94acfc73-7014-4475-9bd9-93a2162f0f8c',
name: 'Company Home'
},
{
id: '55052317-7e59-4058-8e07-769f41e615e1',
name: 'User Homes'
},
{
id: '70e1cc6a-6918-468a-b84a-1048093b06fd',
name: 'Test'
}
]
},
isFolder: true,
name: 'pippo',
id: '7462d28e-bd43-4b91-9e7b-0d71598680ac',
nodeType: 'cm:folder',
allowableOperations
}
}
}
};
};
}
describe('UploadDragAreaComponent', () => {
@@ -100,6 +98,96 @@ describe('UploadDragAreaComponent', () => {
TestBed.resetTestingModule();
});
describe('When disabled', () => {
it('should NOT upload the list of files dropped', () => {
component.enabled = false;
spyOn(uploadService, 'addToQueue');
spyOn(uploadService, 'uploadFilesInTheQueue');
fixture.detectChanges();
const file = <File> {name: 'fake-name-1', size: 10, webkitRelativePath: 'fake-folder1/fake-name-1.json'};
let filesList = [file];
component.onFilesDropped(filesList);
expect(uploadService.addToQueue).not.toHaveBeenCalled();
expect(uploadService.uploadFilesInTheQueue).not.toHaveBeenCalled();
});
it('should NOT upload the file dropped', () => {
component.enabled = false;
spyOn(uploadService, 'addToQueue');
spyOn(uploadService, 'uploadFilesInTheQueue');
fixture.detectChanges();
let itemEntity = {
fullPath: '/folder-fake/file-fake.png',
isDirectory: false,
isFile: true,
name: 'file-fake.png',
file: (callbackFile) => {
let fileFake = new File(['fakefake'], 'file-fake.png', {type: 'image/png'});
callbackFile(fileFake);
}
};
component.onFilesEntityDropped(itemEntity);
expect(uploadService.addToQueue).not.toHaveBeenCalled();
expect(uploadService.uploadFilesInTheQueue).not.toHaveBeenCalled();
});
it('should NOT upload the folder dropped', (done) => {
component.enabled = false;
spyOn(uploadService, 'addToQueue');
spyOn(uploadService, 'uploadFilesInTheQueue');
fixture.detectChanges();
let itemEntity = {
isDirectory: true,
createReader: () => {
return {
readEntries: (cb) => {
cb([]);
}
};
}
};
component.onFolderEntityDropped(itemEntity);
setTimeout(() => {
expect(uploadService.addToQueue).not.toHaveBeenCalled();
expect(uploadService.uploadFilesInTheQueue).not.toHaveBeenCalled();
done();
}, 0);
});
it('should NOT upload the files', () => {
component.enabled = false;
spyOn(uploadService, 'addToQueue');
spyOn(uploadService, 'uploadFilesInTheQueue');
let fakeItem = {
fullPath: '/folder-fake/file-fake.png',
isDirectory: false,
isFile: true,
name: 'file-fake.png',
file: (callbackFile) => {
let fileFake = new File(['fakefake'], 'file-fake.png', {type: 'image/png'});
callbackFile(fileFake);
}
};
fixture.detectChanges();
let fakeCustomEvent: CustomEvent = new CustomEvent('CustomEvent', {
detail: { data: getFakeShareDataRow([]), files: [fakeItem] }
});
component.onUploadFiles(fakeCustomEvent);
expect(uploadService.addToQueue).not.toHaveBeenCalled();
expect(uploadService.uploadFilesInTheQueue).not.toHaveBeenCalled();
});
});
it('should upload the list of files dropped', (done) => {
component.currentFolderPath = '/root-fake-/sites-fake/folder-fake';
component.onSuccess = null;
@@ -203,7 +291,7 @@ describe('UploadDragAreaComponent', () => {
let fakeCustomEvent: CustomEvent = new CustomEvent('CustomEvent', {
detail: {
data: fakeShareDataRow,
data: getFakeShareDataRow(),
files: [fakeItem]
}
});

View File

@@ -15,49 +15,59 @@
* limitations under the License.
*/
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { AlfrescoTranslationService, FileInfo, FileModel, FileUtils, NotificationService, UploadService } from 'ng2-alfresco-core';
import { Component, EventEmitter, forwardRef, Input, Output } from '@angular/core';
import {
AlfrescoTranslationService,
EXTENDIBLE_COMPONENT,
FileInfo,
FileModel,
FileUtils,
NodePermissionSubject,
NotificationService,
UploadService
} from 'ng2-alfresco-core';
@Component({
selector: 'adf-upload-drag-area, alfresco-upload-drag-area',
templateUrl: './upload-drag-area.component.html',
styleUrls: ['./upload-drag-area.component.css']
styleUrls: ['./upload-drag-area.component.css'],
providers: [
{ provide: EXTENDIBLE_COMPONENT, useExisting: forwardRef(() => UploadDragAreaComponent)}
]
})
export class UploadDragAreaComponent {
export class UploadDragAreaComponent implements NodePermissionSubject {
/** @deprecated Deprecated in favor of disabled input property */
@Input()
enabled: boolean = true;
set enabled(enabled: boolean) {
console.warn('Deprecated: enabled input property should not be used for UploadDragAreaComponent. Please use disabled instead.');
this.disabled = !enabled;
}
/**
* @deprecated Deprecated in 1.6.0, you can use UploadService events and NotificationService api instead.
*
* @type {boolean}
* @memberof UploadButtonComponent
*/
/** @deprecated Deprecated in favor of disabled input property */
get enabled(): boolean {
console.warn('Deprecated: enabled input property should not be used for UploadDragAreaComponent. Please use disabled instead.');
return !this.disabled;
}
/** @deprecated Deprecated in 1.6.0, you can use UploadService events and NotificationService api instead. */
@Input()
showNotificationBar: boolean = true;
@Input()
versioning: boolean = false;
/**
* @deprecated Deprecated in 1.6.0, this property is not used for couple of releases already. Use rootFolderId instead.
*
* @type {string}
* @memberof UploadDragAreaComponent
*/
/** @deprecated Deprecated in 1.6.0, this property is not used for couple of releases already. Use rootFolderId instead. */
@Input()
currentFolderPath: string = '/';
/**
* @deprecated Deprecated in 1.6.2, this property is not used for couple of releases already. Use parentId instead.
*
* @type {string}
* @memberof UploadDragAreaComponent
*/
/** @deprecated Deprecated in 1.6.2, this property is not used for couple of releases already. Use parentId instead. */
@Input()
rootFolderId: string = '-root-';
@Input()
disabled: boolean = false;
@Input()
versioning: boolean = false;
@Input()
parentId: string;
@@ -69,38 +79,13 @@ export class UploadDragAreaComponent {
private notificationService: NotificationService) {
}
/**
* Handles 'upload-files' events raised by child components.
* @param event DOM event
*/
onUploadFiles(event: CustomEvent) {
event.stopPropagation();
event.preventDefault();
let isAllowed: boolean = this.isAllowed(event.detail.data.obj.entry);
if (isAllowed) {
let files: FileInfo[] = event.detail.files;
if (files && files.length > 0) {
let parentId = this.parentId || this.rootFolderId;
if (event.detail.data && event.detail.data.obj.entry.isFolder) {
parentId = event.detail.data.obj.entry.id || this.parentId || this.rootFolderId;
}
const fileModels = files.map(fileInfo => new FileModel(fileInfo.file, {
newVersion: this.versioning,
path: fileInfo.relativeFolder,
parentId: parentId
}));
this.uploadFiles(fileModels, isAllowed);
}
}
}
/**
* Method called when files are dropped in the drag area.
*
* @param {File[]} files - files dropped in the drag area.
*/
onFilesDropped(files: File[]): void {
if (this.enabled && files.length) {
if (!this.disabled && files.length) {
const fileModels = files.map(file => new FileModel(file, {
newVersion: this.versioning,
path: '/',
@@ -117,10 +102,11 @@ export class UploadDragAreaComponent {
/**
* Called when the file are dropped in the drag area
*
* @param item - FileEntity
*/
onFilesEntityDropped(item: any): void {
if (this.enabled) {
if (!this.disabled) {
item.file((file: File) => {
const fileModel = new FileModel(file, {
newVersion: this.versioning,
@@ -138,10 +124,11 @@ export class UploadDragAreaComponent {
/**
* Called when a folder are dropped in the drag area
*
* @param folder - name of the dropped folder
*/
onFolderEntityDropped(folder: any): void {
if (this.enabled && folder.isDirectory) {
if (!this.disabled && folder.isDirectory) {
FileUtils.flattern(folder).then(entries => {
let files = entries.map(entry => {
return new FileModel(entry.file, {
@@ -178,6 +165,7 @@ export class UploadDragAreaComponent {
/**
* Show the error inside Notification bar
*
* @param Error message
* @private
*/
@@ -185,8 +173,44 @@ export class UploadDragAreaComponent {
this.notificationService.openSnackMessage(errorMessage, 3000);
}
private uploadFiles(files: FileModel[], isAllowed: boolean): void {
if (isAllowed && files.length) {
/** Returns true or false considering the component options and node permissions */
isDroppable(): boolean {
return !this.disabled;
}
/**
* Handles 'upload-files' events raised by child components.
*
* @param event DOM event
*/
onUploadFiles(event: CustomEvent) {
event.stopPropagation();
event.preventDefault();
let isAllowed: boolean = this.hasCreatePermission(event.detail.data.obj.entry);
if (isAllowed) {
let files: FileInfo[] = event.detail.files;
if (files && files.length > 0) {
let parentId = this.parentId || this.rootFolderId;
if (event.detail.data && event.detail.data.obj.entry.isFolder) {
parentId = event.detail.data.obj.entry.id || this.parentId || this.rootFolderId;
}
const fileModels = files.map(fileInfo => new FileModel(fileInfo.file, {
newVersion: this.versioning,
path: fileInfo.relativeFolder,
parentId: parentId
}));
this.uploadFiles(fileModels);
}
}
}
/**
* Does the actual file uploading and show the notification
*
* @param files
*/
private uploadFiles(files: FileModel[]): void {
if (files.length) {
this.uploadService.addToQueue(...files);
this.uploadService.uploadFilesInTheQueue(this.onSuccess);
let latestFilesAdded = this.uploadService.getQueue();
@@ -196,6 +220,11 @@ export class UploadDragAreaComponent {
}
}
/**
* Check if "create" permission is present on the given node
*
* @param node
*/
private hasCreatePermission(node: any): boolean {
let isPermitted = false;
if (node && node['allowableOperations']) {
@@ -204,8 +233,4 @@ export class UploadDragAreaComponent {
}
return isPermitted;
}
private isAllowed(node: any) {
return this.enabled || this.hasCreatePermission(node);
}
}