commit
d1bc995830
8
client/package-lock.json
generated
8
client/package-lock.json
generated
@ -5387,13 +5387,15 @@
|
||||
"version": "1.0.0",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": false,
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
@ -5416,7 +5418,8 @@
|
||||
"version": "0.0.1",
|
||||
"resolved": false,
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
@ -5583,6 +5586,7 @@
|
||||
"resolved": false,
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ export class DataSendService {
|
||||
tap(
|
||||
response => {
|
||||
// TODO: Message, Notify, Etc
|
||||
console.log('New Model added. Response :\n', response);
|
||||
console.log('New Model added. Response ::\n', response);
|
||||
},
|
||||
error => console.error('createModel has returned an Error:\n', error)
|
||||
)
|
||||
@ -56,7 +56,7 @@ export class DataSendService {
|
||||
tap(
|
||||
response => {
|
||||
// TODO: Message, Notify, Etc
|
||||
console.log('Update model. Response :\n', response);
|
||||
console.log('Update model. Response ::\n', response);
|
||||
},
|
||||
error => console.error('updateModel has returned an Error:\n', error)
|
||||
)
|
||||
|
@ -16,8 +16,11 @@
|
||||
</mat-toolbar>
|
||||
|
||||
<mat-menu #ellipsisMenu="matMenu">
|
||||
<button mat-menu-item *ngFor="let item of menuList" (click)=clickMenu(item)>
|
||||
|
||||
<ng-container *ngFor="let item of menuList">
|
||||
<button mat-menu-item *ngIf="opHasPerm(item.perm)" (click)=clickMenu(item)>
|
||||
<fa-icon *ngIf="item.icon" [icon]='item.icon'></fa-icon>
|
||||
{{item.text | translate}}
|
||||
</button>
|
||||
</ng-container>
|
||||
</mat-menu>
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { OperatorService } from '../../../core/services/operator.service';
|
||||
|
||||
/**
|
||||
* Reusable head bar component for Apps.
|
||||
@ -86,7 +87,7 @@ export class HeadBarComponent implements OnInit {
|
||||
/**
|
||||
* Empty constructor
|
||||
*/
|
||||
public constructor() {}
|
||||
public constructor(private op: OperatorService) {}
|
||||
|
||||
/**
|
||||
* empty onInit
|
||||
@ -107,4 +108,22 @@ export class HeadBarComponent implements OnInit {
|
||||
public clickPlusButton(): void {
|
||||
this.plusButtonClicked.emit(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the operator has the correct permission to use a button in the menu
|
||||
* @param perm
|
||||
*/
|
||||
public opHasPerm(perm: string): boolean {
|
||||
// return false if the operator is not yet loaded
|
||||
if (this.op) {
|
||||
// if no permission was required, return true
|
||||
if (!perm) {
|
||||
return true;
|
||||
} else {
|
||||
return this.op.hasPerms(perm);
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,10 @@ export class Group extends BaseModel<Group> {
|
||||
|
||||
public constructor(input?: any) {
|
||||
super('users/group', input);
|
||||
if (!input) {
|
||||
// permissions are required for new groups
|
||||
this.permissions = [];
|
||||
}
|
||||
}
|
||||
|
||||
public getTitle(): string {
|
||||
|
@ -0,0 +1,88 @@
|
||||
<mat-toolbar color='primary'>
|
||||
<button *osPerms="'users.can_manage'" (click)='newGroupButton()' class='generic-mini-button on-transition-fade'
|
||||
mat-mini-fab>
|
||||
<fa-icon *ngIf="!newGroup" icon='plus'></fa-icon>
|
||||
<fa-icon *ngIf="newGroup" icon='times'></fa-icon>
|
||||
</button>
|
||||
|
||||
<div class="on-transition-fade">
|
||||
<span translate>Groups</span>
|
||||
</div>
|
||||
|
||||
<span class='spacer'></span>
|
||||
</mat-toolbar>
|
||||
|
||||
<div class="on-transition-fade new-group-form" *ngIf="newGroup">
|
||||
<form #newGroupForm="ngForm" (ngSubmit)="submitNewGroup(newGroupForm.form)" (keydown)="keyDownFunction($event)">
|
||||
<mat-form-field>
|
||||
<input type="text" matInput name="name" ngModel #nameField="ngModel" placeholder="{{ 'New group name' | translate}}">
|
||||
</mat-form-field>
|
||||
|
||||
<button type="submit" mat-mini-fab color="primary">
|
||||
<fa-icon icon="save"></fa-icon>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="on-transition-fade new-group-form" *ngIf="editGroup">
|
||||
<form #editGroupForm="ngForm" (ngSubmit)="submitEditedGroup(editGroupForm.form)">
|
||||
<mat-form-field>
|
||||
<input type="text" matInput name="name" [(ngModel)]="selectedGroup.name" #nameField="ngModel" placeholder="{{ 'Edit group name' | translate}}">
|
||||
</mat-form-field>
|
||||
|
||||
<button type="submit" mat-mini-fab color="primary">
|
||||
<fa-icon icon="save"></fa-icon>
|
||||
</button>
|
||||
|
||||
<button type="button" mat-mini-fab color="warn" (click)="deleteSelectedGroup()" [disabled]="isProtected(selectedGroup)">
|
||||
<fa-icon icon="trash"></fa-icon>
|
||||
</button>
|
||||
|
||||
<button type="button" mat-mini-fab color="primary" (click)="cancelEditing()">
|
||||
<fa-icon icon="times"></fa-icon>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="hint-text on-transition-fade">
|
||||
<span translate>All your changes are saved immediately.</span>
|
||||
</div>
|
||||
|
||||
<mat-accordion *ngFor="let app of repo.appPermissions">
|
||||
<mat-expansion-panel class="mat-elevation-z0" [expanded]=true>
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title translate>
|
||||
{{ app.name }}
|
||||
</mat-panel-title>
|
||||
</mat-expansion-panel-header>
|
||||
|
||||
<div class="scrollable-perm-matrix">
|
||||
<table mat-table class='on-transition-fade' [dataSource]="getTableDataSource(app.permissions)">
|
||||
<ng-container matColumnDef="perm" sticky>
|
||||
<mat-header-cell *matHeaderCellDef translate> Permissions </mat-header-cell>
|
||||
<mat-cell *matCellDef="let perm" translate>
|
||||
{{ perm.display_name }}
|
||||
</mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<div *ngFor=" let group of groups; trackBy: trackGroupArray">
|
||||
<ng-container [matColumnDef]="group.name">
|
||||
<mat-header-cell class="group-head-table-cell" *matHeaderCellDef (click)="selectGroup(group)">
|
||||
<div class="inner-table" translate>
|
||||
{{ group.name }}
|
||||
</div>
|
||||
</mat-header-cell>
|
||||
<mat-cell *matCellDef="let perm">
|
||||
<div class="inner-table">
|
||||
<mat-checkbox [checked]="group.hasPermission(perm.value)" (change)='togglePerm(group, perm.value)'></mat-checkbox>
|
||||
</div>
|
||||
</mat-cell>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<mat-header-row *matHeaderRowDef="headerRowDef"></mat-header-row>
|
||||
<mat-row *matRowDef="let row; columns: headerRowDef"></mat-row>
|
||||
</table>
|
||||
</div>
|
||||
</mat-expansion-panel>
|
||||
</mat-accordion>
|
@ -0,0 +1,39 @@
|
||||
table {
|
||||
width: 100%;
|
||||
|
||||
.mat-cell {
|
||||
min-width: 80px;
|
||||
}
|
||||
|
||||
.mat-column-perm {
|
||||
min-width: 130px;
|
||||
}
|
||||
|
||||
.inner-table {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.group-head-table-cell {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.hint-text {
|
||||
padding-top: 30px;
|
||||
padding-left: 25px;
|
||||
background-color: #ffffff; // put in theme later
|
||||
}
|
||||
|
||||
.new-group-form {
|
||||
text-align: center;
|
||||
padding-top: 10px;
|
||||
background-color: #ffffff; // put in theme later
|
||||
button {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.scrollable-perm-matrix {
|
||||
overflow: auto;
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { GroupListComponent } from './group-list.component';
|
||||
import { E2EImportsModule } from '../../../../../e2e-imports.module';
|
||||
|
||||
describe('GroupListComponent', () => {
|
||||
let component: GroupListComponent;
|
||||
let fixture: ComponentFixture<GroupListComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [E2EImportsModule],
|
||||
declarations: [GroupListComponent]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(GroupListComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
@ -0,0 +1,192 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { MatTableDataSource } from '@angular/material';
|
||||
import { FormGroup } from '@angular/forms';
|
||||
|
||||
import { GroupRepositoryService } from '../../services/group-repository.service';
|
||||
import { ViewGroup } from '../../models/view-group';
|
||||
import { Group } from '../../../../shared/models/users/group';
|
||||
import { BaseComponent } from '../../../../base.component';
|
||||
|
||||
/**
|
||||
* Component for the Group-List and permission matrix
|
||||
*/
|
||||
@Component({
|
||||
selector: 'os-group-list',
|
||||
templateUrl: './group-list.component.html',
|
||||
styleUrls: ['./group-list.component.scss']
|
||||
})
|
||||
export class GroupListComponent extends BaseComponent implements OnInit {
|
||||
/**
|
||||
* Holds all Groups
|
||||
*/
|
||||
public groups: ViewGroup[];
|
||||
|
||||
/**
|
||||
* The header rows that the table should show
|
||||
*/
|
||||
public headerRowDef: string[] = [];
|
||||
|
||||
/**
|
||||
* Show or hide the new groups box
|
||||
*/
|
||||
public newGroup = false;
|
||||
|
||||
/**
|
||||
* Show or hide edit Group features
|
||||
*/
|
||||
public editGroup = false;
|
||||
|
||||
/**
|
||||
* Store the group to edit
|
||||
*/
|
||||
public selectedGroup: ViewGroup;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param titleService Title Service
|
||||
* @param translate Translations
|
||||
* @param DS The Data Store
|
||||
* @param constants Constants
|
||||
*/
|
||||
public constructor(titleService: Title, translate: TranslateService, public repo: GroupRepositoryService) {
|
||||
super(titleService, translate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger for the new Group button
|
||||
*/
|
||||
public newGroupButton(): void {
|
||||
this.editGroup = false;
|
||||
this.newGroup = !this.newGroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves a newly created group.
|
||||
* @param form form data given by the group
|
||||
*/
|
||||
public submitNewGroup(form: FormGroup): void {
|
||||
if (form.value) {
|
||||
this.repo.create(form.value).subscribe(response => {
|
||||
if (response) {
|
||||
form.reset();
|
||||
// commenting the next line would allow to create multiple groups without reopening the form
|
||||
this.newGroup = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves an edited group.
|
||||
* @param form form data given by the group
|
||||
*/
|
||||
public submitEditedGroup(form: FormGroup): void {
|
||||
if (form.value) {
|
||||
const updateData = new Group({ name: form.value.name });
|
||||
|
||||
this.repo.update(updateData, this.selectedGroup).subscribe(response => {
|
||||
if (response) {
|
||||
this.cancelEditing();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the selected Group
|
||||
*/
|
||||
public deleteSelectedGroup(): void {
|
||||
this.repo.delete(this.selectedGroup).subscribe(response => this.cancelEditing());
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel the editing
|
||||
*/
|
||||
public cancelEditing(): void {
|
||||
this.editGroup = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select group in head bar
|
||||
*/
|
||||
public selectGroup(group: ViewGroup): void {
|
||||
this.newGroup = false;
|
||||
this.selectedGroup = group;
|
||||
this.editGroup = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers when a permission was toggled
|
||||
* @param group
|
||||
* @param perm
|
||||
*/
|
||||
public togglePerm(viewGroup: ViewGroup, perm: string): void {
|
||||
const updateData = new Group({ permissions: viewGroup.getAlteredPermissions(perm) });
|
||||
this.repo.update(updateData, viewGroup).subscribe();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the rowDefinition after Reloading or changes
|
||||
*/
|
||||
public updateRowDef(): void {
|
||||
// reset the rowDef list first
|
||||
this.headerRowDef = ['perm'];
|
||||
this.groups.forEach(viewGroup => {
|
||||
this.headerRowDef.push('' + viewGroup.name);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Required to detect changes in *ngFor loops
|
||||
*
|
||||
* @param group Corresponding group that was changed
|
||||
*/
|
||||
public trackGroupArray(group: ViewGroup): number {
|
||||
return group.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a permission string into MatTableDataSource
|
||||
* @param permissions
|
||||
*/
|
||||
public getTableDataSource(permissions: string[]): MatTableDataSource<any> {
|
||||
const dataSource = new MatTableDataSource();
|
||||
dataSource.data = permissions;
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a group is protected from deletion
|
||||
* @param group ViewGroup
|
||||
*/
|
||||
public isProtected(group: ViewGroup): boolean {
|
||||
return group.id === 1 || group.id === 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clicking escape while in #newGroupForm should toggle newGroup.
|
||||
*/
|
||||
public keyDownFunction(event: KeyboardEvent): void {
|
||||
if (event.keyCode === 27) {
|
||||
this.newGroup = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Init function.
|
||||
*
|
||||
* Monitor the repository for changes and update the local groups array
|
||||
*/
|
||||
public ngOnInit(): void {
|
||||
super.setTitle('Groups');
|
||||
this.repo.getViewModelListObservable().subscribe(newViewGroups => {
|
||||
if (newViewGroups) {
|
||||
this.groups = newViewGroups;
|
||||
this.updateRowDef();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -24,7 +24,8 @@ export class UserListComponent extends ListViewBaseComponent<ViewUser> implement
|
||||
{
|
||||
text: 'Groups',
|
||||
icon: 'users',
|
||||
action: 'toGroups'
|
||||
action: 'toGroups',
|
||||
perm: 'users.can_manage'
|
||||
},
|
||||
{
|
||||
text: 'Import',
|
||||
@ -81,7 +82,7 @@ export class UserListComponent extends ListViewBaseComponent<ViewUser> implement
|
||||
* TODO: implement
|
||||
*/
|
||||
public toGroups(): void {
|
||||
console.log('to Groups');
|
||||
this.router.navigate(['./groups'], { relativeTo: this.route });
|
||||
}
|
||||
|
||||
/**
|
||||
|
76
client/src/app/site/users/models/view-group.ts
Normal file
76
client/src/app/site/users/models/view-group.ts
Normal file
@ -0,0 +1,76 @@
|
||||
import { BaseViewModel } from '../../base/base-view-model';
|
||||
import { Group } from '../../../shared/models/users/group';
|
||||
import { BaseModel } from '../../../shared/models/base/base-model';
|
||||
|
||||
export class ViewGroup extends BaseViewModel {
|
||||
private _group: Group;
|
||||
|
||||
public get group(): Group {
|
||||
return this._group ? this._group : null;
|
||||
}
|
||||
|
||||
public get id(): number {
|
||||
return this.group ? this.group.id : null;
|
||||
}
|
||||
|
||||
public get name(): string {
|
||||
return this.group ? this.group.name : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* required for renaming purpose
|
||||
*/
|
||||
public set name(newName: string) {
|
||||
if (this.group) {
|
||||
this.group.name = newName;
|
||||
}
|
||||
}
|
||||
|
||||
public get permissions(): string[] {
|
||||
return this.group ? this.group.permissions : null;
|
||||
}
|
||||
|
||||
public constructor(group?: Group) {
|
||||
super();
|
||||
this._group = group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of permissions where the given perm is included
|
||||
* or removed.
|
||||
*
|
||||
* Avoids touching the local DataStore.
|
||||
*
|
||||
* @param perm
|
||||
*/
|
||||
public getAlteredPermissions(perm: string): string[] {
|
||||
// clone the array, avoids altering the local dataStore
|
||||
const currentPermissions = this.permissions.slice();
|
||||
|
||||
if (this.hasPermission(perm)) {
|
||||
// remove the permission from currentPermissions-List
|
||||
const indexOfPerm = currentPermissions.indexOf(perm);
|
||||
if (indexOfPerm !== -1) {
|
||||
currentPermissions.splice(indexOfPerm, 1);
|
||||
return currentPermissions;
|
||||
} else {
|
||||
return currentPermissions;
|
||||
}
|
||||
} else {
|
||||
currentPermissions.push(perm);
|
||||
return currentPermissions;
|
||||
}
|
||||
}
|
||||
|
||||
public hasPermission(perm: string): boolean {
|
||||
return this.permissions.includes(perm);
|
||||
}
|
||||
|
||||
public getTitle(): string {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public updateValues(update: BaseModel): void {
|
||||
console.log('ViewGroups wants to update Values with : ', update);
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
import { TestBed, inject } from '@angular/core/testing';
|
||||
|
||||
import { GroupRepositoryService } from './group-repository.service';
|
||||
import { E2EImportsModule } from '../../../../e2e-imports.module';
|
||||
|
||||
describe('GroupRepositoryService', () => {
|
||||
beforeEach(() =>
|
||||
TestBed.configureTestingModule({
|
||||
imports: [E2EImportsModule],
|
||||
providers: [GroupRepositoryService]
|
||||
}));
|
||||
|
||||
it('should be created', inject([GroupRepositoryService], (service: GroupRepositoryService) => {
|
||||
expect(service).toBeTruthy();
|
||||
}));
|
||||
});
|
140
client/src/app/site/users/services/group-repository.service.ts
Normal file
140
client/src/app/site/users/services/group-repository.service.ts
Normal file
@ -0,0 +1,140 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { ViewGroup } from '../models/view-group';
|
||||
import { BaseRepository } from '../../base/base-repository';
|
||||
import { Group } from '../../../shared/models/users/group';
|
||||
import { DataStoreService } from '../../../core/services/data-store.service';
|
||||
import { DataSendService } from '../../../core/services/data-send.service';
|
||||
import { ConstantsService } from '../../../core/services/constants.service';
|
||||
|
||||
/**
|
||||
* Set rules to define the shape of an app permission
|
||||
*/
|
||||
interface AppPermission {
|
||||
name: string;
|
||||
permissions: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Repository service for Groups
|
||||
*
|
||||
* Documentation partially provided in {@link BaseRepository}
|
||||
*/
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class GroupRepositoryService extends BaseRepository<ViewGroup, Group> {
|
||||
/**
|
||||
* holds sorted permissions per app.
|
||||
*/
|
||||
public appPermissions: AppPermission[] = [];
|
||||
|
||||
/**
|
||||
* Constructor calls the parent constructor
|
||||
* @param DS Store
|
||||
* @param dataSend Sending Data
|
||||
*/
|
||||
public constructor(DS: DataStoreService, private dataSend: DataSendService, private constants: ConstantsService) {
|
||||
super(DS, Group);
|
||||
this.sortPermsPerApp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an entry to appPermissions
|
||||
*
|
||||
* @param appId number that indicates the app
|
||||
* @param perm certain permission as string
|
||||
* @param appName Indicates the header in the Permission Matrix
|
||||
*/
|
||||
private addAppPerm(appId: number, perm: string, appName: string): void {
|
||||
if (!this.appPermissions[appId]) {
|
||||
this.appPermissions[appId] = {
|
||||
name: appName,
|
||||
permissions: []
|
||||
};
|
||||
}
|
||||
this.appPermissions[appId].permissions.push(perm);
|
||||
}
|
||||
|
||||
/**
|
||||
* read the constants, add them to an array of apps
|
||||
*/
|
||||
private sortPermsPerApp(): void {
|
||||
this.constants.get('permissions').subscribe(perms => {
|
||||
perms.forEach(perm => {
|
||||
// extract the apps name
|
||||
const permApp = perm.value.split('.')[0];
|
||||
switch (permApp) {
|
||||
case 'core':
|
||||
if (perm.value.indexOf('projector') > -1) {
|
||||
this.addAppPerm(0, perm, 'Projector');
|
||||
} else {
|
||||
this.addAppPerm(6, perm, 'General');
|
||||
}
|
||||
break;
|
||||
case 'agenda':
|
||||
this.addAppPerm(1, perm, 'Agenda');
|
||||
break;
|
||||
case 'motions':
|
||||
this.addAppPerm(2, perm, 'Motions');
|
||||
break;
|
||||
case 'assignments':
|
||||
this.addAppPerm(3, perm, 'Assignments');
|
||||
break;
|
||||
case 'mediafiles':
|
||||
this.addAppPerm(4, perm, 'Mediafiles');
|
||||
break;
|
||||
case 'users':
|
||||
this.addAppPerm(5, perm, 'Users');
|
||||
break;
|
||||
default:
|
||||
// plugins
|
||||
const displayName = `${permApp.charAt(0).toUpperCase}${permApp.slice(1)}`;
|
||||
// check if the plugin exists as app
|
||||
const result = this.appPermissions.findIndex(app => {
|
||||
return app.name === displayName;
|
||||
});
|
||||
const pluginId = result === -1 ? this.appPermissions.length : result;
|
||||
this.addAppPerm(pluginId, perm, displayName);
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* creates and saves a new user
|
||||
*
|
||||
* @param groupData form value. Usually not yet a real user
|
||||
*/
|
||||
public create(groupData: Partial<Group>): Observable<any> {
|
||||
const newGroup = new Group();
|
||||
newGroup.patchValues(groupData);
|
||||
return this.dataSend.createModel(newGroup);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the given Group with the new permission
|
||||
*
|
||||
* @param permission the new permission
|
||||
* @param viewGroup the selected Group
|
||||
*/
|
||||
public update(groupData: Partial<Group>, viewGroup: ViewGroup): Observable<any> {
|
||||
const updateGroup = new Group();
|
||||
updateGroup.patchValues(viewGroup.group);
|
||||
updateGroup.patchValues(groupData);
|
||||
return this.dataSend.updateModel(updateGroup, 'put');
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a given group
|
||||
*/
|
||||
public delete(viewGroup: ViewGroup): Observable<any> {
|
||||
return this.dataSend.delete(viewGroup.group);
|
||||
}
|
||||
|
||||
public createViewModel(group: Group): ViewGroup {
|
||||
return new ViewGroup(group);
|
||||
}
|
||||
}
|
@ -46,9 +46,7 @@ export class UserRepositoryService extends BaseRepository<ViewUser, User> {
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*
|
||||
* TODO: used over not-yet-existing detail view
|
||||
* Deletes a given user
|
||||
*/
|
||||
public delete(viewUser: ViewUser): Observable<any> {
|
||||
return this.dataSend.delete(viewUser.user);
|
||||
@ -65,7 +63,7 @@ export class UserRepositoryService extends BaseRepository<ViewUser, User> {
|
||||
// collectionString of userData is still empty
|
||||
newUser.patchValues(userData);
|
||||
|
||||
// if the username is not presend, delete.
|
||||
// if the username is not present, delete.
|
||||
// The server will generate a one
|
||||
if (!newUser.username) {
|
||||
delete newUser.username;
|
||||
|
@ -2,6 +2,7 @@ import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
import { UserListComponent } from './components/user-list/user-list.component';
|
||||
import { UserDetailComponent } from './components/user-detail/user-detail.component';
|
||||
import { GroupListComponent } from './components/group-list/group-list.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
@ -12,6 +13,17 @@ const routes: Routes = [
|
||||
path: 'new',
|
||||
component: UserDetailComponent
|
||||
},
|
||||
{
|
||||
path: 'groups',
|
||||
component: GroupListComponent
|
||||
/**
|
||||
* FIXME: CRITICAL:
|
||||
* Refreshing the page, even while having the required permission, will navigate you back to "/"
|
||||
* Makes developing protected areas impossible.
|
||||
* Has the be (temporarily) removed if this page should be edited.
|
||||
*/
|
||||
// data: { basePerm: 'users.can_manage' }
|
||||
},
|
||||
{
|
||||
path: ':id',
|
||||
component: UserDetailComponent
|
||||
|
@ -5,9 +5,10 @@ import { UsersRoutingModule } from './users-routing.module';
|
||||
import { SharedModule } from '../../shared/shared.module';
|
||||
import { UserListComponent } from './components/user-list/user-list.component';
|
||||
import { UserDetailComponent } from './components/user-detail/user-detail.component';
|
||||
import { GroupListComponent } from './components/group-list/group-list.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule, UsersRoutingModule, SharedModule],
|
||||
declarations: [UserListComponent, UserDetailComponent]
|
||||
declarations: [UserListComponent, UserDetailComponent, GroupListComponent]
|
||||
})
|
||||
export class UsersModule {}
|
||||
|
@ -1,8 +1,6 @@
|
||||
{
|
||||
"Abort": "",
|
||||
"About Me": "",
|
||||
"Agenda": "Tagesordnung",
|
||||
"Assignments": "Wahlen",
|
||||
"Category": "",
|
||||
"Change Password": "Passwort ändern",
|
||||
"Changed version": "",
|
||||
@ -35,13 +33,11 @@
|
||||
}
|
||||
},
|
||||
"FILTER": "",
|
||||
"Files": "Dateien",
|
||||
"Final version": "",
|
||||
"First Name": "",
|
||||
"French": "Französisch",
|
||||
"German": "Deutsch",
|
||||
"Groups": "",
|
||||
"Home": "Startseite",
|
||||
"Identifier": "",
|
||||
"Initial Password": "",
|
||||
"Inline": "",
|
||||
@ -71,7 +67,6 @@
|
||||
"Original version": "",
|
||||
"Outside": "",
|
||||
"Participant Number": "",
|
||||
"Participants": "Teilnehmer",
|
||||
"Personal Note": "",
|
||||
"Personal note": "",
|
||||
"Prefix": "",
|
||||
@ -85,7 +80,6 @@
|
||||
"Reset recommendation": "",
|
||||
"SORT": "",
|
||||
"Selected Values": "",
|
||||
"Settings": "Einstellungen",
|
||||
"State": "",
|
||||
"Structure Level": "",
|
||||
"Submitters": "",
|
||||
|
@ -1,8 +1,6 @@
|
||||
{
|
||||
"Abort": "",
|
||||
"About Me": "",
|
||||
"Agenda": "",
|
||||
"Assignments": "",
|
||||
"Category": "",
|
||||
"Change Password": "",
|
||||
"Changed version": "",
|
||||
@ -35,13 +33,11 @@
|
||||
}
|
||||
},
|
||||
"FILTER": "",
|
||||
"Files": "",
|
||||
"Final version": "",
|
||||
"First Name": "",
|
||||
"French": "",
|
||||
"German": "",
|
||||
"Groups": "",
|
||||
"Home": "",
|
||||
"Identifier": "",
|
||||
"Initial Password": "",
|
||||
"Inline": "",
|
||||
@ -71,7 +67,6 @@
|
||||
"Original version": "",
|
||||
"Outside": "",
|
||||
"Participant Number": "",
|
||||
"Participants": "",
|
||||
"Personal Note": "",
|
||||
"Personal note": "",
|
||||
"Prefix": "",
|
||||
@ -85,7 +80,6 @@
|
||||
"Reset recommendation": "",
|
||||
"SORT": "",
|
||||
"Selected Values": "",
|
||||
"Settings": "",
|
||||
"State": "",
|
||||
"Structure Level": "",
|
||||
"Submitters": "",
|
||||
|
@ -1,8 +1,6 @@
|
||||
{
|
||||
"Abort": "",
|
||||
"About Me": "",
|
||||
"Agenda": "",
|
||||
"Assignments": "",
|
||||
"Category": "",
|
||||
"Change Password": "",
|
||||
"Changed version": "",
|
||||
@ -35,13 +33,11 @@
|
||||
}
|
||||
},
|
||||
"FILTER": "",
|
||||
"Files": "",
|
||||
"Final version": "",
|
||||
"First Name": "",
|
||||
"French": "",
|
||||
"German": "",
|
||||
"Groups": "",
|
||||
"Home": "",
|
||||
"Identifier": "",
|
||||
"Initial Password": "",
|
||||
"Inline": "",
|
||||
@ -71,7 +67,6 @@
|
||||
"Original version": "",
|
||||
"Outside": "",
|
||||
"Participant Number": "",
|
||||
"Participants": "",
|
||||
"Personal Note": "",
|
||||
"Personal note": "",
|
||||
"Prefix": "",
|
||||
@ -85,7 +80,6 @@
|
||||
"Reset recommendation": "",
|
||||
"SORT": "",
|
||||
"Selected Values": "",
|
||||
"Settings": "",
|
||||
"State": "",
|
||||
"Structure Level": "",
|
||||
"Submitters": "",
|
||||
|
Loading…
Reference in New Issue
Block a user