diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 2fe798bc4..cd3e0c9fd 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -36,6 +36,7 @@ import { ProductsModule } from './products/products.module'; import { OrganizationModule } from './organization/organization.module'; import { TemplatesModule } from './templates/templates.module'; import { UsersModule } from './users/users.module'; +import { ReportsModule } from './reports/reports.module'; @@ -61,6 +62,7 @@ import { AppRoutingModule } from './app-routing.module'; SettingsModule, NavigationModule, ClientsModule, + ReportsModule, GroupsModule, CentersModule, AccountingModule, diff --git a/src/app/core/shell/toolbar/toolbar.component.html b/src/app/core/shell/toolbar/toolbar.component.html index 1366df12c..1075713ad 100644 --- a/src/app/core/shell/toolbar/toolbar.component.html +++ b/src/app/core/shell/toolbar/toolbar.component.html @@ -90,12 +90,12 @@ - - - - - - + + + + + + diff --git a/src/app/reports/reports-routing.module.ts b/src/app/reports/reports-routing.module.ts new file mode 100644 index 000000000..e88e69c72 --- /dev/null +++ b/src/app/reports/reports-routing.module.ts @@ -0,0 +1,53 @@ +/** Angular Imports */ +import { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; + +/** Routing Imports */ +import { Route } from '../core/route/route.service'; + +/** Translation Imports */ +import { extract } from '../core/i18n/i18n.service'; + +/** Custom Components */ +import { ReportsComponent } from './reports.component'; + +/** Custom Resolvers */ +import { ReportsResolver } from './reports.resolver'; + +/** Reports Routes */ +const routes: Routes = [ + Route.withShell([ + { + path: 'reports', + data: { title: extract('Reports'), breadcrumb: 'Reports' }, + resolve: { + reports: ReportsResolver + }, + children: [ + { + path: '', + component: ReportsComponent, + }, + { + path: ':filter', + data: { routeParamBreadcrumb: 'filter' }, + component: ReportsComponent, + } + ] + } + ]) +]; + +/** + * Reports Routing Module + * + * Configures the reports routes. + */ +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule], + providers: [ + ReportsResolver + ] +}) +export class ReportsRoutingModule { } diff --git a/src/app/reports/reports.component.html b/src/app/reports/reports.component.html new file mode 100644 index 000000000..616b2e6ef --- /dev/null +++ b/src/app/reports/reports.component.html @@ -0,0 +1,39 @@ +
+ +
+ + Filter + + +
+ +
+ + + + + + + + + + + + + + + + + + + + + + +
Name {{ report.reportName }} Type {{ report.reportType }} Category {{ report.reportCategory }}
+ + + +
+ +
diff --git a/src/app/reports/reports.component.scss b/src/app/reports/reports.component.scss new file mode 100644 index 000000000..24edb63bb --- /dev/null +++ b/src/app/reports/reports.component.scss @@ -0,0 +1,7 @@ +table { + width: 100%; + + .select-row:hover { + cursor: pointer; + } +} diff --git a/src/app/reports/reports.component.ts b/src/app/reports/reports.component.ts new file mode 100644 index 000000000..dc5653f20 --- /dev/null +++ b/src/app/reports/reports.component.ts @@ -0,0 +1,108 @@ +/** Angular Imports */ +import { Component, OnInit, ViewChild } from '@angular/core'; +import {MatPaginator, MatSort, MatTableDataSource} from '@angular/material'; +import { ActivatedRoute, Router } from '@angular/router'; + +/** + * Reports component. + */ +@Component({ + selector: 'mifosx-reports', + templateUrl: './reports.component.html', + styleUrls: ['./reports.component.scss'] +}) +export class ReportsComponent implements OnInit { + + /** Reports data. */ + reportsData: any; + /** Report category filter. */ + filter: string; + /** Columns to be displayed in reports table. */ + displayedColumns: string[] = ['reportName', 'reportType', 'reportCategory']; + /** Data source for reports table. */ + dataSource = new MatTableDataSource(); + + /** Paginator for reports table. */ + @ViewChild(MatPaginator) paginator: MatPaginator; + /** Sorter for reports table. */ + @ViewChild(MatSort) sort: MatSort; + + /** + * Retrieves the reports data from `resolve`. + * @param {ActivatedRoute} route Activated Route. + * Prevents reuse of route parameter `filter`. + * @param {Router} router: Router. + */ + constructor(private route: ActivatedRoute, + private router: Router) { + this.router.routeReuseStrategy.shouldReuseRoute = () => false; + this.route.data.subscribe(( data: { reports: any }) => { + this.reportsData = data.reports; + }); + this.filter = this.route.snapshot.params['filter']; + } + + /* + *Sets and filters the reports table by category. + */ + ngOnInit() { + this.setReports(); + this.filterReportsByCategory(); + } + + /** + * Switches filterPredicate if filterValue is not null. + * @param {string} filterValue filter string for mat-table. + */ + applyFilter(filterValue: string) { + if (filterValue.length) { + this.setCustomFilterPredicate(); + this.dataSource.filter = filterValue.trim().toLowerCase(); + } else { + this.filterReportsByCategory(); + } + } + + /** + * Initializes the data source, paginator and sorter for reports table. + */ + setReports() { + this.dataSource = new MatTableDataSource(this.reportsData); + this.dataSource.paginator = this.paginator; + this.dataSource.sort = this.sort; + } + + /** + * Filters the data source only for report category passed in route params. + */ + filterReportsByCategory() { + this.dataSource.filterPredicate = (data: any, filter: string) => { + return data.reportCategory === filter; + }; + this.dataSource.filter = this.filter; + } + + /** + * Filters Reports for filter value string and report category. + */ + setCustomFilterPredicate() { + this.dataSource.filterPredicate = (data: any, filter: string) => { + /** Transform the data into a lowercase string of all property values. */ + const dataStr = Object.keys(data).reduce(function (currentTerm: string, key: string) { + /** Use an obscure Unicode character to delimit the words in the concatenated string. + * This avoids matches where the values of two columns combined will match the user's query + */ + return currentTerm + ((/** @type {any} */ (data)))[key] + '◬'; + }, '').toLowerCase(); + /** Transform the filter by converting it to lowercase and removing whitespace. */ + const transformedFilter = filter.trim().toLowerCase(); + /* Seperates filter for All reports page.*/ + if (this.filter) { + return dataStr.indexOf(transformedFilter) !== -1 && data.reportCategory === this.filter; + } else { + return dataStr.indexOf(transformedFilter) !== -1; + } + }; + } + +} diff --git a/src/app/reports/reports.module.ts b/src/app/reports/reports.module.ts new file mode 100644 index 000000000..d4a27bc81 --- /dev/null +++ b/src/app/reports/reports.module.ts @@ -0,0 +1,23 @@ +/** Angular Imports */ +import { NgModule } from '@angular/core'; + +/** Custom Modules */ +import { SharedModule } from '../shared/shared.module'; +import { ReportsRoutingModule } from 'app/reports/reports-routing.module'; + +/** Custom Components */ +import { ReportsComponent } from './reports.component'; + +/** + * Reports Module + * + * Reports components should be declared here. + */ +@NgModule({ + imports: [ + SharedModule, + ReportsRoutingModule + ], + declarations: [ReportsComponent], +}) +export class ReportsModule { } diff --git a/src/app/reports/reports.resolver.ts b/src/app/reports/reports.resolver.ts new file mode 100644 index 000000000..05cf70c27 --- /dev/null +++ b/src/app/reports/reports.resolver.ts @@ -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 { ReportsService } from './reports.service'; + +/** + * Reports data resolver. + */ +@Injectable() +export class ReportsResolver implements Resolve { + + /** + * @param {ReportsService} reportsService Reports service. + */ + constructor(private reportsService: ReportsService) {} + + /** + * Returns the reports data. + * @returns {Observable} + */ + resolve(): Observable { + return this.reportsService.getReports(); + } + +} diff --git a/src/app/reports/reports.service.ts b/src/app/reports/reports.service.ts new file mode 100644 index 000000000..b3acea4f2 --- /dev/null +++ b/src/app/reports/reports.service.ts @@ -0,0 +1,28 @@ +/** Angular Imports */ +import { Injectable } from '@angular/core'; +import { HttpClient, HttpParams } from '@angular/common/http'; + +/** rxjs Imports */ +import { Observable } from 'rxjs'; + +/** + * Reports service. + */ +@Injectable({ + providedIn: 'root' +}) +export class ReportsService { + + /** + * @param {HttpClient} http Http Client to send requests. + */ + constructor(private http: HttpClient) { } + + /** + * @returns {Observable} Reports data + */ + getReports(): Observable { + return this.http.get('/reports'); + } + +}