IMP-105,IMP-106: Add tables filters, sort routing-rules shops and wallets (#280)

This commit is contained in:
Rinat Arsaev 2023-11-01 19:47:27 +07:00 committed by GitHub
parent 7649b4e2ee
commit 644bec96b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 37 additions and 96 deletions

16
package-lock.json generated
View File

@ -29,7 +29,7 @@
"@vality/dominant-cache-proto": "2.0.0", "@vality/dominant-cache-proto": "2.0.0",
"@vality/fistful-proto": "2.0.1-ed97a0e.0", "@vality/fistful-proto": "2.0.1-ed97a0e.0",
"@vality/magista-proto": "2.0.2-37b81e6.0", "@vality/magista-proto": "2.0.2-37b81e6.0",
"@vality/ng-core": "16.2.1-pr-40-44df7b7.0", "@vality/ng-core": "16.2.1-pr-40-ea573e6.0",
"@vality/payout-manager-proto": "2.0.0", "@vality/payout-manager-proto": "2.0.0",
"@vality/repairer-proto": "2.0.2-f5e3b7a.0", "@vality/repairer-proto": "2.0.2-f5e3b7a.0",
"@vality/thrift-ts": "2.4.1-8ad5123.0", "@vality/thrift-ts": "2.4.1-8ad5123.0",
@ -37,7 +37,6 @@
"coerce-property": "15.0.1", "coerce-property": "15.0.1",
"css-element-queries": "1.2.3", "css-element-queries": "1.2.3",
"date-fns": "2.30.0", "date-fns": "2.30.0",
"fuse.js": "6.6.2",
"humanize-duration": "3.21.0", "humanize-duration": "3.21.0",
"inputmask": "5.0.7", "inputmask": "5.0.7",
"keycloak-angular": "14.0.0", "keycloak-angular": "14.0.0",
@ -6001,9 +6000,9 @@
"integrity": "sha512-gJizpTWuB74L+XuJ+dUaxAwJDkycdnuVwrXWIl/NKcS7++/zgrgTpw+tM5/Te3rWqkkCnSxC1SK0C4aPbbtifg==" "integrity": "sha512-gJizpTWuB74L+XuJ+dUaxAwJDkycdnuVwrXWIl/NKcS7++/zgrgTpw+tM5/Te3rWqkkCnSxC1SK0C4aPbbtifg=="
}, },
"node_modules/@vality/ng-core": { "node_modules/@vality/ng-core": {
"version": "16.2.1-pr-40-44df7b7.0", "version": "16.2.1-pr-40-ea573e6.0",
"resolved": "https://registry.npmjs.org/@vality/ng-core/-/ng-core-16.2.1-pr-40-44df7b7.0.tgz", "resolved": "https://registry.npmjs.org/@vality/ng-core/-/ng-core-16.2.1-pr-40-ea573e6.0.tgz",
"integrity": "sha512-2j4CXD4mhPukIIwijJ3U2Hl+iMDQ5AQ6/LPvBU2TyXbQvc4v2Ne8S8CCXzKetCrUZkY2IGErUqF/5aJ9+j/v4A==", "integrity": "sha512-RgkZntHMFm9QYwE904ZVz1O+Go17FZH1tuTms3/RuAD6Kvrf4vJG+FaKCe7jCDYmzFMWXLfXGjfkQwazQA7zxA==",
"dependencies": { "dependencies": {
"@angular/material-date-fns-adapter": "^16.0.0", "@angular/material-date-fns-adapter": "^16.0.0",
"@ng-matero/extensions": "^16.0.0", "@ng-matero/extensions": "^16.0.0",
@ -6012,6 +6011,7 @@
"@s-libs/ng-core": "^16.0.0", "@s-libs/ng-core": "^16.0.0",
"@s-libs/rxjs-core": "^16.0.0", "@s-libs/rxjs-core": "^16.0.0",
"dinero.js": "^2.0.0-alpha.14", "dinero.js": "^2.0.0-alpha.14",
"fuse.js": "^7.0.0",
"ng-let": "^16.0.1", "ng-let": "^16.0.1",
"tslib": "^2.3.0" "tslib": "^2.3.0"
}, },
@ -13376,9 +13376,9 @@
} }
}, },
"node_modules/fuse.js": { "node_modules/fuse.js": {
"version": "6.6.2", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-6.6.2.tgz", "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.0.0.tgz",
"integrity": "sha512-cJaJkxCCxC8qIIcPBF9yGxY0W/tVZS3uEISDxhYIdtk8OL93pe+6Zj7LjCqVV4dzbqcriOZ+kQ/NE4RXZHsIGA==", "integrity": "sha512-14F4hBIxqKvD4Zz/XjDc3y94mNZN6pRv3U13Udo0lNLCWRBUsrMv2xwcF/y/Z5sV6+FQW+/ow68cHpm4sunt8Q==",
"engines": { "engines": {
"node": ">=10" "node": ">=10"
} }

View File

@ -37,7 +37,7 @@
"@vality/dominant-cache-proto": "2.0.0", "@vality/dominant-cache-proto": "2.0.0",
"@vality/fistful-proto": "2.0.1-ed97a0e.0", "@vality/fistful-proto": "2.0.1-ed97a0e.0",
"@vality/magista-proto": "2.0.2-37b81e6.0", "@vality/magista-proto": "2.0.2-37b81e6.0",
"@vality/ng-core": "16.2.1-pr-40-44df7b7.0", "@vality/ng-core": "16.2.1-pr-40-ea573e6.0",
"@vality/payout-manager-proto": "2.0.0", "@vality/payout-manager-proto": "2.0.0",
"@vality/repairer-proto": "2.0.2-f5e3b7a.0", "@vality/repairer-proto": "2.0.2-f5e3b7a.0",
"@vality/thrift-ts": "2.4.1-8ad5123.0", "@vality/thrift-ts": "2.4.1-8ad5123.0",
@ -45,7 +45,6 @@
"coerce-property": "15.0.1", "coerce-property": "15.0.1",
"css-element-queries": "1.2.3", "css-element-queries": "1.2.3",
"date-fns": "2.30.0", "date-fns": "2.30.0",
"fuse.js": "6.6.2",
"humanize-duration": "3.21.0", "humanize-duration": "3.21.0",
"inputmask": "5.0.7", "inputmask": "5.0.7",
"keycloak-angular": "14.0.0", "keycloak-angular": "14.0.0",

View File

@ -1,6 +1,5 @@
<div fxLayout="column" fxLayoutGap="24px"> <div fxLayout="column" fxLayoutGap="24px">
<div class="mat-headline-4">Shops</div> <div class="mat-headline-4">Shops</div>
<v-input-field [formControl]="filterControl" fxFlex="100" label="Filter"></v-input-field>
<cc-shops-table <cc-shops-table
[progress]="progress$ | async" [progress]="progress$ | async"
[shops]="shopsParty$ | async" [shops]="shopsParty$ | async"

View File

@ -1,7 +1,6 @@
import { ChangeDetectionStrategy, Component } from '@angular/core'; import { ChangeDetectionStrategy, Component } from '@angular/core';
import { FormControl } from '@angular/forms'; import { withLatestFrom } from 'rxjs';
import { combineLatest, map } from 'rxjs'; import { map, shareReplay } from 'rxjs/operators';
import { debounceTime, shareReplay, startWith, withLatestFrom } from 'rxjs/operators';
import { PartyShopsService } from './party-shops.service'; import { PartyShopsService } from './party-shops.service';
@ -11,21 +10,7 @@ import { PartyShopsService } from './party-shops.service';
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
}) })
export class PartyShopsComponent { export class PartyShopsComponent {
filterControl = new FormControl(''); shopsParty$ = this.partyShopsService.shops$.pipe(
shopsParty$ = combineLatest([
this.partyShopsService.shops$,
this.filterControl.valueChanges.pipe(
startWith(this.filterControl.value),
debounceTime(200),
),
]).pipe(
map(([shops, searchStr]) =>
searchStr
? shops.filter((s) =>
JSON.stringify(s).toLowerCase().includes(searchStr.toLowerCase()),
)
: shops,
),
withLatestFrom(this.partyShopsService.party$), withLatestFrom(this.partyShopsService.party$),
map(([shops, party]) => shops.map((shop) => ({ shop, party }))), map(([shops, party]) => shops.map((shop) => ({ shop, party }))),
shareReplay({ refCount: true, bufferSize: 1 }), shareReplay({ refCount: true, bufferSize: 1 }),

View File

@ -131,6 +131,9 @@ export class PayoutsComponent implements OnInit {
search(options?: UpdateOptions) { search(options?: UpdateOptions) {
const value = this.qp.params; const value = this.qp.params;
if (!value.dateRange) {
return;
}
this.fetchPayoutsService.load( this.fetchPayoutsService.load(
clean({ clean({
common_search_query_params: clean({ common_search_query_params: clean({

View File

@ -1,17 +1,10 @@
<cc-page-layout title="Search merchants"> <cc-page-layout title="Search merchants">
<mat-card>
<mat-card-content>
<cc-parties-search-filters
[initParams]="initSearchParams$ | async"
(searchParamsChanged$)="searchParamsUpdated($event)"
></cc-parties-search-filters>
</mat-card-content>
</mat-card>
<v-table <v-table
[columns]="columns" [columns]="columns"
[data]="parties$ | async" [data]="parties$ | async"
[filter]="initSearchParams$ | async"
[progress]="inProgress$ | async" [progress]="inProgress$ | async"
noActions noActions
(filterChange)="searchParamsUpdated($event)"
></v-table> ></v-table>
</cc-page-layout> </cc-page-layout>

View File

@ -3,12 +3,12 @@ import { Router } from '@angular/router';
import { Party } from '@vality/deanonimus-proto/deanonimus'; import { Party } from '@vality/deanonimus-proto/deanonimus';
import { Column, createOperationColumn } from '@vality/ng-core'; import { Column, createOperationColumn } from '@vality/ng-core';
import startCase from 'lodash-es/startCase'; import startCase from 'lodash-es/startCase';
import { map } from 'rxjs/operators';
import { FetchPartiesService } from '@cc/app/shared/services/fetch-parties.service'; import { FetchPartiesService } from '@cc/app/shared/services/fetch-parties.service';
import { getUnionKey } from '../../../utils'; import { getUnionKey } from '../../../utils';
import { PartiesSearchFiltersParams } from './parties-search-filters';
import { SearchPartiesService } from './search-parties.service'; import { SearchPartiesService } from './search-parties.service';
@Component({ @Component({
@ -17,7 +17,7 @@ import { SearchPartiesService } from './search-parties.service';
providers: [SearchPartiesService, FetchPartiesService], providers: [SearchPartiesService, FetchPartiesService],
}) })
export class SearchPartiesComponent { export class SearchPartiesComponent {
initSearchParams$ = this.partiesService.data$; initSearchParams$ = this.partiesService.data$.pipe(map((p) => p?.text ?? ''));
inProgress$ = this.fetchPartiesService.inProgress$; inProgress$ = this.fetchPartiesService.inProgress$;
parties$ = this.fetchPartiesService.parties$; parties$ = this.fetchPartiesService.parties$;
columns: Column<Party>[] = [ columns: Column<Party>[] = [
@ -71,8 +71,8 @@ export class SearchPartiesComponent {
private router: Router, private router: Router,
) {} ) {}
searchParamsUpdated($event: PartiesSearchFiltersParams) { searchParamsUpdated(filter: string) {
this.partiesService.preserve($event); this.partiesService.preserve({ text: filter });
this.fetchPartiesService.searchParties($event.text); this.fetchPartiesService.searchParties(filter);
} }
} }

View File

@ -1,6 +1,5 @@
<cc-page-layout title="Terminals"> <cc-page-layout title="Terminals">
<cc-page-layout-actions></cc-page-layout-actions> <cc-page-layout-actions></cc-page-layout-actions>
<v-input-field [formControl]="searchControl" label="Search"></v-input-field>
<v-table <v-table
[(sort)]="sort" [(sort)]="sort"
[columns]="columns" [columns]="columns"
@ -8,6 +7,7 @@
[progress]="progress$ | async" [progress]="progress$ | async"
size="50" size="50"
sortOnFront sortOnFront
standaloneFilter
(update)="update()" (update)="update()"
> >
<v-table-actions> <v-table-actions>

View File

@ -1,5 +1,4 @@
import { Component, ViewChild, TemplateRef } from '@angular/core'; import { Component, ViewChild, TemplateRef } from '@angular/core';
import { FormControl } from '@angular/forms';
import { Sort } from '@angular/material/sort'; import { Sort } from '@angular/material/sort';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { untilDestroyed, UntilDestroy } from '@ngneat/until-destroy'; import { untilDestroyed, UntilDestroy } from '@ngneat/until-destroy';
@ -11,10 +10,10 @@ import {
} from '@vality/domain-proto/domain'; } from '@vality/domain-proto/domain';
import { Column } from '@vality/ng-core'; import { Column } from '@vality/ng-core';
import startCase from 'lodash-es/startCase'; import startCase from 'lodash-es/startCase';
import { combineLatest } from 'rxjs'; import { of } from 'rxjs';
import { startWith, map, debounceTime, tap, take } from 'rxjs/operators'; import { map, take } from 'rxjs/operators';
import { objectToJSON, createFullTextSearch, getUnionValue, getUnionKey } from '../../../utils'; import { getUnionValue, getUnionKey } from '../../../utils';
import { DomainStoreService } from '../../api/domain-config'; import { DomainStoreService } from '../../api/domain-config';
import { PartiesStoreService } from '../../api/payment-processing'; import { PartiesStoreService } from '../../api/payment-processing';
import { SidenavInfoService } from '../../shared/components/sidenav-info'; import { SidenavInfoService } from '../../shared/components/sidenav-info';
@ -25,7 +24,6 @@ import { SidenavInfoService } from '../../shared/components/sidenav-info';
templateUrl: './terminals.component.html', templateUrl: './terminals.component.html',
}) })
export class TerminalsComponent { export class TerminalsComponent {
searchControl = new FormControl('');
columns: Column<TerminalObject>[] = [ columns: Column<TerminalObject>[] = [
{ field: 'ref.id', sortable: true }, { field: 'ref.id', sortable: true },
{ {
@ -83,32 +81,7 @@ export class TerminalsComponent {
}, },
}, },
]; ];
data$ = combineLatest([ data$ = this.domainStoreService.getObjects('terminal');
this.domainStoreService.getObjects('terminal').pipe(
map((objects) =>
createFullTextSearch(
objects,
objects.map((o) => ({
ref: o.ref.id,
data: JSON.stringify(objectToJSON(o.data)),
name: o.data.name,
description: o.data.description,
})),
),
),
),
this.searchControl.valueChanges.pipe(
startWith(this.searchControl.value),
debounceTime(100),
),
]).pipe(
tap(([, search]) => {
if (search) {
this.sort = { active: '', direction: '' };
}
}),
map(([fts, search]) => fts.search(search)),
);
progress$ = this.domainStoreService.isLoading$; progress$ = this.domainStoreService.isLoading$;
sort: Sort = { active: 'data.name', direction: 'asc' }; sort: Sort = { active: 'data.name', direction: 'asc' };
openedTerminal?: TerminalObject; openedTerminal?: TerminalObject;
@ -200,13 +173,15 @@ export class TerminalsComponent {
} }
private getProvider(terminalObj: TerminalObject) { private getProvider(terminalObj: TerminalObject) {
return this.domainStoreService return terminalObj.data.provider_ref
? this.domainStoreService
.getObjects('provider') .getObjects('provider')
.pipe( .pipe(
map((providers) => map((providers) =>
providers.find((p) => p.ref.id === terminalObj.data.provider_ref.id), providers.find((p) => p.ref.id === terminalObj.data.provider_ref.id),
), ),
); )
: of(null);
} }
private getTerminalShopWalletDelegates(terminalObj: TerminalObject) { private getTerminalShopWalletDelegates(terminalObj: TerminalObject) {

View File

@ -5,6 +5,7 @@
[progress]="progress" [progress]="progress"
[size]="100" [size]="100"
sortOnFront sortOnFront
standaloneFilter
(update)="update.emit()" (update)="update.emit()"
></v-table> ></v-table>

View File

@ -1,12 +0,0 @@
import Fuse from 'fuse.js';
export function createFullTextSearch<T extends object, O extends object>(
source: T[],
objects: O[],
options: Fuse.IFuseOptions<O> = { keys: Object.keys(objects[0]) },
) {
const fuse = new Fuse(objects, options);
return {
search: (str: string) => (str ? fuse.search(str).map((r) => source[r.refIndex]) : source),
};
}

View File

@ -1 +0,0 @@
export * from './create-full-text-search';

View File

@ -15,4 +15,3 @@ export * from './enumerate';
export * from './thrift-instance'; export * from './thrift-instance';
export * from './csv'; export * from './csv';
export * from './thrift'; export * from './thrift';
export * from './full-text-search';