From bbbe772515d7d1c01ee17164cf64cfd22f0d61b0 Mon Sep 17 00:00:00 2001 From: abhay_1806 Date: Thu, 26 Jul 2018 14:09:41 +0530 Subject: [PATCH] feat: add custom data source Add custom data source to implement server side pagination, sorting and filtering. --- src/app/accounting/accounting.service.ts | 20 +++- .../journal-entry.datasource.ts | 36 +++++++ .../search-journal-entry.component.html | 25 ++--- .../search-journal-entry.component.ts | 93 +++++++++++++------ 4 files changed, 128 insertions(+), 46 deletions(-) create mode 100644 src/app/accounting/search-journal-entry/journal-entry.datasource.ts diff --git a/src/app/accounting/accounting.service.ts b/src/app/accounting/accounting.service.ts index 1a0de68f3..09c40f7be 100644 --- a/src/app/accounting/accounting.service.ts +++ b/src/app/accounting/accounting.service.ts @@ -36,8 +36,24 @@ export class AccountingService { return this.http.get(`/journalentries`, { params: httpParams }); } - getJournalEntries() { - return this.http.get('/journalentries'); + // filterBy: officeId, glAccountId, manualEntriesOnly, fromDate, toDate, transactionId + getJournalEntries(filterBy: any, orderBy: any, sortBy: any, offset: number, limit: number) { + console.log('Order By:', orderBy); + console.log('Sort By:', sortBy); + console.log('Filter By:', filterBy); + let httpParams = new HttpParams() + .set('offset', offset.toString()) + .set('limit', limit.toString()) + .set('sortBy', sortBy) + .set('orderBy', orderBy); + filterBy.forEach(function (filter: any) { + if(filter.value) { + httpParams = httpParams.set(filter.type, filter.value); + } + }); + return this.http.get('/journalentries', { + params: httpParams + }); } revertTransaction(transactionId: string, comments: string) { diff --git a/src/app/accounting/search-journal-entry/journal-entry.datasource.ts b/src/app/accounting/search-journal-entry/journal-entry.datasource.ts new file mode 100644 index 000000000..88efd420a --- /dev/null +++ b/src/app/accounting/search-journal-entry/journal-entry.datasource.ts @@ -0,0 +1,36 @@ +import { CollectionViewer, DataSource } from "@angular/cdk/collections"; + +import { Observable, BehaviorSubject } from "rxjs"; + +import { AccountingService } from "../accounting.service"; + +export class JournalEntriesDataSource implements DataSource { + + private journalEntriesSubject = new BehaviorSubject([]); + private recordsSubject = new BehaviorSubject(0); + + public records$ = this.recordsSubject.asObservable(); + + constructor(private accountingService: AccountingService) { } + + loadJournalEntries(filterBy: any, orderBy = '', sortBy = '', offset = 0, limit = 10) { + this.journalEntriesSubject.next([]); + orderBy = (orderBy === 'debit' || orderBy === 'credit') ? 'amount' : orderBy; + this.accountingService.getJournalEntries(filterBy, orderBy, sortBy, offset, limit) + .subscribe((journalEntries: any) => { + console.log(journalEntries); + this.recordsSubject.next(journalEntries.totalFilteredRecords); + this.journalEntriesSubject.next(journalEntries.pageItems); + }); + } + + connect(collectionViewer: CollectionViewer): Observable { + return this.journalEntriesSubject.asObservable(); + } + + disconnect(collectionViewer: CollectionViewer): void { + this.journalEntriesSubject.complete(); + this.recordsSubject.complete(); + } + +} diff --git a/src/app/accounting/search-journal-entry/search-journal-entry.component.html b/src/app/accounting/search-journal-entry/search-journal-entry.component.html index 06a365f82..b635b371a 100644 --- a/src/app/accounting/search-journal-entry/search-journal-entry.component.html +++ b/src/app/accounting/search-journal-entry/search-journal-entry.component.html @@ -1,20 +1,20 @@
- - + + {{ office.name }} - - - {{ affectedGLEntryDebit.name + ' (' + affectedGLEntryDebit.glCode + ')' }} + + + {{ affectedGLEntry.name + ' (' + affectedGLEntry.glCode + ')' }} - + {{ filter.option }} @@ -33,13 +33,6 @@ -
@@ -67,12 +60,12 @@ - Type + Type {{ transaction.glAccountType.value }} - Created by + Created by {{ transaction.createdByUserName }} @@ -101,6 +94,6 @@ - +
diff --git a/src/app/accounting/search-journal-entry/search-journal-entry.component.ts b/src/app/accounting/search-journal-entry/search-journal-entry.component.ts index a5eef7def..f8a710927 100644 --- a/src/app/accounting/search-journal-entry/search-journal-entry.component.ts +++ b/src/app/accounting/search-journal-entry/search-journal-entry.component.ts @@ -1,9 +1,13 @@ import { Component, OnInit, ViewChild } from '@angular/core'; -import { MatPaginator, MatSort, MatTableDataSource } from '@angular/material'; +import { MatPaginator, MatSort } from '@angular/material'; import { FormControl } from '@angular/forms'; import { Router } from '@angular/router'; +import { merge } from 'rxjs'; +import { tap} from 'rxjs/operators'; + import { AccountingService } from '../accounting.service'; +import { JournalEntriesDataSource } from './journal-entry.datasource'; @Component({ selector: 'mifosx-search-journal-entry', @@ -12,13 +16,14 @@ import { AccountingService } from '../accounting.service'; }) export class SearchJournalEntryComponent implements OnInit { + // TODO: Update when date and language are set up throughout the application + minDate = new Date(2000, 0, 1); + maxDate = new Date(); officeName = new FormControl(); glAccountCode = new FormControl(); transactionDateFrom = new FormControl(new Date(2000, 0, 1)); transactionDateTo = new FormControl(new Date()); transactionId = new FormControl(); - minDate = new Date(2000, 0, 1); - maxDate = new Date(); filter = new FormControl(''); displayedColumns: string[] = ['id', 'officeName', 'transactionId', 'transactionDate', 'glAccountType', 'createdByUserName', 'glAccountCode', 'glAccountName', 'debit', 'credit']; dataSource: any; @@ -35,13 +40,46 @@ export class SearchJournalEntryComponent implements OnInit { }, { option: 'System Entries', - value: false + value: false // Bug: unable to implement from server side + } + ]; + filterBy = [ + { + type: 'officeId', + value: '' + }, + { + type: 'glAccountId', + value: '' + }, + { + type: 'manualEntriesOnly', + value: '' + }, + { + type: 'transactionId', + value: '' + }, + { + type: 'fromDate', + value: '1 July 2018' + }, + { + type: 'toDate', + value: '31 July 2018' + }, + { + type: 'dateFormat', + value: 'dd MMMM yyyy' + }, + { + type: 'locale', + value: 'en' } ]; - filterValue: any = { officeName: '', glAccountCode: '', filter: '', transactionId: '' }; @ViewChild(MatPaginator) paginator: MatPaginator; - @ViewChild(MatSort) sort: MatSort; + @ViewChild(MatSort) sort: MatSort; // Bug: Unable to implement desc order sorting constructor(private accountingService: AccountingService, private router: Router) { } @@ -52,33 +90,32 @@ export class SearchJournalEntryComponent implements OnInit { this.getJournalEntries(); } - getJournalEntries() { - this.accountingService.getJournalEntries().subscribe((journalEntryData: any) => { - this.dataSource = new MatTableDataSource(journalEntryData.pageItems); - this.dataSource.paginator = this.paginator; - this.dataSource.sortingDataAccessor = (transaction: any, property: any) => { - switch (property) { - case 'glAccountType': return transaction.glAccountType.value; - case 'debit': return transaction.amount; - case 'credit': return transaction.amount; - default: return transaction[property]; - } - }; - this.dataSource.sort = this.sort; - this.dataSource.filterPredicate = this.filterPredicate; - }); + ngAfterViewInit() { + this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0); + merge(this.sort.sortChange, this.paginator.page) + .pipe( + tap(() => this.loadJournalEntriesPage()) + ) + .subscribe(); } - filterPredicate(data: any, filterValue: string) { - return data.officeName.indexOf(filterValue['officeName']) != -1 - && data.glAccountCode.indexOf(filterValue['glAccountCode']) != -1 - && data.manualEntry.toString().indexOf(filterValue['filter']) != -1 - && data.transactionId.indexOf(filterValue['transactionId']) != -1; + getJournalEntries() { + this.dataSource = new JournalEntriesDataSource(this.accountingService); + this.dataSource.loadJournalEntries(this.filterBy, this.sort.active, this.sort.direction, this.paginator.pageIndex, this.paginator.pageSize); + } + + loadJournalEntriesPage() { + if(!this.sort.direction) { + delete this.sort.active; + } + this.dataSource.loadJournalEntries(this.filterBy, this.sort.active, this.sort.direction, this.paginator.pageIndex * this.paginator.pageSize, this.paginator.pageSize); } applyFilter(filterValue: string, property: string) { - this.filterValue[property] = filterValue; - this.dataSource.filter = this.filterValue; + this.paginator.pageIndex = 0; + let findIndex = this.filterBy.findIndex(filter => filter.type === property); + this.filterBy[findIndex].value = filterValue; + this.loadJournalEntriesPage(); } getOffices() {