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
|
"vendorChunk": false
|
||||||
},
|
},
|
||||||
"development": {
|
"development": {
|
||||||
"optimization": true,
|
"optimization": false,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"namedChunks": true,
|
"namedChunks": true,
|
||||||
"outputHashing": "all",
|
"outputHashing": "all",
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
"build": "npm run env -s && ng build --prod --output-hashing=none",
|
"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/",
|
"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",
|
"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",
|
"serve:sw": "npm run build -s && npx http-server ./dist -p 4200",
|
||||||
"lint": "ng lint && stylelint \"src/**/*.scss\" --syntax scss && htmlhint \"src\" --config .htmlhintrc",
|
"lint": "ng lint && stylelint \"src/**/*.scss\" --syntax scss && htmlhint \"src\" --config .htmlhintrc",
|
||||||
"test": "npm run env -s && ng test",
|
"test": "npm run env -s && ng test",
|
||||||
|
|||||||
@@ -6,9 +6,6 @@
|
|||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
<div class="filter-box" *ngIf="existsClientsToFilter">
|
<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 #showClosedAccounts labelPosition="after" class="m-r-10">Show Closed Accounts
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
</div>
|
</div>
|
||||||
@@ -23,25 +20,26 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div [hidden]="!existsClientsToFilter">
|
<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 -->
|
<!-- Name Column -->
|
||||||
<ng-container matColumnDef="entityName">
|
<ng-container matColumnDef="displayName">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
|
<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>
|
</ng-container>
|
||||||
|
|
||||||
<!-- Account no Column -->
|
<!-- Account no Column -->
|
||||||
<ng-container matColumnDef="entityAccountNo">
|
<ng-container matColumnDef="accountNumber">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Account No. </th>
|
<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>
|
</ng-container>
|
||||||
|
|
||||||
<!-- External ID Column -->
|
<!-- External ID Column -->
|
||||||
<ng-container matColumnDef="entityExternalId">
|
<ng-container matColumnDef="externalId">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> External Id </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header> External Id </th>
|
||||||
<td mat-cell *matCellDef="let row">
|
<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>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
@@ -49,33 +47,27 @@
|
|||||||
<ng-container matColumnDef="status">
|
<ng-container matColumnDef="status">
|
||||||
<th mat-header-cell *matHeaderCellDef> Status </th>
|
<th mat-header-cell *matHeaderCellDef> Status </th>
|
||||||
<td mat-cell *matCellDef="let row">
|
<td mat-cell *matCellDef="let row">
|
||||||
<div [ngClass]="row.entityStatus.code | statusLookup">
|
<div [ngClass]="row.status.code | statusLookup">
|
||||||
<fa-icon icon="stop"></fa-icon>
|
<fa-icon icon="stop"></fa-icon>
|
||||||
<span class="m-l-10 status">
|
<span class="m-l-10 status">
|
||||||
{{ row.entityStatus.value | translate }}
|
{{ row.status.value | translate }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<!-- Color Column -->
|
<!-- Color Column -->
|
||||||
<ng-container matColumnDef="parentName">
|
<ng-container matColumnDef="officeName">
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Office Name </th>
|
<th mat-header-cell *matHeaderCellDef> Office Name </th>
|
||||||
<td mat-cell *matCellDef="let row"> {{row.parentName}} </td>
|
<td mat-cell *matCellDef="let row"> {{row.officeName}} </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>
|
</ng-container>
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
<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>
|
</tr>
|
||||||
</table>
|
</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>
|
showFirstLastButtons></mat-paginator>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
/** Angular Imports. */
|
/** Angular Imports. */
|
||||||
import { Component, OnInit, ViewChild } from '@angular/core';
|
import { Component, OnInit, ViewChild } from '@angular/core';
|
||||||
import { MatCheckbox } from '@angular/material/checkbox';
|
import { MatCheckbox } from '@angular/material/checkbox';
|
||||||
import { MatPaginator } from '@angular/material/paginator';
|
import { MatPaginator, PageEvent } from '@angular/material/paginator';
|
||||||
import { MatSort } from '@angular/material/sort';
|
import { MatSort, Sort } from '@angular/material/sort';
|
||||||
import { MatTableDataSource } from '@angular/material/table';
|
import { MatTableDataSource } from '@angular/material/table';
|
||||||
|
|
||||||
/** Custom Services */
|
/** Custom Services */
|
||||||
import { SearchService } from 'app/search/search.service';
|
|
||||||
import { environment } from 'environments/environment';
|
import { environment } from 'environments/environment';
|
||||||
|
import { ClientsService } from './clients.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'mifosx-clients',
|
selector: 'mifosx-clients',
|
||||||
@@ -15,51 +15,75 @@ import { environment } from 'environments/environment';
|
|||||||
styleUrls: ['./clients.component.scss'],
|
styleUrls: ['./clients.component.scss'],
|
||||||
})
|
})
|
||||||
export class ClientsComponent implements OnInit {
|
export class ClientsComponent implements OnInit {
|
||||||
@ViewChild('showClosedAccounts', { static: true }) showClosedAccounts: MatCheckbox;
|
@ViewChild('showClosedAccounts') showClosedAccounts: MatCheckbox;
|
||||||
|
|
||||||
displayedColumns = ['entityName', 'entityAccountNo', 'entityExternalId', 'status', 'parentName', 'staffName'];
|
displayedColumns = ['displayName', 'accountNumber', 'externalId', 'status', 'officeName'];
|
||||||
dataSource: MatTableDataSource<any>;
|
dataSource: MatTableDataSource<any> = new MatTableDataSource();
|
||||||
|
|
||||||
existsClientsToFilter = false;
|
existsClientsToFilter = false;
|
||||||
notExistsClientsToFilter = false;
|
notExistsClientsToFilter = false;
|
||||||
moreClientsToFilter = false;
|
|
||||||
|
|
||||||
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
|
totalRows: number;
|
||||||
@ViewChild(MatSort, { static: true }) sort: MatSort;
|
isLoading = false;
|
||||||
|
|
||||||
|
pageSize = 50;
|
||||||
|
currentPage = 0;
|
||||||
|
filterText = '';
|
||||||
|
|
||||||
constructor(private searchService: SearchService) { }
|
sortAttribute = '';
|
||||||
|
sortDirection = '';
|
||||||
|
|
||||||
|
@ViewChild(MatPaginator) paginator: MatPaginator;
|
||||||
|
@ViewChild(MatSort) sort: MatSort;
|
||||||
|
|
||||||
|
constructor(private clientService: ClientsService) { }
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
if (environment.preloadClients) {
|
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.
|
* Searches server for query and resource.
|
||||||
*/
|
*/
|
||||||
search(value: string) {
|
search(value: string) {
|
||||||
if (value !== '') {
|
this.filterText = value;
|
||||||
this.getClients(value);
|
this.getClients();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private getClients(value: string) {
|
private getClients() {
|
||||||
this.searchService.getSearchResults(value, 'clients').subscribe((data: any) => {
|
this.isLoading = true;
|
||||||
this.dataSource = new MatTableDataSource(data);
|
this.clientService.searchByText(this.filterText, this.currentPage, this.pageSize, this.sortAttribute, this.sortDirection)
|
||||||
this.dataSource.paginator = this.paginator;
|
.subscribe((data: any) => {
|
||||||
this.dataSource.sort = this.sort;
|
this.dataSource.data = data.content;
|
||||||
this.existsClientsToFilter = (data.length > 0);
|
|
||||||
|
this.totalRows = data.totalElements;
|
||||||
|
|
||||||
|
this.existsClientsToFilter = (data.numberOfElements > 0);
|
||||||
this.notExistsClientsToFilter = !this.existsClientsToFilter;
|
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) {
|
getCollateralTemplate(clientId: any) {
|
||||||
return this.http.get(`/clients/${clientId}/collaterals/template`);
|
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`.
|
* Intercepts a Http request and prefixes it with `serverUrl`.
|
||||||
*/
|
*/
|
||||||
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
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
|
* Ignore URLs that are complete for i18n
|
||||||
*/
|
*/
|
||||||
if (!request.url.includes('http:') && !request.url.includes('https:')) {
|
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);
|
return next.handle(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -148,6 +148,13 @@ export class SettingsService {
|
|||||||
return environment.baseApiUrl;
|
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
|
* Returns server url with api path and version
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user