From 7a95485a05cab709fc12c2c8f897dcc52eb76120 Mon Sep 17 00:00:00 2001 From: Suzana Dirla Date: Mon, 9 Jul 2018 17:20:54 +0300 Subject: [PATCH] [ACA-1113] Node Permissions - experimental (#501) * [ACA-1113] Integrate permissions * [ACA-1113] experimental flag for permissions * [ACA-1113] permissions shown only on write permission * [ACA-1113] remove console.logs --- src/app.config.json | 1 + src/app/app.module.ts | 9 +- .../directives/node-permissions.directive.ts | 80 ++++++++++++++++ .../favorites/favorites.component.html | 10 ++ src/app/components/files/files.component.html | 10 ++ src/app/components/page.component.ts | 2 + .../permissions-manager.component.html | 20 ++++ .../permissions-manager.component.theme.scss | 49 ++++++++++ .../permissions-manager.component.ts | 91 +++++++++++++++++++ .../components/preview/preview.component.html | 10 ++ .../recent-files/recent-files.component.html | 10 ++ .../search-results.component.html | 10 ++ .../shared-files/shared-files.component.html | 10 ++ .../node-permissions.dialog.html | 7 ++ .../node-permissions.dialog.ts | 42 +++++++++ src/app/ui/custom-theme.scss | 2 + src/assets/i18n/en.json | 9 ++ 17 files changed, 371 insertions(+), 1 deletion(-) create mode 100644 src/app/common/directives/node-permissions.directive.ts create mode 100644 src/app/components/permission-manager/permissions-manager.component.html create mode 100644 src/app/components/permission-manager/permissions-manager.component.theme.scss create mode 100644 src/app/components/permission-manager/permissions-manager.component.ts create mode 100644 src/app/dialogs/node-permissions/node-permissions.dialog.html create mode 100644 src/app/dialogs/node-permissions/node-permissions.dialog.ts diff --git a/src/app.config.json b/src/app.config.json index 77853272d..d0220dfbf 100644 --- a/src/app.config.json +++ b/src/app.config.json @@ -12,6 +12,7 @@ "libraries": false, "comments": false, "cardview": false, + "permissions": false, "share": false, "extensions": false }, diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 81316b2f1..6bc9b1f84 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -81,6 +81,9 @@ import { ExtensionsModule } from './extensions.module'; import { ExtensionService } from './extensions/extension.service'; import { CoreExtensionsModule } from './extensions/core.extensions'; import { SearchResultsRowComponent } from './components/search/search-results-row/search-results-row.component'; +import { NodePermissionsDialogComponent } from './dialogs/node-permissions/node-permissions.dialog'; +import { NodePermissionsDirective } from './common/directives/node-permissions.directive'; +import { PermissionsManagerComponent } from './components/permission-manager/permissions-manager.component'; @NgModule({ imports: [ @@ -127,7 +130,10 @@ import { SearchResultsRowComponent } from './components/search/search-results-ro NodePermanentDeleteDirective, NodeUnshareDirective, NodeVersionsDirective, + NodePermissionsDirective, NodeVersionsDialogComponent, + NodePermissionsDialogComponent, + PermissionsManagerComponent, SearchResultsComponent, SettingsComponent, InfoDrawerComponent, @@ -156,7 +162,8 @@ import { SearchResultsRowComponent } from './components/search/search-results-ro ExtensionService ], entryComponents: [ - NodeVersionsDialogComponent + NodeVersionsDialogComponent, + NodePermissionsDialogComponent ], bootstrap: [AppComponent] }) diff --git a/src/app/common/directives/node-permissions.directive.ts b/src/app/common/directives/node-permissions.directive.ts new file mode 100644 index 000000000..6fe39cbe7 --- /dev/null +++ b/src/app/common/directives/node-permissions.directive.ts @@ -0,0 +1,80 @@ +/*! + * @license + * Alfresco Example Content Application + * + * Copyright (C) 2005 - 2018 Alfresco Software Limited + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +import { Directive, HostListener, Input } from '@angular/core'; +import { MinimalNodeEntity } from 'alfresco-js-api'; +import { MatDialog } from '@angular/material'; +import { Store } from '@ngrx/store'; +import { AppStore } from '../../store/states/app.state'; +import { SnackbarErrorAction } from '../../store/actions'; +import { NodePermissionsDialogComponent } from '../../dialogs/node-permissions/node-permissions.dialog'; + +@Directive({ + selector: '[acaNodePermissions]' +}) +export class NodePermissionsDirective { + // tslint:disable-next-line:no-input-rename + @Input('acaNodePermissions') node: MinimalNodeEntity; + + @HostListener('click') + onClick() { + this.showPermissions(); + } + + constructor( + private store: Store, + private dialog: MatDialog + ) {} + + showPermissions() { + if (this.node) { + let entry; + if (this.node.entry) { + entry = this.node.entry; + + } else { + entry = this.node; + } + + const entryId = entry.nodeId || (entry).guid || entry.id; + this.openPermissionsDialog(entryId); + } + } + + openPermissionsDialog(nodeId: string) { + // workaround Shared + if (nodeId) { + this.dialog.open(NodePermissionsDialogComponent, { + data: { nodeId }, + panelClass: 'aca-permissions-dialog-panel', + width: '730px' + }); + } else { + this.store.dispatch( + new SnackbarErrorAction('APP.MESSAGES.ERRORS.PERMISSION') + ); + } + } +} diff --git a/src/app/components/favorites/favorites.component.html b/src/app/components/favorites/favorites.component.html index 975c562af..e64fd52a9 100644 --- a/src/app/components/favorites/favorites.component.html +++ b/src/app/components/favorites/favorites.component.html @@ -116,6 +116,16 @@ history {{ 'APP.ACTIONS.VERSIONS' | translate }} + + + + diff --git a/src/app/components/files/files.component.html b/src/app/components/files/files.component.html index a718f2bfe..d9ebe1826 100644 --- a/src/app/components/files/files.component.html +++ b/src/app/components/files/files.component.html @@ -121,6 +121,16 @@ history {{ 'APP.ACTIONS.VERSIONS' | translate }} + + + + diff --git a/src/app/components/page.component.ts b/src/app/components/page.component.ts index 0bc69dca6..d551e0875 100644 --- a/src/app/components/page.component.ts +++ b/src/app/components/page.component.ts @@ -54,6 +54,7 @@ export abstract class PageComponent implements OnInit, OnDestroy { sharedPreviewUrl$: Observable; actions: Array = []; canUpdateFile = false; + canUpdateNode = false; canDelete = false; canEditFolder = false; canUpload = false; @@ -84,6 +85,7 @@ export abstract class PageComponent implements OnInit, OnDestroy { } this.actions = this.extensions.getSelectedContentActions(selection, this.node); this.canUpdateFile = this.selection.file && this.content.canUpdateNode(selection.file); + this.canUpdateNode = this.selection.count === 1 && this.content.canUpdateNode(selection.first); this.canDelete = !this.selection.isEmpty && this.content.canDeleteNodes(selection.nodes); this.canEditFolder = selection.folder && this.content.canUpdateNode(selection.folder); this.canDeleteShared = !this.selection.isEmpty && this.content.canDeleteSharedNodes(selection.nodes); diff --git a/src/app/components/permission-manager/permissions-manager.component.html b/src/app/components/permission-manager/permissions-manager.component.html new file mode 100644 index 000000000..555ca38c9 --- /dev/null +++ b/src/app/components/permission-manager/permissions-manager.component.html @@ -0,0 +1,20 @@ +
+ + +
+ +
+ + +
+ diff --git a/src/app/components/permission-manager/permissions-manager.component.theme.scss b/src/app/components/permission-manager/permissions-manager.component.theme.scss new file mode 100644 index 000000000..71ce49ddf --- /dev/null +++ b/src/app/components/permission-manager/permissions-manager.component.theme.scss @@ -0,0 +1,49 @@ +@mixin aca-permissions-manager-theme($theme) { + $foreground: map-get($theme, foreground); + $accent: map-get($theme, accent); + + aca-permissions-dialog-panel { + height: 400px; + } + + .aca-node-permissions-dialog { + .mat-dialog-title { + font-size: 20px; + font-weight: 600; + font-style: normal; + font-stretch: normal; + line-height: 1.6; + margin: 0; + letter-spacing: -0.5px; + color: mat-color($foreground, text, 0.87); + } + + .mat-dialog-content { + flex: 1 1 auto; + position: relative; + overflow: auto; + + adf-permission-list { + display: flex; + } + } + + .mat-dialog-actions { + flex: 0 0 auto; + + padding: 8px 8px 24px 8px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: end; + -ms-flex-pack: end; + justify-content: flex-end; + color: mat-color($foreground, text, 0.54); + + button { + text-transform: uppercase; + font-weight: normal; + } + } + } +} diff --git a/src/app/components/permission-manager/permissions-manager.component.ts b/src/app/components/permission-manager/permissions-manager.component.ts new file mode 100644 index 000000000..08265659f --- /dev/null +++ b/src/app/components/permission-manager/permissions-manager.component.ts @@ -0,0 +1,91 @@ +/*! + * @license + * Alfresco Example Content Application + * + * Copyright (C) 2005 - 2018 Alfresco Software Limited + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +import { Component, Input, OnInit, ViewChild } from '@angular/core'; +import { NodePermissionDialogService, PermissionListComponent } from '@alfresco/adf-content-services'; +import { MinimalNodeEntryEntity } from 'alfresco-js-api'; +import { Store } from '@ngrx/store'; +import { AppStore } from '../../store/states/app.state'; +import { SnackbarErrorAction } from '../../store/actions/snackbar.actions'; +import { NodePermissionsDialogComponent } from '../../dialogs/node-permissions/node-permissions.dialog'; +import { MatDialog } from '@angular/material'; +import { ContentApiService } from '../../services/content-api.service'; + +@Component({ + selector: 'aca-permissions-manager', + templateUrl: './permissions-manager.component.html' +}) +export class PermissionsManagerComponent implements OnInit { + @ViewChild('permissionList') + permissionList: PermissionListComponent; + + @Input() + nodeId: string; + + toggleStatus = false; + + constructor( + private store: Store, + private dialog: MatDialog, + private contentApi: ContentApiService, + private nodePermissionDialogService: NodePermissionDialogService + ) { + } + + ngOnInit() { + this.contentApi.getNodeInfo(this.nodeId, {include: ['permissions'] }).subscribe( (currentNode: MinimalNodeEntryEntity) => { + this.toggleStatus = currentNode.permissions.isInheritanceEnabled; + }); + } + + onError(errorMessage: string) { + this.store.dispatch(new SnackbarErrorAction(errorMessage)); + } + + onUpdate(event) { + this.permissionList.reload(); + } + + onUpdatedPermissions(node: MinimalNodeEntryEntity) { + this.toggleStatus = node.permissions.isInheritanceEnabled; + this.permissionList.reload(); + } + + openAddPermissionDialog(event: Event) { + this.nodePermissionDialogService.updateNodePermissionByDialog(this.nodeId) + .subscribe(() => { + this.dialog.open(NodePermissionsDialogComponent, { + data: { nodeId: this.nodeId }, + panelClass: 'aca-permissions-dialog-panel', + width: '800px' + } + ); + }, + (error) => { + this.store.dispatch(new SnackbarErrorAction(error)); + } + ); + } +} diff --git a/src/app/components/preview/preview.component.html b/src/app/components/preview/preview.component.html index b7c360023..8dd91b2dc 100644 --- a/src/app/components/preview/preview.component.html +++ b/src/app/components/preview/preview.component.html @@ -75,6 +75,16 @@ history {{ 'APP.ACTIONS.VERSIONS' | translate }} + + + + diff --git a/src/app/components/recent-files/recent-files.component.html b/src/app/components/recent-files/recent-files.component.html index 9b6493944..0eec19a18 100644 --- a/src/app/components/recent-files/recent-files.component.html +++ b/src/app/components/recent-files/recent-files.component.html @@ -109,6 +109,16 @@ history {{ 'APP.ACTIONS.VERSIONS' | translate }} + + + + diff --git a/src/app/components/search/search-results/search-results.component.html b/src/app/components/search/search-results/search-results.component.html index ac2eeb0ce..fcfb76bd5 100644 --- a/src/app/components/search/search-results/search-results.component.html +++ b/src/app/components/search/search-results/search-results.component.html @@ -72,6 +72,16 @@ history {{ 'APP.ACTIONS.VERSIONS' | translate }} + + + + diff --git a/src/app/components/shared-files/shared-files.component.html b/src/app/components/shared-files/shared-files.component.html index 91c196ec9..65d67faf1 100644 --- a/src/app/components/shared-files/shared-files.component.html +++ b/src/app/components/shared-files/shared-files.component.html @@ -106,6 +106,16 @@ history {{ 'APP.ACTIONS.VERSIONS' | translate }} + + + + diff --git a/src/app/dialogs/node-permissions/node-permissions.dialog.html b/src/app/dialogs/node-permissions/node-permissions.dialog.html new file mode 100644 index 000000000..95ae67afe --- /dev/null +++ b/src/app/dialogs/node-permissions/node-permissions.dialog.html @@ -0,0 +1,7 @@ +
{{'PERMISSIONS.DIALOG.TITLE' | translate}}
+
+ +
+
+ +
diff --git a/src/app/dialogs/node-permissions/node-permissions.dialog.ts b/src/app/dialogs/node-permissions/node-permissions.dialog.ts new file mode 100644 index 000000000..c026b2968 --- /dev/null +++ b/src/app/dialogs/node-permissions/node-permissions.dialog.ts @@ -0,0 +1,42 @@ +/*! + * @license + * Alfresco Example Content Application + * + * Copyright (C) 2005 - 2018 Alfresco Software Limited + * + * This file is part of the Alfresco Example Content Application. + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * + * The Alfresco Example Content Application is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Alfresco Example Content Application is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ + +import { Component, Inject, ViewEncapsulation } from '@angular/core'; +import { MAT_DIALOG_DATA } from '@angular/material'; + +@Component({ + templateUrl: './node-permissions.dialog.html', + encapsulation: ViewEncapsulation.None, + host: { class: 'aca-node-permissions-dialog' } +}) +export class NodePermissionsDialogComponent { + nodeId: string; + + constructor( + @Inject(MAT_DIALOG_DATA) data: any, + ) { + this.nodeId = data.nodeId; + } +} diff --git a/src/app/ui/custom-theme.scss b/src/app/ui/custom-theme.scss index 00dd3cc92..1bb506ee8 100644 --- a/src/app/ui/custom-theme.scss +++ b/src/app/ui/custom-theme.scss @@ -8,6 +8,7 @@ @import '../components/settings/settings.component.theme'; @import '../components/current-user/current-user.component.theme'; @import '../components/header/header.component.theme'; +@import '../components/permission-manager/permissions-manager.component.theme'; @import '../dialogs/node-versions/node-versions.dialog.theme'; @import './overrides/adf-toolbar.theme'; @@ -83,6 +84,7 @@ $custom-theme: mat-light-theme($custom-theme-primary, $custom-theme-accent); @include aca-header-theme($theme); @include aca-search-input-theme($theme); @include aca-generic-error-theme($theme); + @include aca-permissions-manager-theme($theme); @include aca-node-versions-dialog-theme($theme); @include aca-settings-theme($theme); @include snackbar-theme($theme); diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 10e678b8e..b3c2fa9b6 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -120,6 +120,7 @@ "DELETE_PERMANENT": "Permanently delete", "MORE": "More actions", "UNDO": "Undo", + "PERMISSIONS": "Permissions", "RESTORE": "Restore", "FAVORITE": "Favorite", "UNSHARE": "Unshare", @@ -250,6 +251,14 @@ "MOVE_ITEMS": "Move {{ number }} items to...", "SEARCH": "Search" }, + "PERMISSIONS": { + "DIALOG": { + "TITLE": "Manage Permissons", + "CLOSE": "Close", + "INHERIT_PERMISSIONS_BUTTON": "Inherit Permission", + "INHERITED_PERMISSIONS_BUTTON": "Permission Inherited" + } + }, "VERSION": { "DIALOG": { "TITLE": "Manage Versions",