feat: add reports list page (#561)

Fixes: #232
This commit is contained in:
Karan Takalkar
2020-04-27 02:08:28 +05:30
committed by GitHub
parent ee4329ed21
commit 9ab6481406
9 changed files with 296 additions and 6 deletions
+2
View File
@@ -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,
@@ -90,12 +90,12 @@
<!-- Toolbar Menus -->
<mat-menu #reportsMenu="matMenu" [overlapTrigger]="false">
<button mat-menu-item>All</button>
<button mat-menu-item>Clients</button>
<button mat-menu-item>Loans</button>
<button mat-menu-item>Savings</button>
<button mat-menu-item>Funds</button>
<button mat-menu-item>Accounting</button>
<button mat-menu-item [routerLink]="['/reports']">All</button>
<button mat-menu-item [routerLink]="['/reports', 'Client']">Clients</button>
<button mat-menu-item [routerLink]="['/reports', 'Loan']">Loans</button>
<button mat-menu-item [routerLink]="['/reports', 'Savings']">Savings</button>
<button mat-menu-item [routerLink]="['/reports', 'Fund']">Funds</button>
<button mat-menu-item [routerLink]="['/reports', 'Accounting']">Accounting</button>
<button mat-menu-item>XBRL</button>
</mat-menu>
+53
View File
@@ -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 { }
+39
View File
@@ -0,0 +1,39 @@
<div class="container">
<div fxLayout="row" fxLayoutGap="20px">
<mat-form-field fxFlex>
<mat-label>Filter</mat-label>
<input matInput (keyup)="applyFilter($event.target.value)">
</mat-form-field>
</div>
<div class="mat-elevation-z8">
<table mat-table [dataSource]="dataSource" matSort>
<ng-container matColumnDef="reportName">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
<td mat-cell *matCellDef="let report"> {{ report.reportName }} </td>
</ng-container>
<ng-container matColumnDef="reportType">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Type </th>
<td mat-cell *matCellDef="let report"> {{ report.reportType }} </td>
</ng-container>
<ng-container matColumnDef="reportCategory">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Category </th>
<td mat-cell *matCellDef="let report"> {{ report.reportCategory }} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;" class="select-row"></tr>
</table>
<mat-paginator [pageSizeOptions]="[10, 25, 50, 100]" showFirstLastButtons></mat-paginator>
</div>
</div>
+7
View File
@@ -0,0 +1,7 @@
table {
width: 100%;
.select-row:hover {
cursor: pointer;
}
}
+108
View File
@@ -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;
}
};
}
}
+23
View File
@@ -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 { }
+30
View File
@@ -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<Object> {
/**
* @param {ReportsService} reportsService Reports service.
*/
constructor(private reportsService: ReportsService) {}
/**
* Returns the reports data.
* @returns {Observable<any>}
*/
resolve(): Observable<any> {
return this.reportsService.getReports();
}
}
+28
View File
@@ -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<any>} Reports data
*/
getReports(): Observable<any> {
return this.http.get('/reports');
}
}