added TableFilter to share.component, TableFilter now with date range
This commit is contained in:
parent
8ae7547775
commit
dccafcc900
@ -23,11 +23,11 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th></th>
|
<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.reference" (keyup)="filter.trigger($event)"></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.prefix" (keyup)="filter.trigger($event)"></th>
|
||||||
<th><input type="text" class="form-control" [(ngModel)]="filter.criteria.name" (keyup)="filter.trigger()"></th>
|
<th><input type="text" class="form-control" [(ngModel)]="filter.criteria.name" (keyup)="filter.trigger($event)"></th>
|
||||||
<th>
|
<th>
|
||||||
<select class="form-control" [(ngModel)]="filter.criteria.kind" (change)="filter.trigger()">
|
<select class="form-control" [(ngModel)]="filter.criteria.kind" (change)="filter.trigger($event)">
|
||||||
<option value=""></option>
|
<option value=""></option>
|
||||||
<option value="NATURAL" jhiTranslate="{{'hsadminNgApp.CustomerKind.NATURAL'}}">NATURAL</option>
|
<option value="NATURAL" jhiTranslate="{{'hsadminNgApp.CustomerKind.NATURAL'}}">NATURAL</option>
|
||||||
<option value="LEGAL" jhiTranslate="{{'hsadminNgApp.CustomerKind.LEGAL'}}">LEGAL</option>
|
<option value="LEGAL" jhiTranslate="{{'hsadminNgApp.CustomerKind.LEGAL'}}">LEGAL</option>
|
||||||
|
@ -41,9 +41,18 @@ 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.filter = new TableFilter(
|
||||||
|
{
|
||||||
|
reference: 'reference.equals',
|
||||||
|
prefix: 'prefix.contains',
|
||||||
|
name: 'name.contains',
|
||||||
|
kind: 'kind.equals'
|
||||||
|
},
|
||||||
|
500,
|
||||||
|
() => {
|
||||||
this.loadAll();
|
this.loadAll();
|
||||||
});
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
loadAll() {
|
loadAll() {
|
||||||
|
@ -3,7 +3,6 @@ import { ActivatedRoute } from '@angular/router';
|
|||||||
import { HttpResponse, HttpErrorResponse } from '@angular/common/http';
|
import { HttpResponse, HttpErrorResponse } from '@angular/common/http';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { filter, map } from 'rxjs/operators';
|
import { filter, map } from 'rxjs/operators';
|
||||||
import * as moment from 'moment';
|
|
||||||
import { JhiAlertService } from 'ng-jhipster';
|
import { JhiAlertService } from 'ng-jhipster';
|
||||||
import { IShare } from 'app/shared/model/share.model';
|
import { IShare } from 'app/shared/model/share.model';
|
||||||
import { ShareService } from './share.service';
|
import { ShareService } from './share.service';
|
||||||
|
@ -22,14 +22,34 @@
|
|||||||
<th jhiSortBy="membershipDisplayLabel"><span jhiTranslate="hsadminNgApp.share.membership">Membership</span> <fa-icon [icon]="'sort'"></fa-icon></th>
|
<th jhiSortBy="membershipDisplayLabel"><span jhiTranslate="hsadminNgApp.share.membership">Membership</span> <fa-icon [icon]="'sort'"></fa-icon></th>
|
||||||
<th></th>
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th style="width: 10%"></th>
|
||||||
|
<th style="width: 10%"><input type="text" class="form-control" style="max-width: 20em" minlength="4" maxlength="4" [(ngModel)]="filter.criteria.documentDate" (keyup)="filter.trigger($event)"></th>
|
||||||
|
<th style="width: 10%"><input type="text" class="form-control" style="max-width: 20em" minlength="4" maxlength="4" [(ngModel)]="filter.criteria.valueDate" (keyup)="filter.trigger($event)"></th>
|
||||||
|
<th style="width: 10%">
|
||||||
|
<select class="form-control" [(ngModel)]="filter.criteria.action" (change)="filter.trigger($event)">
|
||||||
|
<option value=""></option>
|
||||||
|
<option value="SUBSCRIPTION" jhiTranslate="{{'hsadminNgApp.ShareAction.SUBSCRIPTION'}}">SUBSCRIPTION</option>
|
||||||
|
<option value="CANCELLATION" jhiTranslate="{{'hsadminNgApp.ShareAction.CANCELLATION'}}">CANCELLATION</option>
|
||||||
|
</select>
|
||||||
|
</th>
|
||||||
|
<th style="width: 10%"><input type="text" class="form-control" [(ngModel)]="filter.criteria.quantity" (keyup)="filter.trigger($event)"></th>
|
||||||
|
<th style="width: 30%">
|
||||||
|
<select id="field_membership" class="form-control" name="membership" [(ngModel)]="filter.criteria.membershipId" (change)="filter.trigger($event)">
|
||||||
|
<option [ngValue]="null" selected></option>
|
||||||
|
<option [ngValue]="membershipOption.id" *ngFor="let membershipOption of memberships; trackBy: trackMembershipById">{{membershipOption.displayLabel}}</option>
|
||||||
|
</select>
|
||||||
|
</th>
|
||||||
|
<th style="width: 20%"><button class="btn btn-primary float-left" (click)="filter.reset()">Reset Filter</button></th>
|
||||||
|
</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">
|
||||||
<tr *ngFor="let share of shares ;trackBy: trackId">
|
<tr *ngFor="let share of shares ;trackBy: trackId">
|
||||||
<td><a [routerLink]="['/share', share.id, 'view' ]">{{share.id}}</a></td>
|
<td class="text-right"><a [routerLink]="['/share', share.id, 'view' ]">{{share.id}}</a></td>
|
||||||
<td>{{share.documentDate | date:'mediumDate'}}</td>
|
<td>{{share.documentDate | date:'mediumDate'}}</td>
|
||||||
<td>{{share.valueDate | date:'mediumDate'}}</td>
|
<td>{{share.valueDate | date:'mediumDate'}}</td>
|
||||||
<td jhiTranslate="{{'hsadminNgApp.ShareAction.' + share.action}}">{{share.action}}</td>
|
<td jhiTranslate="{{'hsadminNgApp.ShareAction.' + share.action}}">{{share.action}}</td>
|
||||||
<td>{{share.quantity}}</td>
|
<td class="text-right">{{share.quantity}}</td>
|
||||||
<td>
|
<td>
|
||||||
<div *ngIf="share.membershipId">
|
<div *ngIf="share.membershipId">
|
||||||
<a [routerLink]="['../membership', share.membershipId , 'view' ]" >{{share.membershipDisplayLabel}}</a>
|
<a [routerLink]="['../membership', share.membershipId , 'view' ]" >{{share.membershipDisplayLabel}}</a>
|
||||||
|
@ -9,6 +9,9 @@ import { AccountService } from 'app/core';
|
|||||||
|
|
||||||
import { ITEMS_PER_PAGE } from 'app/shared';
|
import { ITEMS_PER_PAGE } from 'app/shared';
|
||||||
import { ShareService } from './share.service';
|
import { ShareService } from './share.service';
|
||||||
|
import { TableFilter, queryYearAsDateRange, queryEquals } from 'app/shared/util/tablefilter';
|
||||||
|
import { IMembership } from 'app/shared/model/membership.model';
|
||||||
|
import { MembershipService } from 'app/entities/membership';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'jhi-share',
|
selector: 'jhi-share',
|
||||||
@ -24,9 +27,18 @@ export class ShareComponent implements OnInit, OnDestroy {
|
|||||||
predicate: any;
|
predicate: any;
|
||||||
reverse: any;
|
reverse: any;
|
||||||
totalItems: number;
|
totalItems: number;
|
||||||
|
memberships: IMembership[];
|
||||||
|
filter: TableFilter<{
|
||||||
|
documentDate?: string;
|
||||||
|
valueDate?: string;
|
||||||
|
action?: string;
|
||||||
|
quantity?: string;
|
||||||
|
membershipId?: string;
|
||||||
|
}>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected shareService: ShareService,
|
protected shareService: ShareService,
|
||||||
|
protected membershipService: MembershipService,
|
||||||
protected jhiAlertService: JhiAlertService,
|
protected jhiAlertService: JhiAlertService,
|
||||||
protected eventManager: JhiEventManager,
|
protected eventManager: JhiEventManager,
|
||||||
protected parseLinks: JhiParseLinks,
|
protected parseLinks: JhiParseLinks,
|
||||||
@ -40,11 +52,25 @@ export class ShareComponent implements OnInit, OnDestroy {
|
|||||||
};
|
};
|
||||||
this.predicate = 'id';
|
this.predicate = 'id';
|
||||||
this.reverse = true;
|
this.reverse = true;
|
||||||
|
this.filter = new TableFilter(
|
||||||
|
{
|
||||||
|
documentDate: queryYearAsDateRange,
|
||||||
|
valueDate: queryYearAsDateRange,
|
||||||
|
action: queryEquals,
|
||||||
|
quantity: queryEquals,
|
||||||
|
membershipId: queryEquals
|
||||||
|
},
|
||||||
|
500,
|
||||||
|
() => {
|
||||||
|
this.loadAll();
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
loadAll() {
|
loadAll() {
|
||||||
this.shareService
|
this.shareService
|
||||||
.query({
|
.query({
|
||||||
|
...this.filter.buildQueryCriteria(),
|
||||||
page: this.page,
|
page: this.page,
|
||||||
size: this.itemsPerPage,
|
size: this.itemsPerPage,
|
||||||
sort: this.sort()
|
sort: this.sort()
|
||||||
@ -71,6 +97,13 @@ export class ShareComponent implements OnInit, OnDestroy {
|
|||||||
this.accountService.identity().then(account => {
|
this.accountService.identity().then(account => {
|
||||||
this.currentAccount = account;
|
this.currentAccount = account;
|
||||||
});
|
});
|
||||||
|
this.membershipService
|
||||||
|
.query()
|
||||||
|
.pipe(
|
||||||
|
filter((mayBeOk: HttpResponse<IMembership[]>) => mayBeOk.ok),
|
||||||
|
map((response: HttpResponse<IMembership[]>) => response.body)
|
||||||
|
)
|
||||||
|
.subscribe((res: IMembership[]) => (this.memberships = res), (res: HttpErrorResponse) => this.onError(res.message));
|
||||||
this.registerChangeInShares();
|
this.registerChangeInShares();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,9 +127,15 @@ export class ShareComponent implements OnInit, OnDestroy {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trackMembershipById(index: number, item: IMembership) {
|
||||||
|
return item.id;
|
||||||
|
}
|
||||||
|
|
||||||
protected paginateShares(data: IShare[], headers: HttpHeaders) {
|
protected paginateShares(data: IShare[], 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.shares = [];
|
||||||
for (let i = 0; i < data.length; i++) {
|
for (let i = 0; i < data.length; i++) {
|
||||||
this.shares.push(data[i]);
|
this.shares.push(data[i]);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,14 @@
|
|||||||
import { Subject, Subscription } from 'rxjs';
|
import { Subject, Subscription } from 'rxjs';
|
||||||
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
|
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';
|
||||||
|
|
||||||
|
export interface QueryDeclarations {
|
||||||
|
[key: string]: string;
|
||||||
|
}
|
||||||
|
export type DynamicQueryDefinition = (name: string, value: string) => QueryDefinitions;
|
||||||
|
export interface QueryDefinitions {
|
||||||
|
[key: string]: string | DynamicQueryDefinition;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles filtering in data tables by converting the user input to query criteria of the JHipster REST API.
|
* Handles filtering in data tables by converting the user input to query criteria of the JHipster REST API.
|
||||||
*
|
*
|
||||||
@ -12,12 +20,12 @@ export class TableFilter<T extends {}> {
|
|||||||
private criteriaChangedSubject = new Subject<void>();
|
private criteriaChangedSubject = new Subject<void>();
|
||||||
private criteriaChangedDebouncer: Subscription;
|
private criteriaChangedDebouncer: Subscription;
|
||||||
|
|
||||||
constructor(private query: T, private debounceMillis: number, private reload: () => void) {
|
constructor(private query: QueryDefinitions, private debounceMillis: number, private reload: () => void) {
|
||||||
this.criteria = {} as any;
|
this.criteria = {} as any;
|
||||||
this.criteriaChangedDebouncer = this.criteriaChangedSubject.pipe(debounceTime(debounceMillis)).subscribe(() => this.reload());
|
this.criteriaChangedDebouncer = this.criteriaChangedSubject.pipe(debounceTime(debounceMillis)).subscribe(() => this.reload());
|
||||||
}
|
}
|
||||||
|
|
||||||
trigger() {
|
trigger($event) {
|
||||||
this.debounce();
|
this.debounce();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,10 +34,17 @@ export class TableFilter<T extends {}> {
|
|||||||
this.debounce();
|
this.debounce();
|
||||||
}
|
}
|
||||||
|
|
||||||
buildQueryCriteria() {
|
buildQueryCriteria(): QueryDeclarations {
|
||||||
const queryCriteria: T = {} as any;
|
let queryCriteria: any = {} as any;
|
||||||
Object.keys(this.criteria).forEach(e => {
|
Object.keys(this.criteria).forEach(name => {
|
||||||
queryCriteria[e + '.' + this.query[e]] = this.criteria[e];
|
const value = this.criteria[name];
|
||||||
|
const queryDef = this.query[name];
|
||||||
|
if (typeof queryDef !== 'function') {
|
||||||
|
queryCriteria[queryDef] = value;
|
||||||
|
} else {
|
||||||
|
const additionalQueryCriteria = queryDef(name, value);
|
||||||
|
queryCriteria = { ...queryCriteria, ...additionalQueryCriteria };
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return queryCriteria;
|
return queryCriteria;
|
||||||
}
|
}
|
||||||
@ -38,3 +53,21 @@ export class TableFilter<T extends {}> {
|
|||||||
this.criteriaChangedSubject.next();
|
this.criteriaChangedSubject.next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function queryYearAsDateRange(name: string, value: string) {
|
||||||
|
if (value.length === 'YYYY'.length) {
|
||||||
|
const queryCriteria: any = {} as any;
|
||||||
|
queryCriteria[name + '.greaterOrEqualThan'] = value + '-01-01';
|
||||||
|
queryCriteria[name + '.lessOrEqualThan'] = value + '-12-31';
|
||||||
|
return queryCriteria;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function queryEquals(name: string, value: string) {
|
||||||
|
return { [name + '.equals']: value };
|
||||||
|
}
|
||||||
|
|
||||||
|
export function queryContains(name: string, value: string) {
|
||||||
|
return { [name + '.contains']: value };
|
||||||
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { TableFilter } from 'app/shared/util/tablefilter';
|
import { queryContains, queryEquals, queryYearAsDateRange, TableFilter } from 'app/shared/util/tablefilter';
|
||||||
|
|
||||||
/* To run these tests in IntelliJ IDEA, you need a run configuration with
|
/* To run these tests in IntelliJ IDEA, you need a run configuration with
|
||||||
Configuration File:
|
Configuration File:
|
||||||
@ -8,13 +8,23 @@ import { TableFilter } from 'app/shared/util/tablefilter';
|
|||||||
*/
|
*/
|
||||||
describe('TableFilter Tests', () => {
|
describe('TableFilter Tests', () => {
|
||||||
describe('TableFilter', () => {
|
describe('TableFilter', () => {
|
||||||
let filter: TableFilter<{ name: string; number: string }>;
|
const TEST_DEBOUNCE_MILLIS = 100;
|
||||||
|
|
||||||
|
let filter: TableFilter<{ name?: string; number?: string; date?: string }>;
|
||||||
let asynchronously: () => void;
|
let asynchronously: () => void;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
filter = new TableFilter({ name: 'contains', number: 'equals' }, 100, () => {
|
filter = new TableFilter(
|
||||||
|
{
|
||||||
|
name: queryContains,
|
||||||
|
number: queryEquals,
|
||||||
|
date: queryYearAsDateRange
|
||||||
|
},
|
||||||
|
TEST_DEBOUNCE_MILLIS,
|
||||||
|
() => {
|
||||||
asynchronously();
|
asynchronously();
|
||||||
});
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('trigger() asynchronously calls the reload-handler', done => {
|
it('trigger() asynchronously calls the reload-handler', done => {
|
||||||
@ -22,7 +32,7 @@ describe('TableFilter Tests', () => {
|
|||||||
filter.criteria.name = 'Test Filter Value';
|
filter.criteria.name = 'Test Filter Value';
|
||||||
|
|
||||||
// when
|
// when
|
||||||
filter.trigger();
|
filter.trigger({ target: { valid: true } });
|
||||||
const triggerStartedAtMillis = Date.now();
|
const triggerStartedAtMillis = Date.now();
|
||||||
|
|
||||||
// then
|
// then
|
||||||
@ -37,10 +47,10 @@ describe('TableFilter Tests', () => {
|
|||||||
filter.criteria.name = 'Test Filter Value';
|
filter.criteria.name = 'Test Filter Value';
|
||||||
|
|
||||||
// when
|
// when
|
||||||
filter.trigger();
|
filter.trigger({ target: { valid: true } });
|
||||||
let triggerStartedAtMillis = null;
|
let triggerStartedAtMillis = null;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
filter.trigger();
|
filter.trigger({ target: { valid: true } });
|
||||||
triggerStartedAtMillis = Date.now();
|
triggerStartedAtMillis = Date.now();
|
||||||
}, 50);
|
}, 50);
|
||||||
|
|
||||||
@ -52,7 +62,7 @@ describe('TableFilter Tests', () => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
it('when filter "name" is set to "test value", buildQueryCriteria() returns { "name.contains": "test value" }', () => {
|
it('when filter "name" is set, buildQueryCriteria() returns a name.contains query', () => {
|
||||||
// given
|
// given
|
||||||
filter.criteria.name = 'test value';
|
filter.criteria.name = 'test value';
|
||||||
|
|
||||||
@ -63,17 +73,44 @@ describe('TableFilter Tests', () => {
|
|||||||
expect(filter.buildQueryCriteria()).toEqual({ 'name.contains': 'test value' });
|
expect(filter.buildQueryCriteria()).toEqual({ 'name.contains': 'test value' });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('when filter "number" is set, buildQueryCriteria() returns a number.equals query', () => {
|
||||||
|
// given
|
||||||
|
filter.criteria.number = '-42';
|
||||||
|
|
||||||
|
// when
|
||||||
|
const actual = filter.buildQueryCriteria();
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(filter.buildQueryCriteria()).toEqual({ 'number.equals': '-42' });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('when filter "date" is set to "2019", buildQueryCriteria() returns a date range query', () => {
|
||||||
|
// given
|
||||||
|
filter.criteria.date = '2019';
|
||||||
|
|
||||||
|
// when
|
||||||
|
const actual = filter.buildQueryCriteria();
|
||||||
|
|
||||||
|
// then
|
||||||
|
expect(filter.buildQueryCriteria()).toEqual({ 'date.greaterOrEqualThan': '2019-01-01', 'date.lessOrEqualThan': '2019-12-31' });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('queryYearAsDateRange() returns null if year is not 4-digit', () => {
|
||||||
|
expect(queryYearAsDateRange('date', '201')).toBeNull();
|
||||||
|
expect(queryYearAsDateRange('date', '20191')).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
it('reset() clears criteria and calls reload-handler, considering debounce period', done => {
|
it('reset() clears criteria and calls reload-handler, considering debounce period', done => {
|
||||||
// given
|
// given
|
||||||
filter.criteria.name = 'Test Filter Value';
|
filter.criteria.name = 'Test Filter Value';
|
||||||
|
|
||||||
// when
|
// when
|
||||||
filter.trigger();
|
filter.trigger({ target: { valid: true } });
|
||||||
let triggerStartedAtMillis = null;
|
let triggerStartedAtMillis = null;
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
filter.reset();
|
filter.reset();
|
||||||
triggerStartedAtMillis = Date.now();
|
triggerStartedAtMillis = Date.now();
|
||||||
}, 50);
|
}, TEST_DEBOUNCE_MILLIS / 2);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
asynchronously = () => {
|
asynchronously = () => {
|
||||||
|
Loading…
Reference in New Issue
Block a user