filter Customer table + class TableFilter
This commit is contained in:
parent
d182637f41
commit
89437ca067
@ -45,6 +45,10 @@
|
|||||||
<logger name="org.bson" level="WARN"/>
|
<logger name="org.bson" level="WARN"/>
|
||||||
<logger name="org.hibernate.validator" level="WARN"/>
|
<logger name="org.hibernate.validator" level="WARN"/>
|
||||||
<logger name="org.hibernate" level="WARN"/>
|
<logger name="org.hibernate" level="WARN"/>
|
||||||
|
<!-- HOWTO log Hibernate SQL queries with bind parameters
|
||||||
|
<logger name="org.hibernate.SQL" additivity="false" level="DEBUG" />
|
||||||
|
<logger name="org.hibernate.type" additivity="false" level="TRACE" />
|
||||||
|
-->
|
||||||
<logger name="org.hibernate.ejb.HibernatePersistence" level="OFF"/>
|
<logger name="org.hibernate.ejb.HibernatePersistence" level="OFF"/>
|
||||||
<logger name="org.postgresql.jdbc" level="WARN"/>
|
<logger name="org.postgresql.jdbc" level="WARN"/>
|
||||||
<logger name="org.springframework" level="WARN"/>
|
<logger name="org.springframework" level="WARN"/>
|
||||||
|
@ -14,12 +14,26 @@
|
|||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr jhiSort [(predicate)]="predicate" [(ascending)]="reverse" [callback]="reset.bind(this)">
|
<tr jhiSort [(predicate)]="predicate" [(ascending)]="reverse" [callback]="reset.bind(this)">
|
||||||
<th jhiSortBy="id"><span jhiTranslate="global.field.id">ID</span> <fa-icon [icon]="'sort'"></fa-icon></th>
|
<th jhiSortBy="id"><span jhiTranslate="global.field.id">ID</span> <fa-icon [icon]="'sort'"></fa-icon></th>
|
||||||
<th jhiSortBy="reference"><span jhiTranslate="hsadminNgApp.customer.reference">Reference</span> <fa-icon [icon]="'sort'"></fa-icon></th>
|
<th jhiSortBy="reference"><span jhiTranslate="hsadminNgApp.customer.reference">Reference</span> <fa-icon [icon]="'sort'"></fa-icon></th>
|
||||||
<th jhiSortBy="prefix"><span jhiTranslate="hsadminNgApp.customer.prefix">Prefix</span> <fa-icon [icon]="'sort'"></fa-icon></th>
|
<th jhiSortBy="prefix"><span jhiTranslate="hsadminNgApp.customer.prefix">Prefix</span> <fa-icon [icon]="'sort'"></fa-icon></th>
|
||||||
<th jhiSortBy="name"><span jhiTranslate="hsadminNgApp.customer.name">Name</span> <fa-icon [icon]="'sort'"></fa-icon></th>
|
<th jhiSortBy="name"><span jhiTranslate="hsadminNgApp.customer.name">Name</span> <fa-icon [icon]="'sort'"></fa-icon></th>
|
||||||
<th jhiSortBy="kind"><span jhiTranslate="hsadminNgApp.customer.kind">Kind</span> <fa-icon [icon]="'sort'"></fa-icon></thn></th>
|
<th jhiSortBy="kind"><span jhiTranslate="hsadminNgApp.customer.kind">Kind</span> <fa-icon [icon]="'sort'"></fa-icon></th>
|
||||||
<th></th>
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th><input type="text" class="form-control" [(ngModel)]="filter.criteria.reference" (keyup)="filter.trigger()"></th>
|
||||||
|
<th><input type="text" class="form-control" [(ngModel)]="filter.criteria.prefix" (keyup)="filter.trigger()"></th>
|
||||||
|
<th><input type="text" class="form-control" [(ngModel)]="filter.criteria.name" (keyup)="filter.trigger()"></th>
|
||||||
|
<th>
|
||||||
|
<select class="form-control" [(ngModel)]="filter.criteria.kind" (change)="filter.trigger()">
|
||||||
|
<option value=""></option>
|
||||||
|
<option>NATURAL</option>
|
||||||
|
<option>LEGAL</option>
|
||||||
|
</select>
|
||||||
|
</th>
|
||||||
|
<th><button class="btn btn-primary float-left" (click)="filter.reset()">Reset Filter</button></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody infinite-scroll (scrolled)="loadPage(page + 1)" [infiniteScrollDisabled]="page >= links['last']" [infiniteScrollDistance]="0">
|
<tbody infinite-scroll (scrolled)="loadPage(page + 1)" [infiniteScrollDisabled]="page >= links['last']" [infiniteScrollDistance]="0">
|
||||||
|
@ -8,6 +8,7 @@ import { AccountService } from 'app/core';
|
|||||||
|
|
||||||
import { ITEMS_PER_PAGE } from 'app/shared';
|
import { ITEMS_PER_PAGE } from 'app/shared';
|
||||||
import { CustomerService } from './customer.service';
|
import { CustomerService } from './customer.service';
|
||||||
|
import { TableFilter } from 'app/shared/util/tablefilter';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'jhi-customer',
|
selector: 'jhi-customer',
|
||||||
@ -23,6 +24,7 @@ export class CustomerComponent implements OnInit, OnDestroy {
|
|||||||
predicate: any;
|
predicate: any;
|
||||||
reverse: any;
|
reverse: any;
|
||||||
totalItems: number;
|
totalItems: number;
|
||||||
|
filter: TableFilter<{ reference?: string; prefix?: string; name?: string; kind?: string }>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected customerService: CustomerService,
|
protected customerService: CustomerService,
|
||||||
@ -39,11 +41,15 @@ export class CustomerComponent implements OnInit, OnDestroy {
|
|||||||
};
|
};
|
||||||
this.predicate = 'id';
|
this.predicate = 'id';
|
||||||
this.reverse = true;
|
this.reverse = true;
|
||||||
|
this.filter = new TableFilter({ reference: 'equals', prefix: 'contains', name: 'contains', kind: 'equals' }, 500, () => {
|
||||||
|
this.loadAll();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
loadAll() {
|
loadAll() {
|
||||||
this.customerService
|
this.customerService
|
||||||
.query({
|
.query({
|
||||||
|
...this.filter.buildQueryCriteria(),
|
||||||
page: this.page,
|
page: this.page,
|
||||||
size: this.itemsPerPage,
|
size: this.itemsPerPage,
|
||||||
sort: this.sort()
|
sort: this.sort()
|
||||||
@ -96,6 +102,8 @@ export class CustomerComponent implements OnInit, OnDestroy {
|
|||||||
protected paginateCustomers(data: ICustomer[], headers: HttpHeaders) {
|
protected paginateCustomers(data: ICustomer[], headers: HttpHeaders) {
|
||||||
this.links = this.parseLinks.parse(headers.get('link'));
|
this.links = this.parseLinks.parse(headers.get('link'));
|
||||||
this.totalItems = parseInt(headers.get('X-Total-Count'), 10);
|
this.totalItems = parseInt(headers.get('X-Total-Count'), 10);
|
||||||
|
this.page = 0;
|
||||||
|
this.customers = [];
|
||||||
for (let i = 0; i < data.length; i++) {
|
for (let i = 0; i < data.length; i++) {
|
||||||
this.customers.push(data[i]);
|
this.customers.push(data[i]);
|
||||||
}
|
}
|
||||||
|
40
src/main/webapp/app/shared/util/tablefilter.ts
Normal file
40
src/main/webapp/app/shared/util/tablefilter.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import { Subject, Subscription } from 'rxjs';
|
||||||
|
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles filtering in data tables by converting the user input to query criteria of the JHipster REST API.
|
||||||
|
*
|
||||||
|
* It also does not reload during a given debounce period.
|
||||||
|
*/
|
||||||
|
export class TableFilter<T extends {}> {
|
||||||
|
criteria: T;
|
||||||
|
|
||||||
|
private criteriaChangedSubject = new Subject<void>();
|
||||||
|
private criteriaChangedDebouncer: Subscription;
|
||||||
|
|
||||||
|
constructor(private query: T, private debounceMillis: number, private reload: () => void) {
|
||||||
|
this.criteria = {} as any;
|
||||||
|
this.criteriaChangedDebouncer = this.criteriaChangedSubject.pipe(debounceTime(debounceMillis)).subscribe(() => this.reload());
|
||||||
|
}
|
||||||
|
|
||||||
|
trigger() {
|
||||||
|
this.debounce();
|
||||||
|
}
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this.criteria = {} as any;
|
||||||
|
this.debounce();
|
||||||
|
}
|
||||||
|
|
||||||
|
buildQueryCriteria() {
|
||||||
|
let queryCriteria: T = {} as any;
|
||||||
|
Object.keys(this.criteria).forEach(e => {
|
||||||
|
queryCriteria[e + '.' + this.query[e]] = this.criteria[e];
|
||||||
|
});
|
||||||
|
return queryCriteria;
|
||||||
|
}
|
||||||
|
|
||||||
|
private debounce() {
|
||||||
|
this.criteriaChangedSubject.next();
|
||||||
|
}
|
||||||
|
}
|
86
src/test/javascript/spec/app/shared/util/tablefilter.spec.ts
Normal file
86
src/test/javascript/spec/app/shared/util/tablefilter.spec.ts
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
import { TableFilter } from 'app/shared/util/tablefilter';
|
||||||
|
|
||||||
|
/* To run these tests in IntelliJ IDEA, you need a run configuration with
|
||||||
|
Configuration File:
|
||||||
|
~/Projekte/Hostsharing/hsadmin-ng/src/test/javascript/jest.conf.js
|
||||||
|
and a Node Interpreter, e.g. if installed with nvm, this could be:
|
||||||
|
~/.nvm/versions/node/v10.15.3/bin/node
|
||||||
|
*/
|
||||||
|
describe('TableFilter Tests', () => {
|
||||||
|
describe('TableFilter', () => {
|
||||||
|
let filter: TableFilter<{ name: string; number: string }>;
|
||||||
|
let asynchronously: () => void;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
filter = new TableFilter({ name: 'contains', number: 'equals' }, 100, () => {
|
||||||
|
asynchronously();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('trigger() asynchronously calls the reload-handler', done => {
|
||||||
|
// given
|
||||||
|
filter.criteria.name = 'Test Filter Value';
|
||||||
|
|
||||||
|
// when
|
||||||
|
filter.trigger();
|
||||||
|
let triggerStartedAtMillis = Date.now();
|
||||||
|
|
||||||
|
// then
|
||||||
|
asynchronously = () => {
|
||||||
|
expect(Date.now()).toBeGreaterThan(triggerStartedAtMillis);
|
||||||
|
done();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
it('if trigger() is called multiple times during debounce, debounce period ands after last trigger()', done => {
|
||||||
|
// given
|
||||||
|
filter.criteria.name = 'Test Filter Value';
|
||||||
|
|
||||||
|
// when
|
||||||
|
filter.trigger();
|
||||||
|
let triggerStartedAtMillis = null;
|
||||||
|
setTimeout(() => {
|
||||||
|
filter.trigger();
|
||||||
|
triggerStartedAtMillis = Date.now();
|
||||||
|
}, 50);
|
||||||
|
|
||||||
|
// then
|
||||||
|
asynchronously = () => {
|
||||||
|
expect(triggerStartedAtMillis).not.toBeNull();
|
||||||
|
expect(Date.now()).toBeGreaterThan(triggerStartedAtMillis);
|
||||||
|
done();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
it('when filter "name" is set to "test value", buildQueryCriteria() returns { "name.contains": "test value" }', () => {
|
||||||
|
// given
|
||||||
|
filter.criteria.name = 'test value';
|
||||||
|
|
||||||
|
// when
|
||||||
|
let actual = filter.buildQueryCriteria();
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(filter.buildQueryCriteria()).toEqual({ 'name.contains': 'test value' });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('reset() clears criteria and calls reload-handler, considering debounce period', done => {
|
||||||
|
// given
|
||||||
|
filter.criteria.name = 'Test Filter Value';
|
||||||
|
|
||||||
|
// when
|
||||||
|
filter.trigger();
|
||||||
|
let triggerStartedAtMillis = null;
|
||||||
|
setTimeout(() => {
|
||||||
|
filter.reset();
|
||||||
|
triggerStartedAtMillis = Date.now();
|
||||||
|
}, 50);
|
||||||
|
|
||||||
|
// then
|
||||||
|
asynchronously = () => {
|
||||||
|
expect(triggerStartedAtMillis).not.toBeNull();
|
||||||
|
expect(Date.now()).toBeGreaterThan(triggerStartedAtMillis);
|
||||||
|
done();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user