IMP-136: Show Contract Id and Party in Wallets Table (#340)

This commit is contained in:
Rinat Arsaev 2024-03-15 16:49:40 +07:00 committed by GitHub
parent 28bfdd3b1a
commit fc1335e8e0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 92 additions and 8 deletions

8
package-lock.json generated
View File

@ -22,7 +22,7 @@
"@ngneat/input-mask": "6.0.0",
"@vality/deanonimus-proto": "2.0.1-2a02d87.0",
"@vality/domain-proto": "2.0.1-decfa45.0",
"@vality/fistful-proto": "2.0.1-8ecf2b7.0",
"@vality/fistful-proto": "2.0.1-6600be9.0",
"@vality/machinegun-proto": "1.0.0",
"@vality/magista-proto": "2.0.2-28d11b9.0",
"@vality/ng-core": "^17.2.1-pr-57-3adeb57.0",
@ -6439,9 +6439,9 @@
}
},
"node_modules/@vality/fistful-proto": {
"version": "2.0.1-8ecf2b7.0",
"resolved": "https://registry.npmjs.org/@vality/fistful-proto/-/fistful-proto-2.0.1-8ecf2b7.0.tgz",
"integrity": "sha512-F2nR/OIq3dFhVW+Y1hQROMtma5Pyj50grS2GNs8gvNbKzlEIMN8Osvdr6Z5khFbuctfB8GetuWldg/fGm3k8KQ=="
"version": "2.0.1-6600be9.0",
"resolved": "https://registry.npmjs.org/@vality/fistful-proto/-/fistful-proto-2.0.1-6600be9.0.tgz",
"integrity": "sha512-ULrAg0V7GpvdMaIBUgI8WX9m+qoaOPgPFEYF/bqoe+XHh4ktmv8LiCm2La35Wzy6NTdm/1kanT69AxJUtsy7VA=="
},
"node_modules/@vality/machinegun-proto": {
"version": "1.0.0",

View File

@ -30,7 +30,7 @@
"@ngneat/input-mask": "6.0.0",
"@vality/deanonimus-proto": "2.0.1-2a02d87.0",
"@vality/domain-proto": "2.0.1-decfa45.0",
"@vality/fistful-proto": "2.0.1-8ecf2b7.0",
"@vality/fistful-proto": "2.0.1-6600be9.0",
"@vality/machinegun-proto": "1.0.0",
"@vality/magista-proto": "2.0.2-28d11b9.0",
"@vality/ng-core": "^17.2.1-pr-57-3adeb57.0",

View File

@ -0,0 +1,46 @@
import { Injectable } from '@angular/core';
import {
identity_ManagementCodegenClient,
ThriftAstMetadata,
identity_Management,
} from '@vality/fistful-proto';
import * as identity from '@vality/fistful-proto/internal/identity';
import { combineLatest, from, map, Observable, switchMap } from 'rxjs';
import { environment } from '../../../environments/environment';
import { ConfigService } from '../../core/config.service';
import { KeycloakTokenInfoService, toWachterHeaders } from '../../shared/services';
@Injectable({ providedIn: 'root' })
export class IdentityManagementService {
private client$: Observable<identity_ManagementCodegenClient>;
constructor(
private keycloakTokenInfoService: KeycloakTokenInfoService,
configService: ConfigService,
) {
const headers$ = this.keycloakTokenInfoService.info$.pipe(
map(toWachterHeaders('IdentityManagement')),
);
const metadata$ = from(
import('@vality/fistful-proto/metadata.json').then(
(m) => m.default as ThriftAstMetadata[],
),
);
this.client$ = combineLatest([metadata$, headers$]).pipe(
switchMap(([metadata, headers]) =>
identity_Management({
metadata,
headers,
logging: environment.logging.requests,
...configService.config.api.wachter,
}),
),
);
}
// eslint-disable-next-line @typescript-eslint/naming-convention
Get(id: identity.IdentityID, range: identity.EventRange): Observable<identity.IdentityState> {
return this.client$.pipe(switchMap((c) => c.Get(id, range)));
}
}

View File

@ -0,0 +1 @@
export * from './identity-management.service';

View File

@ -2,6 +2,7 @@ import { Component, OnInit, Inject, ViewChild, DestroyRef } from '@angular/core'
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { FormBuilder, FormControl } from '@angular/forms';
import { SearchWalletHit } from '@vality/deanonimus-proto/internal/deanonimus';
import { IdentityState } from '@vality/fistful-proto/identity';
import { AccountBalance } from '@vality/fistful-proto/internal/account';
import { StatWallet } from '@vality/fistful-proto/internal/fistful_stat';
import {
@ -22,6 +23,7 @@ import { MemoizeExpiring } from 'typescript-memoize';
import { WalletParams } from '@cc/app/api/fistful-stat/query-dsl/types/wallet';
import { ManagementService } from '@cc/app/api/wallet';
import { IdentityManagementService } from '../../api/identity';
import { createCurrencyColumn, createPartyColumn } from '../../shared';
import { DEBOUNCE_TIME_MS } from '../../tokens';
@ -67,6 +69,18 @@ export class WalletsComponent implements OnInit {
(d) => this.getBalance(d.id).pipe(map((b) => b.currency.symbolic_code)),
{ lazy: true },
),
{
field: 'contract_id',
formatter: (d) =>
this.getIdentity(d.identity_id).pipe(map((identity) => identity.contract_id)),
lazy: true,
},
createPartyColumn(
'party',
(d) => this.getIdentity(d.identity_id).pipe(map((identity) => identity.party_id)),
undefined,
{ lazy: true },
),
];
fullTextSearchColumns: Column<SearchWalletHit>[] = [
{ field: 'wallet.id' },
@ -114,6 +128,7 @@ export class WalletsComponent implements OnInit {
private log: NotifyLogService,
@Inject(DEBOUNCE_TIME_MS) private debounceTimeMs: number,
private destroyRef: DestroyRef,
private identityManagementService: IdentityManagementService,
) {}
ngOnInit() {
@ -163,4 +178,15 @@ export class WalletsComponent implements OnInit {
shareReplay({ refCount: true, bufferSize: 1 }),
);
}
@MemoizeExpiring(5 * 60_000)
getIdentity(id: string) {
return this.identityManagementService.Get(id, {}).pipe(
catchError((err) => {
this.log.error(err);
return of<Partial<IdentityState>>({});
}),
shareReplay({ refCount: true, bufferSize: 1 }),
);
}
}

View File

@ -1,7 +1,8 @@
import { inject } from '@angular/core';
import { Router } from '@angular/router';
import { PossiblyAsync, ColumnObject, getPossiblyAsyncObservable } from '@vality/ng-core';
import get from 'lodash-es/get';
import { switchMap, map } from 'rxjs/operators';
import { switchMap, map, take } from 'rxjs/operators';
import { PartiesStoreService } from '../../../api/payment-processing';
@ -12,6 +13,7 @@ export function createPartyColumn<T extends object>(
params: Partial<ColumnObject<T>> = {},
): ColumnObject<T> {
const partiesStoreService = inject(PartiesStoreService);
const router = inject(Router);
if (!selectPartyId) {
selectPartyId = (d) => get(d, field);
}
@ -27,7 +29,16 @@ export function createPartyColumn<T extends object>(
header: 'Party',
description: selectPartyId,
formatter: selectPartyEmail,
link: (d) => `/party/${selectPartyId(d)}`,
click: (d) => {
getPossiblyAsyncObservable(selectPartyId(d))
.pipe(
take(1),
map((id) => `/party/${id}`),
)
.subscribe((url) => {
void router.navigate([url]);
});
},
...params,
} as ColumnObject<T>;
}

View File

@ -20,7 +20,7 @@ export function createShopColumn<T extends object>(
return {
field,
header: 'Shop',
description: (d) => selectPartyId(d),
description: (d) => selectShopId(d),
formatter: (d) =>
getPossiblyAsyncObservable(selectPartyId(d)).pipe(
switchMap((partyId) =>