Skip to content
Permalink
Browse files
feat(resource): display permissions (DEV-454) (#660)
* refactor(project): remove old permission implementation

* chore(deps): add cdk overlay

* style: use mat-menu style in cdk overlay

* feat(resource): display resource's and user's permissions

* test(permission-info): init tests

* refactor(pipe): format code

* test(permission): improve tests

* test(pipe): add test and fix pipe

* style(permission-info): open box below button

* feat(permission-info): consider project admin permissions

* refactor(permission-info): clean up code

* test(permission-info): more tests

* test(permission-info): test all permissions from test-data
  • Loading branch information
kilchenmann committed Feb 17, 2022
1 parent a2cf6e0 commit 13a3a49574a5d2b73d8427606b724eec5eaabc8b
Show file tree
Hide file tree
Showing 14 changed files with 518 additions and 15 deletions.
@@ -90,7 +90,9 @@ import { IntermediateComponent } from './workspace/intermediate/intermediate.com
import { DragDropDirective } from './workspace/resource/directives/drag-drop.directive';
import { TextValueHtmlLinkDirective } from './workspace/resource/directives/text-value-html-link.directive';
import { AddValueComponent } from './workspace/resource/operations/add-value/add-value.component';
import { CreateLinkResourceComponent } from './workspace/resource/operations/create-link-resource/create-link-resource.component';
import { DisplayEditComponent } from './workspace/resource/operations/display-edit/display-edit.component';
import { PermissionInfoComponent } from './workspace/resource/permission-info/permission-info.component';
import { PropertiesComponent } from './workspace/resource/properties/properties.component';
import { AddRegionFormComponent } from './workspace/resource/representation/add-region-form/add-region-form.component';
import { ArchiveComponent } from './workspace/resource/representation/archive/archive.component';
@@ -155,7 +157,7 @@ import { SearchSelectOntologyComponent } from './workspace/search/advanced-searc
import { ExpertSearchComponent } from './workspace/search/expert-search/expert-search.component';
import { FulltextSearchComponent } from './workspace/search/fulltext-search/fulltext-search.component';
import { SearchPanelComponent } from './workspace/search/search-panel/search-panel.component';
import { CreateLinkResourceComponent } from './workspace/resource/operations/create-link-resource/create-link-resource.component';
import { TitleFromCamelCasePipe } from './main/pipes/string-transformation/title-from-camel-case.pipe';

// translate: AoT requires an exported function for factories
export function httpLoaderFactory(httpClient: HttpClient) {
@@ -185,6 +187,7 @@ export function httpLoaderFactory(httpClient: HttpClient) {
ConfirmationDialogComponent,
ConfirmationMessageComponent,
CookiePolicyComponent,
CreateLinkResourceComponent,
DashboardComponent,
DateEditComponent,
DateInputComponent,
@@ -236,6 +239,7 @@ export function httpLoaderFactory(httpClient: HttpClient) {
OntologyFormComponent,
PasswordFormComponent,
PermissionComponent,
PermissionInfoComponent,
ProfileComponent,
ProgressIndicatorComponent,
ProjectComponent,
@@ -299,7 +303,7 @@ export function httpLoaderFactory(httpClient: HttpClient) {
UsersComponent,
UsersListComponent,
YetAnotherDateValueComponent,
CreateLinkResourceComponent,
TitleFromCamelCasePipe
],
imports: [
AngularSplitModule.forRoot(),

This file was deleted.

@@ -0,0 +1,27 @@
import { TitleFromCamelCasePipe } from './title-from-camel-case.pipe';
import { waitForAsync, TestBed } from '@angular/core/testing';

describe('TitleFromCamelCasePipe', () => {
let pipe: TitleFromCamelCasePipe;
let textToBeTransformed: string;

beforeEach(waitForAsync(() => {

TestBed.configureTestingModule({});

pipe = new TitleFromCamelCasePipe();

textToBeTransformed = 'HowTheCamelGotItsHump';
}));

it('create an instance', () => {
expect(pipe).toBeTruthy();
});

it('should return "How The Camel Got Its Hump"', () => {
const transformedText = pipe.transform(textToBeTransformed);
expect(transformedText).toEqual('How The Camel Got Its Hump');
});


});
@@ -0,0 +1,13 @@
import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
name: 'titleFromCamelCase'
})
export class TitleFromCamelCasePipe implements PipeTransform {

transform(value: string): string {
const title = value.replace(/([A-Z]+)/g, ' $1').replace(/([A-Z][a-z])/g, '$1');
return title.trim();
}

}
@@ -33,6 +33,7 @@ import { MatTabsModule } from '@angular/material/tabs';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatTooltipModule } from '@angular/material/tooltip';
import { MatTreeModule } from '@angular/material/tree';
import { OverlayModule } from '@angular/cdk/overlay';

const matModules = [
DragDropModule,
@@ -66,7 +67,8 @@ const matModules = [
MatTabsModule,
MatToolbarModule,
MatTooltipModule,
MatTreeModule
MatTreeModule,
OverlayModule
];

@NgModule({
@@ -2,7 +2,6 @@ import { Component, Inject, Input, OnInit } from '@angular/core';
import { MatDialog, MatDialogConfig } from '@angular/material/dialog';
import { Title } from '@angular/platform-browser';
import { ApiResponseData, ApiResponseError, KnoraApiConnection, ProjectsResponse, StoredProject, UserResponse } from '@dasch-swiss/dsp-js';
import { AdminPermissions } from 'src/app/main/declarations/admin-permissions';
import { DspApiConnectionToken } from 'src/app/main/declarations/dsp-api-tokens';
import { DialogComponent } from 'src/app/main/dialog/dialog.component';
import { ErrorHandlerService } from 'src/app/main/error/error-handler.service';
@@ -47,8 +46,6 @@ export class ProjectsComponent implements OnInit {
*/
session: Session;

permissions: AdminPermissions;

// list of active projects
active: StoredProject[] = [];
// list of archived (deleted) projects
@@ -0,0 +1,52 @@
<button
mat-icon-button
class="permissions"
matTooltip="Resource permissions"
matTooltipPosition="above"
cdkOverlayOrigin
#infoButton="cdkOverlayOrigin"
(click)="toggleMenu()">
<mat-icon>lock</mat-icon>
</button>

<ng-template cdkConnectedOverlay
[cdkConnectedOverlayBackdropClass]="'cdk-overlay-transparent-backdrop'"
[cdkConnectedOverlayHasBackdrop]="true"
[cdkConnectedOverlayScrollStrategy]="scrollStrategy"
[cdkConnectedOverlayPositions]="infoBoxPositions"
[cdkConnectedOverlayOrigin]="infoButton"
[cdkConnectedOverlayOpen]="isOpen"
(backdropClick)="isOpen = false">
<div class="overlay-info-box">
<table>
<tr>
<th class="first-col">Permissions</th>
<th *ngFor="let dp of defaultPermissions">
<mat-icon [matTooltip]="dp.label" matTooltipPosition="above">
{{dp.icon}}
</mat-icon>
</th>
</tr>
<ng-container *ngIf="hasPermissions && listOfPermissions.length">
<tr *ngFor="let item of listOfPermissions" [class]="item.group.split(':')[1]">
<td class="first-col">{{item.group.split(':')[1] | titleFromCamelCase}}</td>
<td *ngFor="let dp of defaultPermissions" [class]="'perm-' + dp.name">
<mat-icon class="status" [class.checked]="getStatus(dp.name, item.restriction)"
[matTooltip]="dp.label" matTooltipPosition="above">
{{getStatus(dp.name, item.restriction) ? 'radio_button_checked' : 'radio_button_unchecked'}}
</mat-icon>
</td>
</tr>
</ng-container>
<tr *ngIf="userHasPermission && userRestrictions" class="border-top LoggedInUser">
<td class="first-col">Your permissions</td>
<td *ngFor="let dp of defaultPermissions" [class]="'perm-' + dp.name">
<mat-icon class="status" [class.checked]="getStatus(dp.name, userRestrictions)"
[matTooltip]="dp.label" matTooltipPosition="above">
{{getStatus(dp.name, userRestrictions) ? 'radio_button_checked' : 'radio_button_unchecked'}}
</mat-icon>
</td>
</tr>
</table>
</div>
</ng-template>
@@ -0,0 +1,41 @@
@import "../../../../assets/style/config";
@import "../../../../assets/style/mixins";

.overlay-info-box {
background: white;
padding: 8px 16px;
@include mat-box-shadow();

table {
border-collapse: collapse;

th, td {
min-width: 48px;
text-align: center;
vertical-align: middle;

.mat-icon {
margin-top: 3px;
}
}

.first-col {
padding-right: 16px;
text-align: left;
}

.border-top {
border-top: 1px solid black;
}
}

}

.status {
color: $warn;

&.checked {
color: $active;
}
}

0 comments on commit 13a3a49

Please sign in to comment.