diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml index 2d182c88..e82256df 100644 --- a/src/main/resources/logback-spring.xml +++ b/src/main/resources/logback-spring.xml @@ -45,6 +45,10 @@ + diff --git a/src/main/webapp/app/entities/customer/customer.component.html b/src/main/webapp/app/entities/customer/customer.component.html index c655cc04..5d77faba 100644 --- a/src/main/webapp/app/entities/customer/customer.component.html +++ b/src/main/webapp/app/entities/customer/customer.component.html @@ -14,12 +14,26 @@ - - - - - - + + + + + + + + + + + + + + diff --git a/src/main/webapp/app/entities/customer/customer.component.ts b/src/main/webapp/app/entities/customer/customer.component.ts index 3f95501d..c3e4a5e0 100644 --- a/src/main/webapp/app/entities/customer/customer.component.ts +++ b/src/main/webapp/app/entities/customer/customer.component.ts @@ -8,6 +8,7 @@ import { AccountService } from 'app/core'; import { ITEMS_PER_PAGE } from 'app/shared'; import { CustomerService } from './customer.service'; +import { TableFilter } from 'app/shared/util/tablefilter'; @Component({ selector: 'jhi-customer', @@ -23,6 +24,7 @@ export class CustomerComponent implements OnInit, OnDestroy { predicate: any; reverse: any; totalItems: number; + filter: TableFilter<{ reference?: string; prefix?: string; name?: string; kind?: string }>; constructor( protected customerService: CustomerService, @@ -39,11 +41,15 @@ export class CustomerComponent implements OnInit, OnDestroy { }; this.predicate = 'id'; this.reverse = true; + this.filter = new TableFilter({ reference: 'equals', prefix: 'contains', name: 'contains', kind: 'equals' }, 500, () => { + this.loadAll(); + }); } loadAll() { this.customerService .query({ + ...this.filter.buildQueryCriteria(), page: this.page, size: this.itemsPerPage, sort: this.sort() @@ -96,6 +102,8 @@ export class CustomerComponent implements OnInit, OnDestroy { protected paginateCustomers(data: ICustomer[], headers: HttpHeaders) { this.links = this.parseLinks.parse(headers.get('link')); this.totalItems = parseInt(headers.get('X-Total-Count'), 10); + this.page = 0; + this.customers = []; for (let i = 0; i < data.length; i++) { this.customers.push(data[i]); } diff --git a/src/main/webapp/app/shared/util/tablefilter.ts b/src/main/webapp/app/shared/util/tablefilter.ts new file mode 100644 index 00000000..0d077c47 --- /dev/null +++ b/src/main/webapp/app/shared/util/tablefilter.ts @@ -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 { + criteria: T; + + private criteriaChangedSubject = new Subject(); + 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(); + } +} diff --git a/src/test/javascript/spec/app/shared/util/tablefilter.spec.ts b/src/test/javascript/spec/app/shared/util/tablefilter.spec.ts new file mode 100644 index 00000000..977159a1 --- /dev/null +++ b/src/test/javascript/spec/app/shared/util/tablefilter.spec.ts @@ -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(); + }; + }); + }); +});
ID Reference Prefix Name Kind ID Reference Prefix Name Kind
+ +