mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-31 17:38:48 +00:00
[ADF-2556] Created component for add group or user to permission (#3242)
* [ADF-2556] first step to create add people or group to permissions * [ADF-2556] creating a dialog with user results * [ADF-2556] integrated service for add and remove permission from node * [ADF-2556] fixed behaviour and style for add user group * [ADF-2556] added some refactoring for dialog service * [ADF-2556] refactoring the dependencies of the components * [ADF-2556] added some fix and a new key for dialog * [ADF-2556] start adding test for node permission service * [ADF-2556] added test for add permission panel component * [ADf-2556] adding tests for new add permission component * [ADF-2556] fixed tests and added documentation * [ADF-2556] fixed documentation for add-node components * [ADF-2556] added peer review changes
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
/*!
|
||||
* @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 { MinimalNodeEntity } from 'alfresco-js-api';
|
||||
import { Subject } from 'rxjs/Subject';
|
||||
|
||||
export interface AddPermissionDialogData {
|
||||
title?: string;
|
||||
nodeId: string;
|
||||
confirm: Subject<MinimalNodeEntity[]>;
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
<h2 mat-dialog-title id="add-permission-dialog-title">
|
||||
{{(data?.title ? data?.title : 'PERMISSION_MANAGER.ADD-PERMISSION.BASE-DIALOG-TITLE') | translate}}
|
||||
</h2>
|
||||
<mat-dialog-content>
|
||||
<adf-add-permission-panel
|
||||
(select)="onSelect($event)">
|
||||
</adf-add-permission-panel>
|
||||
</mat-dialog-content>
|
||||
<mat-dialog-actions>
|
||||
<button mat-button mat-dialog-close id="add-permission-dialog-close-button">{{'PERMISSION_MANAGER.ADD-PERMISSION.CLOSE-ACTION' | translate}}</button>
|
||||
<button mat-button id="add-permission-dialog-confirm-button" [mat-dialog-close]="true"
|
||||
class="choose-action"
|
||||
[disabled]="currentSelection?.length === 0"
|
||||
(click)="onAddClicked()">{{'PERMISSION_MANAGER.ADD-PERMISSION.ADD-ACTION' | translate}}</button>
|
||||
</mat-dialog-actions>
|
||||
|
@@ -0,0 +1,55 @@
|
||||
@mixin adf-add-permission-dialog-theme($theme) {
|
||||
|
||||
$primary: map-get($theme, primary);
|
||||
$foreground: map-get($theme, foreground);
|
||||
$background: map-get($theme, background);
|
||||
|
||||
.adf-add-permission-dialog {
|
||||
|
||||
.mat-dialog-title {
|
||||
margin-left: 24px;
|
||||
margin-right: 24px;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
font-style: normal;
|
||||
font-stretch: normal;
|
||||
line-height: 1.6;
|
||||
letter-spacing: -0.5px;
|
||||
color: mat-color($foreground, text, 0.87);
|
||||
}
|
||||
|
||||
.mat-dialog-container {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.mat-dialog-content {
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.mat-dialog-actions {
|
||||
padding: 8px;
|
||||
background-color: mat-color($background, background);
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
color: mat-color($foreground, secondary-text);
|
||||
|
||||
button {
|
||||
text-transform: uppercase;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.choose-action {
|
||||
|
||||
&[disabled] {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
&:enabled {
|
||||
color: mat-color($primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,111 @@
|
||||
/*!
|
||||
* @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 { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { ComponentFixture, TestBed, async } from '@angular/core/testing';
|
||||
import { ContentTestingModule } from '../../../testing/content.testing.module';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { setupTestBed } from '@alfresco/adf-core';
|
||||
import { AddPermissionDialogComponent } from './add-permission-dialog.component';
|
||||
import { MinimalNodeEntity } from 'alfresco-js-api';
|
||||
import { Subject } from 'rxjs/Subject';
|
||||
import { AddPermissionDialogData } from './add-permission-dialog-data.interface';
|
||||
import { fakeAuthorityResults } from '../../../mock/add-permission.component.mock';
|
||||
import { AddPermissionPanelComponent } from './add-permission-panel.component';
|
||||
|
||||
describe('AddPermissionDialog', () => {
|
||||
|
||||
let fixture: ComponentFixture<AddPermissionDialogComponent>;
|
||||
let element: HTMLElement;
|
||||
let data: AddPermissionDialogData = {
|
||||
title: 'dead or alive you are coming with me',
|
||||
nodeId: 'fake-node-id',
|
||||
confirm: new Subject<MinimalNodeEntity[]> ()
|
||||
};
|
||||
const dialogRef = {
|
||||
close: jasmine.createSpy('close')
|
||||
};
|
||||
|
||||
setupTestBed({
|
||||
imports: [ContentTestingModule],
|
||||
providers: [
|
||||
{ provide: MatDialogRef, useValue: dialogRef },
|
||||
{ provide: MAT_DIALOG_DATA, useValue: data }
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
fixture = TestBed.createComponent(AddPermissionDialogComponent);
|
||||
element = fixture.nativeElement;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fixture.destroy();
|
||||
});
|
||||
|
||||
it('should show the INJECTED title', () => {
|
||||
const titleElement = fixture.debugElement.query(By.css('#add-permission-dialog-title'));
|
||||
expect(titleElement).not.toBeNull();
|
||||
expect(titleElement.nativeElement.innerText).toBe('dead or alive you are coming with me');
|
||||
});
|
||||
|
||||
it('should close the dialog when close button is clicked', () => {
|
||||
const closeButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#add-permission-dialog-close-button');
|
||||
expect(closeButton).not.toBeNull();
|
||||
closeButton.click();
|
||||
expect(dialogRef.close).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should disable the confirm button when no selection is applied', () => {
|
||||
const confirmButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#add-permission-dialog-confirm-button');
|
||||
expect(confirmButton.disabled).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should enable the button when a selection is done', async(() => {
|
||||
const addPermissionPanelComponent: AddPermissionPanelComponent = fixture.debugElement.query(By.directive(AddPermissionPanelComponent)).componentInstance;
|
||||
addPermissionPanelComponent.select.emit(fakeAuthorityResults);
|
||||
let confirmButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#add-permission-dialog-confirm-button');
|
||||
expect(confirmButton.disabled).toBeTruthy();
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
confirmButton = <HTMLButtonElement> element.querySelector('#add-permission-dialog-confirm-button');
|
||||
expect(confirmButton.disabled).toBeFalsy();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should stream the confirmed selection on the confirm subject', async(() => {
|
||||
const addPermissionPanelComponent: AddPermissionPanelComponent = fixture.debugElement.query(By.directive(AddPermissionPanelComponent)).componentInstance;
|
||||
addPermissionPanelComponent.select.emit(fakeAuthorityResults);
|
||||
data.confirm.subscribe((selection) => {
|
||||
expect(selection[0]).not.toBeNull();
|
||||
expect(selection[0].entry.id).not.toBeNull();
|
||||
expect(fakeAuthorityResults[0].entry.id).toBe(selection[0].entry.id);
|
||||
});
|
||||
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
const confirmButton = <HTMLButtonElement> element.querySelector('#add-permission-dialog-confirm-button');
|
||||
confirmButton.click();
|
||||
});
|
||||
}));
|
||||
});
|
@@ -0,0 +1,48 @@
|
||||
/*!
|
||||
* @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 { Component, ViewEncapsulation, Inject, ViewChild } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA } from '@angular/material';
|
||||
import { MinimalNodeEntity } from 'alfresco-js-api';
|
||||
import { AddPermissionDialogData } from './add-permission-dialog-data.interface';
|
||||
import { AddPermissionComponent } from '../add-permission/add-permission.component';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-add-permission-dialog',
|
||||
templateUrl: './add-permission-dialog.component.html',
|
||||
styleUrls: ['./add-permission-dialog.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class AddPermissionDialogComponent {
|
||||
|
||||
@ViewChild('addPermission')
|
||||
addPermissionComponent: AddPermissionComponent;
|
||||
|
||||
private currentSelection: MinimalNodeEntity[] = [];
|
||||
|
||||
constructor(@Inject(MAT_DIALOG_DATA) public data: AddPermissionDialogData) {
|
||||
}
|
||||
|
||||
onSelect(items: MinimalNodeEntity[]) {
|
||||
this.currentSelection = items;
|
||||
}
|
||||
|
||||
onAddClicked() {
|
||||
this.data.confirm.next(this.currentSelection);
|
||||
this.data.confirm.complete();
|
||||
}
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
<mat-form-field floatPlaceholder="never" class="adf-permission-search-input">
|
||||
<input matInput
|
||||
id="searchInput"
|
||||
[formControl]="searchInput"
|
||||
type="text"
|
||||
placeholder="{{'PERMISSION_MANAGER.ADD-PERMISSION.SEARCH' | translate}}"
|
||||
[value]="searchedWord">
|
||||
|
||||
<mat-icon *ngIf="searchedWord?.length > 0"
|
||||
class="adf-permission-search-icon"
|
||||
data-automation-id="adf-permission-clear-input"
|
||||
id="adf-permission-clear-input"
|
||||
matSuffix (click)="clearSearch()">clear
|
||||
</mat-icon>
|
||||
|
||||
<mat-icon *ngIf="searchedWord?.length === 0"
|
||||
class="adf-permission-search-icon"
|
||||
data-automation-id="adf-permission-search-icon"
|
||||
matSuffix>search
|
||||
</mat-icon>
|
||||
</mat-form-field>
|
||||
|
||||
<div *ngIf="searchedWord?.length === 0" id="adf-add-permission-type-search">
|
||||
<span class="adf-permission-start-message">{{'PERMISSION_MANAGER.ADD-PERMISSION.TYPE-MESSAGE' | translate}}</span>
|
||||
</div>
|
||||
|
||||
<adf-search #search [searchTerm]="searchedWord"
|
||||
id="adf-add-permission-authority-results"
|
||||
class="adf-permission-result-list"
|
||||
*ngIf="searchedWord.length !== 0">
|
||||
<ng-template let-data>
|
||||
<mat-selection-list [class.adf-permission-result-list-elements]="data?.list?.entries.length !== 0">
|
||||
<mat-list-option *ngFor="let item of data?.list?.entries; let idx = index"
|
||||
(click)="elementClicked(item)"
|
||||
class="adf-list-option-item"
|
||||
id="result_option_{{idx}}">
|
||||
<mat-icon mat-list-icon id="add-group-icon"
|
||||
*ngIf="item?.entry?.nodeType === 'cm:authorityContainer' else show_person_icon">
|
||||
group_add
|
||||
</mat-icon>
|
||||
<ng-template #show_person_icon>
|
||||
<mat-icon id="add-person-icon" mat-list-icon>person_add</mat-icon>
|
||||
</ng-template>
|
||||
<p>
|
||||
{{item.entry?.properties['cm:authorityName']?
|
||||
item.entry?.properties['cm:authorityName'] :
|
||||
item.entry?.properties['cm:firstName']}}</p>
|
||||
</mat-list-option>
|
||||
</mat-selection-list>
|
||||
<div *ngIf="data?.list?.entries.length === 0" class="adf-permission-no-result" id="adf-add-permission-no-results">
|
||||
<span>{{'PERMISSION_MANAGER.ADD-PERMISSION.NO-RESULT' | translate}}</span>
|
||||
</div>
|
||||
</ng-template>
|
||||
</adf-search>
|
@@ -0,0 +1,68 @@
|
||||
@mixin adf-add-permission-panel-theme($theme) {
|
||||
|
||||
$background: map-get($theme, background);
|
||||
$foreground: map-get($theme, foreground);
|
||||
$primary: map-get($theme, primary);
|
||||
$accent: map-get($theme, accent);
|
||||
$mat-menu-border-radius: 2px !default;
|
||||
|
||||
.adf {
|
||||
|
||||
&-permission-result-list {
|
||||
display: flex;
|
||||
height: 300px;
|
||||
overflow: auto;
|
||||
border: 2px solid mat-color($foreground, base, 0.07);
|
||||
|
||||
&-elements {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&-permission-start-message {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
height: 300px;
|
||||
overflow: auto;
|
||||
border: 2px solid mat-color($foreground, base, 0.07);
|
||||
}
|
||||
|
||||
&-permission-no-result{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&-permission-search {
|
||||
&-input {
|
||||
width: 100%;
|
||||
|
||||
&-icon {
|
||||
color: mat-color($foreground, disabled-button);
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: mat-color($foreground, base);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-list-option-item .mat-list-text {
|
||||
display: flex;
|
||||
flex-direction: row !important;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&-permission-action {
|
||||
&[disabled] {
|
||||
opacity: 0.6;
|
||||
}
|
||||
&:enabled {
|
||||
color: mat-color($primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,156 @@
|
||||
/*!
|
||||
* @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 { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { AddPermissionPanelComponent } from './add-permission-panel.component';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { SearchService, setupTestBed, SearchConfigurationService } from '@alfresco/adf-core';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { fakeAuthorityListResult } from '../../../mock/add-permission.component.mock';
|
||||
import { ContentTestingModule } from '../../../testing/content.testing.module';
|
||||
import { DebugElement } from '@angular/core';
|
||||
|
||||
describe('AddPermissionPanelComponent', () => {
|
||||
|
||||
let fixture: ComponentFixture<AddPermissionPanelComponent>;
|
||||
let component: AddPermissionPanelComponent;
|
||||
let element: HTMLElement;
|
||||
let searchApiService: SearchService;
|
||||
let debugElement: DebugElement;
|
||||
|
||||
setupTestBed({
|
||||
imports: [ContentTestingModule],
|
||||
providers: [SearchService, SearchConfigurationService]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(AddPermissionPanelComponent);
|
||||
debugElement = fixture.debugElement;
|
||||
element = fixture.nativeElement;
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fixture.destroy();
|
||||
});
|
||||
|
||||
function typeWordIntoSearchInput(word: string): void {
|
||||
let inputDebugElement = debugElement.query(By.css('#searchInput'));
|
||||
inputDebugElement.nativeElement.value = word;
|
||||
inputDebugElement.nativeElement.focus();
|
||||
inputDebugElement.nativeElement.dispatchEvent(new Event('input'));
|
||||
}
|
||||
|
||||
it('should be able to render the component', () => {
|
||||
expect(element.querySelector('#adf-add-permission-type-search')).not.toBeNull();
|
||||
expect(element.querySelector('#searchInput')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should show search results when user types something', async(() => {
|
||||
searchApiService = fixture.componentRef.injector.get(SearchService);
|
||||
spyOn(searchApiService, 'search').and.returnValue(Observable.of(fakeAuthorityListResult));
|
||||
expect(element.querySelector('#adf-add-permission-type-search')).not.toBeNull();
|
||||
expect(element.querySelector('#searchInput')).not.toBeNull();
|
||||
typeWordIntoSearchInput('a');
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
expect(element.querySelector('#adf-add-permission-authority-results')).not.toBeNull();
|
||||
expect(element.querySelector('#result_option_0')).not.toBeNull();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should emit a select event with the selected items when an item is clicked', async(() => {
|
||||
searchApiService = fixture.componentRef.injector.get(SearchService);
|
||||
spyOn(searchApiService, 'search').and.returnValue(Observable.of(fakeAuthorityListResult));
|
||||
component.select.subscribe((items) => {
|
||||
expect(items).not.toBeNull();
|
||||
expect(items[0].entry.id).toBeDefined();
|
||||
expect(items[0].entry.id).not.toBeNull();
|
||||
expect(items[0].entry.id).toBe(fakeAuthorityListResult.list.entries[0].entry.id);
|
||||
});
|
||||
|
||||
typeWordIntoSearchInput('a');
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
const listElement: DebugElement = fixture.debugElement.query(By.css('#result_option_0'));
|
||||
expect(listElement).not.toBeNull();
|
||||
listElement.triggerEventHandler('click', {});
|
||||
});
|
||||
}));
|
||||
|
||||
it('should show the icon related on the nodeType', async(() => {
|
||||
searchApiService = fixture.componentRef.injector.get(SearchService);
|
||||
spyOn(searchApiService, 'search').and.returnValue(Observable.of(fakeAuthorityListResult));
|
||||
expect(element.querySelector('#adf-add-permission-type-search')).not.toBeNull();
|
||||
expect(element.querySelector('#searchInput')).not.toBeNull();
|
||||
typeWordIntoSearchInput('a');
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
expect(element.querySelector('#adf-add-permission-authority-results')).not.toBeNull();
|
||||
expect(element.querySelector('#result_option_0 #add-person-icon')).toBeDefined();
|
||||
expect(element.querySelector('#result_option_0 #add-person-icon')).not.toBeNull();
|
||||
expect(element.querySelector('#result_option_2 #add-group-icon')).toBeDefined();
|
||||
expect(element.querySelector('#result_option_2 #add-group-icon')).not.toBeNull();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should clear the search when user delete the search input field', async(() => {
|
||||
searchApiService = fixture.componentRef.injector.get(SearchService);
|
||||
spyOn(searchApiService, 'search').and.returnValue(Observable.of(fakeAuthorityListResult));
|
||||
expect(element.querySelector('#adf-add-permission-type-search')).not.toBeNull();
|
||||
expect(element.querySelector('#searchInput')).not.toBeNull();
|
||||
typeWordIntoSearchInput('a');
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
expect(element.querySelector('#adf-add-permission-authority-results')).not.toBeNull();
|
||||
expect(element.querySelector('#result_option_0')).not.toBeNull();
|
||||
const clearButton = fixture.debugElement.query(By.css('#adf-permission-clear-input'));
|
||||
expect(clearButton).not.toBeNull();
|
||||
clearButton.triggerEventHandler('click', {});
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
expect(element.querySelector('#adf-add-permission-authority-results')).toBeNull();
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
it('should remove element from selection when is clicked and already selected', async(() => {
|
||||
searchApiService = fixture.componentRef.injector.get(SearchService);
|
||||
spyOn(searchApiService, 'search').and.returnValue(Observable.of(fakeAuthorityListResult));
|
||||
component.selectedItems.push(fakeAuthorityListResult.list.entries[0]);
|
||||
component.select.subscribe((items) => {
|
||||
expect(items).not.toBeNull();
|
||||
expect(items[0]).toBeUndefined();
|
||||
expect(component.selectedItems.length).toBe(0);
|
||||
});
|
||||
|
||||
typeWordIntoSearchInput('a');
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
const listElement: DebugElement = fixture.debugElement.query(By.css('#result_option_0'));
|
||||
expect(listElement).not.toBeNull();
|
||||
listElement.triggerEventHandler('click', {});
|
||||
});
|
||||
}));
|
||||
|
||||
});
|
@@ -0,0 +1,82 @@
|
||||
/*!
|
||||
* @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 { Component, ViewEncapsulation, EventEmitter, Output, ViewChild } from '@angular/core';
|
||||
import { SearchPermissionConfigurationService } from './search-config-permission.service';
|
||||
import { SearchService, SearchConfigurationService } from '@alfresco/adf-core';
|
||||
import { SearchComponent } from '../../../search/components/search.component';
|
||||
import { FormControl } from '@angular/forms';
|
||||
import { debounceTime } from 'rxjs/operators';
|
||||
import { MinimalNodeEntity } from 'alfresco-js-api';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-add-permission-panel',
|
||||
templateUrl: './add-permission-panel.component.html',
|
||||
styleUrls: ['./add-permission-panel.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
providers: [
|
||||
{ provide: SearchConfigurationService, useClass: SearchPermissionConfigurationService },
|
||||
SearchService
|
||||
]
|
||||
})
|
||||
export class AddPermissionPanelComponent {
|
||||
|
||||
@ViewChild('search')
|
||||
search: SearchComponent;
|
||||
|
||||
@Output()
|
||||
select: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
searchInput: FormControl = new FormControl();
|
||||
searchedWord = '';
|
||||
debounceSearch: number = 200;
|
||||
|
||||
selectedItems: MinimalNodeEntity[] = [];
|
||||
|
||||
constructor() {
|
||||
this.searchInput.valueChanges
|
||||
.pipe(
|
||||
debounceTime(this.debounceSearch)
|
||||
)
|
||||
.subscribe((searchValue) => {
|
||||
this.searchedWord = searchValue;
|
||||
if (!searchValue) {
|
||||
this.search.resetResults();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
elementClicked(item: MinimalNodeEntity) {
|
||||
if (this.isAlreadySelected(item)) {
|
||||
this.selectedItems.splice(this.selectedItems.indexOf(item), 1);
|
||||
} else {
|
||||
this.selectedItems.push(item);
|
||||
}
|
||||
this.select.emit(this.selectedItems);
|
||||
}
|
||||
|
||||
private isAlreadySelected(item: MinimalNodeEntity): boolean {
|
||||
return this.selectedItems.indexOf(item) >= 0;
|
||||
}
|
||||
|
||||
clearSearch() {
|
||||
this.searchedWord = '';
|
||||
this.selectedItems.splice(0, this.selectedItems.length);
|
||||
this.search.resetResults();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
<adf-add-permission-panel
|
||||
(select)="onSelect($event)">
|
||||
</adf-add-permission-panel>
|
||||
<div id="adf-add-permission-actions">
|
||||
<button mat-button
|
||||
id="adf-add-permission-action-button"
|
||||
class="adf-permission-action"
|
||||
[disabled]="selectedItems?.length === 0"
|
||||
(click)="applySelection()">
|
||||
{{'PERMISSION_MANAGER.ADD-PERMISSION.ADD-ACTION' | translate}}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
@@ -0,0 +1,16 @@
|
||||
@mixin adf-add-permission-theme($theme) {
|
||||
|
||||
$primary: map-get($theme, primary);
|
||||
|
||||
.adf {
|
||||
|
||||
&-permission-action {
|
||||
&[disabled] {
|
||||
opacity: 0.6;
|
||||
}
|
||||
&:enabled {
|
||||
color: mat-color($primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,102 @@
|
||||
/*!
|
||||
* @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 { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { AddPermissionComponent } from './add-permission.component';
|
||||
import { AddPermissionPanelComponent } from './add-permission-panel.component';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { setupTestBed } from '@alfresco/adf-core';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { fakeAuthorityResults } from '../../../mock/add-permission.component.mock';
|
||||
import { ContentTestingModule } from '../../../testing/content.testing.module';
|
||||
import { NodePermissionService } from '../../services/node-permission.service';
|
||||
|
||||
describe('AddPermissionComponent', () => {
|
||||
|
||||
let fixture: ComponentFixture<AddPermissionComponent>;
|
||||
let element: HTMLElement;
|
||||
let nodePermissionService: NodePermissionService;
|
||||
|
||||
setupTestBed({
|
||||
imports: [
|
||||
ContentTestingModule
|
||||
]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(AddPermissionComponent);
|
||||
element = fixture.nativeElement;
|
||||
nodePermissionService = TestBed.get(NodePermissionService);
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fixture.destroy();
|
||||
});
|
||||
|
||||
it('should be able to render the component', () => {
|
||||
expect(element.querySelector('#adf-add-permission-type-search')).not.toBeNull();
|
||||
expect(element.querySelector('#searchInput')).not.toBeNull();
|
||||
expect(element.querySelector('#adf-add-permission-actions')).not.toBeNull();
|
||||
const addButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#adf-add-permission-action-button');
|
||||
expect(addButton.disabled).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should enable the ADD button when a selection is sent', async(() => {
|
||||
const addPermissionPanelComponent: AddPermissionPanelComponent = fixture.debugElement.query(By.directive(AddPermissionPanelComponent)).componentInstance;
|
||||
addPermissionPanelComponent.select.emit(fakeAuthorityResults);
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
const addButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#adf-add-permission-action-button');
|
||||
expect(addButton.disabled).toBeFalsy();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should emit a success event when the node is updated', async(() => {
|
||||
fixture.componentInstance.selectedItems = fakeAuthorityResults;
|
||||
spyOn(nodePermissionService, 'updateNodePermissions').and.returnValue(Observable.of({ id: 'fake-node-id'}));
|
||||
|
||||
fixture.componentInstance.success.subscribe((node) => {
|
||||
expect(node.id).toBe('fake-node-id');
|
||||
});
|
||||
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
const addButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#adf-add-permission-action-button');
|
||||
addButton.click();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should emit an error event when the node update fail', async(() => {
|
||||
fixture.componentInstance.selectedItems = fakeAuthorityResults;
|
||||
spyOn(nodePermissionService, 'updateNodePermissions').and.returnValue(Observable.throw({ error: 'errored'}));
|
||||
|
||||
fixture.componentInstance.error.subscribe((error) => {
|
||||
expect(error.error).toBe('errored');
|
||||
});
|
||||
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable().then(() => {
|
||||
fixture.detectChanges();
|
||||
const addButton: HTMLButtonElement = <HTMLButtonElement> element.querySelector('#adf-add-permission-action-button');
|
||||
addButton.click();
|
||||
});
|
||||
}));
|
||||
|
||||
});
|
@@ -0,0 +1,61 @@
|
||||
/*!
|
||||
* @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 { Component, ViewEncapsulation, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { MinimalNodeEntity, MinimalNodeEntryEntity } from 'alfresco-js-api';
|
||||
import { NodePermissionService } from '../../services/node-permission.service';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-add-permission',
|
||||
templateUrl: './add-permission.component.html',
|
||||
styleUrls: ['./add-permission.component.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class AddPermissionComponent {
|
||||
|
||||
@Input()
|
||||
nodeId: string;
|
||||
|
||||
@Output()
|
||||
success: EventEmitter<MinimalNodeEntryEntity> = new EventEmitter();
|
||||
|
||||
@Output()
|
||||
error: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
selectedItems: MinimalNodeEntity[] = [];
|
||||
currentNode: MinimalNodeEntryEntity;
|
||||
currentNodeRoles: string[];
|
||||
|
||||
constructor(private nodePermissionService: NodePermissionService) {
|
||||
}
|
||||
|
||||
onSelect(selection: MinimalNodeEntity[]) {
|
||||
this.selectedItems = selection;
|
||||
}
|
||||
|
||||
applySelection() {
|
||||
this.nodePermissionService.updateNodePermissions(this.nodeId, this.selectedItems)
|
||||
.subscribe(
|
||||
(node) => {
|
||||
this.success.emit(node);
|
||||
},
|
||||
(error) => {
|
||||
this.error.emit(error);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,43 @@
|
||||
/*!
|
||||
* @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 { QueryBody } from 'alfresco-js-api';
|
||||
import { SearchConfigurationInterface } from '@alfresco/adf-core';
|
||||
|
||||
export class SearchPermissionConfigurationService implements SearchConfigurationInterface {
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
public generateQueryBody(searchTerm: string, maxResults: number, skipCount: number): QueryBody {
|
||||
const defaultQueryBody: QueryBody = {
|
||||
query: {
|
||||
query: searchTerm ? `authorityName:${searchTerm}* OR userName:${searchTerm}*` : searchTerm
|
||||
},
|
||||
include: ['properties', 'aspectNames'],
|
||||
paging: {
|
||||
maxItems: maxResults,
|
||||
skipCount: skipCount
|
||||
},
|
||||
filterQueries: [
|
||||
/*tslint:disable-next-line */
|
||||
{ query: "TYPE:'cm:authority'" }]
|
||||
};
|
||||
|
||||
return defaultQueryBody;
|
||||
}
|
||||
}
|
@@ -17,7 +17,7 @@
|
||||
|
||||
import { SimpleInheritedPermissionTestComponent } from '../../mock/inherited-permission.component.mock';
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { PermissionManagerModule } from '../../index';
|
||||
import { InheritPermissionDirective } from './inherited-button.directive';
|
||||
import { NodesApiService, setupTestBed, CoreModule } from '@alfresco/adf-core';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
@@ -33,20 +33,20 @@ describe('InheritPermissionDirective', () => {
|
||||
|
||||
setupTestBed({
|
||||
imports: [
|
||||
CoreModule.forRoot(),
|
||||
PermissionManagerModule
|
||||
CoreModule.forRoot()
|
||||
],
|
||||
declarations: [
|
||||
InheritPermissionDirective,
|
||||
SimpleInheritedPermissionTestComponent
|
||||
]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
beforeEach(async(() => {
|
||||
fixture = TestBed.createComponent(SimpleInheritedPermissionTestComponent);
|
||||
component = fixture.componentInstance;
|
||||
element = fixture.nativeElement;
|
||||
nodeService = TestBed.get(NodesApiService);
|
||||
});
|
||||
}));
|
||||
|
||||
it('should be able to render the simple component', async(() => {
|
||||
fixture.detectChanges();
|
||||
|
@@ -35,15 +35,18 @@ export class InheritPermissionDirective {
|
||||
@Output()
|
||||
updated: EventEmitter<MinimalNodeEntryEntity> = new EventEmitter<MinimalNodeEntryEntity>();
|
||||
|
||||
@Output()
|
||||
error: EventEmitter<any> = new EventEmitter<any>();
|
||||
|
||||
constructor(private nodeService: NodesApiService) {
|
||||
}
|
||||
|
||||
onInheritPermissionClicked() {
|
||||
this.nodeService.getNode(this.nodeId).subscribe((node: MinimalNodeEntryEntity) => {
|
||||
const nodeBody = { permissions : {isInheritanceEnabled : !node.permissions.isInheritanceEnabled} };
|
||||
this.nodeService.updateNode(this.nodeId, nodeBody, {include: ['permissions'] }).subscribe((nodeUpdated: MinimalNodeEntryEntity) => {
|
||||
const nodeBody = { permissions: { isInheritanceEnabled: !node.permissions.isInheritanceEnabled } };
|
||||
this.nodeService.updateNode(this.nodeId, nodeBody, { include: ['permissions'] }).subscribe((nodeUpdated: MinimalNodeEntryEntity) => {
|
||||
this.updated.emit(nodeUpdated);
|
||||
});
|
||||
}, (error) => this.error.emit(error));
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -48,6 +48,13 @@
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
</data-column>
|
||||
<data-column key="delete">
|
||||
<ng-template let-entry="$implicit">
|
||||
<button *ngIf="!entry.row.getValue('isInherited')" mat-icon-button color="primary" (click)="removePermission(entry.row.obj)">
|
||||
<mat-icon>highlight_off</mat-icon>
|
||||
</button>
|
||||
</ng-template>
|
||||
</data-column>
|
||||
</data-columns>
|
||||
</adf-datatable>
|
||||
</div>
|
||||
|
@@ -35,6 +35,9 @@ export class PermissionListComponent implements OnInit {
|
||||
@Output()
|
||||
update: EventEmitter<PermissionElement> = new EventEmitter();
|
||||
|
||||
@Output()
|
||||
error: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
permissionList: PermissionDisplayModel[];
|
||||
settableRoles: any[];
|
||||
actualNode: MinimalNodeEntryEntity;
|
||||
@@ -82,7 +85,7 @@ export class PermissionListComponent implements OnInit {
|
||||
|
||||
saveNewRole(event: any, permissionRow: PermissionDisplayModel) {
|
||||
let updatedPermissionRole: PermissionElement = this.buildUpdatedPermission(event.value, permissionRow);
|
||||
this.nodePermissionService.updatePermissionRoles(this.actualNode, updatedPermissionRole)
|
||||
this.nodePermissionService.updatePermissionRole(this.actualNode, updatedPermissionRole)
|
||||
.subscribe((node: MinimalNodeEntryEntity) => {
|
||||
this.update.emit(updatedPermissionRole);
|
||||
});
|
||||
@@ -96,4 +99,10 @@ export class PermissionListComponent implements OnInit {
|
||||
return permissionRole;
|
||||
}
|
||||
|
||||
removePermission(permissionRow: PermissionDisplayModel) {
|
||||
this.nodePermissionService.removePermission(this.actualNode, permissionRow).subscribe((node) => {
|
||||
this.update.emit(node);
|
||||
}, (error) => this.error.emit(error));
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user