FINERACT-1724: Server-side pagination support for clients screen
This commit is contained in:
committed by
Arnold Gálovics
parent
517584280f
commit
aa438ed4b2
+1
-1
@@ -102,7 +102,7 @@
|
||||
"vendorChunk": false
|
||||
},
|
||||
"development": {
|
||||
"optimization": true,
|
||||
"optimization": false,
|
||||
"sourceMap": true,
|
||||
"namedChunks": true,
|
||||
"outputHashing": "all",
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
"build": "npm run env -s && ng build --prod --output-hashing=none",
|
||||
"build:prod": "node --max-old-space-size=16384 ./node_modules/@angular/cli/bin/ng build --prod --output-hashing=none --base-href=/web-app/",
|
||||
"start": "npm run env -s && ng serve --aot --proxy-config proxy.conf.js",
|
||||
"serve:dev": "npm run env -s && ng serve",
|
||||
"serve:sw": "npm run build -s && npx http-server ./dist -p 4200",
|
||||
"lint": "ng lint && stylelint \"src/**/*.scss\" --syntax scss && htmlhint \"src\" --config .htmlhintrc",
|
||||
"test": "npm run env -s && ng test",
|
||||
|
||||
@@ -6,9 +6,6 @@
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<div class="filter-box" *ngIf="existsClientsToFilter">
|
||||
<mat-form-field class="filter-box m-r-30">
|
||||
<input matInput placeholder="Filter by client name or external Id" class="filter-box" (keyup)="applyFilter($event.target.value)">
|
||||
</mat-form-field>
|
||||
<mat-checkbox #showClosedAccounts labelPosition="after" class="m-r-10">Show Closed Accounts
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
@@ -23,25 +20,26 @@
|
||||
</div>
|
||||
|
||||
<div [hidden]="!existsClientsToFilter">
|
||||
<table mat-table [dataSource]="dataSource" matSort>
|
||||
<mat-progress-bar mode="indeterminate" *ngIf="isLoading"></mat-progress-bar>
|
||||
<table mat-table [dataSource]="dataSource" matSort (matSortChange)="sortChanged($event)">
|
||||
|
||||
<!-- Name Column -->
|
||||
<ng-container matColumnDef="entityName">
|
||||
<ng-container matColumnDef="displayName">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
|
||||
<td mat-cell *matCellDef="let row"> {{row.entityName}} </td>
|
||||
<td mat-cell *matCellDef="let row"> {{row.displayName}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Account no Column -->
|
||||
<ng-container matColumnDef="entityAccountNo">
|
||||
<ng-container matColumnDef="accountNumber">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Account No. </th>
|
||||
<td mat-cell *matCellDef="let row"> {{row.entityAccountNo}} </td>
|
||||
<td mat-cell *matCellDef="let row"> {{row.accountNumber}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- External ID Column -->
|
||||
<ng-container matColumnDef="entityExternalId">
|
||||
<ng-container matColumnDef="externalId">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> External Id </th>
|
||||
<td mat-cell *matCellDef="let row">
|
||||
<mifosx-external-identifier externalId="{{row.entityExternalId}}"></mifosx-external-identifier>
|
||||
<mifosx-external-identifier externalId="{{row.externalId}}"></mifosx-external-identifier>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
@@ -49,33 +47,27 @@
|
||||
<ng-container matColumnDef="status">
|
||||
<th mat-header-cell *matHeaderCellDef> Status </th>
|
||||
<td mat-cell *matCellDef="let row">
|
||||
<div [ngClass]="row.entityStatus.code | statusLookup">
|
||||
<div [ngClass]="row.status.code | statusLookup">
|
||||
<fa-icon icon="stop"></fa-icon>
|
||||
<span class="m-l-10 status">
|
||||
{{ row.entityStatus.value | translate }}
|
||||
{{ row.status.value | translate }}
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Color Column -->
|
||||
<ng-container matColumnDef="parentName">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Office Name </th>
|
||||
<td mat-cell *matCellDef="let row"> {{row.parentName}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- ID Column -->
|
||||
<ng-container matColumnDef="staffName">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Staff Name </th>
|
||||
<td mat-cell *matCellDef="let row"> {{row.staffName}} </td>
|
||||
<ng-container matColumnDef="officeName">
|
||||
<th mat-header-cell *matHeaderCellDef> Office Name </th>
|
||||
<td mat-cell *matCellDef="let row"> {{row.officeName}} </td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;" [routerLink]="[row.entityId,'general']" class="select-row">
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;" [routerLink]="[row.id,'general']" class="select-row">
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<mat-paginator [hidden]="!moreClientsToFilter" [pageSize]="50" [pageSizeOptions]="[50, 100]"
|
||||
<mat-paginator [pageSize]="pageSize" [pageSizeOptions]="[5, 50, 100]" [length]="totalRows" (page)="pageChanged($event)"
|
||||
showFirstLastButtons></mat-paginator>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
/** Angular Imports. */
|
||||
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||
import { MatCheckbox } from '@angular/material/checkbox';
|
||||
import { MatPaginator } from '@angular/material/paginator';
|
||||
import { MatSort } from '@angular/material/sort';
|
||||
import { MatPaginator, PageEvent } from '@angular/material/paginator';
|
||||
import { MatSort, Sort } from '@angular/material/sort';
|
||||
import { MatTableDataSource } from '@angular/material/table';
|
||||
|
||||
/** Custom Services */
|
||||
import { SearchService } from 'app/search/search.service';
|
||||
import { environment } from 'environments/environment';
|
||||
import { ClientsService } from './clients.service';
|
||||
|
||||
@Component({
|
||||
selector: 'mifosx-clients',
|
||||
@@ -15,51 +15,75 @@ import { environment } from 'environments/environment';
|
||||
styleUrls: ['./clients.component.scss'],
|
||||
})
|
||||
export class ClientsComponent implements OnInit {
|
||||
@ViewChild('showClosedAccounts', { static: true }) showClosedAccounts: MatCheckbox;
|
||||
@ViewChild('showClosedAccounts') showClosedAccounts: MatCheckbox;
|
||||
|
||||
displayedColumns = ['entityName', 'entityAccountNo', 'entityExternalId', 'status', 'parentName', 'staffName'];
|
||||
dataSource: MatTableDataSource<any>;
|
||||
displayedColumns = ['displayName', 'accountNumber', 'externalId', 'status', 'officeName'];
|
||||
dataSource: MatTableDataSource<any> = new MatTableDataSource();
|
||||
|
||||
existsClientsToFilter = false;
|
||||
notExistsClientsToFilter = false;
|
||||
moreClientsToFilter = false;
|
||||
|
||||
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
|
||||
@ViewChild(MatSort, { static: true }) sort: MatSort;
|
||||
totalRows: number;
|
||||
isLoading = false;
|
||||
|
||||
constructor(private searchService: SearchService) { }
|
||||
pageSize = 50;
|
||||
currentPage = 0;
|
||||
filterText = '';
|
||||
|
||||
sortAttribute = '';
|
||||
sortDirection = '';
|
||||
|
||||
@ViewChild(MatPaginator) paginator: MatPaginator;
|
||||
@ViewChild(MatSort) sort: MatSort;
|
||||
|
||||
constructor(private clientService: ClientsService) { }
|
||||
|
||||
ngOnInit() {
|
||||
if (environment.preloadClients) {
|
||||
this.getClients('');
|
||||
this.getClients();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter Client Data
|
||||
* @param {string} filterValue Value to filter data.
|
||||
*/
|
||||
applyFilter(filterValue: string = '') {
|
||||
this.dataSource.filter = filterValue.trim().toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches server for query and resource.
|
||||
*/
|
||||
search(value: string) {
|
||||
if (value !== '') {
|
||||
this.getClients(value);
|
||||
}
|
||||
this.filterText = value;
|
||||
this.getClients();
|
||||
}
|
||||
|
||||
private getClients(value: string) {
|
||||
this.searchService.getSearchResults(value, 'clients').subscribe((data: any) => {
|
||||
this.dataSource = new MatTableDataSource(data);
|
||||
this.dataSource.paginator = this.paginator;
|
||||
this.dataSource.sort = this.sort;
|
||||
this.existsClientsToFilter = (data.length > 0);
|
||||
private getClients() {
|
||||
this.isLoading = true;
|
||||
this.clientService.searchByText(this.filterText, this.currentPage, this.pageSize, this.sortAttribute, this.sortDirection)
|
||||
.subscribe((data: any) => {
|
||||
this.dataSource.data = data.content;
|
||||
|
||||
this.totalRows = data.totalElements;
|
||||
|
||||
this.existsClientsToFilter = (data.numberOfElements > 0);
|
||||
this.notExistsClientsToFilter = !this.existsClientsToFilter;
|
||||
this.moreClientsToFilter = (data.length > 50);
|
||||
this.isLoading = false;
|
||||
}, (error: any) => {
|
||||
this.isLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
pageChanged(event: PageEvent) {
|
||||
this.pageSize = event.pageSize;
|
||||
this.currentPage = event.pageIndex;
|
||||
this.getClients();
|
||||
}
|
||||
|
||||
sortChanged(event: Sort) {
|
||||
if (event.direction === '') {
|
||||
this.sortDirection = '';
|
||||
this.sortAttribute = '';
|
||||
} else {
|
||||
this.sortAttribute = event.active;
|
||||
this.sortDirection = event.direction;
|
||||
}
|
||||
this.currentPage = 0;
|
||||
this.paginator.firstPage();
|
||||
this.getClients();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,4 +381,26 @@ export class ClientsService {
|
||||
getCollateralTemplate(clientId: any) {
|
||||
return this.http.get(`/clients/${clientId}/collaterals/template`);
|
||||
}
|
||||
|
||||
searchByText(text: string, page: number, pageSize: number, sortAttribute: string = '', sortDirection: string = '') {
|
||||
let request: any = {
|
||||
request: {
|
||||
text
|
||||
},
|
||||
page,
|
||||
size: pageSize
|
||||
}
|
||||
if (sortAttribute !== '' && sortDirection !== '') {
|
||||
request = {
|
||||
...request,
|
||||
sorts: [
|
||||
{
|
||||
direction: sortDirection,
|
||||
property: sortAttribute
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
return this.http.post(`/v2/clients/search`, request);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,13 +22,18 @@ export class ApiPrefixInterceptor implements HttpInterceptor {
|
||||
* Intercepts a Http request and prefixes it with `serverUrl`.
|
||||
*/
|
||||
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||
let baseUrl = this.settingsService.serverUrl;
|
||||
|
||||
const versionRegex = /^\/(v[1-9][0-9]*\/).*$/;
|
||||
if (versionRegex.test(request.url)) {
|
||||
baseUrl = this.settingsService.baseServerUrl;
|
||||
}
|
||||
/**
|
||||
* Ignore URLs that are complete for i18n
|
||||
*/
|
||||
if (!request.url.includes('http:') && !request.url.includes('https:')) {
|
||||
request = request.clone({ url: this.settingsService.serverUrl + request.url });
|
||||
request = request.clone({ url: baseUrl + request.url });
|
||||
}
|
||||
|
||||
return next.handle(request);
|
||||
}
|
||||
|
||||
|
||||
@@ -148,6 +148,13 @@ export class SettingsService {
|
||||
return environment.baseApiUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns server url with api path without version
|
||||
*/
|
||||
get baseServerUrl() {
|
||||
return this.server + environment.apiProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns server url with api path and version
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user