feat: add global-configurations component (#357)

* view global configurations
* edit global configuration

Fixes: #178
This commit is contained in:
Chirag Gupta
2019-01-27 20:33:47 +05:30
committed by Abhay Chawla
parent d0a5123d68
commit 370fc9b481
15 changed files with 437 additions and 3 deletions
+2
View File
@@ -47,6 +47,7 @@ import {
faPlay,
faPlus,
faPlusCircle,
faQuestionCircle,
faRandom,
faRoad,
faSearch,
@@ -111,6 +112,7 @@ library.add(
faPlay,
faPlus,
faPlusCircle,
faQuestionCircle,
faRandom,
faRoad,
faSearch,
@@ -0,0 +1,37 @@
<div class="container">
<mat-card>
<form [formGroup]="configurationForm" (ngSubmit)="submit()">
<mat-card-content>
<div fxLayout="column">
<mat-form-field>
<mat-label>Configuration Name</mat-label>
<input matInput required formControlName="name">
</mat-form-field>
<mat-form-field>
<mat-label>Configuration Value</mat-label>
<input matInput required type="number" formControlName="value">
<mat-error *ngIf="configurationForm.controls.value.hasError('required')">
Configuration Value 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]="configurationForm.pristine || !configurationForm.valid"> Submit </button>
</mat-card-actions>
</form>
</mat-card>
</div>
@@ -0,0 +1,3 @@
.container {
max-width: 37rem;
}
@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { EditConfigurationComponent } from './edit-configuration.component';
describe('EditConfigurationComponent', () => {
let component: EditConfigurationComponent;
let fixture: ComponentFixture<EditConfigurationComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ EditConfigurationComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(EditConfigurationComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,69 @@
/** Angular Imports */
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
/** Custom Services */
import { SystemService } from '../../system.service';
/**
* Edit Configuration Component
*/
@Component({
selector: 'mifosx-edit-configuration',
templateUrl: './edit-configuration.component.html',
styleUrls: ['./edit-configuration.component.scss']
})
export class EditConfigurationComponent implements OnInit {
/** Global Configuration form. */
configurationForm: FormGroup;
/** Configuration. */
configuration: any;
/**
* Retrieves the configuration 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: { configuration: any }) => {
this.configuration = data.configuration;
});
}
/**
* Creates and sets the configuration form.
*/
ngOnInit() {
this.createConfigurationForm();
}
/**
* Creates and sets the global configuration form.
*/
createConfigurationForm() {
this.configurationForm = this.formBuilder.group({
'name': [{ value: this.configuration.name, disabled: true }, Validators.required],
'value': [this.configuration.value, Validators.required]
});
}
/**
* Submits the global configuration form and updates global configuration,
* if successful redirects to view all global configurations.
*/
submit() {
this.systemService
.updateConfiguration(this.configuration.id, this.configurationForm.value)
.subscribe((response: any) => {
this.router.navigate(['../../'], { relativeTo: this.route });
});
}
}
@@ -0,0 +1,31 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, Resolve } from '@angular/router';
/** rxjs Imports */
import { Observable } from 'rxjs';
/** Custom Services */
import { SystemService } from '../system.service';
/**
* Global Configuration data resolver.
*/
@Injectable()
export class GlobalConfigurationResolver implements Resolve<Object> {
/**
* @param {SystemService} systemService System service.
*/
constructor(private systemService: SystemService) {}
/**
* Returns the Configuration data.
* @returns {Observable<any>}
*/
resolve(route: ActivatedRouteSnapshot): Observable<any> {
const configurationId = route.paramMap.get('id');
return this.systemService.getConfiguration(configurationId);
}
}
@@ -0,0 +1,65 @@
<div class="container">
<div fxLayout="row">
<mat-form-field fxFlex>
<mat-label>Filter</mat-label>
<input matInput (keyup)="applyFilter($event.target.value)">
</mat-form-field>
</div>
<div class="mat-elevation-z8">
<table mat-table [dataSource]="dataSource" matSort>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
<td mat-cell *matCellDef="let configuration"> {{ configuration.name }}&nbsp;&nbsp;
<fa-icon icon="question-circle" matTooltip="{{ configuration.description === undefined ? 'No Description' : configuration.description }}" matTooltipPosition="right"></fa-icon>
</td>
</ng-container>
<ng-container matColumnDef="enabled">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Status </th>
<td mat-cell *matCellDef="let configuration">
<div [className]="configuration.enabled ? 'enabled' : 'disabled'">
<fa-icon icon="circle" size="lg" matTooltip="{{ configuration.enabled ? 'Enabled' : 'Disabled' }}" matTooltipPosition="right"></fa-icon>
</div>
</td>
</ng-container>
<ng-container matColumnDef="value">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Value </th>
<td mat-cell *matCellDef="let configuration"> {{ configuration.value }}</td>
</ng-container>
<ng-container matColumnDef="action">
<th mat-header-cell *matHeaderCellDef> Action </th>
<td mat-cell *matCellDef="let configuration">
<button mat-button *ngIf="!configuration.enabled" color="accent" (click)="toggleStatus(configuration)">
<fa-icon icon="lock-open"></fa-icon>&nbsp;&nbsp;Enable
</button>
<button mat-button *ngIf="configuration.enabled" color="warn" (click)="toggleStatus(configuration)">
<fa-icon icon="lock"></fa-icon>&nbsp;&nbsp;Disable
</button>
</td>
</ng-container>
<ng-container matColumnDef="edit">
<th mat-header-cell *matHeaderCellDef> Edit </th>
<td mat-cell *matCellDef="let configuration">
<button mat-button color="primary" [routerLink]="[configuration.id, 'edit']">
<fa-icon icon="edit"></fa-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<mat-paginator [pageSizeOptions]="[10, 25, 50, 100]" showFirstLastButtons></mat-paginator>
</div>
</div>
@@ -0,0 +1,12 @@
table {
width: 100%;
}
// TODO: CONFIGURE THESE CLASSES GLOBALLY
.enabled {
color: #32cd32;
}
.disabled {
color: #f44366;
}
@@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { GlobalConfigurationsComponent } from './global-configurations.component';
describe('GlobalConfigurationsComponent', () => {
let component: GlobalConfigurationsComponent;
let fixture: ComponentFixture<GlobalConfigurationsComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ GlobalConfigurationsComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(GlobalConfigurationsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,79 @@
/** Angular Imports */
import { Component, OnInit, ViewChild } from '@angular/core';
import { MatPaginator, MatSort, MatTableDataSource } from '@angular/material';
import { ActivatedRoute, Router } from '@angular/router';
/** Custom Services */
import { SystemService } from '../system.service';
/**
* Global Configurations Component
*/
@Component({
selector: 'mifosx-global-configurations',
templateUrl: './global-configurations.component.html',
styleUrls: ['./global-configurations.component.scss']
})
export class GlobalConfigurationsComponent implements OnInit {
/** Configuration data. */
configurationData: any;
/** Columns to be displayed in configurations table. */
displayedColumns: string[] = ['name', 'enabled', 'value', 'action', 'edit'];
/** Data source for configurations table. */
dataSource: MatTableDataSource<any>;
/** Paginator for configurations table. */
@ViewChild(MatPaginator) paginator: MatPaginator;
/** Sorter for configurations table. */
@ViewChild(MatSort) sort: MatSort;
/**
* Retrieves the configurations data from `resolve`.
* @param {ActivatedRoute} route Activated Route.
* @param {SystemService} systemService System Service.
* @param {Router} router Router for navigation.
*/
constructor(private route: ActivatedRoute,
private systemService: SystemService,
private router: Router) {
this.route.data.subscribe((data: { configurations: any }) => {
this.configurationData = data.configurations.globalConfiguration;
});
}
/**
* Sets the configurations table.
*/
ngOnInit() {
this.setConfigurations();
}
/**
* Initializes the data source, paginator and sorter for configurations table.
*/
setConfigurations() {
this.dataSource = new MatTableDataSource(this.configurationData);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}
/**
* Filters data in configurations table based on passed value.
* @param {string} filterValue Value to filter data.
*/
applyFilter(filterValue: string) {
this.dataSource.filter = filterValue.trim().toLowerCase();
}
/**
* Enables/Disables respective configuration
*/
toggleStatus(configuration: any) {
this.systemService.updateConfiguration(configuration.id, { enabled: !configuration.enabled })
.subscribe((response: any) => {
configuration.enabled = response.changes.enabled;
});
}
}
@@ -0,0 +1,30 @@
/** Angular Imports */
import { Injectable } from '@angular/core';
import { Resolve } from '@angular/router';
/** rxjs Imports */
import { Observable } from 'rxjs';
/** Custom Services */
import { SystemService } from '../system.service';
/**
* Configurations data resolver.
*/
@Injectable()
export class GlobalConfigurationsResolver implements Resolve<Object> {
/**
* @param {SystemService} systemService System service.
*/
constructor(private systemService: SystemService) {}
/**
* Returns the configurations data.
* @returns {Observable<any>}
*/
resolve(): Observable<any> {
return this.systemService.getConfigurations();
}
}
+29 -1
View File
@@ -15,6 +15,8 @@ import { ManageHooksComponent } from './manage-hooks/manage-hooks.component';
import { RolesAndPermissionsComponent } from './roles-and-permissions/roles-and-permissions.component';
import { ManageSurveysComponent } from './manage-surveys/manage-surveys.component';
import { ManageSchedulerJobsComponent } from './manage-scheduler-jobs/manage-scheduler-jobs.component';
import { GlobalConfigurationsComponent } from './global-configurations/global-configurations.component';
import { EditConfigurationComponent } from './global-configurations/edit-configuration/edit-configuration.component';
/** Custom Resolvers */
import { CodesResolver } from './codes/codes.resolver';
@@ -23,6 +25,8 @@ import { ManageHooksResolver } from './manage-hooks/manage-hooks.resolver';
import { RolesAndPermissionsResolver } from './roles-and-permissions/roles-and-permissions.resolver';
import { ManageSurveysResolver } from './manage-surveys/manage-surveys.resolver';
import { ManageSchedulerJobsResolver } from './manage-scheduler-jobs/manage-scheduler-jobs.resolver';
import { GlobalConfigurationsResolver } from './global-configurations/global-configurations.resolver';
import { GlobalConfigurationResolver } from './global-configurations/global-configuration.resolver';
const routes: Routes = [
Route.withShell([
@@ -98,7 +102,29 @@ const routes: Routes = [
},
data: { title: extract('Manage Scheduler Jobs'), breadcrumb: 'Manage Scheduler Jobs' },
},
]
{
path: 'global-configurations',
data: { title: extract('Global Configurations'), breadcrumb: 'Global Configurations' },
children: [
{
path: '',
component: GlobalConfigurationsComponent,
resolve: {
configurations: GlobalConfigurationsResolver
}
},
{
path: ':id/edit',
component: EditConfigurationComponent,
data: { title: extract('Edit Configuration'), breadcrumb: 'Edit' },
resolve: {
configuration: GlobalConfigurationResolver
}
}
],
},
]
}
])
];
@@ -113,6 +139,8 @@ const routes: Routes = [
RolesAndPermissionsResolver,
ManageSurveysResolver,
ManageSchedulerJobsResolver,
GlobalConfigurationsResolver,
GlobalConfigurationResolver
]
})
export class SystemRoutingModule { }
+1 -1
View File
@@ -96,7 +96,7 @@
<p matLine>Schedule a job, modify or delete jobs</p>
</mat-list-item>
<mat-list-item>
<mat-list-item [routerLink]="['global-configurations']">
<mat-icon matListIcon>
<fa-icon icon="cogs" size="sm"></fa-icon>
</mat-icon>
+5 -1
View File
@@ -15,6 +15,8 @@ import { ManageHooksComponent } from './manage-hooks/manage-hooks.component';
import { RolesAndPermissionsComponent } from './roles-and-permissions/roles-and-permissions.component';
import { ManageSurveysComponent } from './manage-surveys/manage-surveys.component';
import { ManageSchedulerJobsComponent } from './manage-scheduler-jobs/manage-scheduler-jobs.component';
import { GlobalConfigurationsComponent } from './global-configurations/global-configurations.component';
import { EditConfigurationComponent } from './global-configurations/edit-configuration/edit-configuration.component';
@NgModule({
imports: [
@@ -30,7 +32,9 @@ import { ManageSchedulerJobsComponent } from './manage-scheduler-jobs/manage-sch
ManageHooksComponent,
RolesAndPermissionsComponent,
ManageSurveysComponent,
ManageSchedulerJobsComponent
ManageSchedulerJobsComponent,
GlobalConfigurationsComponent,
EditConfigurationComponent
]
})
export class SystemModule { }
+24
View File
@@ -75,4 +75,28 @@ export class SystemService {
return this.http.post('/codes', code);
}
/**
* @returns {Observable<any>} Configurations data.
*/
getConfigurations(): Observable<any> {
return this.http.get('/configurations');
}
/**
* @param {string} configurationId Configuration ID of configuration.
* @returns {Observable<any>} Configuration.
*/
getConfiguration(configurationId: string): Observable<any> {
return this.http.get(`/configurations/${configurationId}`);
}
/**
* @param {string} configurationId Configuration ID of configuration to be updated.
* @param {any} configuration Configuration to be updated.
* @returns {Observable<any>}
*/
updateConfiguration(configurationId: string, configuration: any): Observable<any> {
return this.http.put(`/configurations/${configurationId}`, configuration);
}
}