diff --git a/src/app/organization/offices/edit-office/edit-office.resolver.ts b/src/app/organization/offices/common-resolvers/edit-office.resolver.ts similarity index 100% rename from src/app/organization/offices/edit-office/edit-office.resolver.ts rename to src/app/organization/offices/common-resolvers/edit-office.resolver.ts diff --git a/src/app/organization/offices/common-resolvers/office-datatable.resolver.ts b/src/app/organization/offices/common-resolvers/office-datatable.resolver.ts new file mode 100644 index 000000000..6b9b4a227 --- /dev/null +++ b/src/app/organization/offices/common-resolvers/office-datatable.resolver.ts @@ -0,0 +1,32 @@ +/** Angular Imports */ +import { Injectable } from '@angular/core'; +import { Resolve, ActivatedRouteSnapshot } from '@angular/router'; + +/** rxjs Imports */ +import { Observable } from 'rxjs'; + +/** Custom Services */ +import { OrganizationService } from '../../organization.service'; + +/** + * Office Datatable data resolver. + */ +@Injectable() +export class OfficeDatatableResolver implements Resolve { + + /** + * @param {OrganizationService} OrganizationService Organization service. + */ + constructor(private organizationService: OrganizationService) { } + + /** + * Returns the Office's Datatable data. + * @returns {Observable} + */ + resolve(route: ActivatedRouteSnapshot): Observable { + const officeId = route.parent.parent.paramMap.get('id'); + const datatableName = route.paramMap.get('datatableName'); + return this.organizationService.getOfficeDatatable(officeId, datatableName); + } + +} diff --git a/src/app/organization/offices/common-resolvers/office-datatables.resolver.ts b/src/app/organization/offices/common-resolvers/office-datatables.resolver.ts new file mode 100644 index 000000000..c05e0b1db --- /dev/null +++ b/src/app/organization/offices/common-resolvers/office-datatables.resolver.ts @@ -0,0 +1,30 @@ +/** Angular Imports */ +import { Injectable } from '@angular/core'; +import { Resolve, ActivatedRouteSnapshot } from '@angular/router'; + +/** rxjs Imports */ +import { Observable } from 'rxjs'; + +/** Custom Services */ +import { OrganizationService } from '../../organization.service'; + +/** + * Office Datatables data resolver. + */ +@Injectable() +export class OfficeDatatablesResolver implements Resolve { + + /** + * @param {organizationService} OrganizationService Organization service. + */ + constructor(private organizationService: OrganizationService) { } + + /** + * Returns the Office's Datatables data. + * @returns {Observable} + */ + resolve(): Observable { + return this.organizationService.getOfficeDatatables(); + } + +} diff --git a/src/app/organization/offices/common-resolvers/office.resolver.ts b/src/app/organization/offices/common-resolvers/office.resolver.ts new file mode 100644 index 000000000..67e9a93cc --- /dev/null +++ b/src/app/organization/offices/common-resolvers/office.resolver.ts @@ -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 { OrganizationService } from '../../organization.service'; + +/** + * Office data resolver. + */ +@Injectable() +export class OfficeResolver implements Resolve { + + /** + * @param {OrganizationService} organizationService Organization service. + */ + constructor(private organizationService: OrganizationService) {} + + /** + * Returns the office data. + * @returns {Observable} + */ + resolve(route: ActivatedRouteSnapshot): Observable { + const officeId = route.paramMap.get('id'); + return this.organizationService.getOffice(officeId); + } + +} diff --git a/src/app/organization/offices/offices.resolver.ts b/src/app/organization/offices/common-resolvers/offices.resolver.ts similarity index 90% rename from src/app/organization/offices/offices.resolver.ts rename to src/app/organization/offices/common-resolvers/offices.resolver.ts index 8438be6dc..8d0a3e6fa 100644 --- a/src/app/organization/offices/offices.resolver.ts +++ b/src/app/organization/offices/common-resolvers/offices.resolver.ts @@ -6,7 +6,7 @@ import { Resolve } from '@angular/router'; import { Observable } from 'rxjs'; /** Custom Services */ -import { OrganizationService } from '../organization.service'; +import { OrganizationService } from '../../organization.service'; /** * Manage Offices data resolver. diff --git a/src/app/organization/offices/edit-office/edit-office.component.html b/src/app/organization/offices/edit-office/edit-office.component.html index fd5da0cc1..ab456602d 100644 --- a/src/app/organization/offices/edit-office/edit-office.component.html +++ b/src/app/organization/offices/edit-office/edit-office.component.html @@ -48,7 +48,7 @@ - + diff --git a/src/app/organization/offices/offices.component.html b/src/app/organization/offices/offices.component.html index fb5b3cdfa..b04c7858f 100644 --- a/src/app/organization/offices/offices.component.html +++ b/src/app/organization/offices/offices.component.html @@ -51,7 +51,7 @@ - + diff --git a/src/app/organization/offices/view-office/datatable-tabs/datatable-tabs.component.html b/src/app/organization/offices/view-office/datatable-tabs/datatable-tabs.component.html new file mode 100644 index 000000000..ae62fb3f0 --- /dev/null +++ b/src/app/organization/offices/view-office/datatable-tabs/datatable-tabs.component.html @@ -0,0 +1,4 @@ +
+ + +
diff --git a/src/app/organization/offices/view-office/datatable-tabs/datatable-tabs.component.scss b/src/app/organization/offices/view-office/datatable-tabs/datatable-tabs.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src/app/organization/offices/view-office/datatable-tabs/datatable-tabs.component.spec.ts b/src/app/organization/offices/view-office/datatable-tabs/datatable-tabs.component.spec.ts new file mode 100644 index 000000000..0f1dfa604 --- /dev/null +++ b/src/app/organization/offices/view-office/datatable-tabs/datatable-tabs.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { DatatableTabsComponent } from './datatable-tabs.component'; + +describe('DatatableTabsComponent', () => { + let component: DatatableTabsComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ DatatableTabsComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(DatatableTabsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/organization/offices/view-office/datatable-tabs/datatable-tabs.component.ts b/src/app/organization/offices/view-office/datatable-tabs/datatable-tabs.component.ts new file mode 100644 index 000000000..06fab630d --- /dev/null +++ b/src/app/organization/offices/view-office/datatable-tabs/datatable-tabs.component.ts @@ -0,0 +1,31 @@ +/** Angular Imports */ +import { Component } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; + +/** + * Offices Datatable Tabs Component + */ +@Component({ + selector: 'mifosx-datatable-tabs', + templateUrl: './datatable-tabs.component.html', + styleUrls: ['./datatable-tabs.component.scss'] +}) +export class DatatableTabsComponent { + + /** Office Datatable */ + officeDatatable: any; + /** Multi Row Datatable Flag */ + multiRowDatatableFlag: boolean; + + /** + * Fetches data table data from `resolve` + * @param {ActivatedRoute} route Activated Route. + */ + constructor(private route: ActivatedRoute) { + this.route.data.subscribe((data: { officeDatatable: any }) => { + this.officeDatatable = data.officeDatatable; + this.multiRowDatatableFlag = this.officeDatatable.columnHeaders[0].columnName === 'id' ? true : false; + }); + } + +} diff --git a/src/app/organization/offices/view-office/datatable-tabs/multi-row/multi-row.component.html b/src/app/organization/offices/view-office/datatable-tabs/multi-row/multi-row.component.html new file mode 100644 index 000000000..c339f8643 --- /dev/null +++ b/src/app/organization/offices/view-office/datatable-tabs/multi-row/multi-row.component.html @@ -0,0 +1,33 @@ +
+ +
+
+

{{datatableName}}

+
+
+ + + + + + +
+
+ + + + + + + + + + + +
{{datatableColumn}} {{data.row[i]}}
+ +
diff --git a/src/app/organization/offices/view-office/datatable-tabs/multi-row/multi-row.component.scss b/src/app/organization/offices/view-office/datatable-tabs/multi-row/multi-row.component.scss new file mode 100644 index 000000000..6fa6a5f4e --- /dev/null +++ b/src/app/organization/offices/view-office/datatable-tabs/multi-row/multi-row.component.scss @@ -0,0 +1,10 @@ +.tab-container { + padding: 1%; + margin: 1%; + .action-button{ + margin-left: auto; + } + table { + width: 100%; + } +} diff --git a/src/app/organization/offices/view-office/datatable-tabs/multi-row/multi-row.component.spec.ts b/src/app/organization/offices/view-office/datatable-tabs/multi-row/multi-row.component.spec.ts new file mode 100644 index 000000000..dd46589d8 --- /dev/null +++ b/src/app/organization/offices/view-office/datatable-tabs/multi-row/multi-row.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MultiRowComponent } from './multi-row.component'; + +describe('MultiRowComponent', () => { + let component: MultiRowComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ MultiRowComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MultiRowComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/organization/offices/view-office/datatable-tabs/multi-row/multi-row.component.ts b/src/app/organization/offices/view-office/datatable-tabs/multi-row/multi-row.component.ts new file mode 100644 index 000000000..f103258c5 --- /dev/null +++ b/src/app/organization/offices/view-office/datatable-tabs/multi-row/multi-row.component.ts @@ -0,0 +1,184 @@ +/** Angular Imports */ +import { Component, OnChanges, OnInit, Input, ViewChild } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { MatTable } from '@angular/material/table'; +import { MatDialog } from '@angular/material'; +import { DatePipe } from '@angular/common'; + +/** Custom Dialogs */ +import { FormDialogComponent } from 'app/shared/form-dialog/form-dialog.component'; +import { DeleteDialogComponent } from 'app/shared/delete-dialog/delete-dialog.component'; + +/** Custom Models */ +import { FormfieldBase } from 'app/shared/form-dialog/formfield/model/formfield-base'; +import { InputBase } from 'app/shared/form-dialog/formfield/model/input-base'; +import { SelectBase } from 'app/shared/form-dialog/formfield/model/select-base'; +import { CheckboxBase } from 'app/shared/form-dialog/formfield/model/checkbox-base'; +import { DatepickerBase } from 'app/shared/form-dialog/formfield/model/datepicker-base'; + +/** Custom Services */ +import { OrganizationService } from '../../../../organization.service'; + +/** + * Office Multi Row Data Tables + */ +@Component({ + selector: 'mifosx-multi-row', + templateUrl: './multi-row.component.html', + styleUrls: ['./multi-row.component.scss'] +}) +export class MultiRowComponent implements OnInit, OnChanges { + + /** Data Object */ + @Input() dataObject: any; + + /** Data Table Name */ + datatableName: string; + /** Data Table Columns */ + datatableColumns: string[] = []; + /** Data Table Data */ + datatableData: any; + /** Office Id */ + officeId: string; + /** Toggle button visibility */ + showDeleteBotton: boolean; + + /** Data Table Reference */ + @ViewChild('dataTable') dataTableRef: MatTable; + + /** + * Fetches office Id from parent route params. + * @param {ActivatedRoute} route Activated Route. + * @param {DatePipe} datePipe Date Pipe. + * @param {OrganizationService} organizationService Organization Service. + * @param {MatDialog} dialog Mat Dialog. + */ + constructor(private route: ActivatedRoute, + private datePipe: DatePipe, + private organizationService: OrganizationService, + private dialog: MatDialog) { + this.officeId = this.route.parent.parent.snapshot.paramMap.get('id'); + } + + /** + * Updates related variables on changes to dataObject. + */ + ngOnChanges() { + this.datatableColumns = this.dataObject.columnHeaders.map((columnHeader: any) => { + return columnHeader.columnName; + }); + this.datatableData = this.dataObject.data; + this.showDeleteBotton = this.datatableData[0] ? true : false; + } + + /** + * Fetches data table name from route params. + * subscription is required due to asynchronicity. + */ + ngOnInit() { + this.route.params.subscribe((routeParams: any) => { + this.datatableName = routeParams.datatableName; + }); + } + + /** + * Adds a new row to the given multi row data table. + */ + add() { + let dataTableEntryObject: any = { locale: 'en' }; + const dateTransformColumns: string[] = []; + const columns = this.dataObject.columnHeaders.filter((column: any) => { + return ((column.columnName !== 'id') && (column.columnName !== 'office_id')); + }); + const formfields: FormfieldBase[] = columns.map((column: any) => { + switch (column.columnDisplayType) { + case 'INTEGER': + case 'STRING': + case 'DECIMAL': + case 'TEXT': return new InputBase({ + controlName: column.columnName, + label: column.columnName, + value: '', + type: (column.columnDisplayType === 'INTEGER' || column.columnDisplayType === 'DECIMAL') ? 'number' : 'text', + required: (column.isColumnNullable) ? false : true + }); + case 'BOOLEAN': return new CheckboxBase({ + controlName: column.columnName, + label: column.columnName, + value: '', + type: 'checkbox', + required: (column.isColumnNullable) ? false : true + }); + case 'CODELOOKUP': return new SelectBase({ + controlName: column.columnName, + label: column.columnName, + value: '', + options: { label: 'value', value: 'id', data: column.columnValues }, + required: (column.isColumnNullable) ? false : true + }); + case 'DATE': { + dateTransformColumns.push(column.columnName); + dataTableEntryObject.dateFormat = 'yyyy-MM-dd'; + return new DatepickerBase({ + controlName: column.columnName, + label: column.columnName, + value: '', + type: 'date', + required: (column.isColumnNullable) ? false : true + }); + } + case 'DATETIME': { + dateTransformColumns.push(column.columnName); + dataTableEntryObject.dateFormat = 'yyyy-MM-dd HH:mm'; + return new DatepickerBase({ + controlName: column.columnName, + label: column.columnName, + value: '', + type: 'datetime-local', + required: (column.isColumnNullable) ? false : true + }); + } + } + }); + const data = { + title: 'Add ' + this.datatableName, + formfields: formfields + }; + const addDialogRef = this.dialog.open(FormDialogComponent, { data }); + addDialogRef.afterClosed().subscribe((response: any) => { + if (response.data) { + dateTransformColumns.forEach((column) => { + response.data.value[column] = this.datePipe.transform(response.data.value[column], dataTableEntryObject.dateFormat); + }); + dataTableEntryObject = { ...response.data.value, ...dataTableEntryObject }; + this.organizationService.addOfficeDatatableEntry(this.officeId, this.datatableName, dataTableEntryObject).subscribe(() => { + this.organizationService.getOfficeDatatable(this.officeId, this.datatableName).subscribe((dataObject: any) => { + this.datatableData = dataObject.data; + this.dataTableRef.renderRows(); + }); + }); + } + }); + } + + /** + * Deletes all rows of the given multi row data table. + */ + delete() { + const deleteDataTableDialogRef = this.dialog.open(DeleteDialogComponent, { + data: { deleteContext: `the contents of ${this.datatableName}` } + }); + deleteDataTableDialogRef.afterClosed().subscribe((response: any) => { + if (response.delete) { + this.organizationService.deleteDatatableContent(this.officeId, this.datatableName).subscribe(() => { + this.organizationService.getOfficeDatatable(this.officeId, this.datatableName).subscribe((dataObject: any) => { + this.datatableData = dataObject.data; + this.showDeleteBotton = false; + this.dataTableRef.renderRows(); + }); + }); + } + }); + } + +} diff --git a/src/app/organization/offices/view-office/datatable-tabs/single-row/single-row.component.html b/src/app/organization/offices/view-office/datatable-tabs/single-row/single-row.component.html new file mode 100644 index 000000000..c2536b86a --- /dev/null +++ b/src/app/organization/offices/view-office/datatable-tabs/single-row/single-row.component.html @@ -0,0 +1,29 @@ +
+ +

{{datatableName}}

+ +
+ + + + + + + + + +
+ + + + {{columnHeader.columnName}} : {{dataObject.data[0].row[i]}} + + + +
diff --git a/src/app/organization/offices/view-office/datatable-tabs/single-row/single-row.component.scss b/src/app/organization/offices/view-office/datatable-tabs/single-row/single-row.component.scss new file mode 100644 index 000000000..63d2cfc9e --- /dev/null +++ b/src/app/organization/offices/view-office/datatable-tabs/single-row/single-row.component.scss @@ -0,0 +1,7 @@ +.tab-container { + padding: 1%; + margin: 1%; + .delete-button { + margin-left: 1%; + } +} diff --git a/src/app/organization/offices/view-office/datatable-tabs/single-row/single-row.component.spec.ts b/src/app/organization/offices/view-office/datatable-tabs/single-row/single-row.component.spec.ts new file mode 100644 index 000000000..8aece650c --- /dev/null +++ b/src/app/organization/offices/view-office/datatable-tabs/single-row/single-row.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SingleRowComponent } from './single-row.component'; + +describe('SingleRowComponent', () => { + let component: SingleRowComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ SingleRowComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SingleRowComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/organization/offices/view-office/datatable-tabs/single-row/single-row.component.ts b/src/app/organization/offices/view-office/datatable-tabs/single-row/single-row.component.ts new file mode 100644 index 000000000..55f2d11a0 --- /dev/null +++ b/src/app/organization/offices/view-office/datatable-tabs/single-row/single-row.component.ts @@ -0,0 +1,206 @@ +/** Angular Imports */ +import { Component, Input, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { MatDialog } from '@angular/material'; +import { DatePipe } from '@angular/common'; + +/** Custom Components */ +import { FormDialogComponent } from 'app/shared/form-dialog/form-dialog.component'; +import { DeleteDialogComponent } from 'app/shared/delete-dialog/delete-dialog.component'; + +/** Custom Models */ +import { FormfieldBase } from 'app/shared/form-dialog/formfield/model/formfield-base'; +import { InputBase } from 'app/shared/form-dialog/formfield/model/input-base'; +import { DatepickerBase } from 'app/shared/form-dialog/formfield/model/datepicker-base'; +import { SelectBase } from 'app/shared/form-dialog/formfield/model/select-base'; +import { CheckboxBase } from 'app/shared/form-dialog/formfield/model/checkbox-base'; + +/** Custom Services */ +import { OrganizationService } from '../../../../organization.service'; + +/** + * Offices Single Row Data Tables + */ +@Component({ + selector: 'mifosx-single-row', + templateUrl: './single-row.component.html', + styleUrls: ['./single-row.component.scss'] +}) +export class SingleRowComponent implements OnInit { + + /** Data Object */ + @Input() dataObject: any; + + /** Data Table Name */ + datatableName: string; + /** Office Id */ + officeId: string; + + /** + * Fetches office Id from parent route params. + * @param {ActivatedRoute} route Activated Route. + * @param {DatePipe} datePipe Date Pipe. + * @param {OrganizationService} organizationService Organization Service. + * @param {MatDialog} dialog Mat Dialog. + */ + constructor(private route: ActivatedRoute, + private datePipe: DatePipe, + private dialog: MatDialog, + private organizationService: OrganizationService) { + this.officeId = this.route.parent.parent.snapshot.paramMap.get('id'); + } + + /** + * Fetches data table name from route params. + * subscription is required due to asynchronicity. + */ + ngOnInit() { + this.route.params.subscribe((routeParams: any) => { + this.datatableName = routeParams.datatableName; + }); + } + + /** + * Creates a new instance of the given single row data table. + */ + add() { + let dataTableEntryObject: any = { locale: 'en' }; + const dateTransformColumns: string[] = []; + const columns = this.dataObject.columnHeaders.filter((column: any) => { + return ((column.columnName !== 'id') && (column.columnName !== 'office_id')); + }); + const formfields: FormfieldBase[] = this.getFormfields(columns, dateTransformColumns, dataTableEntryObject); + const data = { + title: 'Add ' + this.datatableName, + formfields: formfields + }; + const addDialogRef = this.dialog.open(FormDialogComponent, { data }); + addDialogRef.afterClosed().subscribe((response: any) => { + if (response.data) { + dateTransformColumns.forEach((column) => { + response.data.value[column] = this.datePipe.transform(response.data.value[column], dataTableEntryObject.dateFormat); + }); + dataTableEntryObject = { ...response.data.value, ...dataTableEntryObject }; + this.organizationService.addOfficeDatatableEntry(this.officeId, this.datatableName, dataTableEntryObject).subscribe(() => { + this.organizationService.getOfficeDatatable(this.officeId, this.datatableName).subscribe((dataObject: any) => { + this.dataObject = dataObject; + }); + }); + } + }); + } + + /** + * Edits the current instance of single row data table. + */ + edit() { + let dataTableEntryObject: any = { locale: 'en' }; + const dateTransformColumns: string[] = []; + const columns = this.dataObject.columnHeaders.filter((column: any) => { + return ((column.columnName !== 'id') && (column.columnName !== 'office_id')); + }); + let formfields: FormfieldBase[] = this.getFormfields(columns, dateTransformColumns, dataTableEntryObject); + formfields = formfields.map((formfield: FormfieldBase, index: number) => { + formfield.value = (this.dataObject.data[0].row[index + 1]) ? this.dataObject.data[0].row[index + 1] : ''; + return formfield; + }); + const data = { + title: 'Edit ' + this.datatableName, + layout: { addButtonText: 'Confirm' }, + formfields: formfields + }; + const editDialogRef = this.dialog.open(FormDialogComponent, { data }); + editDialogRef.afterClosed().subscribe((response: any) => { + if (response.data) { + dateTransformColumns.forEach((column) => { + response.data.value[column] = this.datePipe.transform(response.data.value[column], dataTableEntryObject.dateFormat); + }); + dataTableEntryObject = { ...response.data.value, ...dataTableEntryObject }; + this.organizationService.editOfficeDatatableEntry(this.officeId, this.datatableName, dataTableEntryObject).subscribe(() => { + this.organizationService.getOfficeDatatable(this.officeId, this.datatableName).subscribe((dataObject: any) => { + this.dataObject = dataObject; + }); + }); + } + }); + } + + /** + * Deletes the current instance of single row data table. + */ + delete() { + const deleteDataTableDialogRef = this.dialog.open(DeleteDialogComponent, { + data: { deleteContext: `the contents of ${this.datatableName}` } + }); + deleteDataTableDialogRef.afterClosed().subscribe((response: any) => { + if (response.delete) { + this.organizationService.deleteDatatableContent(this.officeId, this.datatableName) + .subscribe(() => { + this.organizationService.getOfficeDatatable(this.officeId, this.datatableName).subscribe((dataObject: any) => { + this.dataObject = dataObject; + }); + }); + } + }); + } + + /** + * Maps API response to data table form fields. + * @param {any} columns Data Table Columns. + * @param {string[]} dateTransformColumns Columns transformed with date pipe. + * @param {any} dataTableEntryObject Additional data table details. + */ + getFormfields(columns: any, dateTransformColumns: string[], dataTableEntryObject: any) { + return columns.map((column: any) => { + switch (column.columnDisplayType) { + case 'INTEGER': + case 'STRING': + case 'DECIMAL': + case 'TEXT': return new InputBase({ + controlName: column.columnName, + label: column.columnName, + value: '', + type: (column.columnDisplayType === 'INTEGER' || column.columnDisplayType === 'DECIMAL') ? 'number' : 'text', + required: (column.isColumnNullable) ? false : true + }); + case 'BOOLEAN': return new CheckboxBase({ + controlName: column.columnName, + label: column.columnName, + value: '', + type: 'checkbox', + required: (column.isColumnNullable) ? false : true + }); + case 'CODELOOKUP': return new SelectBase({ + controlName: column.columnName, + label: column.columnName, + value: '', + options: { label: 'value', value: 'id', data: column.columnValues }, + required: (column.isColumnNullable) ? false : true + }); + case 'DATE': { + dateTransformColumns.push(column.columnName); + dataTableEntryObject.dateFormat = 'yyyy-MM-dd'; + return new DatepickerBase({ + controlName: column.columnName, + label: column.columnName, + value: '', + type: 'date', + required: (column.isColumnNullable) ? false : true + }); + } + case 'DATETIME': { + dateTransformColumns.push(column.columnName); + dataTableEntryObject.dateFormat = 'yyyy-MM-dd HH:mm'; + return new DatepickerBase({ + controlName: column.columnName, + label: column.columnName, + value: '', + type: 'datetime-local', + required: (column.isColumnNullable) ? false : true + }); + } + } + }); + } + +} diff --git a/src/app/organization/offices/view-office/general-tab/general-tab.component.html b/src/app/organization/offices/view-office/general-tab/general-tab.component.html new file mode 100644 index 000000000..fcfe1bf80 --- /dev/null +++ b/src/app/organization/offices/view-office/general-tab/general-tab.component.html @@ -0,0 +1,23 @@ +
+ + + + + Parent Office : {{ officeData.parentName ? officeData.parentName : 'N/A' }} + + + + Opened On : {{ officeData.openingDate ? (officeData.openingDate | date) : 'Unassigned' }} + + + + Name Decorated : {{ officeData.nameDecorated ? officeData.nameDecorated : 'Unassigned' }} + + + + External Id : {{ officeData.externalId ? officeData.externalId : 'Unassigned' }} + + + + +
diff --git a/src/app/organization/offices/view-office/general-tab/general-tab.component.scss b/src/app/organization/offices/view-office/general-tab/general-tab.component.scss new file mode 100644 index 000000000..b40728956 --- /dev/null +++ b/src/app/organization/offices/view-office/general-tab/general-tab.component.scss @@ -0,0 +1,4 @@ +.tab-container { + padding: 1%; + margin: 1%; +} diff --git a/src/app/organization/offices/view-office/general-tab/general-tab.component.spec.ts b/src/app/organization/offices/view-office/general-tab/general-tab.component.spec.ts new file mode 100644 index 000000000..68ff6503e --- /dev/null +++ b/src/app/organization/offices/view-office/general-tab/general-tab.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { GeneralTabComponent } from './general-tab.component'; + +describe('GeneralTabComponent', () => { + let component: GeneralTabComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ GeneralTabComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(GeneralTabComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/organization/offices/view-office/general-tab/general-tab.component.ts b/src/app/organization/offices/view-office/general-tab/general-tab.component.ts new file mode 100644 index 000000000..4738d4fb6 --- /dev/null +++ b/src/app/organization/offices/view-office/general-tab/general-tab.component.ts @@ -0,0 +1,28 @@ +/** Angular Imports */ +import { Component } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; + +/** + * Office View General Tab + */ +@Component({ + selector: 'mifosx-general-tab', + templateUrl: './general-tab.component.html', + styleUrls: ['./general-tab.component.scss'] +}) +export class GeneralTabComponent { + + /** Office data */ + officeData: any; + + /** + * Fetches office data from `resolve` + * @param {ActivatedRoute} route Activated Route + */ + constructor(private route: ActivatedRoute) { + this.route.parent.data.subscribe((data: { office: any }) => { + this.officeData = data.office; + }); + } + +} diff --git a/src/app/organization/offices/view-office/view-office.component.html b/src/app/organization/offices/view-office/view-office.component.html new file mode 100644 index 000000000..de4df4cf1 --- /dev/null +++ b/src/app/organization/offices/view-office/view-office.component.html @@ -0,0 +1,35 @@ +
+ +
+ + + +
+ + + + + + + + + + + + + +
diff --git a/src/app/organization/offices/view-office/view-office.component.scss b/src/app/organization/offices/view-office/view-office.component.scss new file mode 100644 index 000000000..a179edb6d --- /dev/null +++ b/src/app/organization/offices/view-office/view-office.component.scss @@ -0,0 +1,11 @@ +.action-button{ + width: 95%; +} +.office-card { + margin: 0 auto; + width: 90%; + padding: 0; + .navigation-tabs { + overflow: auto; + } +} diff --git a/src/app/organization/offices/view-office/view-office.component.spec.ts b/src/app/organization/offices/view-office/view-office.component.spec.ts new file mode 100644 index 000000000..1003f346b --- /dev/null +++ b/src/app/organization/offices/view-office/view-office.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ViewOfficeComponent } from './view-office.component'; + +describe('ViewOfficeComponent', () => { + let component: ViewOfficeComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ ViewOfficeComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(ViewOfficeComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/organization/offices/view-office/view-office.component.ts b/src/app/organization/offices/view-office/view-office.component.ts new file mode 100644 index 000000000..76c272d71 --- /dev/null +++ b/src/app/organization/offices/view-office/view-office.component.ts @@ -0,0 +1,28 @@ +/** Angular Imports */ +import { Component } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; + +/** + * View Office Component + */ +@Component({ + selector: 'mifosx-view-office', + templateUrl: './view-office.component.html', + styleUrls: ['./view-office.component.scss'] +}) +export class ViewOfficeComponent { + + /** Office datatables data */ + officeDatatables: any; + + /** + * Fetches office datatables from `resolve` + * @param {ActivatedRoute} route Activated Route + */ + constructor(private route: ActivatedRoute) { + this.route.data.subscribe((data: { officeDatatables: any }) => { + this.officeDatatables = data.officeDatatables; + }); + } + +} diff --git a/src/app/organization/organization-routing.module.ts b/src/app/organization/organization-routing.module.ts index f6c3e2962..cf195d811 100644 --- a/src/app/organization/organization-routing.module.ts +++ b/src/app/organization/organization-routing.module.ts @@ -35,10 +35,13 @@ import { CreateTellerComponent } from './tellers/create-teller/create-teller.com import { EditTellerComponent } from './tellers/edit-teller/edit-teller.component'; import { ViewCashierComponent } from './tellers/view-cashier/view-cashier.component'; import { ViewHolidaysComponent } from './holidays/view-holidays/view-holidays.component'; +import { ViewOfficeComponent } from './offices/view-office/view-office.component'; +import { GeneralTabComponent } from './offices/view-office/general-tab/general-tab.component'; +import { DatatableTabsComponent } from './offices/view-office/datatable-tabs/datatable-tabs.component'; /** Custom Resolvers */ import { LoanProvisioningCriteriaResolver } from './loan-provisioning-criteria/loan-provisioning-criteria.resolver'; -import { OfficesResolver } from './offices/offices.resolver'; +import { OfficesResolver } from './offices/common-resolvers/offices.resolver'; import { EmployeesResolver } from './employees/employees.resolver'; import { EmployeeResolver } from './employees/employee.resolver'; import { EditEmployeeResolver } from './employees/edit-employee.resolver'; @@ -53,13 +56,16 @@ import { PaymentTypeResolver } from './payment-types/payment-type.resolver'; import { PasswordPreferencesTemplateResolver } from './password-preferences/password-preferences-template.resolver'; import { EntityDataTableChecksResolver } from './entity-data-table-checks/entity-data-table-checks.resolver'; import { WorkingDaysResolver } from './working-days/working-days.resolver'; -import { EditOfficeResolver } from './offices/edit-office/edit-office.resolver'; +import { EditOfficeResolver } from './offices/common-resolvers/edit-office.resolver'; import { EditOfficeComponent } from './offices/edit-office/edit-office.component'; import { AdhocQueryTemplateResolver } from './adhoc-query/adhoc-query-template.resolver'; import { ViewLoanProvisioningCriteriaComponent } from './loan-provisioning-criteria/view-loan-provisioning-criteria/view-loan-provisioning-criteria.component'; import { LoanProvisioningCriteriasResolver } from './loan-provisioning-criteria/loan-provisioning-criterias.resolver'; import { CashierResolver } from './tellers/cashier.resolver'; import { HolidayResolver } from './holidays/holiday.resolver'; +import { OfficeResolver } from './offices/common-resolvers/office.resolver'; +import { OfficeDatatableResolver } from './offices/common-resolvers/office-datatable.resolver'; +import { OfficeDatatablesResolver } from './offices/common-resolvers/office-datatables.resolver'; /** Organization Routes */ const routes: Routes = [ @@ -118,6 +124,35 @@ const routes: Routes = [ offices: OfficesResolver, } }, + { + path: ':id', + data: { title: extract('View Office'), routeResolveBreadcrumb: ['office', 'name'] }, + component: ViewOfficeComponent, + resolve: { + officeDatatables: OfficeDatatablesResolver, + office: OfficeResolver + }, + children: [ + { + path: 'general', + component: GeneralTabComponent, + data: { title: extract('General') }, + }, + { + path: 'datatables', + children: [ + { + path: ':datatableName', + component: DatatableTabsComponent, + data: { title: extract('View Data Table') }, + resolve: { + officeDatatable: OfficeDatatableResolver + } + } + ] + } + ] + }, { path: ':id', data: { title: extract('View Office'), routeParamBreadcrumb: 'id' }, @@ -132,6 +167,7 @@ const routes: Routes = [ } ] } + ] }, { @@ -398,7 +434,10 @@ const routes: Routes = [ AdhocQueryTemplateResolver, LoanProvisioningCriteriasResolver, CashierResolver, - HolidayResolver + HolidayResolver, + OfficeResolver, + OfficeDatatableResolver, + OfficeDatatablesResolver ] }) export class OrganizationRoutingModule { } diff --git a/src/app/organization/organization.module.ts b/src/app/organization/organization.module.ts index 77c8647ab..8ce02a66a 100644 --- a/src/app/organization/organization.module.ts +++ b/src/app/organization/organization.module.ts @@ -5,6 +5,7 @@ import { NgModule } from '@angular/core'; import { SharedModule } from '../shared/shared.module'; import { OrganizationRoutingModule } from './organization-routing.module'; import { PipesModule } from 'app/pipes/pipes.module'; +import { DirectivesModule } from 'app/directives/directives.module'; /** Custom Components */ import { OrganizationComponent } from './organization.component'; @@ -35,6 +36,11 @@ import { EditTellerComponent } from './tellers/edit-teller/edit-teller.component import { ViewLoanProvisioningCriteriaComponent } from './loan-provisioning-criteria/view-loan-provisioning-criteria/view-loan-provisioning-criteria.component'; import { ViewCashierComponent } from './tellers/view-cashier/view-cashier.component'; import { ViewHolidaysComponent } from './holidays/view-holidays/view-holidays.component'; +import { ViewOfficeComponent } from './offices/view-office/view-office.component'; +import { GeneralTabComponent } from './offices/view-office/general-tab/general-tab.component'; +import { DatatableTabsComponent } from './offices/view-office/datatable-tabs/datatable-tabs.component'; +import { SingleRowComponent } from './offices/view-office/datatable-tabs/single-row/single-row.component'; +import { MultiRowComponent } from './offices/view-office/datatable-tabs/multi-row/multi-row.component'; /** * Organization Module @@ -44,8 +50,9 @@ import { ViewHolidaysComponent } from './holidays/view-holidays/view-holidays.co @NgModule({ imports: [ SharedModule, - OrganizationRoutingModule, - PipesModule + PipesModule, + DirectivesModule, + OrganizationRoutingModule ], declarations: [ OrganizationComponent, @@ -75,7 +82,12 @@ import { ViewHolidaysComponent } from './holidays/view-holidays/view-holidays.co EditTellerComponent, ViewLoanProvisioningCriteriaComponent, ViewCashierComponent, - ViewHolidaysComponent + ViewHolidaysComponent, + ViewOfficeComponent, + GeneralTabComponent, + DatatableTabsComponent, + SingleRowComponent, + MultiRowComponent ] }) export class OrganizationModule { } diff --git a/src/app/organization/organization.service.ts b/src/app/organization/organization.service.ts index cbda67e77..170c73d0d 100644 --- a/src/app/organization/organization.service.ts +++ b/src/app/organization/organization.service.ts @@ -83,6 +83,56 @@ export class OrganizationService { return this.http.put(`/offices/${officeId}`, office); } + /** + * @returns {Observable} + */ + getOfficeDatatables(): Observable { + const httpParams = new HttpParams().set('apptable', 'm_office'); + return this.http.get(`/datatables`, { params: httpParams }); + } + + /** + * @param officeId Office Id of office to get datatable for. + * @param datatableName Data table name. + * @returns {Observable} + */ + getOfficeDatatable(officeId: string, datatableName: string): Observable { + const httpParams = new HttpParams().set('genericResultSet', 'true'); + return this.http.get(`/datatables/${datatableName}/${officeId}`, { params: httpParams }); + } + + /** + * @param officeId Office Id of office to get add datatable entry for. + * @param datatableName Data Table name. + * @param data Data. + * @returns {Observable} + */ + addOfficeDatatableEntry(officeId: string, datatableName: string, data: any): Observable { + const httpParams = new HttpParams().set('genericResultSet', 'true'); + return this.http.post(`/datatables/${datatableName}/${officeId}`, data, { params: httpParams }); + } + + /** + * @param officeId Office Id of office to get add datatable entry for. + * @param datatableName Data Table name. + * @param data Data. + * @returns {Observable} + */ + editOfficeDatatableEntry(officeId: string, datatableName: string, data: any): Observable { + const httpParams = new HttpParams().set('genericResultSet', 'true'); + return this.http.put(`/datatables/${datatableName}/${officeId}`, data, { params: httpParams }); + } + + /** + * @param officeId Office Id of office to get add datatable entry for. + * @param datatableName Data Table name. + * @returns {Observable} + */ + deleteDatatableContent(officeId: string, datatableName: string): Observable { + const httpParams = new HttpParams().set('genericResultSet', 'true'); + return this.http.delete(`/datatables/${datatableName}/${officeId}`, { params: httpParams }); + } + /** * @returns {Observable} Employees data */