diff --git a/demo-shell/src/app/components/permissions/demo-permissions.component.html b/demo-shell/src/app/components/permissions/demo-permissions.component.html
index 2adeb22178..6cb86d301d 100644
--- a/demo-shell/src/app/components/permissions/demo-permissions.component.html
+++ b/demo-shell/src/app/components/permissions/demo-permissions.component.html
@@ -2,11 +2,17 @@
+
+
diff --git a/demo-shell/src/app/components/permissions/demo-permissions.component.scss b/demo-shell/src/app/components/permissions/demo-permissions.component.scss
index a6da03dab0..18a2c1fa49 100644
--- a/demo-shell/src/app/components/permissions/demo-permissions.component.scss
+++ b/demo-shell/src/app/components/permissions/demo-permissions.component.scss
@@ -1,6 +1,6 @@
.inherit_permission_button {
padding-top: 20px;
display: flex;
- justify-content: space-evenly;
+ justify-content: center;
padding-bottom: 20px;
}
diff --git a/demo-shell/src/app/components/permissions/demo-permissions.component.ts b/demo-shell/src/app/components/permissions/demo-permissions.component.ts
index cc4ad25a3e..49455b8c51 100644
--- a/demo-shell/src/app/components/permissions/demo-permissions.component.ts
+++ b/demo-shell/src/app/components/permissions/demo-permissions.component.ts
@@ -17,9 +17,9 @@
import { Component, Optional, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute, Params} from '@angular/router';
-import { PermissionListComponent } from '@alfresco/adf-content-services';
+import { PermissionListComponent, NodePermissionDialogService } from '@alfresco/adf-content-services';
import { MinimalNodeEntryEntity } from 'alfresco-js-api';
-import { NodesApiService } from '@alfresco/adf-core';
+import { NodesApiService, NotificationService } from '@alfresco/adf-core';
@Component({
selector: 'app-permissions',
@@ -35,7 +35,9 @@ export class DemoPermissionComponent implements OnInit {
toggleStatus = false;
constructor(@Optional() private route: ActivatedRoute,
- private nodeService: NodesApiService) {
+ private nodeService: NodesApiService,
+ private nodePermissionDialogService: NodePermissionDialogService,
+ private notificationService: NotificationService) {
}
ngOnInit() {
@@ -56,4 +58,24 @@ export class DemoPermissionComponent implements OnInit {
this.displayPermissionComponent.reload();
}
+ reloadList() {
+ this.displayPermissionComponent.reload();
+ }
+
+ openAddPermissionDialog(event: Event) {
+ this.nodePermissionDialogService.updateNodePermissionByDialog(this.nodeId).subscribe(() => {
+ this.displayPermissionComponent.reload();
+ },
+ (error) => {
+ this.showErrorMessage(error);
+ });
+ }
+
+ showErrorMessage(error) {
+ this.notificationService.openSnackMessage(
+ JSON.parse(error.response.text).error.errorKey,
+ 4000
+ );
+ }
+
}
diff --git a/docs/content-services/add-permission-dialog.component.md b/docs/content-services/add-permission-dialog.component.md
new file mode 100644
index 0000000000..1a5daaa4f1
--- /dev/null
+++ b/docs/content-services/add-permission-dialog.component.md
@@ -0,0 +1,63 @@
+---
+Added: v2.4.0
+Status: Active
+Last reviewed: 2018-05-03
+---
+
+# Add Permission Dialog Component
+
+Allow user to search people or group that could be added to the current node permissions.
+
+
+
+## Basic Usage
+
+```ts
+import { NodePermissionDialogService } from '@alfresco/adf-content-services';
+
+ constructor(private nodePermissionDialogService: nodePermissionDialogService) {
+ }
+
+ this.nodePermissionDialogService.openAddPermissionDialog(this.nodeId).subscribe((selectedNodes) => {
+ //action for selected nodes
+ },
+ (error) => {
+ this.showErrorMessage(error);
+ });
+```
+
+## Class members
+
+### Properties
+
+| Name | Type | Default value | Description |
+| -- | -- | -- | -- |
+| nodeId | `string` | "" | |
+
+### Events
+
+| Name | Type | Description |
+| -- | -- | -- |
+| success | `EventEmitter` | |
+| error | `EventEmitter` | |
+
+## Details
+
+This component extends the [Add permission panel component](../add-permission-panel.component.md)
+and apply the action confirm when the selection made is accepted.
+The dialog will be opened via the nodePermissionDialogService which will provide an Observable to subscribe to for getting the node selected.
+In case you want the dialog service to take care of update the current node you can call `updateNodePermissionByDialog` in this way :
+
+```ts
+import { NodePermissionDialogService } from '@alfresco/adf-content-services';
+
+ constructor(private nodePermissionDialogService: nodePermissionDialogService) {
+ }
+
+ this.nodePermissionDialogService.updateNodePermissionByDialog(this.nodeId).subscribe((node) => {
+ //updated node
+ },
+ (error) => {
+ this.showErrorMessage(error);
+ });
+```
\ No newline at end of file
diff --git a/docs/content-services/add-permission-panel.component.md b/docs/content-services/add-permission-panel.component.md
new file mode 100644
index 0000000000..479e7bd0bb
--- /dev/null
+++ b/docs/content-services/add-permission-panel.component.md
@@ -0,0 +1,37 @@
+---
+Added: v2.4.0
+Status: Active
+Last reviewed: 2018-05-03
+---
+
+# Add Permission Component
+
+Allow user to search people or group that could be added to the current node permissions.
+
+
+
+## Basic Usage
+
+```html
+
+
+```
+
+## Class members
+
+### Properties
+
+| Name | Type | Default value | Description |
+| -- | -- | -- | -- |
+
+### Events
+
+| Name | Type | Description |
+| -- | -- | -- |
+| select | `EventEmitter` | |
+
+## Details
+This component uses a [Search component](../search.component.md) to retrieve the
+groups and people that could be added to the permission list of the current node.
+The `select` event will be emitted when a result is clicked from the list.
\ No newline at end of file
diff --git a/docs/content-services/add-permission.component.md b/docs/content-services/add-permission.component.md
new file mode 100644
index 0000000000..f86e89bd2a
--- /dev/null
+++ b/docs/content-services/add-permission.component.md
@@ -0,0 +1,41 @@
+---
+Added: v2.4.0
+Status: Active
+Last reviewed: 2018-05-03
+---
+
+# Add Permission Component
+
+Allow user to search people or group that could be added to the current node permissions.
+
+
+
+## Basic Usage
+
+```html
+
+
+```
+
+## Class members
+
+### Properties
+
+| Name | Type | Default value | Description |
+| -- | -- | -- | -- |
+| nodeId | `string` | "" | |
+
+### Events
+
+| Name | Type | Description |
+| -- | -- | -- |
+| success | `EventEmitter` | |
+| error | `EventEmitter` | |
+
+## Details
+
+This component extends the [Add permission panel component](../add-permission-panel.component.md)
+and apply the action confirm when the selection made is accepted.
+The `success` event will be emitted when the node is correctly updated.
+The `error` event will be thrown whenever the node update permission will fail.
diff --git a/docs/docassets/images/add-permission-component.png b/docs/docassets/images/add-permission-component.png
new file mode 100644
index 0000000000..b3a9628f85
Binary files /dev/null and b/docs/docassets/images/add-permission-component.png differ
diff --git a/lib/content-services/i18n/en.json b/lib/content-services/i18n/en.json
index 4cd29e1d0c..b8f7b14292 100644
--- a/lib/content-services/i18n/en.json
+++ b/lib/content-services/i18n/en.json
@@ -261,6 +261,14 @@
"ROLE": "Role",
"LOCALLY_SET": "Locally set",
"NO_PERMISSIONS": "No permissions"
- }
+ },
+ "ADD-PERMISSION": {
+ "SEARCH" : "Search",
+ "TYPE-MESSAGE" : "Type something to start searching groups or people",
+ "NO-RESULT": "No result found for this search",
+ "ADD-ACTION" : "ADD",
+ "CLOSE-ACTION" : "CLOSE",
+ "BASE-DIALOG-TITLE" : "Search a group or people to add..."
+ }
}
}
diff --git a/lib/content-services/mock/add-permission.component.mock.ts b/lib/content-services/mock/add-permission.component.mock.ts
new file mode 100644
index 0000000000..e63efafe46
--- /dev/null
+++ b/lib/content-services/mock/add-permission.component.mock.ts
@@ -0,0 +1,153 @@
+/*!
+ * @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.
+ */
+
+export const fakeAuthorityResults: any[] = [{
+ 'entry': {
+ 'aspectNames': [
+ 'cm:personDisabled',
+ 'cm:ownable',
+ 'cm:preferences'
+ ],
+ 'isFolder': false,
+ 'search': {
+ 'score': 4.014668
+ },
+ 'isFile': false,
+ 'name': 'dc103838-645f-43c1-8a2a-bc187e13c343',
+ 'location': 'nodes',
+ 'id': 'dc103838-645f-43c1-8a2a-bc187e13c343',
+ 'nodeType': 'cm:person',
+ 'properties': {
+ 'cm:location': 'Tilbury, UK',
+ 'cm:persondescription': {
+ 'contentUrl': 'store://2018/4/18/9/30/514bb261-bc61-4502-ad2f-dfafec9ae4eb.bin',
+ 'mimetype': 'application/octet-stream',
+ 'size': 55,
+ 'encoding': 'UTF-8',
+ 'locale': 'en_US',
+ 'id': 148,
+ 'infoUrl': 'contentUrl=store://2018/4/18/9/30/514bb261-bc61-4502-ad2f-dfafec9ae4eb.bin|mimetype=application/octet-stream|size=55|encoding=UTF-8|locale=en_US_'
+ },
+ 'cm:owner': {
+ 'id': 'abeecher',
+ 'displayName': 'Alice Beecher'
+ },
+ 'cm:companyaddress2': 'Tilbury',
+ 'cm:userStatus': 'Helping to design the look and feel of the new web site',
+ 'cm:companyaddress1': '200 Butterwick Street',
+ 'cm:telephone': '0112211001100',
+ 'cm:preferenceValues': {
+ 'contentUrl': 'store://2018/4/18/9/30/afc39bc9-6bac-4f24-8730-9d9f617a322e.bin',
+ 'mimetype': 'text/plain',
+ 'size': 709,
+ 'encoding': 'UTF-8',
+ 'locale': 'en_US',
+ 'id': 147,
+ 'infoUrl': 'contentUrl=store://2018/4/18/9/30/afc39bc9-6bac-4f24-8730-9d9f617a322e.bin|mimetype=text/plain|size=709|encoding=UTF-8|locale=en_US_'
+ },
+ 'cm:userName': 'abeecher',
+ 'cm:companyaddress3': 'UK',
+ 'cm:userStatusTime': '2011-02-15T20:20:13.432+0000',
+ 'cm:email': 'abeecher@example.com',
+ 'cm:skype': 'abeecher',
+ 'cm:jobtitle': 'Graphic Designer',
+ 'cm:homeFolderProvider': 'userHomesHomeFolderProvider',
+ 'cm:homeFolder': '242533d8-68e6-4811-bc3d-61ec63c614aa',
+ 'cm:lastName': 'Beecher',
+ 'cm:sizeCurrent': 8382006,
+ 'cm:sizeQuota': -1,
+ 'cm:firstName': 'Alice',
+ 'cm:emailFeedId': 440,
+ 'cm:authorizationStatus': 'NEVER_AUTHORIZED',
+ 'cm:mobile': '0112211001100',
+ 'cm:organization': 'Moresby, Garland and Wedge',
+ 'cm:companypostcode': 'ALF1 SAM1'
+ },
+ 'parentId': '063f5d48-a0b3-4cbf-826c-88a4fbfa3336'
+ }
+},
+{
+ 'entry': {
+ 'aspectNames': [
+ 'cm:ownable',
+ 'cm:preferences'
+ ],
+ 'isFolder': false,
+ 'search': {
+ 'score': 4.014668
+ },
+ 'isFile': false,
+ 'name': 'e320c16b-a763-4a4e-9f22-286ff5d8dca2',
+ 'location': 'nodes',
+ 'id': 'e320c16b-a763-4a4e-9f22-286ff5d8dca2',
+ 'nodeType': 'cm:person',
+ 'properties': {
+ 'cm:homeFolderProvider': 'bootstrapHomeFolderProvider',
+ 'cm:preferenceValues': {
+ 'contentUrl': 'store://2018/4/23/14/42/92bb4aa9-db27-41a4-9804-ddab3cc83d3e.bin',
+ 'mimetype': 'text/plain',
+ 'size': 102,
+ 'encoding': 'UTF-8',
+ 'locale': 'en',
+ 'id': 313,
+ 'infoUrl': 'contentUrl=store://2018/4/23/14/42/92bb4aa9-db27-41a4-9804-ddab3cc83d3e.bin|mimetype=text/plain|size=102|encoding=UTF-8|locale=en_'
+ },
+ 'cm:authorizationStatus': 'AUTHORIZED',
+ 'cm:homeFolder': 'a20cd541-4ada-4525-9807-9fa0a047d9f4',
+ 'cm:userName': 'admin',
+ 'cm:sizeCurrent': 0,
+ 'cm:email': 'admin@alfresco.com',
+ 'cm:firstName': 'Administrator',
+ 'cm:owner': {
+ 'id': 'admin',
+ 'displayName': 'Administrator'
+ }
+ },
+ 'parentId': '063f5d48-a0b3-4cbf-826c-88a4fbfa3336'
+ }
+},
+{
+ 'entry': {
+ 'isFolder': false,
+ 'search': {
+ 'score': 0.3541112
+ },
+ 'isFile': false,
+ 'name': 'GROUP_ALFRESCO_ADMINISTRATORS',
+ 'location': 'nodes',
+ 'id': 'GROUP_ALFRESCO_ADMINISTRATORS',
+ 'nodeType': 'cm:authorityContainer',
+ 'properties': {
+ 'cm:authorityName': 'GROUP_ALFRESCO_ADMINISTRATORS'
+ },
+ 'parentId': '030d833e-da8e-4f5c-8ef9-d809638bd04b'
+ }
+}];
+
+export const fakeAuthorityListResult: any = {
+'list': {
+'pagination': {
+ 'count': 0,
+ 'hasMoreItems': false,
+ 'totalItems': 0,
+ 'skipCount': 0,
+ 'maxItems': 100
+},
+'context': {},
+'entries': fakeAuthorityResults
+}
+};
diff --git a/lib/content-services/mock/permission-list.component.mock.ts b/lib/content-services/mock/permission-list.component.mock.ts
index 903a8d7173..9dacbb68dc 100644
--- a/lib/content-services/mock/permission-list.component.mock.ts
+++ b/lib/content-services/mock/permission-list.component.mock.ts
@@ -251,6 +251,89 @@ export const fakeNodeWithOnlyLocally: any = {
}
};
+export const fakeNodeToRemovePermission: any = {
+ 'aspectNames': [
+ 'cm:auditable',
+ 'cm:taggable',
+ 'cm:author',
+ 'cm:titled',
+ 'app:uifacets'
+ ],
+ 'createdAt': '2017-11-16T16:29:38.638+0000',
+ 'path': {
+ 'name': '/Company Home/Sites/testsite/documentLibrary',
+ 'isComplete': true,
+ 'elements': [
+ {
+ 'id': '2be275a1-b00d-4e45-83d8-66af43ac2252',
+ 'name': 'Company Home'
+ },
+ {
+ 'id': '1be10a97-6eb9-4b60-b6c6-1673900e9631',
+ 'name': 'Sites'
+ },
+ {
+ 'id': 'e002c740-b8f9-482a-a554-8fff4e4c9dc0',
+ 'name': 'testsite'
+ },
+ {
+ 'id': '71626fae-0c04-4d0c-a129-20fa4c178716',
+ 'name': 'documentLibrary'
+ }
+ ]
+ },
+ 'isFolder': true,
+ 'isFile': false,
+ 'createdByUser': {
+ 'id': 'System',
+ 'displayName': 'System'
+ },
+ 'modifiedAt': '2018-03-21T03:17:58.783+0000',
+ 'permissions': {
+ 'locallySet': [
+ {
+ 'authorityId': 'GROUP_EVERYONE',
+ 'name': 'Contributor',
+ 'accessStatus': 'ALLOWED'
+ },
+ {
+ 'authorityId': 'GROUP_FAKE_1',
+ 'name': 'Contributor',
+ 'accessStatus': 'ALLOWED'
+ },
+ {
+ 'authorityId': 'FAKE_PERSON_1',
+ 'name': 'Contributor',
+ 'accessStatus': 'ALLOWED'
+ }
+ ],
+ 'settable': [
+ 'Contributor',
+ 'Collaborator',
+ 'Coordinator',
+ 'Editor',
+ 'Consumer'
+ ],
+ 'isInheritanceEnabled': true
+ },
+ 'modifiedByUser': {
+ 'id': 'admin',
+ 'displayName': 'PedroH Hernandez'
+ },
+ 'name': 'test',
+ 'id': 'f472543f-7218-403d-917b-7a5861257244',
+ 'nodeType': 'cm:folder',
+ 'properties': {
+ 'cm:title': 'test',
+ 'cm:author': 'yagud',
+ 'cm:taggable': [
+ 'e8c8fbba-03ba-4fa6-86b1-f7ad7c296409'
+ ],
+ 'cm:description': 'sleepery',
+ 'app:icon': 'space-icon-default'
+ }
+};
+
export const fakeNodeWithoutPermissions: any = {
'aspectNames': [
'cm:auditable',
diff --git a/lib/content-services/permission-manager/components/add-permission/add-permission-dialog-data.interface.ts b/lib/content-services/permission-manager/components/add-permission/add-permission-dialog-data.interface.ts
new file mode 100644
index 0000000000..37282feb84
--- /dev/null
+++ b/lib/content-services/permission-manager/components/add-permission/add-permission-dialog-data.interface.ts
@@ -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;
+}
diff --git a/lib/content-services/permission-manager/components/add-permission/add-permission-dialog.component.html b/lib/content-services/permission-manager/components/add-permission/add-permission-dialog.component.html
new file mode 100644
index 0000000000..0a6891632d
--- /dev/null
+++ b/lib/content-services/permission-manager/components/add-permission/add-permission-dialog.component.html
@@ -0,0 +1,16 @@
+
+ {{(data?.title ? data?.title : 'PERMISSION_MANAGER.ADD-PERMISSION.BASE-DIALOG-TITLE') | translate}}
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/content-services/permission-manager/components/add-permission/add-permission-dialog.component.scss b/lib/content-services/permission-manager/components/add-permission/add-permission-dialog.component.scss
new file mode 100644
index 0000000000..457536fef1
--- /dev/null
+++ b/lib/content-services/permission-manager/components/add-permission/add-permission-dialog.component.scss
@@ -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);
+ }
+ }
+ }
+ }
+}
diff --git a/lib/content-services/permission-manager/components/add-permission/add-permission-dialog.component.spec.ts b/lib/content-services/permission-manager/components/add-permission/add-permission-dialog.component.spec.ts
new file mode 100644
index 0000000000..b523e751d4
--- /dev/null
+++ b/lib/content-services/permission-manager/components/add-permission/add-permission-dialog.component.spec.ts
@@ -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;
+ let element: HTMLElement;
+ let data: AddPermissionDialogData = {
+ title: 'dead or alive you are coming with me',
+ nodeId: 'fake-node-id',
+ confirm: new Subject ()
+ };
+ 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 = 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 = 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 = element.querySelector('#add-permission-dialog-confirm-button');
+ expect(confirmButton.disabled).toBeTruthy();
+ fixture.detectChanges();
+ fixture.whenStable().then(() => {
+ fixture.detectChanges();
+ confirmButton = 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 = element.querySelector('#add-permission-dialog-confirm-button');
+ confirmButton.click();
+ });
+ }));
+});
diff --git a/lib/content-services/permission-manager/components/add-permission/add-permission-dialog.component.ts b/lib/content-services/permission-manager/components/add-permission/add-permission-dialog.component.ts
new file mode 100644
index 0000000000..c41d208557
--- /dev/null
+++ b/lib/content-services/permission-manager/components/add-permission/add-permission-dialog.component.ts
@@ -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();
+ }
+}
diff --git a/lib/content-services/permission-manager/components/add-permission/add-permission-panel.component.html b/lib/content-services/permission-manager/components/add-permission/add-permission-panel.component.html
new file mode 100644
index 0000000000..801c16b3de
--- /dev/null
+++ b/lib/content-services/permission-manager/components/add-permission/add-permission-panel.component.html
@@ -0,0 +1,54 @@
+
+
+
+ 0"
+ class="adf-permission-search-icon"
+ data-automation-id="adf-permission-clear-input"
+ id="adf-permission-clear-input"
+ matSuffix (click)="clearSearch()">clear
+
+
+ search
+
+
+
+
+ {{'PERMISSION_MANAGER.ADD-PERMISSION.TYPE-MESSAGE' | translate}}
+
+
+
+
+
+
+
+ group_add
+
+
+ person_add
+
+
+ {{item.entry?.properties['cm:authorityName']?
+ item.entry?.properties['cm:authorityName'] :
+ item.entry?.properties['cm:firstName']}}
+
+
+
+ {{'PERMISSION_MANAGER.ADD-PERMISSION.NO-RESULT' | translate}}
+
+
+
diff --git a/lib/content-services/permission-manager/components/add-permission/add-permission-panel.component.scss b/lib/content-services/permission-manager/components/add-permission/add-permission-panel.component.scss
new file mode 100644
index 0000000000..10e293d7ac
--- /dev/null
+++ b/lib/content-services/permission-manager/components/add-permission/add-permission-panel.component.scss
@@ -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);
+ }
+ }
+ }
+}
diff --git a/lib/content-services/permission-manager/components/add-permission/add-permission-panel.component.spec.ts b/lib/content-services/permission-manager/components/add-permission/add-permission-panel.component.spec.ts
new file mode 100644
index 0000000000..d6e869e282
--- /dev/null
+++ b/lib/content-services/permission-manager/components/add-permission/add-permission-panel.component.spec.ts
@@ -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;
+ 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', {});
+ });
+ }));
+
+});
diff --git a/lib/content-services/permission-manager/components/add-permission/add-permission-panel.component.ts b/lib/content-services/permission-manager/components/add-permission/add-permission-panel.component.ts
new file mode 100644
index 0000000000..df35119d07
--- /dev/null
+++ b/lib/content-services/permission-manager/components/add-permission/add-permission-panel.component.ts
@@ -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 = 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();
+ }
+
+}
diff --git a/lib/content-services/permission-manager/components/add-permission/add-permission.component.html b/lib/content-services/permission-manager/components/add-permission/add-permission.component.html
new file mode 100644
index 0000000000..99d3792e9d
--- /dev/null
+++ b/lib/content-services/permission-manager/components/add-permission/add-permission.component.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
diff --git a/lib/content-services/permission-manager/components/add-permission/add-permission.component.scss b/lib/content-services/permission-manager/components/add-permission/add-permission.component.scss
new file mode 100644
index 0000000000..c3324845cd
--- /dev/null
+++ b/lib/content-services/permission-manager/components/add-permission/add-permission.component.scss
@@ -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);
+ }
+ }
+ }
+}
diff --git a/lib/content-services/permission-manager/components/add-permission/add-permission.component.spec.ts b/lib/content-services/permission-manager/components/add-permission/add-permission.component.spec.ts
new file mode 100644
index 0000000000..71c3f28321
--- /dev/null
+++ b/lib/content-services/permission-manager/components/add-permission/add-permission.component.spec.ts
@@ -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;
+ 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 = 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 = 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 = 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 = element.querySelector('#adf-add-permission-action-button');
+ addButton.click();
+ });
+ }));
+
+});
diff --git a/lib/content-services/permission-manager/components/add-permission/add-permission.component.ts b/lib/content-services/permission-manager/components/add-permission/add-permission.component.ts
new file mode 100644
index 0000000000..c6d4b1734d
--- /dev/null
+++ b/lib/content-services/permission-manager/components/add-permission/add-permission.component.ts
@@ -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 = new EventEmitter();
+
+ @Output()
+ error: EventEmitter = 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);
+ });
+ }
+
+}
diff --git a/lib/content-services/permission-manager/components/add-permission/search-config-permission.service.ts b/lib/content-services/permission-manager/components/add-permission/search-config-permission.service.ts
new file mode 100644
index 0000000000..7b58ce3783
--- /dev/null
+++ b/lib/content-services/permission-manager/components/add-permission/search-config-permission.service.ts
@@ -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;
+ }
+}
diff --git a/lib/content-services/permission-manager/components/inherited-button.directive.spec.ts b/lib/content-services/permission-manager/components/inherited-button.directive.spec.ts
index 97202ec06b..4828b39779 100644
--- a/lib/content-services/permission-manager/components/inherited-button.directive.spec.ts
+++ b/lib/content-services/permission-manager/components/inherited-button.directive.spec.ts
@@ -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();
diff --git a/lib/content-services/permission-manager/components/inherited-button.directive.ts b/lib/content-services/permission-manager/components/inherited-button.directive.ts
index 01e5e21468..9bc1c3faa9 100644
--- a/lib/content-services/permission-manager/components/inherited-button.directive.ts
+++ b/lib/content-services/permission-manager/components/inherited-button.directive.ts
@@ -35,15 +35,18 @@ export class InheritPermissionDirective {
@Output()
updated: EventEmitter = new EventEmitter();
+ @Output()
+ error: EventEmitter = new EventEmitter();
+
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));
});
}
diff --git a/lib/content-services/permission-manager/components/permission-list/permission-list.component.html b/lib/content-services/permission-manager/components/permission-list/permission-list.component.html
index 2a1cce741f..4c9f58c330 100644
--- a/lib/content-services/permission-manager/components/permission-list/permission-list.component.html
+++ b/lib/content-services/permission-manager/components/permission-list/permission-list.component.html
@@ -48,6 +48,13 @@
+
+
+
+
+
diff --git a/lib/content-services/permission-manager/components/permission-list/permission-list.component.ts b/lib/content-services/permission-manager/components/permission-list/permission-list.component.ts
index e741ebce98..0a49a03841 100644
--- a/lib/content-services/permission-manager/components/permission-list/permission-list.component.ts
+++ b/lib/content-services/permission-manager/components/permission-list/permission-list.component.ts
@@ -35,6 +35,9 @@ export class PermissionListComponent implements OnInit {
@Output()
update: EventEmitter = new EventEmitter();
+ @Output()
+ error: EventEmitter = 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));
+ }
+
}
diff --git a/lib/content-services/permission-manager/models/permission.model.ts b/lib/content-services/permission-manager/models/permission.model.ts
index 7e9600e31c..3500496d58 100644
--- a/lib/content-services/permission-manager/models/permission.model.ts
+++ b/lib/content-services/permission-manager/models/permission.model.ts
@@ -31,7 +31,7 @@ export class PermissionDisplayModel implements PermissionElement {
this.name = obj.name;
this.accessStatus = obj.accessStatus;
this.isInherited = obj.isInherited !== null && obj.isInherited !== undefined ? obj.isInherited : false;
- this.icon = obj.icon ? obj.icon : 'lock_open';
+ this.icon = obj.icon ? obj.icon : 'vpn_key';
}
}
}
diff --git a/lib/content-services/permission-manager/permission-manager.module.ts b/lib/content-services/permission-manager/permission-manager.module.ts
index ff918e5d2c..9a4385d5f7 100644
--- a/lib/content-services/permission-manager/permission-manager.module.ts
+++ b/lib/content-services/permission-manager/permission-manager.module.ts
@@ -21,10 +21,15 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { TranslateModule } from '@ngx-translate/core';
import { MaterialModule } from '../material.module';
import { PermissionListComponent } from './components/permission-list/permission-list.component';
+import { AddPermissionComponent } from './components/add-permission/add-permission.component';
+import { AddPermissionDialogComponent } from './components/add-permission/add-permission-dialog.component';
import { DataTableModule, DataColumnModule } from '@alfresco/adf-core';
import { InheritPermissionDirective } from './components/inherited-button.directive';
import { NodePermissionService } from './services/node-permission.service';
import { NoPermissionTemplateComponent } from './components/permission-list/no-permission.component';
+import { SearchModule } from '..';
+import { NodePermissionDialogService } from './services/node-permission-dialog.service';
+import { AddPermissionPanelComponent } from './components/add-permission/add-permission-panel.component';
@NgModule({
imports: [
@@ -34,20 +39,29 @@ import { NoPermissionTemplateComponent } from './components/permission-list/no-p
MaterialModule,
TranslateModule,
DataTableModule,
- DataColumnModule
+ DataColumnModule,
+ SearchModule
],
declarations: [
PermissionListComponent,
NoPermissionTemplateComponent,
- InheritPermissionDirective
+ AddPermissionPanelComponent,
+ InheritPermissionDirective,
+ AddPermissionComponent,
+ AddPermissionDialogComponent
],
providers: [
+ NodePermissionDialogService,
NodePermissionService
],
+ entryComponents: [ AddPermissionPanelComponent, AddPermissionComponent, AddPermissionDialogComponent ],
exports: [
PermissionListComponent,
NoPermissionTemplateComponent,
- InheritPermissionDirective
+ AddPermissionPanelComponent,
+ InheritPermissionDirective,
+ AddPermissionComponent,
+ AddPermissionDialogComponent
]
})
export class PermissionManagerModule {}
diff --git a/lib/content-services/permission-manager/public-api.ts b/lib/content-services/permission-manager/public-api.ts
index 3e76f09728..d49beb12bd 100644
--- a/lib/content-services/permission-manager/public-api.ts
+++ b/lib/content-services/permission-manager/public-api.ts
@@ -18,7 +18,12 @@
export * from './components/permission-list/permission-list.component';
export * from './components/permission-list/no-permission.component';
export * from './components/inherited-button.directive';
-export * from './services/node-permission.service';
export * from './models/permission.model';
+export * from './services/node-permission-dialog.service';
+export * from './services/node-permission.service';
+export * from './components/add-permission/add-permission-dialog-data.interface';
+export * from './components/add-permission/add-permission-panel.component';
+export * from './components/add-permission/add-permission.component';
+export * from './components/add-permission/add-permission-dialog.component';
export * from './permission-manager.module';
diff --git a/lib/content-services/permission-manager/services/node-permission-dialog.service.spec.ts b/lib/content-services/permission-manager/services/node-permission-dialog.service.spec.ts
new file mode 100644
index 0000000000..afcd3b7c17
--- /dev/null
+++ b/lib/content-services/permission-manager/services/node-permission-dialog.service.spec.ts
@@ -0,0 +1,83 @@
+/*!
+ * @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 { TestBed, async } from '@angular/core/testing';
+import { AppConfigService, setupTestBed } from '@alfresco/adf-core';
+import { NodePermissionDialogService } from './node-permission-dialog.service';
+import { MatDialog } from '@angular/material';
+import { Observable } from 'rxjs/Observable';
+import { Subject } from 'rxjs/Subject';
+import { ContentTestingModule } from '../../testing/content.testing.module';
+import { NodePermissionService } from './node-permission.service';
+
+describe('NodePermissionDialogService', () => {
+
+ let service: NodePermissionDialogService;
+ let materialDialog: MatDialog;
+ let spyOnDialogOpen: jasmine.Spy;
+ let afterOpenObservable: Subject;
+ let nodePermissionService: NodePermissionService;
+
+ setupTestBed({
+ imports: [ContentTestingModule],
+ providers: [NodePermissionService]
+ });
+
+ beforeEach(() => {
+ let appConfig: AppConfigService = TestBed.get(AppConfigService);
+ appConfig.config.ecmHost = 'http://localhost:9876/ecm';
+ service = TestBed.get(NodePermissionDialogService);
+ materialDialog = TestBed.get(MatDialog);
+ afterOpenObservable = new Subject();
+ nodePermissionService = TestBed.get(NodePermissionService);
+ spyOnDialogOpen = spyOn(materialDialog, 'open').and.returnValue({
+ afterOpen: () => afterOpenObservable,
+ afterClosed: () => Observable.of({}),
+ componentInstance: {
+ error: new Subject()
+ }
+ });
+ });
+
+ it('should be able to create the service', () => {
+ expect(service).not.toBeNull();
+ });
+
+ it('should be able to open the dialog showing node permissions', () => {
+ service.openAddPermissionDialog('fake-node-id', 'fake-title');
+ expect(spyOnDialogOpen).toHaveBeenCalled();
+ });
+
+ it('should throw an error if the update of the node fails', async(() => {
+ spyOn(nodePermissionService, 'updateNodePermissions').and.returnValue(Observable.throw({error : 'error'}));
+ spyOn(service, 'openAddPermissionDialog').and.returnValue(Observable.of({}));
+ service.updateNodePermissionByDialog('fake-node-id', 'fake-title').subscribe(() => {
+ Observable.throw('This call should fail');
+ }, (error) => {
+ expect(error.error).toBe('error');
+ });
+ }));
+
+ it('should return the updated node', async(() => {
+ spyOn(nodePermissionService, 'updateNodePermissions').and.returnValue(Observable.of({id : 'fake-node'}));
+ spyOn(service, 'openAddPermissionDialog').and.returnValue(Observable.of({}));
+ service.updateNodePermissionByDialog('fake-node-id', 'fake-title').subscribe((node) => {
+ expect(node.id).toBe('fake-node');
+ });
+ }));
+
+});
diff --git a/lib/content-services/permission-manager/services/node-permission-dialog.service.ts b/lib/content-services/permission-manager/services/node-permission-dialog.service.ts
new file mode 100644
index 0000000000..b0c433021b
--- /dev/null
+++ b/lib/content-services/permission-manager/services/node-permission-dialog.service.ts
@@ -0,0 +1,64 @@
+/*!
+ * @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 { MatDialog } from '@angular/material';
+import { Injectable } from '@angular/core';
+import { Subject } from 'rxjs/Subject';
+import { Observable } from 'rxjs/Observable';
+import { AddPermissionDialogComponent } from '../components/add-permission/add-permission-dialog.component';
+import { AddPermissionDialogData } from '../components/add-permission/add-permission-dialog-data.interface';
+import { MinimalNodeEntity, MinimalNodeEntryEntity } from 'alfresco-js-api';
+import { NodePermissionService } from './node-permission.service';
+
+@Injectable()
+export class NodePermissionDialogService {
+
+ constructor(private dialog: MatDialog,
+ private nodePermissionService: NodePermissionService) {
+ }
+
+ openAddPermissionDialog(nodeId: string, title?: string): Observable {
+ const confirm = new Subject();
+
+ confirm.subscribe({
+ complete: this.close.bind(this)
+ });
+
+ const data: AddPermissionDialogData = {
+ nodeId: nodeId,
+ title: title,
+ confirm : confirm
+ };
+
+ this.openDialog(data, 'adf-add-permission-dialog', '630px');
+ return confirm;
+ }
+
+ private openDialog(data: any, currentPanelClass: string, chosenWidth: string) {
+ this.dialog.open(AddPermissionDialogComponent, { data, panelClass: currentPanelClass, width: chosenWidth });
+ }
+
+ close() {
+ this.dialog.closeAll();
+ }
+
+ updateNodePermissionByDialog(nodeId?: string, title?: string): Observable {
+ return this.openAddPermissionDialog(nodeId, title).switchMap((selection) => {
+ return this.nodePermissionService.updateNodePermissions(nodeId, selection);
+ });
+ }
+}
diff --git a/lib/content-services/permission-manager/services/node-permission.service.spec.ts b/lib/content-services/permission-manager/services/node-permission.service.spec.ts
index b45554d6b7..588f80426a 100644
--- a/lib/content-services/permission-manager/services/node-permission.service.spec.ts
+++ b/lib/content-services/permission-manager/services/node-permission.service.spec.ts
@@ -20,7 +20,10 @@ import { NodePermissionService } from './node-permission.service';
import { SearchService, NodesApiService, setupTestBed, CoreModule } from '@alfresco/adf-core';
import { MinimalNodeEntryEntity, PermissionElement } from 'alfresco-js-api';
import { Observable } from 'rxjs/Observable';
-import { fakeEmptyResponse, fakeNodeWithOnlyLocally, fakeSiteRoles, fakeSiteNodeResponse } from '../../mock/permission-list.component.mock';
+import { fakeEmptyResponse, fakeNodeWithOnlyLocally, fakeSiteRoles, fakeSiteNodeResponse,
+ fakeNodeToRemovePermission } from '../../mock/permission-list.component.mock';
+import { fakeAuthorityResults } from '../../mock/add-permission.component.mock';
+import { NodePermissionDialogService } from './node-permission-dialog.service';
describe('NodePermissionService', () => {
@@ -33,6 +36,7 @@ describe('NodePermissionService', () => {
CoreModule.forRoot()
],
providers: [
+ NodePermissionDialogService,
NodePermissionService
]
});
@@ -85,7 +89,7 @@ describe('NodePermissionService', () => {
spyOn(nodeService, 'updateNode').and.callFake((nodeId, permissionBody) => returnUpdatedNode(nodeId, permissionBody));
- service.updatePermissionRoles(fakeNodeWithOnlyLocally, fakePermission).subscribe((node: MinimalNodeEntryEntity) => {
+ service.updatePermissionRole(fakeNodeWithOnlyLocally, fakePermission).subscribe((node: MinimalNodeEntryEntity) => {
expect(node).not.toBeNull();
expect(node.id).toBe('fake-updated-node');
expect(node.permissions.locallySet.length).toBe(1);
@@ -95,4 +99,53 @@ describe('NodePermissionService', () => {
});
}));
+ it('should be able to remove a locally set permission', async(() => {
+ const fakePermission: PermissionElement = {
+ 'authorityId': 'FAKE_PERSON_1',
+ 'name': 'Contributor',
+ 'accessStatus' : 'ALLOWED'
+ };
+ spyOn(nodeService, 'updateNode').and.callFake((nodeId, permissionBody) => returnUpdatedNode(nodeId, permissionBody));
+ const fakeNodeCopy = Object.assign(fakeNodeToRemovePermission);
+
+ service.removePermission(fakeNodeCopy, fakePermission).subscribe((node: MinimalNodeEntryEntity) => {
+ expect(node).not.toBeNull();
+ expect(node.id).toBe('fake-updated-node');
+ expect(node.permissions.locallySet.length).toBe(2);
+ expect(node.permissions.locallySet[0].authorityId).not.toBe(fakePermission.authorityId);
+ expect(node.permissions.locallySet[1].authorityId).not.toBe(fakePermission.authorityId);
+ });
+ }));
+
+ it('should be able to update locally set permissions on the node by node id', async(() => {
+ const fakeNodeCopy = Object.assign(fakeNodeWithOnlyLocally);
+ spyOn(nodeService, 'getNode').and.returnValue(Observable.of(fakeNodeCopy));
+ spyOn(nodeService, 'updateNode').and.callFake((nodeId, permissionBody) => returnUpdatedNode(nodeId, permissionBody));
+ spyOn(searchApiService, 'searchByQueryBody').and.returnValue(Observable.of(fakeSiteNodeResponse));
+ spyOn(service, 'getGroupMemeberByGroupName').and.returnValue(Observable.of(fakeSiteRoles));
+
+ service.updateNodePermissions('fake-node-id', fakeAuthorityResults).subscribe((node: MinimalNodeEntryEntity) => {
+ expect(node).not.toBeNull();
+ expect(node.id).toBe('fake-updated-node');
+ expect(node.permissions.locallySet.length).toBe(4);
+ expect(node.permissions.locallySet[3].authorityId).not.toBe(fakeAuthorityResults[0].entry['cm:userName']);
+ expect(node.permissions.locallySet[2].authorityId).not.toBe(fakeAuthorityResults[1].entry['cm:userName']);
+ expect(node.permissions.locallySet[1].authorityId).not.toBe(fakeAuthorityResults[2].entry['cm:userName']);
+ });
+ }));
+
+ it('should be able to update locally permissions on the node', async(() => {
+ const fakeNodeCopy = Object.assign(fakeNodeWithOnlyLocally);
+ spyOn(nodeService, 'updateNode').and.callFake((nodeId, permissionBody) => returnUpdatedNode(nodeId, permissionBody));
+
+ service.updateLocallySetPermissions(fakeNodeCopy, fakeAuthorityResults, fakeSiteRoles).subscribe((node: MinimalNodeEntryEntity) => {
+ expect(node).not.toBeNull();
+ expect(node.id).toBe('fake-updated-node');
+ expect(node.permissions.locallySet.length).toBe(4);
+ expect(node.permissions.locallySet[3].authorityId).not.toBe(fakeAuthorityResults[0].entry['cm:userName']);
+ expect(node.permissions.locallySet[2].authorityId).not.toBe(fakeAuthorityResults[1].entry['cm:userName']);
+ expect(node.permissions.locallySet[1].authorityId).not.toBe(fakeAuthorityResults[2].entry['cm:userName']);
+ });
+ }));
+
});
diff --git a/lib/content-services/permission-manager/services/node-permission.service.ts b/lib/content-services/permission-manager/services/node-permission.service.ts
index 6c3bb34f39..63d74e73fa 100644
--- a/lib/content-services/permission-manager/services/node-permission.service.ts
+++ b/lib/content-services/permission-manager/services/node-permission.service.ts
@@ -18,8 +18,10 @@
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { AlfrescoApiService, SearchService, NodesApiService } from '@alfresco/adf-core';
-import { QueryBody, MinimalNodeEntryEntity, PathElement, GroupMemberEntry, GroupsPaging, GroupMemberPaging, PermissionElement } from 'alfresco-js-api';
+import { QueryBody, MinimalNodeEntryEntity, MinimalNodeEntity, PathElement, GroupMemberEntry, GroupsPaging, GroupMemberPaging, PermissionElement } from 'alfresco-js-api';
import 'rxjs/add/operator/switchMap';
+import { of } from 'rxjs/observable/of';
+import { switchMap } from 'rxjs/operators';
@Injectable()
export class NodePermissionService {
@@ -42,7 +44,7 @@ export class NodePermissionService {
});
}
- updatePermissionRoles(node: MinimalNodeEntryEntity, updatedPermissionRole: PermissionElement): Observable {
+ updatePermissionRole(node: MinimalNodeEntryEntity, updatedPermissionRole: PermissionElement): Observable {
let permissionBody = { permissions: { locallySet: []} };
const index = node.permissions.locallySet.map((permission) => permission.authorityId).indexOf(updatedPermissionRole.authorityId);
permissionBody.permissions.locallySet = permissionBody.permissions.locallySet.concat(node.permissions.locallySet);
@@ -54,6 +56,47 @@ export class NodePermissionService {
return this.nodeService.updateNode(node.id, permissionBody);
}
+ updateNodePermissions(nodeId: string, permissionList: MinimalNodeEntity[]): Observable {
+ return this.nodeService.getNode(nodeId).pipe(
+ switchMap(node => {
+ return this.getNodeRoles(node).pipe(
+ switchMap((nodeRoles) => of({node, nodeRoles}) )
+ );
+ }),
+ switchMap(({node, nodeRoles}) => this.updateLocallySetPermissions(node, permissionList, nodeRoles))
+ );
+ }
+
+ updateLocallySetPermissions(node: MinimalNodeEntryEntity, nodes: MinimalNodeEntity[], nodeRole: string[]): Observable {
+ let permissionBody = { permissions: { locallySet: []} };
+ const permissionList = this.transformNodeToPermissionElement(nodes, nodeRole[0]);
+ permissionBody.permissions.locallySet = node.permissions.locallySet ? node.permissions.locallySet.concat(permissionList) : permissionList;
+ return this.nodeService.updateNode(node.id, permissionBody);
+ }
+
+ private transformNodeToPermissionElement(nodes: MinimalNodeEntity[], nodeRole: any): PermissionElement[] {
+ return nodes.map((node) => {
+ let newPermissionElement: PermissionElement = {
+ 'authorityId': node.entry.properties['cm:authorityName'] ?
+ node.entry.properties['cm:authorityName'] :
+ node.entry.properties['cm:userName'],
+ 'name': nodeRole,
+ 'accessStatus': 'ALLOWED'
+ };
+ return newPermissionElement;
+ });
+ }
+
+ removePermission(node: MinimalNodeEntryEntity, permissionToRemove: PermissionElement): Observable {
+ let permissionBody = { permissions: { locallySet: [] } };
+ const index = node.permissions.locallySet.map((permission) => permission.authorityId).indexOf(permissionToRemove.authorityId);
+ if (index !== -1) {
+ node.permissions.locallySet.splice(index, 1);
+ permissionBody.permissions.locallySet = node.permissions.locallySet;
+ return this.nodeService.updateNode(node.id, permissionBody);
+ }
+ }
+
private getGroupMembersBySiteName(siteName: string): Observable {
const groupName = 'GROUP_site_' + siteName;
return this.getGroupMemeberByGroupName(groupName)
diff --git a/lib/content-services/search/components/search-trigger.directive.ts b/lib/content-services/search/components/search-trigger.directive.ts
index 4c9b16eb68..f27f3cb892 100644
--- a/lib/content-services/search/components/search-trigger.directive.ts
+++ b/lib/content-services/search/components/search-trigger.directive.ts
@@ -201,7 +201,7 @@ export class SearchTriggerDirective implements ControlValueAccessor, OnDestroy {
}
private setValueAndClose(event: any | null): void {
- if (this.isPanelOptionClicked(event)) {
+ if (this.isPanelOptionClicked(event) && !event.defaultPrevented) {
this.setTriggerValue(event.target.textContent.trim());
this.onChange(event.target.textContent.trim());
this.element.nativeElement.focus();
diff --git a/lib/content-services/styles/_index.scss b/lib/content-services/styles/_index.scss
index bf8be12a5d..547bbbbf41 100644
--- a/lib/content-services/styles/_index.scss
+++ b/lib/content-services/styles/_index.scss
@@ -15,6 +15,9 @@
@import '../content-node-selector/content-node-selector.component';
@import '../content-metadata/content-metadata.module';
@import '../permission-manager/components/permission-list/permission-list.component';
+@import '../permission-manager/components/add-permission/add-permission.component';
+@import '../permission-manager/components/add-permission/add-permission-dialog.component';
+@import '../permission-manager/components/add-permission/add-permission-panel.component';
@mixin adf-content-services-theme($theme) {
@include adf-breadcrumb-theme($theme);
@@ -30,4 +33,7 @@
@include adf-content-node-selector-dialog-theme($theme) ;
@include adf-content-metadata-module-theme($theme);
@include adf-permission-list-theme($theme);
+ @include adf-add-permission-theme($theme);
+ @include adf-add-permission-dialog-theme($theme);
+ @include adf-add-permission-panel-theme($theme);
}