From b1a3646bc22c2e21a5e36e1bbecf9b13cfde82f9 Mon Sep 17 00:00:00 2001 From: Chirag Gupta Date: Mon, 23 Mar 2020 02:06:57 +0530 Subject: [PATCH] feat: create, view, edit, delete data-table (#365) - Add view-data-table - Add edit-data-table - Add create-data-table Fixes #171 Co-authored-by: Chirag Gupta --- .../manage-data-tables/app-table-data.ts | 10 + .../column-dialog.component.html | 54 ++++ .../column-dialog.component.scss | 0 .../column-dialog.component.spec.ts | 25 ++ .../column-dialog/column-dialog.component.ts | 101 ++++++ .../manage-data-tables/column-type-data.ts | 10 + .../create-data-table.component.html | 109 +++++++ .../create-data-table.component.scss | 18 ++ .../create-data-table.component.spec.ts | 25 ++ .../create-data-table.component.ts | 188 +++++++++++ .../manage-data-tables/data-table.resolver.ts | 33 ++ .../edit-data-table.component.html | 103 ++++++ .../edit-data-table.component.scss | 3 + .../edit-data-table.component.spec.ts | 25 ++ .../edit-data-table.component.ts | 305 ++++++++++++++++++ .../manage-data-tables.component.html | 4 +- .../view-data-table.component.html | 78 +++++ .../view-data-table.component.scss | 12 + .../view-data-table.component.spec.ts | 25 ++ .../view-data-table.component.ts | 88 +++++ src/app/system/system-routing.module.ts | 48 ++- src/app/system/system.module.ts | 13 +- src/app/system/system.service.ts | 33 ++ 23 files changed, 1302 insertions(+), 8 deletions(-) create mode 100644 src/app/system/manage-data-tables/app-table-data.ts create mode 100644 src/app/system/manage-data-tables/column-dialog/column-dialog.component.html create mode 100644 src/app/system/manage-data-tables/column-dialog/column-dialog.component.scss create mode 100644 src/app/system/manage-data-tables/column-dialog/column-dialog.component.spec.ts create mode 100644 src/app/system/manage-data-tables/column-dialog/column-dialog.component.ts create mode 100644 src/app/system/manage-data-tables/column-type-data.ts create mode 100644 src/app/system/manage-data-tables/create-data-table/create-data-table.component.html create mode 100644 src/app/system/manage-data-tables/create-data-table/create-data-table.component.scss create mode 100644 src/app/system/manage-data-tables/create-data-table/create-data-table.component.spec.ts create mode 100644 src/app/system/manage-data-tables/create-data-table/create-data-table.component.ts create mode 100644 src/app/system/manage-data-tables/data-table.resolver.ts create mode 100644 src/app/system/manage-data-tables/edit-data-table/edit-data-table.component.html create mode 100644 src/app/system/manage-data-tables/edit-data-table/edit-data-table.component.scss create mode 100644 src/app/system/manage-data-tables/edit-data-table/edit-data-table.component.spec.ts create mode 100644 src/app/system/manage-data-tables/edit-data-table/edit-data-table.component.ts create mode 100644 src/app/system/manage-data-tables/view-data-table/view-data-table.component.html create mode 100644 src/app/system/manage-data-tables/view-data-table/view-data-table.component.scss create mode 100644 src/app/system/manage-data-tables/view-data-table/view-data-table.component.spec.ts create mode 100644 src/app/system/manage-data-tables/view-data-table/view-data-table.component.ts diff --git a/src/app/system/manage-data-tables/app-table-data.ts b/src/app/system/manage-data-tables/app-table-data.ts new file mode 100644 index 000000000..5fbd4ace7 --- /dev/null +++ b/src/app/system/manage-data-tables/app-table-data.ts @@ -0,0 +1,10 @@ +export const appTableData: { displayValue: string, value: string }[] = [ + { displayValue: 'Client', value: 'm_client' }, + { displayValue: 'Group', value: 'm_group' }, + { displayValue: 'Loan', value: 'm_loan' }, + { displayValue: 'Center', value: 'm_center' }, + { displayValue: 'Office', value: 'm_office' }, + { displayValue: 'Saving Account', value: 'm_savings_account' }, + { displayValue: 'Product Loan', value: 'm_product_loan' }, + { displayValue: 'Savings Product', value: 'm_savings_product' } + ]; diff --git a/src/app/system/manage-data-tables/column-dialog/column-dialog.component.html b/src/app/system/manage-data-tables/column-dialog/column-dialog.component.html new file mode 100644 index 000000000..5f7dc6057 --- /dev/null +++ b/src/app/system/manage-data-tables/column-dialog/column-dialog.component.html @@ -0,0 +1,54 @@ +

{{ data.columnName ? "Edit" : "Add" }} Column

+ + + +
+ +
+ + + Column Name + + + Column Name is required + + + + + Column Type + + + {{ columnType.displayValue }} + + + + +
+ Mandatory +
+ + + Column Length + + + + + Column Code + + + {{ columnCode.name }} + + + + +
+ +
+ +
+ + + + + diff --git a/src/app/system/manage-data-tables/column-dialog/column-dialog.component.scss b/src/app/system/manage-data-tables/column-dialog/column-dialog.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/system/manage-data-tables/column-dialog/column-dialog.component.spec.ts b/src/app/system/manage-data-tables/column-dialog/column-dialog.component.spec.ts new file mode 100644 index 000000000..a304ea04b --- /dev/null +++ b/src/app/system/manage-data-tables/column-dialog/column-dialog.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ColumnDialogComponent } from './column-dialog.component'; + +describe('ColumnDialogComponent', () => { + let component: ColumnDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ColumnDialogComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ColumnDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/system/manage-data-tables/column-dialog/column-dialog.component.ts b/src/app/system/manage-data-tables/column-dialog/column-dialog.component.ts new file mode 100644 index 000000000..b5d720e4c --- /dev/null +++ b/src/app/system/manage-data-tables/column-dialog/column-dialog.component.ts @@ -0,0 +1,101 @@ +/** Angular Imports */ +import { Component, OnInit, Inject } from '@angular/core'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material'; +import { FormGroup, FormBuilder, Validators } from '@angular/forms'; + +/** Data Imports */ +import { columnTypeData } from '../column-type-data'; + +/** + * Column Dialog Component. + */ +@Component({ + selector: 'mifosx-column-dialog', + templateUrl: './column-dialog.component.html', + styleUrls: ['./column-dialog.component.scss'] +}) +export class ColumnDialogComponent implements OnInit { + + /** Column Form. */ + columnForm: FormGroup; + /** Column Type Data */ + columnTypeData = columnTypeData; + + /** + * @param {MatDialogRef} dialogRef Component reference to dialog. + * @param {FormBuilder} formBuilder Form Builder. + * @param {any} data Provides the column codes and values for the form (if available). + */ + constructor(public dialogRef: MatDialogRef, + public formBuilder: FormBuilder, + @Inject(MAT_DIALOG_DATA) public data: any) { } + + /** + * Creates the add column form. + */ + ngOnInit() { + this.columnForm = this.formBuilder.group({ + 'name': [this.data ? this.data.columnName : '', Validators.required], + 'type': [{ value: this.data ? (this.data.columnDisplayType === '' ? '' : this.getColumnType(this.data.columnDisplayType)) : '', disabled: this.data.type === 'existing' }, Validators.required], + 'mandatory': [{ value: this.data ? this.data.isColumnPrimaryKey : false, disabled: this.data.type === 'existing' }], + 'length': [{ value: this.data ? +this.data.columnLength : '', disabled: this.getColumnType(this.data.columnDisplayType) !== 'String' || this.data.type === 'existing' }, Validators.required], + 'code': [{ value: this.data ? this.data.columnCode : '', disabled: this.getColumnType(this.data.columnDisplayType) !== 'Dropdown' || this.data.type === 'existing' }, Validators.required] + }); + this.onColumnTypeChanges(); + } + + /** + * Returns the modified Column Type. + * @param {string} columnDisplayType Column Display Type. + * @returns {string} Column Type. + */ + getColumnType(columnDisplayType: string): string { + switch (columnDisplayType) { + case undefined: { + return ''; + } + case 'INTEGER': { + return 'Number'; + } + case 'CODELOOKUP': { + return 'Dropdown'; + } + default: { + return columnDisplayType[0] + columnDisplayType.substr(1).toLowerCase(); + } + } + } + + /** + * Watches on Column Type field to enable/diable certain fields. + */ + onColumnTypeChanges() { + this.columnForm.get('type').valueChanges + .subscribe(type => { + switch (type) { + case 'String': { + this.columnForm.get('length').enable(); + this.columnForm.get('code').disable(); + break; + } + case 'Dropdown': { + this.columnForm.get('code').enable(); + this.columnForm.get('length').disable(); + break; + } + default: { + this.columnForm.get('code').disable(); + this.columnForm.get('length').disable(); + } + } + }); + } + + /** + * Closes the dialog and returns value of the form. + */ + submit() { + this.dialogRef.close(this.columnForm.value); + } + +} diff --git a/src/app/system/manage-data-tables/column-type-data.ts b/src/app/system/manage-data-tables/column-type-data.ts new file mode 100644 index 000000000..bc799a050 --- /dev/null +++ b/src/app/system/manage-data-tables/column-type-data.ts @@ -0,0 +1,10 @@ +export const columnTypeData: { displayValue: string, value: string }[] = [ + { displayValue: 'Boolean', value: 'Boolean' }, + { displayValue: 'Date', value: 'Date' }, + { displayValue: 'Date and Time', value: 'Datetime' }, + { displayValue: 'Decimal', value: 'Decimal' }, + { displayValue: 'Dropdown', value: 'Dropdown' }, + { displayValue: 'Number', value: 'Number' }, + { displayValue: 'String', value: 'String' }, + { displayValue: 'Text', value: 'Text' } + ]; diff --git a/src/app/system/manage-data-tables/create-data-table/create-data-table.component.html b/src/app/system/manage-data-tables/create-data-table/create-data-table.component.html new file mode 100644 index 000000000..f92636ebf --- /dev/null +++ b/src/app/system/manage-data-tables/create-data-table/create-data-table.component.html @@ -0,0 +1,109 @@ +
+ + + +
+ + + +
+ + + Data Table Name + + + Data Table Name is required + + + + + Application Table Name + + + {{ appTable.displayValue }} + + + + Application Table Name is required + + + +
+ Multi Row +
+ +
+
+ +
+ +

Columns

+ + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name {{ column.name }} Type {{ column.type }} Mandatory {{ column.mandatory }} Length {{ column.length }} Code {{ column.code }} Actions + + +
+ + + +
+ + + + + + +
+ +
+ +
diff --git a/src/app/system/manage-data-tables/create-data-table/create-data-table.component.scss b/src/app/system/manage-data-tables/create-data-table/create-data-table.component.scss new file mode 100644 index 000000000..eac57d1fe --- /dev/null +++ b/src/app/system/manage-data-tables/create-data-table/create-data-table.component.scss @@ -0,0 +1,18 @@ +@media (min-width: 992px) { + + .multi-row-wrapper { + position: relative; + + .multi-row { + padding: 0 0 17.5px 0; + position: absolute; + bottom: 0; + right: 0; + } + } + +} + +table { + width: 100%; +} diff --git a/src/app/system/manage-data-tables/create-data-table/create-data-table.component.spec.ts b/src/app/system/manage-data-tables/create-data-table/create-data-table.component.spec.ts new file mode 100644 index 000000000..64788c2b2 --- /dev/null +++ b/src/app/system/manage-data-tables/create-data-table/create-data-table.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateDataTableComponent } from './create-data-table.component'; + +describe('CreateDataTableComponent', () => { + let component: CreateDataTableComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ CreateDataTableComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateDataTableComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/system/manage-data-tables/create-data-table/create-data-table.component.ts b/src/app/system/manage-data-tables/create-data-table/create-data-table.component.ts new file mode 100644 index 000000000..c2abe94f2 --- /dev/null +++ b/src/app/system/manage-data-tables/create-data-table/create-data-table.component.ts @@ -0,0 +1,188 @@ +/** Angular Imports */ +import { Component, OnInit, ViewChild } from '@angular/core'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { ActivatedRoute, Router } from '@angular/router'; +import { MatTableDataSource, MatPaginator, MatSort, MatDialog } from '@angular/material'; + +/** Custom Services */ +import { SystemService } from '../../system.service'; + +/** Data Imports */ +import { appTableData } from '../app-table-data'; + +/** Custom Components */ +import { ColumnDialogComponent } from '../column-dialog/column-dialog.component'; +import { DeleteDialogComponent } from 'app/shared/delete-dialog/delete-dialog.component'; + +/** + * Create Data Table Component. + */ +@Component({ + selector: 'mifosx-create-data-table', + templateUrl: './create-data-table.component.html', + styleUrls: ['./create-data-table.component.scss'] +}) +export class CreateDataTableComponent implements OnInit { + + /** Data Table Form */ + dataTableForm: FormGroup; + /** Application Table Data */ + appTableData = appTableData; + /** Column Data */ + columnData: any[] = []; + /** Data passed to dialog. */ + dataForDialog: { + columnName: string, + columnDisplayType: string, + isColumnPrimaryKey: boolean, + columnLength: string, + columnCode: string, + columnCodes: any, + type: string + } = { + columnName: undefined, + columnDisplayType: undefined, + isColumnPrimaryKey: undefined, + columnLength: undefined, + columnCode: undefined, + columnCodes: undefined, + type: undefined + }; + /** Columns to be displayed in columns table. */ + displayedColumns: string[] = ['name', 'type', 'mandatory', 'length', 'code', 'actions']; + /** Data source for columns table. */ + dataSource: MatTableDataSource; + /** Paginator for columns table. */ + @ViewChild(MatPaginator) paginator: MatPaginator; + /** Sorter for columns table. */ + @ViewChild(MatSort) sort: MatSort; + + /** + * Retrieves the column codes data from `resolve`. + * @param {FormBuilder} formBuilder Form Builder. + * @param {SystemService} systemService System Service. + * @param {ActivatedRoute} route Activated Route. + * @param {Router} router Router for navigation. + * @param {MatDialog} dialog Dialog Reference. + */ + constructor(private formBuilder: FormBuilder, + private systemService: SystemService, + private route: ActivatedRoute, + private router: Router, + private dialog: MatDialog) { + this.route.data.subscribe((data: { columnCodes: any }) => { + this.dataForDialog.columnCodes = data.columnCodes; + }); + } + + /** + * Creates data table form and sets columns table. + */ + ngOnInit() { + this.createDataTableForm(); + this.setColumns(); + } + + /** + * Initializes the data source, paginator and sorter for columns table. + */ + setColumns() { + this.dataSource = new MatTableDataSource(this.columnData); + this.dataSource.paginator = this.paginator; + this.dataSource.sort = this.sort; + } + + /** + * Creates the data table form. + */ + createDataTableForm() { + this.dataTableForm = this.formBuilder.group({ + 'datatableName': ['', Validators.required], + 'apptableName': ['', Validators.required], + 'multiRow': [''] + }); + } + + /** + * Adds a new column. + */ + addColumn() { + this.dataForDialog.columnName = undefined; + this.dataForDialog.columnDisplayType = undefined; + this.dataForDialog.isColumnPrimaryKey = false; + this.dataForDialog.columnLength = undefined; + this.dataForDialog.columnCode = undefined; + this.dataForDialog.type = 'new'; + const addColumnDialogRef = this.dialog.open(ColumnDialogComponent, { + data: this.dataForDialog + }); + addColumnDialogRef.afterClosed().subscribe((response: any) => { + if (response !== '') { + this.columnData.push({ + name: response.name, + type: response.type, + mandatory: response.mandatory, + length: response.length, + code: response.code + }); + this.dataSource.connect().next(this.columnData); + } + }); + } + + /** + * Edits column. + * @param {any} column Column. + */ + editColumn(column: any) { + this.dataForDialog.columnName = column.name; + this.dataForDialog.columnDisplayType = column.type; + this.dataForDialog.isColumnPrimaryKey = column.mandatory; + this.dataForDialog.columnLength = column.length; + this.dataForDialog.columnCode = column.code; + this.dataForDialog.type = 'new'; + const editColumnDialogRef = this.dialog.open(ColumnDialogComponent, { + data: this.dataForDialog + }); + editColumnDialogRef.afterClosed().subscribe((response: any) => { + if (response !== '') { + this.columnData[this.columnData.findIndex(newColumn => newColumn.name === column.name)] = { + name: response.name, + type: response.type, + mandatory: response.mandatory, + length: response.length, + code: response.code + }; + this.dataSource.connect().next(this.columnData); + } + }); + } + + /** + * Deletes the column. + * @param {any} column Column. + */ + deleteColumn(column: any) { + const deleteColumnDialogRef = this.dialog.open(DeleteDialogComponent, { + data: { deleteContext: `column ${column.name}` } + }); + deleteColumnDialogRef.afterClosed().subscribe((response: any) => { + if (response.delete) { + this.columnData.splice(this.columnData.indexOf(column), 1); + this.dataSource.connect().next(this.columnData); + } + }); + } + + /** + * Submits the data table form and creates data table, + * if successful redirects to view created data table. + */ + submit() { + this.dataTableForm.value.columns = this.columnData; + this.systemService.createDataTable(this.dataTableForm.value) + .subscribe((response: any) => { + this.router.navigate(['../', response.resourceIdentifier], { relativeTo: this.route }); + }); + } +} diff --git a/src/app/system/manage-data-tables/data-table.resolver.ts b/src/app/system/manage-data-tables/data-table.resolver.ts new file mode 100644 index 000000000..4492da060 --- /dev/null +++ b/src/app/system/manage-data-tables/data-table.resolver.ts @@ -0,0 +1,33 @@ +/** 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'; + +/** + * Data Table data resolver. + */ +@Injectable() +export class DataTableResolver implements Resolve { + + /** + * @param {SystemService} systemService System service. + */ + constructor(private systemService: SystemService) {} + + /** + * Returns the Data Table data. + * TODO: Delete the extra column to avoid multiple usages of `this.columnsData.shift()`. + * @returns {Observable} + */ + resolve(route: ActivatedRouteSnapshot): Observable { + const dataTableName = route.paramMap.get('datatableName'); + return this.systemService.getDataTable(dataTableName); + } + +} + diff --git a/src/app/system/manage-data-tables/edit-data-table/edit-data-table.component.html b/src/app/system/manage-data-tables/edit-data-table/edit-data-table.component.html new file mode 100644 index 000000000..14d55e843 --- /dev/null +++ b/src/app/system/manage-data-tables/edit-data-table/edit-data-table.component.html @@ -0,0 +1,103 @@ +
+ + + +
+ + + +
+ + + Data Table Name + + + + + Application Table Name + + + {{ appTable.displayValue }} + + + + Application Table Name is required + + + +
+ +
+ +
+ +

Columns

+ + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Name {{ column.columnName }} Type {{ column.columnDisplayType }} Mandatory {{ column.isColumnPrimaryKey }} Length {{ column.columnLength }} Code {{ column.columnCode }} Actions + + +
+ + + +
+ + + + + + +
+ +
+ +
diff --git a/src/app/system/manage-data-tables/edit-data-table/edit-data-table.component.scss b/src/app/system/manage-data-tables/edit-data-table/edit-data-table.component.scss new file mode 100644 index 000000000..1922e7ffa --- /dev/null +++ b/src/app/system/manage-data-tables/edit-data-table/edit-data-table.component.scss @@ -0,0 +1,3 @@ +table { + width: 100%; +} diff --git a/src/app/system/manage-data-tables/edit-data-table/edit-data-table.component.spec.ts b/src/app/system/manage-data-tables/edit-data-table/edit-data-table.component.spec.ts new file mode 100644 index 000000000..a18135ac8 --- /dev/null +++ b/src/app/system/manage-data-tables/edit-data-table/edit-data-table.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { EditDataTableComponent } from './edit-data-table.component'; + +describe('EditDataTableComponent', () => { + let component: EditDataTableComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ EditDataTableComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(EditDataTableComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/system/manage-data-tables/edit-data-table/edit-data-table.component.ts b/src/app/system/manage-data-tables/edit-data-table/edit-data-table.component.ts new file mode 100644 index 000000000..5ee415d64 --- /dev/null +++ b/src/app/system/manage-data-tables/edit-data-table/edit-data-table.component.ts @@ -0,0 +1,305 @@ +/** Angular Imports */ +import { Component, OnInit, ViewChild } from '@angular/core'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { ActivatedRoute, Router } from '@angular/router'; +import { MatTableDataSource, MatPaginator, MatSort, MatDialog } from '@angular/material'; + +/** Custom Services */ +import { SystemService } from '../../system.service'; + +/** Data Imports */ +import { appTableData } from '../app-table-data'; + +/** Custom Components */ +import { ColumnDialogComponent } from '../column-dialog/column-dialog.component'; +import { DeleteDialogComponent } from 'app/shared/delete-dialog/delete-dialog.component'; + +/** + * Edit Data Table Component. + */ +@Component({ + selector: 'mifosx-edit-data-table', + templateUrl: './edit-data-table.component.html', + styleUrls: ['./edit-data-table.component.scss'] +}) +export class EditDataTableComponent implements OnInit { + + /** Data Table Form. */ + dataTableForm: FormGroup; + /** Data Table Data. */ + dataTableData: any; + /** Column Data. */ + columnData: any[]; + /** Application Table Data. */ + appTableData = appTableData; + /** Boolean to check if form is edited or not. */ + isFormEdited = false; + /** Data Table Changes Data. */ + dataTableChangesData: { + apptableName: string, + dropColumns?: { name: string }[], + changeColumns: { name: string, newName?: string, code?: string, newCode?: string, mandatory: boolean, length?: number }[], + addColumns?: { name?: string, type?: string, code?: string, mandatory?: boolean, length?: number }[] + } = { apptableName: '', changeColumns: [], addColumns: [], dropColumns: [] }; + /** Data passed to dialog. */ + dataForDialog: { + columnName: string, + columnDisplayType: string, + isColumnPrimaryKey: boolean, + columnLength: string, + columnCode: string, + columnCodes: any, + type: string + } = { + columnName: undefined, + columnDisplayType: undefined, + isColumnPrimaryKey: undefined, + columnLength: undefined, + columnCode: undefined, + columnCodes: undefined, + type: undefined + }; + /** Columns to be displayed in columns table. */ + displayedColumns: string[] = ['name', 'type', 'mandatory', 'length', 'code', 'actions']; + /** Data source for columns table. */ + dataSource: MatTableDataSource; + /** Paginator for columns table. */ + @ViewChild(MatPaginator) paginator: MatPaginator; + /** Sorter for columns table. */ + @ViewChild(MatSort) sort: MatSort; + + /** + * Retrieves the data table and column codes 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 Dialog Reference. + */ + constructor(private systemService: SystemService, + private formBuilder: FormBuilder, + private route: ActivatedRoute, + private router: Router, + private dialog: MatDialog) { + this.route.data.subscribe((data: { dataTable: any, columnCodes: any }) => { + this.dataTableData = data.dataTable; + this.columnData = this.dataTableData.columnHeaderData; + this.dataForDialog.columnCodes = data.columnCodes; + }); + } + + /** + * Creates and sets data table form and columns table. + */ + ngOnInit() { + this.initData(); + this.createDataTableForm(); + this.setColumns(); + } + + /** + * Initializes the data source, paginator and sorter for columns table. + */ + setColumns() { + this.dataSource = new MatTableDataSource(this.columnData); + this.dataSource.paginator = this.paginator; + this.dataSource.sort = this.sort; + } + + /** + * Initializes data table changes and column data. + */ + initData() { + this.columnData.shift(); + this.dataTableChangesData.apptableName = this.dataTableData.applicationTableName; + for (let index = 0; index < this.columnData.length; index++) { + this.columnData[index].columnDisplayType = this.getColumnType(this.columnData[index].columnDisplayType); + this.columnData[index].type = 'existing'; + } + } + + /** + * Creates the data table form. + */ + createDataTableForm() { + this.dataTableForm = this.formBuilder.group({ + 'datatableName': [{ value: this.dataTableData.registeredTableName, disabled: true }, Validators.required], + 'apptableName': [this.dataTableData.applicationTableName, Validators.required] + }); + } + + /** + * Adds a new column. + */ + addColumn() { + this.dataForDialog.columnName = undefined; + this.dataForDialog.columnDisplayType = undefined; + this.dataForDialog.isColumnPrimaryKey = false; + this.dataForDialog.columnLength = undefined; + this.dataForDialog.columnCode = undefined; + this.dataForDialog.type = 'new'; + const addColumnDialogRef = this.dialog.open(ColumnDialogComponent, { + data: this.dataForDialog + }); + addColumnDialogRef.afterClosed().subscribe((response: any) => { + if (response !== '') { + this.isFormEdited = true; + this.dataTableChangesData.addColumns.push({ + name: response.name, + type: response.type, + mandatory: response.mandatory, + length: response.length, + code: response.code + }); + this.columnData.push({ + columnName: response.name, + columnDisplayType: response.type, + isColumnPrimaryKey: response.mandatory, + columnLength: response.length, + columnCode: response.code, + type: 'new' + }); + this.dataSource.connect().next(this.columnData); + } + }); + } + + /** + * Edits column. + * @param {any} column Column. + */ + editColumn(column: any) { + this.dataForDialog.columnName = column.columnName; + this.dataForDialog.columnDisplayType = column.columnDisplayType; + this.dataForDialog.isColumnPrimaryKey = column.isColumnPrimaryKey; + this.dataForDialog.columnLength = column.columnLength; + this.dataForDialog.columnCode = column.columnCode; + this.dataForDialog.type = column.type; + const editColumnDialogRef = this.dialog.open(ColumnDialogComponent, { + data: this.dataForDialog + }); + editColumnDialogRef.afterClosed().subscribe((response: any) => { + if (response !== '') { + this.isFormEdited = true; + if (column.type === 'new') { + this.dataTableChangesData.addColumns[this.dataTableChangesData.addColumns + .findIndex(newColumn => newColumn.name === column.columnName + && newColumn.type === column.columnDisplayType + && newColumn.mandatory === column.isColumnPrimaryKey)] = { + name: response.name, + type: response.type, + code: response.code, + mandatory: response.mandatory, + length: response.length + }; + this.columnData[this.columnData.indexOf(column)] = { + columnName: response.name, + columnDisplayType: response.type, + isColumnPrimaryKey: response.mandatory, + columnLength: response.length, + columnCode: response.code, + type: 'new' + }; + } else if (column.type === 'existing') { + this.columnData[this.columnData.indexOf(column)] = { + columnName: response.name, + columnDisplayType: column.columnDisplayType, + isColumnPrimaryKey: column.isColumnPrimaryKey, + columnLength: column.columnLength, + columnCode: column.columnCode, + type: 'existing' + }; + + const index = this.dataTableChangesData.changeColumns.findIndex(newColumn => newColumn.newName === column.columnName); + if (index === -1) { + this.dataTableChangesData.changeColumns.push({ + name: column.columnName, + newName: response.name, + code: column.columnCode, + newCode: response.code, + mandatory: response.mandatory, + length: response.length + }); + } else { + this.dataTableChangesData.changeColumns[index] = { + name: column.columnName, + newName: response.name, + code: column.columnCode, + newCode: response.code, + mandatory: response.mandatory, + length: response.length + }; + } + } + this.dataSource.connect().next(this.columnData); + } + }); + } + + /** + * Deletes the column. + * @param {any} column Column. + */ + deleteColumn(column: any) { + const deleteColumnDialogRef = this.dialog.open(DeleteDialogComponent, { + data: { deleteContext: `column ${column.columnName}` } + }); + deleteColumnDialogRef.afterClosed().subscribe((response: any) => { + if (response.delete) { + this.isFormEdited = true; + this.columnData.splice(this.columnData.indexOf(column), 1); + this.dataSource.connect().next(this.columnData); + if (column.type === 'existing') { + this.dataTableChangesData.dropColumns.push({ + name: column.columnName + }); + } else if (column.type === 'new') { + this.dataTableChangesData.addColumns.splice(this.dataTableChangesData.addColumns + .findIndex(newColumn => newColumn.name === column.columnName + && newColumn.type === column.columnDisplayType + && newColumn.mandatory === column.isColumnPrimaryKey), 1); + } + } + }); + } + + /** + * Returns the modified Column Type. + * @param {string} columnDisplayType Column Display Type. + * @returns {string} Column Type. + */ + getColumnType(columnDisplayType: string): string { + switch (columnDisplayType) { + case 'INTEGER': { + return 'Number'; + } + case 'CODELOOKUP': { + return 'Dropdown'; + } + default: { + return columnDisplayType[0] + columnDisplayType.substr(1).toLowerCase(); + } + } + } + + /** + * Submits the data table form and updates data table, + * if successful redirects to view updated data table. + */ + submit() { + if (!this.dataTableChangesData.addColumns || this.dataTableChangesData.addColumns.length === 0) { + this.dataTableChangesData.addColumns = undefined; + } + if (!this.dataTableChangesData.changeColumns || this.dataTableChangesData.changeColumns.length === 0) { + this.dataTableChangesData.changeColumns = undefined; + } + if (!this.dataTableChangesData.dropColumns || this.dataTableChangesData.dropColumns.length === 0) { + this.dataTableChangesData.dropColumns = undefined; + } + this.systemService.updateDataTable(this.dataTableChangesData, this.dataTableData.registeredTableName) + .subscribe((response: any) => { + this.router.navigate(['../'], { relativeTo: this.route }); + }); + } + +} diff --git a/src/app/system/manage-data-tables/manage-data-tables.component.html b/src/app/system/manage-data-tables/manage-data-tables.component.html index f8cb2529e..66d9759d4 100644 --- a/src/app/system/manage-data-tables/manage-data-tables.component.html +++ b/src/app/system/manage-data-tables/manage-data-tables.component.html @@ -1,5 +1,5 @@
- @@ -29,7 +29,7 @@ - + diff --git a/src/app/system/manage-data-tables/view-data-table/view-data-table.component.html b/src/app/system/manage-data-tables/view-data-table/view-data-table.component.html new file mode 100644 index 000000000..691de9795 --- /dev/null +++ b/src/app/system/manage-data-tables/view-data-table/view-data-table.component.html @@ -0,0 +1,78 @@ +
+ + + + + +
+ +
+ + + + + +
+
+ Associated With +
+
+ {{ dataTableData.applicationTableName }} +
+ +
+ +
+ +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Field Name {{ dataTableColumn.columnName }} Type {{ dataTable.columnDisplayType }} Length {{ dataTable.columnLength }} Code {{ dataTable.columnCode }} Mandatory + + +
+ + + +
diff --git a/src/app/system/manage-data-tables/view-data-table/view-data-table.component.scss b/src/app/system/manage-data-tables/view-data-table/view-data-table.component.scss new file mode 100644 index 000000000..b9ff73da3 --- /dev/null +++ b/src/app/system/manage-data-tables/view-data-table/view-data-table.component.scss @@ -0,0 +1,12 @@ +table { + width: 100%; +} + +// TODO: CONFIGURE THESE CLASSES GLOBALLY +.column-primary-key { + color: #32cd32; +} + +.not-column-primary-key { + color: #f44366; +} diff --git a/src/app/system/manage-data-tables/view-data-table/view-data-table.component.spec.ts b/src/app/system/manage-data-tables/view-data-table/view-data-table.component.spec.ts new file mode 100644 index 000000000..753384604 --- /dev/null +++ b/src/app/system/manage-data-tables/view-data-table/view-data-table.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ViewDataTableComponent } from './view-data-table.component'; + +describe('ViewDataTableComponent', () => { + let component: ViewDataTableComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ViewDataTableComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ViewDataTableComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/system/manage-data-tables/view-data-table/view-data-table.component.ts b/src/app/system/manage-data-tables/view-data-table/view-data-table.component.ts new file mode 100644 index 000000000..f2ec6ea25 --- /dev/null +++ b/src/app/system/manage-data-tables/view-data-table/view-data-table.component.ts @@ -0,0 +1,88 @@ +/** Angular Imports */ +import { Component, OnInit, ViewChild } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { MatTableDataSource, MatPaginator, MatSort, MatDialog } from '@angular/material'; + +/** Custom Services */ +import { SystemService } from '../../system.service'; + +/** Custom Components */ +import { DeleteDialogComponent } from 'app/shared/delete-dialog/delete-dialog.component'; + +/** + * View Data Table Component + */ +@Component({ + selector: 'mifosx-view-data-table', + templateUrl: './view-data-table.component.html', + styleUrls: ['./view-data-table.component.scss'] +}) +export class ViewDataTableComponent implements OnInit { + + /** Data Table Data */ + dataTableData: any; + /** Column Data */ + columnsData: any; + /** Columns to be displayed in columns table. */ + displayedColumns: string[] = ['columnName', 'columnDisplayType', 'columnLength', 'columnCode', 'isColumnPrimaryKey']; + /** Data source for columns table. */ + dataSource: MatTableDataSource; + + /** Paginator for columns table. */ + @ViewChild(MatPaginator) paginator: MatPaginator; + /** Sorter for columns table. */ + @ViewChild(MatSort) sort: MatSort; + + /** + * Retrieves the data table data from `resolve`. + * @param {ActivatedRoute} route Activated Route. + * @param {SystemService} systemService System Service. + * @param {Router} router Router for navigation. + * @param {MatDialog} dialog Dialog reference. + */ + constructor(private route: ActivatedRoute, + private systemService: SystemService, + private router: Router, + private dialog: MatDialog) { + this.route.data.subscribe((data: { dataTable: any }) => { + this.dataTableData = data.dataTable; + this.columnsData = this.dataTableData.columnHeaderData; + }); + } + + /** + * Sets the columns table. + */ + ngOnInit() { + this.setColumnsTable(); + } + + /** + * Initializes the data source, paginator and sorter for columns table. + */ + setColumnsTable() { + this.columnsData.shift(); + // TODO: Figure out a better approach in order to pass only updated parameters instead of all of them. + this.dataSource = new MatTableDataSource(this.columnsData); + this.dataSource.paginator = this.paginator; + this.dataSource.sort = this.sort; + } + + /** + * Deletes the current data table. + */ + delete() { + const deleteDataTableDialogRef = this.dialog.open(DeleteDialogComponent, { + data: { deleteContext: `data table ${this.dataTableData.registeredTableName}` } + }); + deleteDataTableDialogRef.afterClosed().subscribe((response: any) => { + if (response.delete) { + this.systemService.deleteDataTable(this.dataTableData.registeredTableName) + .subscribe(() => { + this.router.navigate(['/system/data-tables'], { relativeTo: this.route }); + }); + } + }); + + } +} diff --git a/src/app/system/system-routing.module.ts b/src/app/system/system-routing.module.ts index 76c698677..e4e9d6578 100644 --- a/src/app/system/system-routing.module.ts +++ b/src/app/system/system-routing.module.ts @@ -13,6 +13,9 @@ import { ViewCodeComponent } from './codes/view-code/view-code.component'; import { EditCodeComponent } from './codes/edit-code/edit-code.component'; import { ExternalServicesComponent } from './external-services/external-services.component'; import { ManageDataTablesComponent } from './manage-data-tables/manage-data-tables.component'; +import { CreateDataTableComponent } from './manage-data-tables/create-data-table/create-data-table.component'; +import { ViewDataTableComponent } from './manage-data-tables/view-data-table/view-data-table.component'; +import { EditDataTableComponent } from './manage-data-tables/edit-data-table/edit-data-table.component'; import { ManageHooksComponent } from './manage-hooks/manage-hooks.component'; import { ViewHookComponent } from './manage-hooks/view-hook/view-hook.component'; import { CreateHookComponent } from './manage-hooks/create-hook/create-hook.component'; @@ -45,6 +48,7 @@ import { CodesResolver } from './codes/codes.resolver'; import { CodeResolver } from './codes/code.resolver'; import { CodeValuesResolver } from './codes/view-code/code-values.resolver'; import { ManageDataTablesResolver } from './manage-data-tables/manage-data-tables.resolver'; +import { DataTableResolver } from './manage-data-tables/data-table.resolver'; import { ManageHooksResolver } from './manage-hooks/manage-hooks.resolver'; import { HookResolver } from './manage-hooks/view-hook/hook.resolver'; import { HooksTemplateResolver } from './manage-hooks/hooks-template.resolver'; @@ -211,11 +215,46 @@ const routes: Routes = [ }, { path: 'data-tables', - component: ManageDataTablesComponent, - resolve: { - dataTables: ManageDataTablesResolver - }, data: { title: extract('Manage Data Tables'), breadcrumb: 'Manage Data Tables' }, + children: [ + { + path: '', + component: ManageDataTablesComponent, + resolve: { + dataTables: ManageDataTablesResolver + }, + }, + { + path: 'create', + component: CreateDataTableComponent, + data: { title: extract('Create Data Table'), breadcrumb: 'Create'}, + resolve: { + columnCodes: CodesResolver + } + }, + { + path: ':datatableName', + data: { title: extract('View Data Table'), routeParamBreadcrumb: 'datatableName'}, + children: [ + { + path: '', + component: ViewDataTableComponent, + resolve: { + dataTable: DataTableResolver + } + }, + { + path: 'edit', + component: EditDataTableComponent, + data: { title: extract('Edit Data table'), breadcrumb: 'Edit', routeParamBreadcrumb: false}, + resolve: { + dataTable: DataTableResolver, + columnCodes: CodesResolver + } + } + ] + } + ], }, { path: 'hooks', @@ -414,6 +453,7 @@ const routes: Routes = [ CodeResolver, CodeValuesResolver, ManageDataTablesResolver, + DataTableResolver, ManageHooksResolver, HookResolver, HooksTemplateResolver, diff --git a/src/app/system/system.module.ts b/src/app/system/system.module.ts index fbb9358a2..3465ca457 100644 --- a/src/app/system/system.module.ts +++ b/src/app/system/system.module.ts @@ -11,6 +11,9 @@ import { SystemComponent } from './system.component'; import { CreateCodeComponent } from './codes/create-code/create-code.component'; import { ExternalServicesComponent } from './external-services/external-services.component'; import { ManageDataTablesComponent } from './manage-data-tables/manage-data-tables.component'; +import { CreateDataTableComponent } from './manage-data-tables/create-data-table/create-data-table.component'; +import { ViewDataTableComponent } from './manage-data-tables/view-data-table/view-data-table.component'; +import { EditDataTableComponent } from './manage-data-tables/edit-data-table/edit-data-table.component'; import { ManageHooksComponent } from './manage-hooks/manage-hooks.component'; import { RolesAndPermissionsComponent } from './roles-and-permissions/roles-and-permissions.component'; import { AddRoleComponent } from './roles-and-permissions/add-role/add-role.component'; @@ -39,6 +42,7 @@ import { EditReportComponent } from './manage-reports/edit-report/edit-report.co import { EditHookComponent } from './manage-hooks/edit-hook/edit-hook.component'; import { ViewHookComponent } from './manage-hooks/view-hook/view-hook.component'; import { CreateHookComponent } from './manage-hooks/create-hook/create-hook.component'; +import { ColumnDialogComponent } from './manage-data-tables/column-dialog/column-dialog.component'; /** Dialog Component Imports */ import { ReportParameterDialogComponent } from './manage-reports/report-parameter-dialog/report-parameter-dialog.component'; @@ -57,6 +61,9 @@ import { AddEventDialogComponent } from './manage-hooks/add-event-dialog/add-eve EditCodeComponent, ExternalServicesComponent, ManageDataTablesComponent, + CreateDataTableComponent, + ViewDataTableComponent, + EditDataTableComponent, ManageHooksComponent, RolesAndPermissionsComponent, ManageSurveysComponent, @@ -84,11 +91,13 @@ import { AddEventDialogComponent } from './manage-hooks/add-event-dialog/add-eve EditHookComponent, ViewHookComponent, CreateHookComponent, - AddEventDialogComponent + AddEventDialogComponent, + ColumnDialogComponent ], entryComponents: [ ReportParameterDialogComponent, - AddEventDialogComponent + AddEventDialogComponent, + ColumnDialogComponent ] }) export class SystemModule { } diff --git a/src/app/system/system.service.ts b/src/app/system/system.service.ts index a347bb60b..b82d60302 100644 --- a/src/app/system/system.service.ts +++ b/src/app/system/system.service.ts @@ -184,6 +184,39 @@ export class SystemService { return this.http.post('/codes', code); } + /** + * @param {any} dataTable Data Table to be created. + * @return {Observable} + */ + createDataTable(dataTable: any): Observable { + return this.http.post('/datatables', dataTable); + } + + /** + * @param dataTableName Data Table Name. + * @return {Observable} + */ + getDataTable(dataTableName: string): Observable { + return this.http.get(`/datatables/${dataTableName}`); + } + + /** + * @param dataTableName Data Table Name. + * @return {Observable} + */ + deleteDataTable(dataTableName: string): Observable { + return this.http.delete(`/datatables/${dataTableName}`); + } + + /** + * @param dataTable Data Table. + * @param dataTableName Data Table Name. + * @return {Observable} + */ + updateDataTable(dataTable: any, dataTableName: string): Observable { + return this.http.put(`/datatables/${dataTableName}`, dataTable); + } + /** * @returns {Observable} Configurations data. */