mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-12 17:04:57 +00:00
[ASF-1227] new adf-node-permission directive (#2154)
* directive implementation * update docs * unit tests and api docs * code improvements * simplify code * update type def and docs
This commit is contained in:
parent
152e7805bc
commit
91ef0b6947
@ -30,7 +30,9 @@
|
|||||||
<button md-icon-button (click)="onCreateFolderClicked($event)">
|
<button md-icon-button (click)="onCreateFolderClicked($event)">
|
||||||
<md-icon>create_new_folder</md-icon>
|
<md-icon>create_new_folder</md-icon>
|
||||||
</button>
|
</button>
|
||||||
<button md-icon-button>
|
<button md-icon-button
|
||||||
|
adf-node-permission="delete"
|
||||||
|
[adf-nodes]="documentList.selection">
|
||||||
<md-icon>delete</md-icon>
|
<md-icon>delete</md-icon>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
@ -90,6 +90,11 @@ You should see result similar to the following one:
|
|||||||
|
|
||||||
For more details about the [toolbar](src/components/toolbar/toolbar.md).
|
For more details about the [toolbar](src/components/toolbar/toolbar.md).
|
||||||
|
|
||||||
|
| Feature | Notes | Docs |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| toolbar | toolbar component | [Docs](src/components/toolbar/toolbar.md) |
|
||||||
|
| node-permission | disable elements based on node permissions | [Docs](src/directives/node-permission.md)
|
||||||
|
|
||||||
## Upload Directive
|
## Upload Directive
|
||||||
|
|
||||||
Allows your components or common HTML elements reacting on File drag and drop in order to upload content.
|
Allows your components or common HTML elements reacting on File drag and drop in order to upload content.
|
||||||
|
@ -98,6 +98,7 @@ export { DiscoveryApiService } from './src/services/discovery-api.service';
|
|||||||
|
|
||||||
import { DataColumnListComponent } from './src/components/data-column/data-column-list.component';
|
import { DataColumnListComponent } from './src/components/data-column/data-column-list.component';
|
||||||
import { DataColumnComponent } from './src/components/data-column/data-column.component';
|
import { DataColumnComponent } from './src/components/data-column/data-column.component';
|
||||||
|
import { NodePermissionDirective } from './src/directives/node-permission.directive';
|
||||||
import { UploadDirective } from './src/directives/upload.directive';
|
import { UploadDirective } from './src/directives/upload.directive';
|
||||||
import { FileSizePipe } from './src/pipes/file-size.pipe';
|
import { FileSizePipe } from './src/pipes/file-size.pipe';
|
||||||
import { HighlightPipe } from './src/pipes/text-highlight.pipe';
|
import { HighlightPipe } from './src/pipes/text-highlight.pipe';
|
||||||
@ -209,6 +210,7 @@ export function createTranslateLoader(http: Http, logService: LogService) {
|
|||||||
declarations: [
|
declarations: [
|
||||||
...obsoleteMdlDirectives(),
|
...obsoleteMdlDirectives(),
|
||||||
UploadDirective,
|
UploadDirective,
|
||||||
|
NodePermissionDirective,
|
||||||
DataColumnComponent,
|
DataColumnComponent,
|
||||||
DataColumnListComponent,
|
DataColumnListComponent,
|
||||||
FileSizePipe,
|
FileSizePipe,
|
||||||
@ -229,6 +231,7 @@ export function createTranslateLoader(http: Http, logService: LogService) {
|
|||||||
ToolbarModule,
|
ToolbarModule,
|
||||||
...obsoleteMdlDirectives(),
|
...obsoleteMdlDirectives(),
|
||||||
UploadDirective,
|
UploadDirective,
|
||||||
|
NodePermissionDirective,
|
||||||
DataColumnComponent,
|
DataColumnComponent,
|
||||||
DataColumnListComponent,
|
DataColumnListComponent,
|
||||||
FileSizePipe,
|
FileSizePipe,
|
||||||
|
@ -0,0 +1,112 @@
|
|||||||
|
/*!
|
||||||
|
* @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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ElementRef, SimpleChange } from '@angular/core';
|
||||||
|
import { AlfrescoContentService } from './../services/alfresco-content.service';
|
||||||
|
import { NodePermissionDirective } from './node-permission.directive';
|
||||||
|
|
||||||
|
describe('NodePermissionDirective', () => {
|
||||||
|
|
||||||
|
it('updates element once it is loaded', () => {
|
||||||
|
const directive = new NodePermissionDirective(null, null, null);
|
||||||
|
spyOn(directive, 'updateElement').and.stub();
|
||||||
|
|
||||||
|
directive.ngAfterViewInit();
|
||||||
|
|
||||||
|
expect(directive.updateElement).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('updates element on nodes change', () => {
|
||||||
|
const directive = new NodePermissionDirective(null, null, null);
|
||||||
|
spyOn(directive, 'updateElement').and.stub();
|
||||||
|
|
||||||
|
const nodes = [{}, {}];
|
||||||
|
const change = new SimpleChange([], nodes, false);
|
||||||
|
directive.ngOnChanges({ nodes: change });
|
||||||
|
|
||||||
|
expect(directive.updateElement).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('updates element only on subsequent change', () => {
|
||||||
|
const directive = new NodePermissionDirective(null, null, null);
|
||||||
|
spyOn(directive, 'updateElement').and.stub();
|
||||||
|
|
||||||
|
const nodes = [{}, {}];
|
||||||
|
const change = new SimpleChange([], nodes, true);
|
||||||
|
directive.ngOnChanges({ nodes: change });
|
||||||
|
|
||||||
|
expect(directive.updateElement).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('enables decorated element', () => {
|
||||||
|
const renderer = jasmine.createSpyObj('renderer', ['removeAttribute']);
|
||||||
|
const elementRef = new ElementRef({});
|
||||||
|
const directive = new NodePermissionDirective(elementRef, renderer, null);
|
||||||
|
|
||||||
|
directive.enableElement();
|
||||||
|
|
||||||
|
expect(renderer.removeAttribute).toHaveBeenCalledWith(elementRef.nativeElement, 'disabled');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('disables decorated element', () => {
|
||||||
|
const renderer = jasmine.createSpyObj('renderer', ['setAttribute']);
|
||||||
|
const elementRef = new ElementRef({});
|
||||||
|
const directive = new NodePermissionDirective(elementRef, renderer, null);
|
||||||
|
|
||||||
|
directive.disableElement();
|
||||||
|
|
||||||
|
expect(renderer.setAttribute).toHaveBeenCalledWith(elementRef.nativeElement, 'disabled', 'true');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('disables element when nodes not available', () => {
|
||||||
|
const directive = new NodePermissionDirective(null, null, null);
|
||||||
|
spyOn(directive, 'disableElement').and.stub();
|
||||||
|
|
||||||
|
directive.nodes = null;
|
||||||
|
expect(directive.updateElement()).toBeFalsy();
|
||||||
|
|
||||||
|
directive.nodes = [];
|
||||||
|
expect(directive.updateElement()).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('enables element when all nodes have expected permission', () => {
|
||||||
|
const contentService = new AlfrescoContentService(null, null, null);
|
||||||
|
spyOn(contentService, 'hasPermission').and.returnValue(true);
|
||||||
|
|
||||||
|
const directive = new NodePermissionDirective(null, null, contentService);
|
||||||
|
spyOn(directive, 'enableElement').and.stub();
|
||||||
|
|
||||||
|
directive.nodes = <any> [{}, {}];
|
||||||
|
|
||||||
|
expect(directive.updateElement()).toBeTruthy();
|
||||||
|
expect(directive.enableElement).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('disables element when one of the nodes have no permission', () => {
|
||||||
|
const contentService = new AlfrescoContentService(null, null, null);
|
||||||
|
spyOn(contentService, 'hasPermission').and.returnValue(false);
|
||||||
|
|
||||||
|
const directive = new NodePermissionDirective(null, null, contentService);
|
||||||
|
spyOn(directive, 'disableElement').and.stub();
|
||||||
|
|
||||||
|
directive.nodes = <any> [{}, {}];
|
||||||
|
|
||||||
|
expect(directive.updateElement()).toBeFalsy();
|
||||||
|
expect(directive.disableElement).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -0,0 +1,100 @@
|
|||||||
|
/*!
|
||||||
|
* @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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { AfterViewInit, Directive, ElementRef, Input, OnChanges, Renderer2, SimpleChanges } from '@angular/core';
|
||||||
|
import { MinimalNodeEntity } from 'alfresco-js-api';
|
||||||
|
import { AlfrescoContentService } from './../services/alfresco-content.service';
|
||||||
|
|
||||||
|
@Directive({
|
||||||
|
selector: '[adf-node-permission]'
|
||||||
|
})
|
||||||
|
export class NodePermissionDirective implements OnChanges, AfterViewInit {
|
||||||
|
|
||||||
|
@Input('adf-node-permission')
|
||||||
|
permission: string = null;
|
||||||
|
|
||||||
|
@Input('adf-nodes')
|
||||||
|
nodes: MinimalNodeEntity[] = [];
|
||||||
|
|
||||||
|
constructor(private elementRef: ElementRef,
|
||||||
|
private renderer: Renderer2,
|
||||||
|
private contentService: AlfrescoContentService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
ngAfterViewInit() {
|
||||||
|
this.updateElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
|
if (changes.nodes && !changes.nodes.firstChange) {
|
||||||
|
this.updateElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates disabled state for the decorated elememtn
|
||||||
|
*
|
||||||
|
* @returns {boolean} True if decorated element got disabled, otherwise False
|
||||||
|
* @memberof NodePermissionDirective
|
||||||
|
*/
|
||||||
|
updateElement(): boolean {
|
||||||
|
let enable = this.hasPermission(this.nodes, this.permission);
|
||||||
|
|
||||||
|
if (enable) {
|
||||||
|
this.enableElement();
|
||||||
|
} else {
|
||||||
|
this.disableElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
return enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables decorated element
|
||||||
|
*
|
||||||
|
* @memberof NodePermissionDirective
|
||||||
|
*/
|
||||||
|
enableElement(): void {
|
||||||
|
this.renderer.removeAttribute(this.elementRef.nativeElement, 'disabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables decorated element
|
||||||
|
*
|
||||||
|
* @memberof NodePermissionDirective
|
||||||
|
*/
|
||||||
|
disableElement(): void {
|
||||||
|
this.renderer.setAttribute(this.elementRef.nativeElement, 'disabled', 'true');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether all nodes have a particular permission
|
||||||
|
*
|
||||||
|
* @param {MinimalNodeEntity[]} nodes Node collection to check
|
||||||
|
* @param {string} permission Permission to check for each node
|
||||||
|
* @returns {boolean} True if all nodes have provided permission, otherwise False
|
||||||
|
* @memberof NodePermissionDirective
|
||||||
|
*/
|
||||||
|
hasPermission(nodes: MinimalNodeEntity[], permission: string): boolean {
|
||||||
|
if (nodes && nodes.length > 0) {
|
||||||
|
return nodes.every(node => this.contentService.hasPermission(node.entry, permission));
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
# Node Permission Directive
|
||||||
|
|
||||||
|
The `NodePermissionDirective` allows you to disable an HTML element or Angular component
|
||||||
|
by taking a collection of the `MinimalNodeEntity` instances and checking the particular permission.
|
||||||
|
|
||||||
|
The decorated element will be disabled if:
|
||||||
|
|
||||||
|
- there are no nodes in the collection
|
||||||
|
- at least one of the nodes has no expected permission
|
||||||
|
|
||||||
|
## Basic example
|
||||||
|
|
||||||
|
The best example to show `NodePermissionDirective` in action is by binding DocumentList selection property to a toolbar button.
|
||||||
|
|
||||||
|
For example the "Delete" button should be disabled if no selection is present or if user has no rights to delete at least one node in the selection.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<adf-toolbar title="toolbar example">
|
||||||
|
<button md-icon-button
|
||||||
|
adf-node-permission="delete"
|
||||||
|
[adf-nodes]="documentList.selection">
|
||||||
|
<md-icon>delete</md-icon>
|
||||||
|
</button>
|
||||||
|
</adf-toolbar>
|
||||||
|
|
||||||
|
<adf-document-list #documentList ...>
|
||||||
|
...
|
||||||
|
</adf-document-list>
|
||||||
|
```
|
||||||
|
|
||||||
|
The button will become disabled by default, and is going to change its state once user selects/unselects one or multiple documents that current user has permission to delete.
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
| Name | Type | Default | Description |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| adf-node-permission | string | null | Node permission to check |
|
||||||
|
| adf-nodes | MinimalNodeEntity[] | [] | Nodes to check permission for |
|
Loading…
x
Reference in New Issue
Block a user