feat: add view, edit roles and permission component (#632)

- Add view roles and permission
- Edit roles and permission
- Edit role description

Fixes: #176
This commit is contained in:
Muskan Khedia
2020-05-31 13:05:52 +05:30
committed by GitHub
parent ab3bef463d
commit 28b3f730f0
23 changed files with 864 additions and 8 deletions
@@ -0,0 +1,37 @@
<div class="container">
<mat-card>
<form [formGroup]="roleForm" (ngSubmit)="submit()">
<mat-card-content>
<div fxLayout="column">
<mat-form-field>
<mat-label>Role Name</mat-label>
<input matInput disabled formControlName="name">
</mat-form-field>
<mat-form-field>
<mat-label>Role Description</mat-label>
<input matInput required formControlName="description">
<mat-error *ngIf="roleForm.controls.description.hasError('required')">
Description is <strong>required</strong>
</mat-error>
</mat-form-field>
</div>
</mat-card-content>
<mat-card-actions fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px">
<button type="button" mat-raised-button [routerLink]="['../../']">Cancel</button>
<button mat-raised-button color="primary" [disabled]="!roleForm.valid || roleForm.pristine">Submit</button>
</mat-card-actions>
</form>
</mat-card>
</div>
@@ -0,0 +1,11 @@
.container {
max-width: 37rem;
}
span {
font-size: 1rem;
}
.roleName {
line-height: 3rem;
}
@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { EditRoleComponent } from './edit-role.component';
describe('EditRoleComponent', () => {
let component: EditRoleComponent;
let fixture: ComponentFixture<EditRoleComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ EditRoleComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(EditRoleComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,67 @@
/** Angular Imports */
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
/** Custom Services */
import { SystemService } from '../../system.service';
/**
* Edit Role Description Component.
*/
@Component({
selector: 'mifosx-edit-role',
templateUrl: './edit-role.component.html',
styleUrls: ['./edit-role.component.scss'],
})
export class EditRoleComponent implements OnInit {
/** Role Form */
roleForm: FormGroup;
/** Role Data */
roleData: any;
/**
* Retrieves the code data from `resolve`.
* @param {FormBuilder} formBuilder Form Builder.
* @param {SystemService} systemService System Service.
* @param {ActivatedRoute} route Activated Route.
* @param {Router} router Router for navigation.
*/
constructor(
private formBuilder: FormBuilder,
private systemService: SystemService,
private route: ActivatedRoute,
private router: Router
) {
this.route.data.subscribe((data: { role: any }) => {
this.roleData = data.role;
});
}
/**
* Creates and sets the role form.
*/
ngOnInit() {
this.createRoleForm();
}
/**
* Creates and sets role form.
*/
createRoleForm() {
this.roleForm = this.formBuilder.group({
name: [{ value: this.roleData.name, disabled: true }, Validators.required],
description: [this.roleData.description, Validators.required],
});
}
/**
* Submits the role form and updates role description,
* if successful redirects to view updated roles and permissions.
*/
submit() {
this.systemService.updateRole(this.roleForm.value, this.roleData.id).subscribe(() => {
this.router.navigate(['../../'], { relativeTo: this.route });
});
}
}
@@ -37,8 +37,17 @@
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef>Actions</th>
<td mat-cell *matCellDef="let role;" >
<button *ngIf="role.name !== 'Super user'" mat-icon-button color="primary" (click)="routeEdit($event)" [routerLink]="[role.id, 'edit']">
<fa-icon icon="edit"> Edit </fa-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;" class="select-row"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;" [routerLink]="[row.id]" class="select-row"></tr>
</table>
@@ -19,7 +19,7 @@ export class RolesAndPermissionsComponent implements OnInit {
/** Role data. */
roleData: any;
/** Columns to be displayed in roles and permissions table. */
displayedColumns: string[] = ['name', 'description', 'disabled'];
displayedColumns: string[] = ['name', 'description', 'disabled', 'actions'];
/** Data source for roles and permissions table. */
dataSource: MatTableDataSource<any>;
@@ -53,6 +53,14 @@ export class RolesAndPermissionsComponent implements OnInit {
this.setRoles();
}
/**
* Stops the propagation to view roles and permissions
* @param event Mouse Event
*/
routeEdit(event: MouseEvent) {
event.stopPropagation();
}
/**
* Initializes the data source, paginator and sorter for roles and permissions table.
*/
@@ -0,0 +1,99 @@
<div fxLayout="row" fxLayoutAlign="end" fxLayoutGap="2%" fxLayout.lt-md="column" class="container m-b-20">
<button mat-raised-button color="primary" (click)="editRoles(); backupCheckValues();" [disabled]="rolePermissionService.name === 'Super user'">
<fa-icon icon="edit"></fa-icon>&nbsp;&nbsp;
Edit Role
</button>
<button *ngIf="!isRoleEnable(rolePermissionService.disabled)" mat-raised-button color="danger" (click)="disableRolesConfirmation()" [disabled]="rolePermissionService.name === 'Super user'">
<fa-icon icon="lock"></fa-icon>&nbsp;&nbsp;
Disable Role
</button>
<button *ngIf="isRoleEnable(rolePermissionService.disabled)" mat-raised-button color="primary" (click)="enableRolesConfirmation()" [disabled]="rolePermissionService.name === 'Super user'">
<fa-icon icon="lock-open"></fa-icon>&nbsp;&nbsp;
Enable Role
</button>
<button mat-raised-button color="warn" (click)="deleteRole()" [disabled]="rolePermissionService.name === 'Super user'">
<fa-icon icon="trash"></fa-icon>&nbsp;&nbsp;
Delete Role
</button>
</div>
<div class="container">
<mat-card>
<div fxFlexFill>
<span fxFlex="30%">Name:</span>
<span fxFlex="70%">{{ rolePermissionService.name }}</span>
</div>
<div fxFlexFill>
<span fxFlex="30%">Description:</span>
<span fxFlex="70%">{{ rolePermissionService.description }}</span>
</div>
<mat-divider></mat-divider>
<ng-container>
<div fxLayout="row" class="permissionSelected">
<div fxFlex="75">
<h3>
Permissions: <strong>{{ formatName(previousGrouping) }}</strong>
</h3>
</div>
<div fxFlex= "25" fxLayout="row" fxLayout.xs="column" fxLayoutAlign="end" fxLayoutGap="5px" *ngIf="!isDisabled" class="selectDeselect">
<button mat-raised-button color="primary" (click)="selectAll()">Select All</button>
<button mat-raised-button color="default" (click)="deselectAll()">Deselect All</button>
</div>
</div>
<div fxLayout="row">
<div fxFlex="30" fxLayout="column">
<mat-list>
<mat-list-item [ngClass]="selectedItem == grouping ? 'active' : 'inactive'" *ngFor="let grouping of groupings" (click)="showPermissions(grouping)">
<span class="groupingName">
{{ formatName(grouping) }}
</span>
</mat-list-item>
</mat-list>
</div>
<div fxFlex="70" fxLayout="column" class="listPermission">
<form [formGroup]="formGroup" (submit)="submit()">
<div *ngFor="let permission of permissions.permissions" class="displayPermissions">
<div formArrayName="roster">
<div [formGroupName]="permission.id">
<mat-checkbox name="cp" id="{{ permission.code }}" formControlName="selected"
>
{{ permissionName(permission.code) }}
</mat-checkbox>
</div>
</div>
</div>
</form>
</div>
</div>
</ng-container>
<div fxLayout="row" fxLayout.xs="column" fxLayoutAlign="center" fxLayoutGap="5px" *ngIf="!isDisabled">
<mat-card-actions>
<button type="button" mat-raised-button (click)="cancel(); restoreCheckboxes();">Cancel</button>
<button mat-raised-button color="primary" (click)="submit()">Submit</button>
</mat-card-actions>
</div>
</mat-card>
</div>
@@ -0,0 +1,40 @@
.displayPermissions {
padding-top: 15px;
}
span {
font-size: 1rem;
}
mat-list-item {
cursor: pointer;
}
.mat-list-base .mat-list-item .mat-list-item-content {
cursor: pointer;
}
.active {
background-color: #f2f2f2;
}
.groupingName {
padding: 0px 10px;
}
.listPermission {
padding-left: 20px;
}
.permissionSelected {
margin-top: 10px;
height: 40px;
}
.inactive {
transition: all .2s ease-in-out;
}
.inactive:hover {
transform: scale(1.1);
}
@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ViewRoleComponent } from './view-role.component';
describe('ViewRoleComponent', () => {
let component: ViewRoleComponent;
let fixture: ComponentFixture<ViewRoleComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ViewRoleComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ViewRoleComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,301 @@
/** Angular Imports */
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { MatDialog } from '@angular/material';
import { SystemService } from '../../system.service';
import * as _ from 'lodash';
/** Custom Components */
import { DeleteDialogComponent } from '../../../shared/delete-dialog/delete-dialog.component';
import { DisableDialogComponent } from '../../../shared/disable-dialog/disable-dialog.component';
import { EnableDialogComponent } from '../../../shared/enable-dialog/enable-dialog.component';
/**
* View Role and Permissions Component
*/
@Component({
selector: 'mifosx-view-role',
templateUrl: './view-role.component.html',
styleUrls: ['./view-role.component.scss']
})
export class ViewRoleComponent implements OnInit {
/** Role Permissions Data */
rolePermissionService: any;
/** Stores the current grouping */
currentGrouping: string;
/** Stores the previous grouping */
previousGrouping = '';
/** Stores Grouping Data */
groupings: string[] = [];
/** Stores the selected role */
selectedItem = '';
/** Checks if its disabled */
isDisabled: Boolean = true;
/** Checks if there is any change in data */
checkboxesChanged: Boolean = false;
/** Stores backup values */
bValuesOnly: string[] = [];
/** Role ID */
roleId: any;
/** Creates permission form */
formGroup: FormGroup;
/** Creates Backup form */
backupform: FormGroup;
/** Temporarily stores Permission data */
tempPermissionUIData: {
permissions: { code: string }[]
}[];
/** Stores permissions */
permissions: {
permissions: { code: string, id: number }[]
};
/**
* Retrieves the roledetails data from `resolve`.
* @param {ActivatedRoute} route Activated Route.
* @param {SystemService} systemService System Service.
* @param {Router} router Router for navigation.
* @param {FormBuilder} formBuilder Form Builder.
* @param {MatDialog} dialog Shared Dialog Boxes.
*/
constructor(private route: ActivatedRoute,
private systemService: SystemService,
private router: Router,
private formBuilder: FormBuilder,
public dialog: MatDialog) {
this.route.data.subscribe((data: { roledetails: any }) => {
this.rolePermissionService = data.roledetails;
});
}
/**
* Groups all the data on init
*/
ngOnInit() {
this.permissions = {
permissions: []
};
this.createForm();
this.groupRules();
this.selectedItem = 'special';
this.showPermissions('special');
this.route.params.subscribe((routeParams: any) => {
this.roleId = routeParams.id;
});
}
/**
* creates the form to display and edit permissions
*/
createForm() {
this.formGroup = this.formBuilder.group({
roster: this.formBuilder.array(this.rolePermissionService.permissionUsageData.map((elem: any) => this.createMemberGroup(elem)))
});
}
createMemberGroup(permission: any): FormGroup {
return this.formBuilder.group({
...permission,
...{
code: [permission.code, Validators.required],
selected: [{ value: permission.selected, disabled: true }, Validators.required]
}
});
}
/**
* Groups the permissions based on rules
*/
groupRules() {
this.tempPermissionUIData = [{
permissions: []
}];
for (const i in this.rolePermissionService.permissionUsageData) {
if (this.rolePermissionService.permissionUsageData[i]) {
if (this.rolePermissionService.permissionUsageData[i].grouping !== this.currentGrouping) {
this.currentGrouping = this.rolePermissionService.permissionUsageData[i].grouping;
this.groupings.push(this.currentGrouping);
this.tempPermissionUIData[this.currentGrouping] = { permissions: [] };
}
const temp = { code: this.rolePermissionService.permissionUsageData[i].code, id: i, selected: this.rolePermissionService.permissionUsageData[i].selected };
this.tempPermissionUIData[this.currentGrouping].permissions.push(temp);
}
}
}
/**
* Displays the permission for selected role
* @param grouping Selected Role
*/
showPermissions(grouping: string) {
this.permissions = this.tempPermissionUIData[grouping];
this.selectedItem = grouping;
this.previousGrouping = grouping;
}
/**
* Formats the Role Name
* @param string String
*/
formatName(string: any) {
if (string.indexOf('portfolio_') > -1) {
string = string.replace('portfolio_', '');
}
if (string.indexOf('transaction_') > -1) {
const temp = string.split('_');
string = temp[1] + ' ' + temp[0].charAt(0).toUpperCase() + temp[0].slice(1) + 's';
}
string = string.charAt(0).toUpperCase() + string.slice(1);
return string;
}
/**
* Formats the permission from permission code
* @param name String
*/
permissionName(name: any) {
name = name || '';
// replace '_' with ' '
name = name.replace(/_/g, ' ');
// for reorts replace read with view
if (this.previousGrouping === 'report') {
name = name.replace(/READ/g, 'View');
}
return name;
}
/**
* Backups the valued
*/
backupCheckValues() {
this.backupform = _.cloneDeep(this.formGroup) as FormGroup;
}
/**
* Restores the checkboxes to previous data on clicking cancel
*/
restoreCheckboxes() {
this.formGroup = _.cloneDeep(this.backupform) as FormGroup;
}
isRoleEnable(value: any) {
return value;
}
editRoles() {
this.isDisabled = false;
this.formGroup.controls.roster.enable();
}
/**
* Cancel the changes
*/
cancel() {
this.isDisabled = true;
this.formGroup.controls.roster.disable();
}
/**
* Submits the modified permissions
*/
submit() {
const value = this.formGroup.get('roster').value;
const data = {};
const permissionData = {
permissions: {}
};
for (let i = 0; i < value.length; i++ ) {
data[value[i].code] = value[i].selected;
}
permissionData.permissions = data;
this.formGroup.controls.roster.disable();
this.checkboxesChanged = false;
this.isDisabled = true;
this.systemService.updateRolePermission(this.roleId, permissionData).subscribe((response: any) => {
console.log('response: ', response);
});
}
/**
* Selects all the permission of a particular role
*/
selectAll() {
for (let i = 0; i < this.permissions.permissions.length; i++) {
this.formGroup.controls.roster['controls'][this.permissions.permissions[i].id].patchValue({
selected: true
});
}
}
/**
* Deselects all the permissions of a particular role
*/
deselectAll() {
for (let i = 0; i < this.permissions.permissions.length; i++) {
this.formGroup.controls.roster['controls'][this.permissions.permissions[i].id].patchValue({
selected: false
});
}
}
/**
* Deletes the Role and redirects to Roles and Permissions.
*/
deleteRole() {
const deleteRoleDialogRef = this.dialog.open(DeleteDialogComponent, {
data: { deleteContext: `role ${this.roleId}` }
});
deleteRoleDialogRef.afterClosed().subscribe((response: any) => {
if (response.delete) {
this.systemService.deleteRole(this.roleId)
.subscribe(() => {
this.router.navigate(['/system/roles-and-permissions']);
});
} else {
}
});
}
/**
* Enables the Role and redirects to Roles and Permissions.
*/
enableRolesConfirmation() {
const enableRoleDialogRef = this.dialog.open(EnableDialogComponent, {
data: { enableContext: `role ${this.roleId}` }
});
enableRoleDialogRef.afterClosed().subscribe((response: any) => {
if (response.enable) {
this.systemService.enableRole(this.roleId)
.subscribe(() => {
this.router.navigate(['/system/roles-and-permissions']);
});
} else {
}
});
}
/**
* Disables the Role and redirects to Roles and Permissions.
*/
disableRolesConfirmation() {
const deleteRoleDialogRef = this.dialog.open(DisableDialogComponent, {
data: { disableContext: `role ${this.roleId}` }
});
deleteRoleDialogRef.afterClosed().subscribe((response: any) => {
if (response.disable) {
this.systemService.disableRole(this.roleId)
.subscribe(() => {
this.router.navigate(['/system/roles-and-permissions']);
});
} else {
}
});
}
}
@@ -0,0 +1,31 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot } from '@angular/router';
/** rxjs Imports */
import { Observable } from 'rxjs';
/** Custom Services */
import { SystemService } from '../../system.service';
/**
* Roles and Permission data resolver.
*/
@Injectable()
export class ViewRoleResolver implements Resolve<Object> {
/**
* @param {SystemService} systemService System service.
*/
constructor(private systemService: SystemService) { }
/**
* Returns the roles and permissions data.
* @returns {Observable<any>}
*/
resolve(route: ActivatedRouteSnapshot): Observable<any> {
const id = route.paramMap.get('id');
return this.systemService.getRole(id);
}
}