diff --git a/package-lock.json b/package-lock.json index 8fd8eb78..13bc0391 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,7 +26,7 @@ "@vality/fistful-proto": "2.0.1-88e69a5.0", "@vality/machinegun-proto": "1.0.1-3decc8f.0", "@vality/magista-proto": "2.0.2-ec1bdb9.0", - "@vality/ng-core": "18.4.1-pr-74-55d4acd.0", + "@vality/ng-core": "18.4.1-pr-78-9131f9a.0", "@vality/ng-thrift": "18.0.1-pr-13-bdb6d51.0", "@vality/repairer-proto": "2.0.2-07b73e9.0", "@vality/scrooge-proto": "0.1.1-9ce7fc6.0", @@ -5969,9 +5969,9 @@ "integrity": "sha512-XWF7qM/CARRAey0scGVhfGU6jNq+UdlGE2mg3jn4eIFDuIWQJqsT+Bah300RBUrl+XgFsmj95C6HWRfeA5Q8kw==" }, "node_modules/@vality/ng-core": { - "version": "18.4.1-pr-74-55d4acd.0", - "resolved": "https://registry.npmjs.org/@vality/ng-core/-/ng-core-18.4.1-pr-74-55d4acd.0.tgz", - "integrity": "sha512-EkGTPth5+HA0MLc+BYLIV5ie7xnwBrXftTxoVJw+5zlcWoLm5V1+10AGz6wmhX4VIunFFZR/p9XUNAhNqvluVw==", + "version": "18.4.1-pr-78-9131f9a.0", + "resolved": "https://registry.npmjs.org/@vality/ng-core/-/ng-core-18.4.1-pr-78-9131f9a.0.tgz", + "integrity": "sha512-qmTGnGe+pBWlIQ+cX64pt2aLWdoLM6M2Apc180dQQrLca4VBHB4Oh8yo7vvv/sxws1DLXEzWutgNzi9/bRdtZQ==", "dependencies": { "@angular/material-date-fns-adapter": "^18.2.2", "@ng-matero/extensions": "^18.2.0", diff --git a/package.json b/package.json index cb3affb4..1f9a42e1 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "@vality/fistful-proto": "2.0.1-88e69a5.0", "@vality/machinegun-proto": "1.0.1-3decc8f.0", "@vality/magista-proto": "2.0.2-ec1bdb9.0", - "@vality/ng-core": "18.4.1-pr-74-55d4acd.0", + "@vality/ng-core": "18.4.1-pr-78-9131f9a.0", "@vality/ng-thrift": "18.0.1-pr-13-bdb6d51.0", "@vality/repairer-proto": "2.0.2-07b73e9.0", "@vality/scrooge-proto": "0.1.1-9ce7fc6.0", diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 2b2c6249..433ddcdb 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -12,8 +12,8 @@ import { environment } from '../environments/environment'; import { ROUTING_CONFIG as CLAIMS_ROUTING_CONFIG } from './sections/claims/routing-config'; import { ROUTING_CONFIG as DEPOSITS_ROUTING_CONFIG } from './sections/deposits/routing-config'; import { ROUTING_CONFIG as DOMAIN_ROUTING_CONFIG } from './sections/domain/routing-config'; +import { ROUTING_CONFIG as MACHINES_ROUTING_CONFIG } from './sections/machines/routing-config'; import { ROUTING_CONFIG as PAYMENTS_ROUTING_CONFIG } from './sections/payments/routing-config'; -import { ROUTING_CONFIG as REPAIRING_ROUTING_CONFIG } from './sections/repairing/routing-config'; import { ROUTING_CONFIG as PARTIES_ROUTING_CONFIG } from './sections/search-parties/routing-config'; import { SHOPS_ROUTING_CONFIG } from './sections/shops'; import { ROUTING_CONFIG as SOURCES_ROUTING_CONFIG } from './sections/sources/routing-config'; @@ -73,7 +73,7 @@ export class AppComponent { { label: 'Machines', url: '/machines', - services: REPAIRING_ROUTING_CONFIG.services, + services: MACHINES_ROUTING_CONFIG.services, }, { label: 'Sources', diff --git a/src/app/sections/chargebacks/chargebacks.component.html b/src/app/sections/chargebacks/chargebacks.component.html index bb82293f..2e33f3bc 100644 --- a/src/app/sections/chargebacks/chargebacks.component.html +++ b/src/app/sections/chargebacks/chargebacks.component.html @@ -1,4 +1,4 @@ - + @@ -47,14 +47,6 @@ (more)="more()" (update)="reload($event)" > - diff --git a/src/app/sections/chargebacks/chargebacks.component.ts b/src/app/sections/chargebacks/chargebacks.component.ts index 7e1462ae..42898af0 100644 --- a/src/app/sections/chargebacks/chargebacks.component.ts +++ b/src/app/sections/chargebacks/chargebacks.component.ts @@ -29,7 +29,6 @@ import { CHARGEBACK_CATEGORIES, } from '@cc/app/api/fistful-stat'; -import { ChangeChargebacksStatusDialogComponent } from '../../shared/components/change-chargebacks-status-dialog'; import { DATE_RANGE_DAYS, DEBOUNCE_TIME_MS } from '../../tokens'; import { CreateChargebacksByFileDialogComponent } from './components/create-chargebacks-by-file-dialog/create-chargebacks-by-file-dialog.component'; @@ -46,7 +45,7 @@ type FormValue = { @Component({ selector: 'cc-chargebacks', templateUrl: './chargebacks.component.html', - styles: [], + providers: [FetchChargebacksService], }) export class ChargebacksComponent implements OnInit { filtersForm = new FormGroup( @@ -141,17 +140,4 @@ export class ChargebacksComponent implements OnInit { }); }); } - - changeStatuses() { - this.dialog - .open(ChangeChargebacksStatusDialogComponent, { chargebacks: this.selected }) - .afterClosed() - .pipe( - filter((res) => res.status === DialogResponseStatus.Success), - takeUntilDestroyed(this.dr), - ) - .subscribe(() => { - this.reload(); - }); - } } diff --git a/src/app/sections/chargebacks/chargebacks.module.ts b/src/app/sections/chargebacks/chargebacks.module.ts index 39d874f5..d5a64468 100644 --- a/src/app/sections/chargebacks/chargebacks.module.ts +++ b/src/app/sections/chargebacks/chargebacks.module.ts @@ -20,6 +20,8 @@ import { } from '@vality/ng-core'; import { ThriftPipesModule } from '@vality/ng-thrift'; +import { ChargebacksTableComponent } from '@cc/app/shared/components/chargebacks-table'; + import { UploadCsvComponent } from '../../../components/upload-csv'; import { PageLayoutModule, ShopFieldModule } from '../../shared'; import { MerchantFieldModule } from '../../shared/components/merchant-field'; @@ -31,15 +33,10 @@ import { import { ChargebacksRoutingModule } from './chargebacks-routing.module'; import { ChargebacksComponent } from './chargebacks.component'; -import { ChargebacksTableComponent } from './components/chargebacks-table/chargebacks-table.component'; import { CreateChargebacksByFileDialogComponent } from './components/create-chargebacks-by-file-dialog/create-chargebacks-by-file-dialog.component'; @NgModule({ - declarations: [ - ChargebacksComponent, - ChargebacksTableComponent, - CreateChargebacksByFileDialogComponent, - ], + declarations: [ChargebacksComponent, CreateChargebacksByFileDialogComponent], imports: [ CommonModule, ChargebacksRoutingModule, @@ -67,6 +64,7 @@ import { CreateChargebacksByFileDialogComponent } from './components/create-char MatInputModule, MatCheckboxModule, UploadCsvComponent, + ChargebacksTableComponent, ], }) export class ChargebacksModule {} diff --git a/src/app/sections/chargebacks/components/chargebacks-table/chargebacks-table.component.ts b/src/app/sections/chargebacks/components/chargebacks-table/chargebacks-table.component.ts deleted file mode 100644 index 370edbce..00000000 --- a/src/app/sections/chargebacks/components/chargebacks-table/chargebacks-table.component.ts +++ /dev/null @@ -1,144 +0,0 @@ -import { Component, Input, Output, EventEmitter } from '@angular/core'; -import { InvoicePaymentChargebackStatus } from '@vality/magista-proto/internal/proto/domain'; -import { StatChargeback } from '@vality/magista-proto/magista'; -import { LoadOptions, Column, TagColumn } from '@vality/ng-core'; -import { getUnionKey } from '@vality/ng-thrift'; -import startCase from 'lodash-es/startCase'; - -import { AmountCurrencyService } from '../../../../shared/services'; - -@Component({ - selector: 'cc-chargebacks-table', - templateUrl: './chargebacks-table.component.html', - styles: [], -}) -export class ChargebacksTableComponent { - @Input() data!: StatChargeback[]; - @Input() isLoading?: boolean | null; - @Input() hasMore?: boolean | null; - @Input() selected?: StatChargeback[]; - - @Output() selectedChange = new EventEmitter(); - @Output() update = new EventEmitter(); - @Output() more = new EventEmitter(); - - columns: Column[] = [ - { field: 'chargeback_id', header: 'Id' }, - { - field: 'chargeback_reason', - header: 'Reason', - formatter: (data) => startCase(getUnionKey(data.chargeback_reason.category)), - description: (data) => data.chargeback_reason.code, - }, - { - field: 'chargeback_status', - type: 'tag', - header: 'Status', - formatter: (data) => getUnionKey(data.chargeback_status), - typeParameters: { - label: (data) => startCase(getUnionKey(data.chargeback_status)), - tags: { - pending: { color: 'pending' }, - accepted: { color: 'success' }, - rejected: { color: 'warn' }, - cancelled: { color: 'neutral' }, - }, - }, - } as TagColumn, - { - field: 'amount', - type: 'currency', - formatter: (data) => - this.amountCurrencyService.toMajor(data.amount, data.currency_code.symbolic_code), - typeParameters: { - currencyCode: (data) => data.currency_code.symbolic_code, - }, - }, - { - field: 'levy_amount', - type: 'currency', - formatter: (data) => - this.amountCurrencyService.toMajor( - data.levy_amount, - data.levy_currency_code.symbolic_code, - ), - typeParameters: { - currencyCode: (data) => data.levy_currency_code.symbolic_code, - }, - }, - { - field: 'fee', - type: 'currency', - formatter: (data) => - this.amountCurrencyService.toMajor(data.fee, data.currency_code.symbolic_code), - typeParameters: { - currencyCode: (data) => data.currency_code.symbolic_code, - }, - }, - { - field: 'provider_fee', - type: 'currency', - formatter: (data) => - this.amountCurrencyService.toMajor( - data.provider_fee, - data.currency_code.symbolic_code, - ), - typeParameters: { - currencyCode: (data) => data.currency_code.symbolic_code, - }, - }, - { - field: 'external_fee', - type: 'currency', - formatter: (data) => - this.amountCurrencyService.toMajor( - data.external_fee, - data.currency_code.symbolic_code, - ), - typeParameters: { - currencyCode: (data) => data.currency_code.symbolic_code, - }, - }, - { - field: 'stage', - formatter: (data) => getUnionKey(data.stage), - }, - { - field: 'invoice_id', - header: 'Invoice Id (Payment Id)', - description: 'payment_id', - link: (data) => - `/party/${data.party_id}/invoice/${data.invoice_id}/payment/${data.payment_id}`, - }, - { - field: 'created_at', - type: 'datetime', - }, - { - field: 'party_id', - header: 'Party', - }, - { - field: 'shop_id', - header: 'Shop', - }, - { - field: 'external_id', - hide: true, - }, - { - field: 'content.type', - description: 'content.data', - header: 'Content', - hide: true, - }, - // createOperationColumn([ - // { - // label: 'Change status', - // click: (data) => undefined, - // }, - // ]), - ]; - - constructor(private amountCurrencyService: AmountCurrencyService) {} -} diff --git a/src/app/sections/chargebacks/fetch-chargebacks.service.ts b/src/app/sections/chargebacks/fetch-chargebacks.service.ts index dd25c79b..1106eb55 100644 --- a/src/app/sections/chargebacks/fetch-chargebacks.service.ts +++ b/src/app/sections/chargebacks/fetch-chargebacks.service.ts @@ -6,9 +6,7 @@ import { map, catchError } from 'rxjs/operators'; import { MerchantStatisticsService } from '../../api/magista'; -@Injectable({ - providedIn: 'root', -}) +@Injectable() export class FetchChargebacksService extends FetchSuperclass< StatChargeback, ChargebackSearchQuery diff --git a/src/app/sections/claims/claims-table/claims-table.component.html b/src/app/sections/claims/claims-table/claims-table.component.html index 4576b42a..524f7d90 100644 --- a/src/app/sections/claims/claims-table/claims-table.component.html +++ b/src/app/sections/claims/claims-table/claims-table.component.html @@ -1,5 +1,5 @@ - - + diff --git a/src/app/sections/claims/claims-table/claims-table.component.ts b/src/app/sections/claims/claims-table/claims-table.component.ts index 8c2c068a..13664d98 100644 --- a/src/app/sections/claims/claims-table/claims-table.component.ts +++ b/src/app/sections/claims/claims-table/claims-table.component.ts @@ -1,20 +1,11 @@ -import { - Component, - Input, - Output, - EventEmitter, - booleanAttribute, - input, - computed, -} from '@angular/core'; -import { Router } from '@angular/router'; -import { Claim, ClaimStatus } from '@vality/domain-proto/claim_management'; -import { Column, LoadOptions, TagColumn, createOperationColumn } from '@vality/ng-core'; +import { Component, Input, Output, EventEmitter, booleanAttribute, input } from '@angular/core'; +import { toObservable } from '@angular/core/rxjs-interop'; +import { Claim } from '@vality/domain-proto/claim_management'; +import { Column2, LoadOptions, createMenuColumn } from '@vality/ng-core'; import { getUnionKey } from '@vality/ng-thrift'; -import isObject from 'lodash-es/isObject'; import startCase from 'lodash-es/startCase'; -import { createPartyColumn } from '../../../shared'; +import { createPartyColumn } from '@cc/app/shared/utils/table2'; @Component({ selector: 'cc-claims-table', @@ -30,48 +21,33 @@ export class ClaimsTableComponent { @Output() update = new EventEmitter(); @Output() more = new EventEmitter(); - columns = computed[]>(() => - this.sourceColumns.filter( - (c) => (isObject(c) && c?.field !== 'party_id') || !this.noParty(), - ), - ); - private sourceColumns: Column[] = [ - { field: 'id', link: (d) => this.getClaimLink(d.party_id, d.id) }, - createPartyColumn('party_id'), + columns: Column2[] = [ + { field: 'id', cell: (d) => ({ link: () => `/party/${d.party_id}/claim/${d.id}` }) }, + createPartyColumn((d) => ({ id: d.party_id }), { hidden: toObservable(this.noParty) }), { field: 'status', - type: 'tag', - formatter: (claim) => getUnionKey(claim.status), - typeParameters: { - label: (claim) => startCase(getUnionKey(claim.status)), + cell: (d) => ({ + value: startCase(getUnionKey(d.status)), tags: { - pending: { color: 'pending' }, - review: { color: 'pending' }, - pending_acceptance: { color: 'pending' }, - accepted: { color: 'success' }, - denied: { color: 'warn' }, - revoked: { color: 'neutral' }, + pending: 'pending', + review: 'pending', + pending_acceptance: 'pending', + accepted: 'success', + denied: 'warn', + revoked: 'neutral', }, - }, - } as TagColumn, - 'revision', - { field: 'created_at', type: 'datetime' }, - { field: 'updated_at', type: 'datetime' }, - createOperationColumn([ - { - label: 'Details', - click: (claim) => this.navigateToClaim(claim.party_id, claim.id), - }, - ]), + }), + }, + { field: 'revision' }, + { field: 'created_at', cell: { type: 'datetime' } }, + { field: 'updated_at', cell: { type: 'datetime' } }, + createMenuColumn((d) => ({ + items: [ + { + label: 'Details', + link: () => `/party/${d.party_id}/claim/${d.id}`, + }, + ], + })), ]; - - constructor(private router: Router) {} - - navigateToClaim(partyId: string, claimID: number) { - void this.router.navigate([this.getClaimLink(partyId, claimID)]); - } - - private getClaimLink(partyId: string, claimID: number): string { - return `/party/${partyId}/claim/${claimID}`; - } } diff --git a/src/app/sections/claims/claims.component.html b/src/app/sections/claims/claims.component.html index c009fb7f..41a7ff77 100644 --- a/src/app/sections/claims/claims.component.html +++ b/src/app/sections/claims/claims.component.html @@ -1,4 +1,4 @@ - + diff --git a/src/app/sections/deposit-details/reverts/reverts.component.html b/src/app/sections/deposit-details/reverts/reverts.component.html index 370142c0..85f628a2 100644 --- a/src/app/sections/deposit-details/reverts/reverts.component.html +++ b/src/app/sections/deposit-details/reverts/reverts.component.html @@ -1,6 +1,6 @@

Reverts

- - +
diff --git a/src/app/sections/deposit-details/reverts/reverts.component.ts b/src/app/sections/deposit-details/reverts/reverts.component.ts index 9f31e08e..7bb58fbc 100644 --- a/src/app/sections/deposit-details/reverts/reverts.component.ts +++ b/src/app/sections/deposit-details/reverts/reverts.component.ts @@ -1,11 +1,11 @@ import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core'; import { DepositStatus, StatDeposit, StatDepositRevert } from '@vality/fistful-proto/fistful_stat'; -import { DialogService, Column, UpdateOptions } from '@vality/ng-core'; +import { DialogService, UpdateOptions, Column2 } from '@vality/ng-core'; import { getUnionKey } from '@vality/ng-thrift'; import startCase from 'lodash-es/startCase'; import { filter } from 'rxjs/operators'; -import { createCurrencyColumn } from '@cc/app/shared/utils'; +import { createCurrencyColumn } from '@cc/app/shared/utils/table2'; import { CreateRevertDialogComponent } from './create-revert-dialog/create-revert-dialog.component'; import { FetchRevertsService } from './services/fetch-reverts/fetch-reverts.service'; @@ -23,27 +23,29 @@ export class RevertsComponent implements OnInit { reverts$ = this.fetchRevertsService.result$; hasMore$ = this.fetchRevertsService.hasMore$; isLoading$ = this.fetchRevertsService.isLoading$; - columns: Column[] = [ + columns: Column2[] = [ { field: 'id' }, { field: 'status', - type: 'tag', - formatter: (d) => getUnionKey(d.status), - typeParameters: { - label: (d) => startCase(getUnionKey(d.status)), - tags: { - pending: { color: 'pending' }, - succeeded: { color: 'success' }, - failed: { color: 'warn' }, - }, - }, + cell: (d) => ({ + value: startCase(getUnionKey(d.status)), + color: ( + { + pending: 'pending', + succeeded: 'success', + failed: 'warn', + } as const + )[getUnionKey(d.status)], + }), }, createCurrencyColumn( - 'amount', - (d) => d.body.amount, - (d) => d.body.currency.symbolic_code, + (d) => ({ + amount: d.body.amount, + code: d.body.currency.symbolic_code, + }), + { header: 'Amount' }, ), - { field: 'created_at', type: 'datetime' }, + { field: 'created_at', cell: { type: 'datetime' } }, ]; constructor( diff --git a/src/app/sections/deposits/deposits.component.html b/src/app/sections/deposits/deposits.component.html index 33226571..967ce329 100644 --- a/src/app/sections/deposits/deposits.component.html +++ b/src/app/sections/deposits/deposits.component.html @@ -1,4 +1,4 @@ - + @@ -22,7 +22,7 @@ - - + - + diff --git a/src/app/sections/deposits/deposits.component.ts b/src/app/sections/deposits/deposits.component.ts index d7a39e9a..6c55fae5 100644 --- a/src/app/sections/deposits/deposits.component.ts +++ b/src/app/sections/deposits/deposits.component.ts @@ -2,10 +2,9 @@ import { ChangeDetectionStrategy, Component, OnInit, Inject, DestroyRef } from ' import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { NonNullableFormBuilder } from '@angular/forms'; import { Router } from '@angular/router'; -import { StatDeposit, RevertStatus } from '@vality/fistful-proto/fistful_stat'; +import { fistful_stat } from '@vality/fistful-proto'; +import { StatDeposit } from '@vality/fistful-proto/fistful_stat'; import { - Column, - createOperationColumn, UpdateOptions, createDateRangeToToday, QueryParamsService, @@ -17,26 +16,24 @@ import { debounceTimeWithFirst, getValueChanges, countChanged, + Column2, + getEnumKey, + createMenuColumn, } from '@vality/ng-core'; import { getUnionKey } from '@vality/ng-thrift'; import { endOfDay } from 'date-fns'; import startCase from 'lodash-es/startCase'; import { filter, map, shareReplay } from 'rxjs/operators'; +import { createCurrencyColumn } from '@cc/app/shared/utils/table2'; + import { QueryDsl } from '../../api/fistful-stat'; -import { createCurrencyColumn } from '../../shared'; import { DATE_RANGE_DAYS, DEBOUNCE_TIME_MS } from '../../tokens'; import { CreateDepositDialogComponent } from './components/create-deposit-dialog/create-deposit-dialog.component'; import { CreateDepositsByFileDialogComponent } from './components/create-deposits-by-file-dialog/create-deposits-by-file-dialog.component'; import { FetchDepositsService } from './services/fetch-deposits/fetch-deposits.service'; -const REVERT_STATUS: { [N in RevertStatus]: string } = { - 0: 'none', - 1: 'partial', - 2: 'full', -}; - @Component({ templateUrl: 'deposits.component.html', changeDetection: ChangeDetectionStrategy.OnPush, @@ -56,30 +53,31 @@ export class DepositsComponent implements OnInit { deposits$ = this.fetchDepositsService.result$; hasMore$ = this.fetchDepositsService.hasMore$; isLoading$ = this.fetchDepositsService.isLoading$; - columns: Column[] = [ + columns: Column2[] = [ { field: 'id', - formatter: (d) => d.description || `#${d.id}`, - link: (d) => `/deposits/${d.id}`, - description: 'id', - maxWidth: 'max(300px, 30vw)', + cell: (d) => ({ + value: d.description || `#${d.id}`, + link: () => `/deposits/${d.id}`, + description: d.id, + }), }, { field: 'status', - type: 'tag', - formatter: (d) => getUnionKey(d.status), - typeParameters: { - label: (d) => startCase(getUnionKey(d.status)), - tags: { - pending: { color: 'pending' }, - succeeded: { color: 'success' }, - failed: { color: 'warn' }, - }, - }, + cell: (d) => ({ + value: startCase(getUnionKey(d.status)), + color: ( + { + pending: 'pending', + succeeded: 'success', + failed: 'warn', + } as const + )[getUnionKey(d.status)], + }), }, { field: 'created_at', - type: 'datetime', + cell: { type: 'datetime' }, }, { field: 'destination_id', @@ -87,36 +85,33 @@ export class DepositsComponent implements OnInit { { field: 'identity_id', }, - createCurrencyColumn( - 'amount', - (d) => d.amount, - (d) => d.currency_symbolic_code, - ), - createCurrencyColumn( - 'fee', - (d) => d.fee, - (d) => d.currency_symbolic_code, - { hide: true }, - ), - { - field: 'source_id', - hide: true, - }, + createCurrencyColumn((d) => ({ amount: d.amount, code: d.currency_symbolic_code }), { + header: 'Amount', + }), + createCurrencyColumn((d) => ({ amount: d.fee, code: d.currency_symbolic_code }), { + header: 'Fee', + }), { field: 'revert_status', - type: 'tag', - formatter: (d) => REVERT_STATUS[d.revert_status], - typeParameters: { - label: (d) => startCase(REVERT_STATUS[d.revert_status]), - tags: {}, - }, + cell: (d) => ({ + value: startCase(getEnumKey(fistful_stat.RevertStatus, d.revert_status)), + color: ( + { + none: 'neutral', + partial: 'pending', + full: 'success', + } as const + )[getEnumKey(fistful_stat.RevertStatus, d.revert_status)], + }), }, - createOperationColumn([ - { - label: 'Details', - click: (d) => this.router.navigate([`/deposits/${d.id}`]), - }, - ]), + createMenuColumn((d) => ({ + items: [ + { + label: 'Details', + click: () => this.router.navigate([`/deposits/${d.id}`]), + }, + ], + })), ]; depositStatuses: QueryDsl['query']['deposits']['status'][] = ['Pending', 'Succeeded', 'Failed']; active$ = getValueChanges(this.filtersForm).pipe( diff --git a/src/app/sections/domain/domain-info/domain-objects-table/domain-objects-table.component.ts b/src/app/sections/domain/domain-info/domain-objects-table/domain-objects-table.component.ts index 972252b0..203cf4e3 100644 --- a/src/app/sections/domain/domain-info/domain-objects-table/domain-objects-table.component.ts +++ b/src/app/sections/domain/domain-info/domain-objects-table/domain-objects-table.component.ts @@ -13,7 +13,6 @@ import { getValueChanges, Column2, createMenuColumn, - TABLE_WRAPPER_STYLE, } from '@vality/ng-core'; import sortBy from 'lodash-es/sortBy'; import startCase from 'lodash-es/startCase'; @@ -51,7 +50,6 @@ interface DomainObjectData { ActionsModule, MatButtonModule, ], - host: { style: TABLE_WRAPPER_STYLE }, }) export class DomainObjectsTableComponent implements OnInit { @Output() selectedChange = new EventEmitter(); diff --git a/src/app/sections/machines/components/machine-status-history-card.component.ts b/src/app/sections/machines/components/machine-status-history-card.component.ts new file mode 100644 index 00000000..9dfe25bb --- /dev/null +++ b/src/app/sections/machines/components/machine-status-history-card.component.ts @@ -0,0 +1,36 @@ +import { Component, input } from '@angular/core'; +import { Column2, getEnumKey, TableModule } from '@vality/ng-core'; +import { repairer } from '@vality/repairer-proto'; +import { StatusHistory } from '@vality/repairer-proto/repairer'; +import { startCase } from 'lodash-es'; + +import { SidenavInfoModule } from '@cc/app/shared/components/sidenav-info'; + +@Component({ + standalone: true, + template: ``, + imports: [TableModule, SidenavInfoModule], +}) +export class MachineStatusHistoryCardComponent { + history = input([]); + id = input(''); + + columns: Column2[] = [ + { field: 'changed_at', cell: { type: 'datetime' } }, + { + field: 'status', + cell: (d) => ({ + value: startCase(getEnumKey(repairer.RepairStatus, d.status)), + color: ( + { + failed: 'warn', + in_progress: 'pending', + repaired: 'success', + } as const + )[getEnumKey(repairer.RepairStatus, d.status)], + }), + }, + ]; +} diff --git a/src/app/sections/repairing/components/repair-by-scenario-dialog/repair-by-scenario-dialog.component.html b/src/app/sections/machines/components/repair-by-scenario-dialog/repair-by-scenario-dialog.component.html similarity index 100% rename from src/app/sections/repairing/components/repair-by-scenario-dialog/repair-by-scenario-dialog.component.html rename to src/app/sections/machines/components/repair-by-scenario-dialog/repair-by-scenario-dialog.component.html diff --git a/src/app/sections/repairing/components/repair-by-scenario-dialog/repair-by-scenario-dialog.component.ts b/src/app/sections/machines/components/repair-by-scenario-dialog/repair-by-scenario-dialog.component.ts similarity index 100% rename from src/app/sections/repairing/components/repair-by-scenario-dialog/repair-by-scenario-dialog.component.ts rename to src/app/sections/machines/components/repair-by-scenario-dialog/repair-by-scenario-dialog.component.ts diff --git a/src/app/sections/repairing/repairing-routing.module.ts b/src/app/sections/machines/machines-routing.module.ts similarity index 75% rename from src/app/sections/repairing/repairing-routing.module.ts rename to src/app/sections/machines/machines-routing.module.ts index 7e86e4dc..dedcf641 100644 --- a/src/app/sections/repairing/repairing-routing.module.ts +++ b/src/app/sections/machines/machines-routing.module.ts @@ -3,7 +3,7 @@ import { RouterModule } from '@angular/router'; import { AppAuthGuardService } from '../../shared/services'; -import { RepairingComponent } from './repairing.component'; +import { MachinesComponent } from './machines.component'; import { ROUTING_CONFIG } from './routing-config'; @NgModule({ @@ -11,7 +11,7 @@ import { ROUTING_CONFIG } from './routing-config'; RouterModule.forChild([ { path: '', - component: RepairingComponent, + component: MachinesComponent, canActivate: [AppAuthGuardService], data: ROUTING_CONFIG, }, @@ -19,4 +19,4 @@ import { ROUTING_CONFIG } from './routing-config'; ], exports: [RouterModule], }) -export class RepairingRoutingModule {} +export class MachinesRoutingModule {} diff --git a/src/app/sections/repairing/repairing.component.html b/src/app/sections/machines/machines.component.html similarity index 96% rename from src/app/sections/repairing/repairing.component.html rename to src/app/sections/machines/machines.component.html index 0118c400..69062304 100644 --- a/src/app/sections/repairing/repairing.component.html +++ b/src/app/sections/machines/machines.component.html @@ -1,4 +1,4 @@ - + @@ -33,7 +33,7 @@ - - + diff --git a/src/app/sections/repairing/repairing.component.ts b/src/app/sections/machines/machines.component.ts similarity index 78% rename from src/app/sections/repairing/repairing.component.ts rename to src/app/sections/machines/machines.component.ts index 76fd6a87..1fcd808d 100644 --- a/src/app/sections/repairing/repairing.component.ts +++ b/src/app/sections/machines/machines.component.ts @@ -5,7 +5,6 @@ import { DialogResponseStatus, DialogService, clean, - Column, ConfirmDialogComponent, QueryParamsService, NotifyLogService, @@ -18,6 +17,7 @@ import { debounceTimeWithFirst, FetchOptions, getEnumKey, + Column2, } from '@vality/ng-core'; import { repairer } from '@vality/repairer-proto'; import { Namespace, ProviderID, RepairStatus, Machine } from '@vality/repairer-proto/repairer'; @@ -27,10 +27,13 @@ import startCase from 'lodash-es/startCase'; import { BehaviorSubject } from 'rxjs'; import { filter, switchMap, map, shareReplay } from 'rxjs/operators'; +import { SidenavInfoService } from '@cc/app/shared/components/sidenav-info'; +import { createDomainObjectColumn } from '@cc/app/shared/utils/table2'; + import { RepairManagementService } from '../../api/repairer'; -import { createProviderColumn } from '../../shared/utils/table/create-provider-column'; import { DATE_RANGE_DAYS, DEBOUNCE_TIME_MS } from '../../tokens'; +import { MachineStatusHistoryCardComponent } from './components/machine-status-history-card.component'; import { RepairByScenarioDialogComponent } from './components/repair-by-scenario-dialog/repair-by-scenario-dialog.component'; import { MachinesService } from './services/machines.service'; @@ -44,11 +47,11 @@ interface Filters { } @Component({ - selector: 'cc-repairing', - templateUrl: './repairing.component.html', + selector: 'cc-machines', + templateUrl: './machines.component.html', providers: [MachinesService], }) -export class RepairingComponent implements OnInit { +export class MachinesComponent implements OnInit { machines$ = this.machinesService.result$; inProgress$ = this.machinesService.isLoading$; hasMore$ = this.machinesService.hasMore$; @@ -62,28 +65,36 @@ export class RepairingComponent implements OnInit { }); selected$ = new BehaviorSubject([]); status = repairer.RepairStatus; - columns: Column[] = [ - { field: 'id' }, + columns: Column2[] = [ + { field: 'id', sticky: 'start' }, { header: 'Namespace', field: 'ns' }, - { field: 'created_at', type: 'datetime' }, - createProviderColumn((d) => Number(d.provider_id)), + { field: 'created_at', cell: { type: 'datetime' } }, + createDomainObjectColumn((d) => ({ ref: { terminal: { id: Number(d.provider_id) } } }), { + header: 'Terminal', + }), { field: 'status', - formatter: (d) => getEnumKey(repairer.RepairStatus, d.status), - type: 'tag', - typeParameters: { - label: (d) => startCase(getEnumKey(repairer.RepairStatus, d.status)), - tags: { - failed: { color: 'warn' }, - in_progress: { color: 'pending' }, - repaired: { color: 'success' }, - }, - }, + cell: (d) => ({ + value: startCase(getEnumKey(repairer.RepairStatus, d.status)), + color: ( + { + failed: 'warn', + in_progress: 'pending', + repaired: 'success', + } as const + )[getEnumKey(repairer.RepairStatus, d.status)], + }), }, { field: 'history', - formatter: (data) => (data.history?.length ? String(data.history.length) : ''), - tooltip: 'history', + cell: (d) => ({ + value: d.history?.length ? String(d.history.length) : '', + click: () => { + this.sidenavInfoService.toggle(MachineStatusHistoryCardComponent, { + history: d.history, + }); + }, + }), }, { field: 'error_message', @@ -106,6 +117,7 @@ export class RepairingComponent implements OnInit { private destroyRef: DestroyRef, @Inject(DATE_RANGE_DAYS) private dateRangeDays: number, @Inject(DEBOUNCE_TIME_MS) private debounceTimeMs: number, + private sidenavInfoService: SidenavInfoService, ) {} ngOnInit() { diff --git a/src/app/sections/repairing/repairing.module.ts b/src/app/sections/machines/machines.module.ts similarity index 88% rename from src/app/sections/repairing/repairing.module.ts rename to src/app/sections/machines/machines.module.ts index 402bc28c..36f2640a 100644 --- a/src/app/sections/repairing/repairing.module.ts +++ b/src/app/sections/machines/machines.module.ts @@ -28,13 +28,13 @@ import { ThriftFormModule } from '@cc/app/shared/components/metadata-form'; import { DomainObjectFieldComponent } from '@cc/app/shared/components/thrift-api-crud'; import { RepairByScenarioDialogComponent } from './components/repair-by-scenario-dialog/repair-by-scenario-dialog.component'; -import { RepairingRoutingModule } from './repairing-routing.module'; -import { RepairingComponent } from './repairing.component'; +import { MachinesRoutingModule } from './machines-routing.module'; +import { MachinesComponent } from './machines.component'; @NgModule({ imports: [ CommonModule, - RepairingRoutingModule, + MachinesRoutingModule, TableModule, MatCardModule, ReactiveFormsModule, @@ -59,6 +59,6 @@ import { RepairingComponent } from './repairing.component'; ThriftPipesModule, FiltersModule, ], - declarations: [RepairingComponent, RepairByScenarioDialogComponent], + declarations: [MachinesComponent, RepairByScenarioDialogComponent], }) -export class RepairingModule {} +export class MachinesModule {} diff --git a/src/app/sections/repairing/routing-config.ts b/src/app/sections/machines/routing-config.ts similarity index 100% rename from src/app/sections/repairing/routing-config.ts rename to src/app/sections/machines/routing-config.ts diff --git a/src/app/sections/repairing/services/machines.service.ts b/src/app/sections/machines/services/machines.service.ts similarity index 100% rename from src/app/sections/repairing/services/machines.service.ts rename to src/app/sections/machines/services/machines.service.ts diff --git a/src/app/sections/party-shops/party-shops.component.html b/src/app/sections/party-shops/party-shops.component.html index e1744965..defd830c 100644 --- a/src/app/sections/party-shops/party-shops.component.html +++ b/src/app/sections/party-shops/party-shops.component.html @@ -1,4 +1,4 @@ - + + + + diff --git a/src/app/sections/payment-details/components/payment-chargebacks/payment-chargebacks.component.html b/src/app/sections/payment-details/components/payment-chargebacks/payment-chargebacks.component.html index d43ec197..62ceafd9 100644 --- a/src/app/sections/payment-details/components/payment-chargebacks/payment-chargebacks.component.html +++ b/src/app/sections/payment-details/components/payment-chargebacks/payment-chargebacks.component.html @@ -1,10 +1,12 @@ - - + + - - + diff --git a/src/app/sections/payment-details/components/payment-chargebacks/payment-chargebacks.component.ts b/src/app/sections/payment-details/components/payment-chargebacks/payment-chargebacks.component.ts index 9307aaca..aeb5ba1a 100644 --- a/src/app/sections/payment-details/components/payment-chargebacks/payment-chargebacks.component.ts +++ b/src/app/sections/payment-details/components/payment-chargebacks/payment-chargebacks.component.ts @@ -1,49 +1,42 @@ import { CommonModule } from '@angular/common'; -import { Component, DestroyRef } from '@angular/core'; +import { Component, DestroyRef, OnInit } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { MatButton } from '@angular/material/button'; import { ActivatedRoute } from '@angular/router'; import { DialogResponseStatus, DialogService } from '@vality/ng-core'; -import { merge, defer, Subject } from 'rxjs'; -import { map, switchMap, shareReplay } from 'rxjs/operators'; +import { first } from 'rxjs'; + +import { FetchChargebacksService } from '@cc/app/sections/chargebacks/fetch-chargebacks.service'; +import { ChargebacksTableComponent } from '@cc/app/shared/components/chargebacks-table'; -import { InvoicingService } from '../../../../api/payment-processing'; import { PageLayoutModule } from '../../../../shared'; -import { ChargebacksComponent } from '../../../../shared/components/chargebacks/chargebacks.component'; import { CreateChargebackDialogComponent } from '../../create-chargeback-dialog/create-chargeback-dialog.component'; import { PaymentDetailsService } from '../../payment-details.service'; @Component({ selector: 'cc-payment-chargebacks', standalone: true, - imports: [CommonModule, PageLayoutModule, MatButton, ChargebacksComponent], + imports: [CommonModule, PageLayoutModule, MatButton, ChargebacksTableComponent], templateUrl: './payment-chargebacks.component.html', - styles: ``, + providers: [FetchChargebacksService], }) -export class PaymentChargebacksComponent { +export class PaymentChargebacksComponent implements OnInit { payment$ = this.paymentDetailsService.payment$; isLoading$ = this.paymentDetailsService.isLoading$; - chargebacks$ = merge( - this.route.params, - defer(() => this.updateChargebacks$), - ).pipe( - map(() => this.route.snapshot.params as Record<'invoiceID' | 'paymentID', string>), - switchMap(({ invoiceID, paymentID }) => - this.invoicingService.GetPayment(invoiceID, paymentID), - ), - map(({ chargebacks }) => chargebacks), - shareReplay({ refCount: true, bufferSize: 1 }), - ); - private updateChargebacks$ = new Subject(); + chargebacks$ = this.fetchChargebacksService.result$; constructor( private route: ActivatedRoute, - private invoicingService: InvoicingService, private dialogService: DialogService, private dr: DestroyRef, private paymentDetailsService: PaymentDetailsService, + protected fetchChargebacksService: FetchChargebacksService, ) {} + ngOnInit() { + this.update(); + } + createChargeback() { this.dialogService .open( @@ -54,8 +47,21 @@ export class PaymentChargebacksComponent { .pipe(takeUntilDestroyed(this.dr)) .subscribe(({ status }) => { if (status === DialogResponseStatus.Success) { - this.updateChargebacks$.next(); + this.update(); } }); } + + update() { + this.payment$.pipe(first(), takeUntilDestroyed(this.dr)).subscribe((p) => { + this.fetchChargebacksService.load({ + common_search_query_params: { + from_time: new Date(0).toISOString(), + to_time: new Date().toISOString(), + }, + payment_id: p.id, + invoice_ids: [p.invoice_id], + }); + }); + } } diff --git a/src/app/sections/payment-details/create-chargeback-dialog/create-chargeback-dialog.component.ts b/src/app/sections/payment-details/create-chargeback-dialog/create-chargeback-dialog.component.ts index 4e1d94e4..a3acf995 100644 --- a/src/app/sections/payment-details/create-chargeback-dialog/create-chargeback-dialog.component.ts +++ b/src/app/sections/payment-details/create-chargeback-dialog/create-chargeback-dialog.component.ts @@ -3,8 +3,8 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { FormControl } from '@angular/forms'; import { InvoicePaymentChargeback } from '@vality/domain-proto/domain'; import { InvoicePaymentChargebackParams } from '@vality/domain-proto/payment_processing'; -import { DialogSuperclass, NotifyLogService } from '@vality/ng-core'; -import { from } from 'rxjs'; +import { DialogSuperclass, getImportValue, NotifyLogService } from '@vality/ng-core'; +import { ThriftAstMetadata } from '@vality/ng-thrift'; import short from 'short-uuid'; import { InvoicingService } from '@cc/app/api/payment-processing'; @@ -20,7 +20,7 @@ export class CreateChargebackDialogComponent extends DialogSuperclass< InvoicePaymentChargeback > { form = new FormControl>({ id: short().generate() }); - metadata$ = from(import('@vality/domain-proto/metadata.json').then((m) => m.default)); + metadata$ = getImportValue(import('@vality/domain-proto/metadata.json')); extensions$ = this.domainMetadataFormExtensionsService.extensions$; constructor( diff --git a/src/app/sections/payment-details/payment-details.component.html b/src/app/sections/payment-details/payment-details.component.html index 600b1618..c7d73c02 100644 --- a/src/app/sections/payment-details/payment-details.component.html +++ b/src/app/sections/payment-details/payment-details.component.html @@ -5,7 +5,6 @@ { label: 'Refunds', url: 'refunds' }, { label: 'Chargebacks', url: 'chargebacks' } ]" - [tags]="tags$ | async" id="{{ (payment$ | async) ? (payment$ | async)?.invoice_id + '.' + (payment$ | async)?.id : '' }}" diff --git a/src/app/sections/payment-details/payment-details.module.ts b/src/app/sections/payment-details/payment-details.module.ts index 99ec83a1..debb36df 100644 --- a/src/app/sections/payment-details/payment-details.module.ts +++ b/src/app/sections/payment-details/payment-details.module.ts @@ -12,7 +12,6 @@ import { StatusModule, PageLayoutModule, SubPageLayoutComponent } from '@cc/app/ import { DetailsItemModule } from '@cc/components/details-item'; import { HeadlineModule } from '@cc/components/headline'; -import { ChargebacksComponent } from '../../shared/components/chargebacks/chargebacks.component'; import { JsonViewerModule } from '../../shared/components/json-viewer'; import { ThriftFormModule } from '../../shared/components/metadata-form'; import { MagistaThriftViewerComponent } from '../../shared/components/thrift-api-crud'; @@ -34,7 +33,6 @@ import { RefundsTableModule } from './refunds-table'; MatProgressSpinnerModule, MatButtonModule, MatDialogModule, - ChargebacksComponent, ActionsModule, DialogModule, ThriftFormModule, diff --git a/src/app/sections/payments/components/payments-table/payments-table.component.ts b/src/app/sections/payments/components/payments-table/payments-table.component.ts index 6c1e44e1..2a1dffd7 100644 --- a/src/app/sections/payments/components/payments-table/payments-table.component.ts +++ b/src/app/sections/payments/components/payments-table/payments-table.component.ts @@ -1,7 +1,7 @@ import { Component, Input, Output, EventEmitter } from '@angular/core'; import { Router } from '@angular/router'; import { StatPayment } from '@vality/magista-proto/magista'; -import { LoadOptions, Column2, createMenuColumn, TABLE_WRAPPER_STYLE } from '@vality/ng-core'; +import { LoadOptions, Column2, createMenuColumn } from '@vality/ng-core'; import { getUnionKey } from '@vality/ng-thrift'; import startCase from 'lodash-es/startCase'; @@ -18,7 +18,6 @@ import { @Component({ selector: 'cc-payments-table', templateUrl: './payments-table.component.html', - host: { style: TABLE_WRAPPER_STYLE }, }) export class PaymentsTableComponent { @Input() data!: StatPayment[]; diff --git a/src/app/sections/sections-routing.module.ts b/src/app/sections/sections-routing.module.ts index 30b6c866..10f26970 100644 --- a/src/app/sections/sections-routing.module.ts +++ b/src/app/sections/sections-routing.module.ts @@ -34,7 +34,7 @@ const ROUTES: Routes = [ }, { path: 'machines', - loadChildren: () => import('./repairing/repairing.module').then((m) => m.RepairingModule), + loadChildren: () => import('./machines/machines.module').then((m) => m.MachinesModule), }, { path: 'payments', diff --git a/src/app/sections/shops/shops.component.html b/src/app/sections/shops/shops.component.html index 5103321f..4d38e87e 100644 --- a/src/app/sections/shops/shops.component.html +++ b/src/app/sections/shops/shops.component.html @@ -1,9 +1,7 @@ - - + diff --git a/src/app/sections/shops/shops.component.ts b/src/app/sections/shops/shops.component.ts index 3684f289..4d0f4642 100644 --- a/src/app/sections/shops/shops.component.ts +++ b/src/app/sections/shops/shops.component.ts @@ -2,7 +2,14 @@ import { Component } from '@angular/core'; import { SearchShopHit } from '@vality/deanonimus-proto/deanonimus'; import { Column, progressTo, NotifyLogService } from '@vality/ng-core'; import { BehaviorSubject, defer, of, combineLatest, Subject, Observable } from 'rxjs'; -import { switchMap, shareReplay, catchError, map } from 'rxjs/operators'; +import { + switchMap, + shareReplay, + catchError, + map, + debounceTime, + distinctUntilChanged, +} from 'rxjs/operators'; import { DeanonimusService } from '../../api/deanonimus'; import { ShopParty } from '../../shared/components/shops-table'; @@ -14,7 +21,7 @@ import { ShopParty } from '../../shared/components/shops-table'; export class ShopsComponent { filterChange$ = new Subject(); shopsParty$: Observable = combineLatest([ - this.filterChange$, + this.filterChange$.pipe(distinctUntilChanged(), debounceTime(500)), defer(() => this.updateShops$), ]).pipe( switchMap(([search]) => diff --git a/src/app/sections/sources/sources.component.html b/src/app/sections/sources/sources.component.html index 05c7b503..3b6172bf 100644 --- a/src/app/sections/sources/sources.component.html +++ b/src/app/sections/sources/sources.component.html @@ -1,13 +1,12 @@ - + - + standaloneFilter + > diff --git a/src/app/sections/sources/sources.component.ts b/src/app/sections/sources/sources.component.ts index 1d0cb39a..5247fe0b 100644 --- a/src/app/sections/sources/sources.component.ts +++ b/src/app/sections/sources/sources.component.ts @@ -1,6 +1,7 @@ import { Component } from '@angular/core'; +import { Sort } from '@angular/material/sort'; import { Source } from '@vality/fistful-proto/internal/source'; -import { DialogService, Column } from '@vality/ng-core'; +import { DialogService, Column2 } from '@vality/ng-core'; import { CreateSourceComponent } from './create-source/create-source.component'; import { FetchSourcesService } from './fetch-sources.service'; @@ -11,13 +12,14 @@ import { FetchSourcesService } from './fetch-sources.service'; export class SourcesComponent { sources$ = this.fetchSourcesService.sources$; progress$ = this.fetchSourcesService.progress$; - columns: Column[] = [ + columns: Column2[] = [ { field: 'id' }, - { field: 'name', sortable: true }, - 'identity', - { field: 'currency_symbolic_code', sortable: true }, - { field: 'created_at', type: 'datetime' }, + { field: 'name' }, + { field: 'identity' }, + { field: 'currency_symbolic_code' }, + { field: 'created_at', cell: { type: 'datetime' } }, ]; + sort: Sort = { direction: 'asc', active: 'name' }; constructor( private fetchSourcesService: FetchSourcesService, diff --git a/src/app/sections/wallets/wallets.component.html b/src/app/sections/wallets/wallets.component.html index 7d7e185c..a25fe3de 100644 --- a/src/app/sections/wallets/wallets.component.html +++ b/src/app/sections/wallets/wallets.component.html @@ -1,53 +1,53 @@ - + - + @if (!(party$ | async)) { + + } - - - - - - Identity ID - - - - - + @if (isFilterTable$ | async) { + + + + + + Identity ID + + + + + + } - - + @if (isFilterTable$ | async) { + + } @else { + + } diff --git a/src/app/sections/wallets/wallets.component.ts b/src/app/sections/wallets/wallets.component.ts index 23b405bf..5b1a3ed5 100644 --- a/src/app/sections/wallets/wallets.component.ts +++ b/src/app/sections/wallets/wallets.component.ts @@ -1,12 +1,4 @@ -import { - Component, - OnInit, - Inject, - ViewChild, - DestroyRef, - Injector, - runInInjectionContext, -} from '@angular/core'; +import { Component, OnInit, Inject, ViewChild, DestroyRef } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { FormControl, NonNullableFormBuilder } from '@angular/forms'; import { SearchWalletHit } from '@vality/deanonimus-proto/internal/deanonimus'; @@ -15,17 +7,17 @@ import { AccountBalance } from '@vality/fistful-proto/internal/account'; import { StatWallet } from '@vality/fistful-proto/internal/fistful_stat'; import { clean, - Column, QueryParamsService, - NotifyLogService, FiltersComponent, UpdateOptions, getValueChanges, countChanged, debounceTimeWithFirst, + Column2, + DebounceTime, } from '@vality/ng-core'; import isNil from 'lodash-es/isNil'; -import { of } from 'rxjs'; +import { combineLatest, of } from 'rxjs'; import { map, shareReplay, catchError, take } from 'rxjs/operators'; import { MemoizeExpiring } from 'typescript-memoize'; @@ -33,7 +25,7 @@ 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 { createCurrencyColumn, createPartyColumn } from '../../shared/utils/table2'; import { DEBOUNCE_TIME_MS } from '../../tokens'; import { PartyStoreService } from '../party'; @@ -55,81 +47,81 @@ export class WalletsComponent implements OnInit { fullTextSearchWallets$ = this.fetchWalletsTextService.result$; fullTextSearchLoading$ = this.fetchWalletsTextService.isLoading$; - filterColumns$ = this.partyStoreService.party$.pipe( - map((party) => - runInInjectionContext(this.injector, () => [ - { field: 'id' }, - { field: 'name' }, - 'currency_symbolic_code', - 'identity_id', - { field: 'created_at', type: 'datetime' }, - createCurrencyColumn( - 'balance', - (d) => this.getBalance(d.id).pipe(map((b) => b.current)), - (d) => this.getBalance(d.id).pipe(map((b) => b.currency.symbolic_code)), - { lazy: true }, + filterColumns: Column2[] = [ + { field: 'id' }, + { field: 'name' }, + { field: 'currency_symbolic_code' }, + { field: 'identity_id' }, + { field: 'created_at', cell: { type: 'datetime' } }, + createCurrencyColumn( + (d) => + this.getBalance(d.id).pipe( + map((b) => ({ amount: b.current, code: b.currency.symbolic_code })), ), - createCurrencyColumn( - 'hold', - (d) => this.getBalance(d.id).pipe(map((b) => b.current - b.expected_min)), - (d) => this.getBalance(d.id).pipe(map((b) => b.currency.symbolic_code)), - { lazy: true }, - ), - createCurrencyColumn( - 'expected_min', - (d) => this.getBalance(d.id).pipe(map((b) => b.expected_min)), - (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, - }, - ...(party - ? [] - : [ - createPartyColumn( - 'party', - (d) => - this.getIdentity(d.identity_id).pipe( - map((identity) => identity.party_id), - ), - undefined, - { lazy: true }, - ), - ]), - ]), + { header: 'Balance', isLazyCell: true }, ), - ); - fullTextSearchColumns: Column[] = [ + createCurrencyColumn( + (d) => + this.getBalance(d.id).pipe( + map((b) => ({ + amount: b.current - b.expected_min, + code: b.currency.symbolic_code, + })), + ), + { header: 'Hold', isLazyCell: true }, + ), + createCurrencyColumn( + (d) => + this.getBalance(d.id).pipe( + map((b) => ({ amount: b.expected_min, code: b.currency.symbolic_code })), + ), + { header: 'Expected Min', isLazyCell: true }, + ), + { + field: 'contract_id', + lazyCell: (d) => + this.getIdentity(d.identity_id).pipe( + map((identity) => ({ value: identity.contract_id })), + ), + }, + createPartyColumn( + (d) => + this.getIdentity(d.identity_id).pipe( + map((identity) => ({ id: identity.party_id })), + ), + { hidden: this.partyStoreService.party$.pipe(map((p) => !p)) }, + ), + ]; + fullTextSearchColumns: Column2[] = [ { field: 'wallet.id' }, { field: 'wallet.name' }, - createPartyColumn( - 'party', - (d) => d.party.id, - (d) => d.party.email, + createPartyColumn((d) => ({ + id: d.party.id, + partyName: d.party.email, + })), + createCurrencyColumn( + (d) => + this.getBalance(d.wallet.id).pipe( + map((b) => ({ amount: b.current, code: b.currency.symbolic_code })), + ), + { header: 'Balance', isLazyCell: true }, ), - createCurrencyColumn( - 'balance', - (d) => this.getBalance(d.wallet.id).pipe(map((b) => b.current)), - (d) => this.getBalance(d.wallet.id).pipe(map((b) => b.currency.symbolic_code)), - { lazy: true }, + createCurrencyColumn( + (d) => + this.getBalance(d.wallet.id).pipe( + map((b) => ({ + amount: b.current - b.expected_min, + code: b.currency.symbolic_code, + })), + ), + { header: 'Hold', isLazyCell: true }, ), - createCurrencyColumn( - 'hold', - (d) => this.getBalance(d.wallet.id).pipe(map((b) => b.current - b.expected_min)), - (d) => this.getBalance(d.wallet.id).pipe(map((b) => b.currency.symbolic_code)), - { lazy: true }, - ), - createCurrencyColumn( - 'expected_min', - (d) => this.getBalance(d.wallet.id).pipe(map((b) => b.expected_min)), - (d) => this.getBalance(d.wallet.id).pipe(map((b) => b.currency.symbolic_code)), - { lazy: true }, + createCurrencyColumn( + (d) => + this.getBalance(d.wallet.id).pipe( + map((b) => ({ amount: b.expected_min, code: b.currency.symbolic_code })), + ), + { header: 'Expected Min', isLazyCell: true }, ), ]; filtersForm = this.fb.group({ @@ -145,6 +137,10 @@ export class WalletsComponent implements OnInit { @ViewChild(FiltersComponent) filters!: FiltersComponent; typeQp = this.qp.createNamespace<{ isFilter: boolean }>('type'); party$ = this.partyStoreService.party$; + isFilterTable$ = combineLatest([getValueChanges(this.isFilterControl), this.party$]).pipe( + map(([isFilterControl, party]) => isFilterControl || !!party), + shareReplay({ refCount: true, bufferSize: 1 }), + ); private initFilters = this.filtersForm.value; @@ -154,12 +150,10 @@ export class WalletsComponent implements OnInit { private qp: QueryParamsService, private fb: NonNullableFormBuilder, private walletManagementService: ManagementService, - private log: NotifyLogService, @Inject(DEBOUNCE_TIME_MS) private debounceTimeMs: number, private destroyRef: DestroyRef, private identityManagementService: IdentityManagementService, private partyStoreService: PartyStoreService, - private injector: Injector, ) {} ngOnInit() { @@ -198,6 +192,7 @@ export class WalletsComponent implements OnInit { this.fetchWalletsService.more(); } + @DebounceTime() fullTextSearch(text: string) { this.fetchWalletsTextService.load(text); } diff --git a/src/app/shared/components/change-chargebacks-status-dialog/change-chargebacks-status-dialog.component.ts b/src/app/shared/components/change-chargebacks-status-dialog/change-chargebacks-status-dialog.component.ts index 2e3aeb39..58926f6c 100644 --- a/src/app/shared/components/change-chargebacks-status-dialog/change-chargebacks-status-dialog.component.ts +++ b/src/app/shared/components/change-chargebacks-status-dialog/change-chargebacks-status-dialog.component.ts @@ -13,8 +13,10 @@ import { NotifyLogService, EnumKeysPipe, EnumKeyPipe, + getImportValue, } from '@vality/ng-core'; -import { from, BehaviorSubject } from 'rxjs'; +import { ThriftAstMetadata } from '@vality/ng-thrift'; +import { BehaviorSubject } from 'rxjs'; import { InvoicingService } from '@cc/app/api/payment-processing'; import { DomainMetadataFormExtensionsService } from '@cc/app/shared/services'; @@ -57,7 +59,7 @@ export class ChangeChargebacksStatusDialogComponent > implements OnInit { - metadata$ = from(import('@vality/domain-proto/metadata.json').then((m) => m.default)); + metadata$ = getImportValue(import('@vality/domain-proto/metadata.json')); extensions$ = this.domainMetadataFormExtensionsService.extensions$; control = new FormControl(); actionControl = new FormControl(null, Validators.required); diff --git a/src/app/sections/chargebacks/components/chargebacks-table/chargebacks-table.component.html b/src/app/shared/components/chargebacks-table/chargebacks-table.component.html similarity index 56% rename from src/app/sections/chargebacks/components/chargebacks-table/chargebacks-table.component.html rename to src/app/shared/components/chargebacks-table/chargebacks-table.component.html index 3f6f87f5..a9686268 100644 --- a/src/app/sections/chargebacks/components/chargebacks-table/chargebacks-table.component.html +++ b/src/app/shared/components/chargebacks-table/chargebacks-table.component.html @@ -1,15 +1,17 @@ - + - + diff --git a/src/app/shared/components/chargebacks-table/chargebacks-table.component.ts b/src/app/shared/components/chargebacks-table/chargebacks-table.component.ts new file mode 100644 index 00000000..0d8c8074 --- /dev/null +++ b/src/app/shared/components/chargebacks-table/chargebacks-table.component.ts @@ -0,0 +1,155 @@ +import { CommonModule } from '@angular/common'; +import { + Component, + Input, + Output, + EventEmitter, + booleanAttribute, + input, + DestroyRef, + model, +} from '@angular/core'; +import { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop'; +import { MatButtonModule } from '@angular/material/button'; +import { StatChargeback } from '@vality/magista-proto/magista'; +import { + LoadOptions, + Column2, + TableModule, + DialogService, + createMenuColumn, + DialogResponseStatus, +} from '@vality/ng-core'; +import { getUnionKey } from '@vality/ng-thrift'; +import startCase from 'lodash-es/startCase'; +import { filter } from 'rxjs'; + +import { createCurrencyColumn, createPartyColumn, createShopColumn } from '../../utils/table2'; +import { ChangeChargebacksStatusDialogComponent } from '../change-chargebacks-status-dialog'; + +@Component({ + standalone: true, + selector: 'cc-chargebacks-table', + templateUrl: './chargebacks-table.component.html', + imports: [CommonModule, TableModule, MatButtonModule], +}) +export class ChargebacksTableComponent { + @Input() data!: StatChargeback[]; + @Input() isLoading?: boolean | null; + @Input() hasMore?: boolean | null; + selected = model([]); + onePayment = input(false, { transform: booleanAttribute }); + + @Output() selectedChange = new EventEmitter(); + @Output() update = new EventEmitter(); + @Output() more = new EventEmitter(); + + columns: Column2[] = [ + { field: 'chargeback_id', header: 'Id' }, + { + field: 'chargeback_reason', + header: 'Reason', + cell: (d) => ({ + value: startCase(getUnionKey(d.chargeback_reason.category)), + description: d.chargeback_reason.code, + }), + }, + { + field: 'chargeback_status', + header: 'Status', + cell: (d) => ({ + value: startCase(getUnionKey(d.chargeback_status)), + color: ( + { + pending: 'pending', + accepted: 'success', + rejected: 'warn', + cancelled: 'neutral', + } as const + )[getUnionKey(d.chargeback_status)], + }), + }, + createCurrencyColumn((d) => ({ amount: d.amount, code: d.currency_code.symbolic_code }), { + header: 'Amount', + }), + createCurrencyColumn( + (d) => ({ amount: d.levy_amount, code: d.levy_currency_code.symbolic_code }), + { header: 'Levy Amount' }, + ), + createCurrencyColumn((d) => ({ amount: d.fee, code: d.currency_code.symbolic_code }), { + header: 'Fee', + }), + createCurrencyColumn( + (d) => ({ amount: d.provider_fee, code: d.currency_code.symbolic_code }), + { header: 'Provider Fee' }, + ), + createCurrencyColumn( + (d) => ({ amount: d.external_fee, code: d.currency_code.symbolic_code }), + { header: 'External Fee' }, + ), + { + field: 'stage', + cell: (d) => ({ value: startCase(getUnionKey(d.stage)) }), + }, + { + field: 'invoice_id', + header: { + value: 'Invoice Id', + description: 'Payment Id', + }, + cell: (d) => ({ + description: d.payment_id, + link: () => `/party/${d.party_id}/invoice/${d.invoice_id}/payment/${d.payment_id}`, + }), + hidden: toObservable(this.onePayment), + }, + { + field: 'created_at', + cell: { type: 'datetime' }, + }, + createPartyColumn((d) => ({ id: d.party_id }), { hidden: toObservable(this.onePayment) }), + createShopColumn((d) => ({ shopId: d.shop_id, partyId: d.party_id }), { + hidden: toObservable(this.onePayment), + }), + createMenuColumn((d) => ({ + items: [ + { + label: 'Change status', + click: () => { + this.changeStatus(d); + }, + }, + ], + })), + ]; + + constructor( + private dialogService: DialogService, + private dr: DestroyRef, + ) {} + + changeStatus(chargeback: StatChargeback) { + this.dialogService.open(ChangeChargebacksStatusDialogComponent, { + chargebacks: [ + { + payment_id: chargeback.payment_id, + invoice_id: chargeback.invoice_id, + chargeback_id: chargeback.chargeback_id, + }, + ], + }); + } + + changeStatuses() { + this.dialogService + .open(ChangeChargebacksStatusDialogComponent, { chargebacks: this.selected() }) + .afterClosed() + .pipe( + filter((res) => res.status === DialogResponseStatus.Success), + takeUntilDestroyed(this.dr), + ) + .subscribe(() => { + this.update.emit(); + }); + } +} diff --git a/src/app/shared/components/chargebacks-table/index.ts b/src/app/shared/components/chargebacks-table/index.ts new file mode 100644 index 00000000..35bfa6c2 --- /dev/null +++ b/src/app/shared/components/chargebacks-table/index.ts @@ -0,0 +1 @@ +export * from './chargebacks-table.component'; diff --git a/src/app/shared/components/chargebacks/chargebacks.component.html b/src/app/shared/components/chargebacks/chargebacks.component.html deleted file mode 100644 index 5141912c..00000000 --- a/src/app/shared/components/chargebacks/chargebacks.component.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/app/shared/components/chargebacks/chargebacks.component.ts b/src/app/shared/components/chargebacks/chargebacks.component.ts deleted file mode 100644 index 2159889d..00000000 --- a/src/app/shared/components/chargebacks/chargebacks.component.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { CommonModule } from '@angular/common'; -import { Component, Input } from '@angular/core'; -import { InvoicePaymentChargeback } from '@vality/domain-proto/payment_processing'; -import { DialogService, Column, TableModule, createOperationColumn } from '@vality/ng-core'; -import { getUnionKey } from '@vality/ng-thrift'; -import startCase from 'lodash-es/startCase'; - -import { createCurrencyColumn } from '@cc/app/shared'; -import { DetailsDialogComponent } from '@cc/app/shared/components/details-dialog/details-dialog.component'; - -import { ChangeChargebacksStatusDialogComponent } from '../change-chargebacks-status-dialog'; - -@Component({ - standalone: true, - selector: 'cc-chargebacks', - templateUrl: './chargebacks.component.html', - imports: [CommonModule, TableModule], -}) -export class ChargebacksComponent { - @Input() chargebacks: InvoicePaymentChargeback[]; - @Input() paymentId: string; - @Input() invoiceId: string; - - columns: Column[] = [ - 'chargeback.id', - { - field: 'status', - type: 'tag', - formatter: (d) => getUnionKey(d.chargeback.status), - typeParameters: { - label: (d) => startCase(getUnionKey(d.chargeback.status)), - tags: { - pending: { color: 'pending' }, - accepted: { color: 'success' }, - rejected: { color: 'warn' }, - cancelled: { color: 'neutral' }, - }, - }, - }, - { field: 'chargeback.created_at', type: 'datetime' }, - createCurrencyColumn( - 'body', - (d) => d.chargeback.body.amount, - (d) => d.chargeback.body.currency.symbolic_code, - ), - createCurrencyColumn( - 'levy', - (d) => d.chargeback.levy.amount, - (d) => d.chargeback.levy.currency.symbolic_code, - ), - { field: 'stage', formatter: (d) => getUnionKey(d.chargeback.stage) }, - createOperationColumn([ - { - label: 'Details', - click: (d) => this.showDetails(d), - }, - { - label: 'Change status', - click: (d) => this.changeStatus(d.chargeback.id), - }, - ]), - ]; - - constructor(private dialogService: DialogService) {} - - changeStatus(id: string) { - this.dialogService.open(ChangeChargebacksStatusDialogComponent, { - chargebacks: [ - { - payment_id: this.paymentId, - invoice_id: this.invoiceId, - chargeback_id: id, - }, - ], - }); - } - - showDetails(chargeback: InvoicePaymentChargeback) { - this.dialogService.open(DetailsDialogComponent, { - title: 'Chargeback details', - json: chargeback, - }); - } -} diff --git a/src/app/shared/components/metadata-form/thrift-form.component.html b/src/app/shared/components/metadata-form/thrift-form.component.html index bb6340e5..95e8bfbb 100644 --- a/src/app/shared/components/metadata-form/thrift-form.component.html +++ b/src/app/shared/components/metadata-form/thrift-form.component.html @@ -4,44 +4,44 @@ (extensionResult$ | async)?.type || (extensionResult$ | async)?.template; else defaultFields " - [data]="data" + [data]="$any(data)" [extensions]="extensions" [formControl]="control" > diff --git a/src/app/shared/components/page-layout/page-layout.component.scss b/src/app/shared/components/page-layout/page-layout.component.scss index e4bf1d1f..7cbfd056 100644 --- a/src/app/shared/components/page-layout/page-layout.component.scss +++ b/src/app/shared/components/page-layout/page-layout.component.scss @@ -16,4 +16,9 @@ $offset: 24px; min-height: 48px; gap: 8px; } + + ::ng-deep & > *:last-child { + min-height: 0; + height: 100%; + } } diff --git a/src/app/shared/components/shop-contract-card/shop-contract-card.component.ts b/src/app/shared/components/shop-contract-card/shop-contract-card.component.ts index 71b3930e..ff4d1904 100644 --- a/src/app/shared/components/shop-contract-card/shop-contract-card.component.ts +++ b/src/app/shared/components/shop-contract-card/shop-contract-card.component.ts @@ -9,7 +9,7 @@ import { CardComponent } from '../sidenav-info/components/card/card.component'; import { DomainThriftViewerComponent } from '../thrift-api-crud'; @Component({ - selector: 'cc-contract-card', + selector: 'cc-shop-contract-card', standalone: true, imports: [CommonModule, CardComponent, DomainThriftViewerComponent], templateUrl: './shop-contract-card.component.html', diff --git a/src/app/shared/components/shop-field/shop-field.component.ts b/src/app/shared/components/shop-field/shop-field.component.ts index 1bec376b..e4c99aea 100644 --- a/src/app/shared/components/shop-field/shop-field.component.ts +++ b/src/app/shared/components/shop-field/shop-field.component.ts @@ -18,6 +18,7 @@ import { Option, NotifyLogService, progressTo, + SelectFieldComponent, } from '@vality/ng-core'; import { BehaviorSubject, @@ -47,8 +48,8 @@ export class ShopFieldComponent { @Input() label: string; @Input({ transform: booleanAttribute }) required: boolean; - @Input() size?: string; - @Input() appearance?: string; + @Input() size?: SelectFieldComponent['size']; + @Input() appearance?: SelectFieldComponent['appearance']; @Input() hint?: string; @Input({ transform: booleanAttribute }) multiple = false; partyId = input(); diff --git a/src/app/shared/components/shops-table/shops-table.component.html b/src/app/shared/components/shops-table/shops-table.component.html index d5057ceb..d9d63eb2 100644 --- a/src/app/shared/components/shops-table/shops-table.component.html +++ b/src/app/shared/components/shops-table/shops-table.component.html @@ -1,14 +1,11 @@ - +> diff --git a/src/app/shared/components/shops-table/shops-table.component.ts b/src/app/shared/components/shops-table/shops-table.component.ts index 5318aa64..ff7dd6af 100644 --- a/src/app/shared/components/shops-table/shops-table.component.ts +++ b/src/app/shared/components/shops-table/shops-table.component.ts @@ -5,8 +5,8 @@ import { EventEmitter, Input, booleanAttribute, - OnChanges, input, + Injector, } from '@angular/core'; import { toObservable } from '@angular/core/rxjs-interop'; import { MatCardModule } from '@angular/material/card'; @@ -16,18 +16,17 @@ import { Shop, Party, PartyID, RoutingRulesetRef } from '@vality/domain-proto/do import { InputFieldModule, TableModule, - Column, - createOperationColumn, DialogService, NotifyLogService, ConfirmDialogComponent, DialogResponseStatus, - ComponentChanges, + Column2, + createMenuColumn, } from '@vality/ng-core'; import { getUnionKey } from '@vality/ng-thrift'; -import isNil from 'lodash-es/isNil'; +import { isNil } from 'lodash-es'; import startCase from 'lodash-es/startCase'; -import { map, switchMap, Subject, defer, combineLatest, of } from 'rxjs'; +import { map, switchMap, combineLatest, of } from 'rxjs'; import { filter, shareReplay, startWith, take, first } from 'rxjs/operators'; import { MemoizeExpiring } from 'typescript-memoize'; @@ -38,6 +37,7 @@ import { DelegateWithPaymentInstitution, } from '../../../sections/routing-rules/party-delegate-rulesets'; import { RoutingRulesType } from '../../../sections/routing-rules/types/routing-rules-type'; +import { createPartyColumn } from '../../utils/table2'; import { ShopCardComponent } from '../shop-card/shop-card.component'; import { ShopContractCardComponent } from '../shop-contract-card/shop-contract-card.component'; import { SidenavInfoService } from '../sidenav-info'; @@ -68,172 +68,140 @@ export interface ShopParty { templateUrl: './shops-table.component.html', providers: [PartyDelegateRulesetsService], }) -export class ShopsTableComponent implements OnChanges { +export class ShopsTableComponent { shops = input([]); - @Input({ transform: booleanAttribute }) changed!: boolean; @Input() progress: number | boolean = false; @Output() update = new EventEmitter(); @Output() filterChange = new EventEmitter(); - @Input({ transform: booleanAttribute }) noSort: boolean = false; - @Input({ transform: booleanAttribute }) noPartyColumn: boolean = false; + noPartyColumn = input(false, { transform: booleanAttribute }); - columns$ = combineLatest([ - toObservable(this.shops).pipe( - startWith(null), - map((shops) => - shops?.length ? Array.from(new Set(shops.map((s) => s.party.id))) : [], - ), - switchMap((parties) => - parties?.length - ? combineLatest( - parties.map((id) => - this.partyDelegateRulesetsService.getDelegatesWithPaymentInstitution( - RoutingRulesType.Payment, - id, - ), - ), - ).pipe(map((rules) => new Map(rules.map((r, idx) => [parties[idx], r])))) - : of(new Map()), - ), - map((delegatesWithPaymentInstitutionByParty) => ({ - delegatesWithPaymentInstitutionByParty, - rulesetIds: Array.from( - Array.from(delegatesWithPaymentInstitutionByParty.values()).reduce((acc, d) => { - d?.map((v) => v?.partyDelegate?.ruleset?.id).forEach((v) => acc.add(v)); - return acc; - }, new Set([])), - ), - })), - ), - defer(() => this.updateColumns$).pipe(startWith(null)), - ]).pipe( - map(([delegatesByParty]): Column[] => [ - { - field: 'shop.id', - sortable: !this.noSort, - }, - { - field: 'shop.details.name', - description: 'shop.details.description', - click: (d) => { + columns: Column2[] = [ + { + field: 'shop.id', + }, + { + field: 'shop.details.name', + cell: (d) => ({ + description: d.shop.details.description, + click: () => { this.sidenavInfoService.toggle(ShopCardComponent, { partyId: d.party.id, id: d.shop.id, }); }, - sortable: !this.noSort, - }, - ...(this.noPartyColumn - ? [] - : [ - { - field: 'party.email', - header: 'Party', - description: 'party.id', - link: (d) => `/party/${d.party.id}`, - }, - ]), + }), + }, + createPartyColumn( + (d) => ({ + id: d.party.id, + partyName: d.party.email, + }), { - field: 'shop.contract_id', - header: 'Contract', - click: (d) => { + hidden: toObservable(this.noPartyColumn), + }, + ), + { + field: 'shop.contract_id', + header: 'Contract', + cell: (d) => ({ + click: () => { this.sidenavInfoService.toggle(ShopContractCardComponent, { partyId: d.party.id, id: d.shop.id, }); }, - }, - { - field: 'terms', - formatter: (d) => - this.getTerms(d.party.id, d.shop.id).pipe( - map((terms) => getDomainObjectDetails(terms).label), - ), - description: (d) => - this.getTerms(d.party.id, d.shop.id).pipe( - map((terms) => getDomainObjectDetails(terms).id), - ), - lazy: true, - click: (d) => { - this.getTerms(d.party.id, d.shop.id).subscribe((terms) => { - this.sidenavInfoService.toggle(DomainObjectCardComponent, { - ref: { term_set_hierarchy: terms.term_set_hierarchy.ref }, - }); - }); - }, - }, - { - field: 'shop.location.url', - }, - { - field: 'shop.account.currency.symbolic_code', - header: 'Currency', - }, - { - field: 'shop.blocking', - type: 'tag', - formatter: ({ shop }) => getUnionKey(shop.blocking), - typeParameters: { - label: ({ shop }) => startCase(getUnionKey(shop.blocking)), - tags: { - blocked: { color: 'warn' }, - unblocked: { color: 'success' }, - }, - }, - }, - { - field: 'shop.suspension', - type: 'tag', - formatter: ({ shop }) => getUnionKey(shop.suspension), - typeParameters: { - label: ({ shop }) => startCase(getUnionKey(shop.suspension)), - tags: { - suspended: { color: 'warn' }, - active: { color: 'success' }, - }, - }, - }, - createOperationColumn([ - ...delegatesByParty.rulesetIds.map((id) => ({ - label: `Routing rules #${id}`, - click: ({ shop, party }) => - this.openRoutingRules( - delegatesByParty.delegatesWithPaymentInstitutionByParty - .get(party.id) - .find((d) => d?.partyDelegate?.ruleset?.id === id)?.partyDelegate - ?.ruleset?.id, - shop.id, - party.id, - ), - disabled: ({ party }) => - isNil( - delegatesByParty.delegatesWithPaymentInstitutionByParty - .get(party.id) - .find((d) => d?.partyDelegate?.ruleset?.id === id)?.partyDelegate - ?.ruleset?.id, - ), + }), + }, + { + field: 'terms', + lazyCell: (d) => + this.getTerms(d.party.id, d.shop.id).pipe( + map((terms) => getDomainObjectDetails(terms)), + map((details) => ({ + value: details.label, + description: details.description, + click: () => { + this.getTerms(d.party.id, d.shop.id).subscribe((terms) => { + this.sidenavInfoService.toggle(DomainObjectCardComponent, { + ref: { + term_set_hierarchy: terms.term_set_hierarchy.ref, + }, + }); + }); + }, + })), + ), + }, + { + field: 'shop.location.url', + }, + { + field: 'shop.account.currency.symbolic_code', + header: 'Currency', + }, + { + field: 'shop.blocking', + cell: (d) => ({ + value: startCase(getUnionKey(d.shop.blocking)), + color: ( + { + blocked: 'warn', + unblocked: 'success', + } as const + )[getUnionKey(d.shop.blocking)], + }), + }, + { + field: 'shop.suspension', + cell: (d) => ({ + value: startCase(getUnionKey(d.shop.suspension)), + color: ( + { + suspended: 'warn', + active: 'success', + } as const + )[getUnionKey(d.shop.suspension)], + }), + }, + createMenuColumn((d) => + this.getDelegatesByParty().pipe( + map((delegatesByParty) => ({ + items: [ + ...delegatesByParty.rulesetIds.map((id) => { + const rulesetId = + delegatesByParty.delegatesWithPaymentInstitutionByParty + ?.get?.(d.party.id) + ?.find?.((v) => v?.partyDelegate?.ruleset?.id === id) + ?.partyDelegate?.ruleset?.id; + return { + label: `Routing rules #${id}`, + click: () => + this.openRoutingRules(rulesetId, d.shop.id, d.party.id), + disabled: isNil(rulesetId), + }; + }), + { + label: + getUnionKey(d.shop.suspension) === 'suspended' + ? 'Activate' + : 'Suspend', + click: () => { + this.toggleSuspension(d); + }, + }, + { + label: getUnionKey(d.shop.blocking) === 'blocked' ? 'Unblock' : 'Block', + click: () => { + this.toggleBlocking(d); + }, + }, + ], })), - { - label: ({ shop }) => - getUnionKey(shop.suspension) === 'suspended' ? 'Activate' : 'Suspend', - click: (d) => { - this.toggleSuspension(d); - }, - }, - { - label: ({ shop }) => - getUnionKey(shop.blocking) === 'blocked' ? 'Unblock' : 'Block', - click: (d) => { - this.toggleBlocking(d); - }, - }, - ]), - ]), - shareReplay({ refCount: true, bufferSize: 1 }), - ); + ), + ), + ]; sort: Sort = { active: 'shop.details.name', direction: 'asc' }; - private updateColumns$ = new Subject(); constructor( private sidenavInfoService: SidenavInfoService, @@ -243,17 +211,9 @@ export class ShopsTableComponent implements OnChanges { private router: Router, private partyDelegateRulesetsService: PartyDelegateRulesetsService, private domainStoreService: DomainStoreService, + private injector: Injector, ) {} - ngOnChanges(changes: ComponentChanges) { - if (changes.noSort || changes.noPartyColumn) { - if (this.noSort) { - this.sort = { active: '', direction: '' }; - } - this.updateColumns$.next(); - } - } - toggleBlocking({ party, shop }: ShopParty) { this.dialogService .open(ConfirmDialogComponent, { @@ -369,4 +329,34 @@ export class ShopsTableComponent implements OnChanges { }); }); } + + private getDelegatesByParty() { + return toObservable(this.shops, { injector: this.injector }).pipe( + startWith(null), + map((shops) => + shops?.length ? Array.from(new Set(shops.map((s) => s.party.id))) : [], + ), + switchMap((parties) => + parties?.length + ? combineLatest( + parties.map((id) => + this.partyDelegateRulesetsService.getDelegatesWithPaymentInstitution( + RoutingRulesType.Payment, + id, + ), + ), + ).pipe(map((rules) => new Map(rules.map((r, idx) => [parties[idx], r])))) + : of(new Map()), + ), + map((delegatesWithPaymentInstitutionByParty) => ({ + delegatesWithPaymentInstitutionByParty, + rulesetIds: Array.from( + Array.from(delegatesWithPaymentInstitutionByParty.values()).reduce((acc, d) => { + d?.map((v) => v?.partyDelegate?.ruleset?.id).forEach((v) => acc.add(v)); + return acc; + }, new Set([])), + ), + })), + ); + } } diff --git a/src/app/shared/components/thrift-api-crud/domain/domain-thrift-viewer/domain-thrift-viewer.component.ts b/src/app/shared/components/thrift-api-crud/domain/domain-thrift-viewer/domain-thrift-viewer.component.ts index 28d50c9e..e64f84e7 100644 --- a/src/app/shared/components/thrift-api-crud/domain/domain-thrift-viewer/domain-thrift-viewer.component.ts +++ b/src/app/shared/components/thrift-api-crud/domain/domain-thrift-viewer/domain-thrift-viewer.component.ts @@ -1,7 +1,7 @@ import { CommonModule } from '@angular/common'; import { Component, Input, booleanAttribute } from '@angular/core'; import { ThriftAstMetadata } from '@vality/domain-proto'; -import { getImportValue } from '@vality/ng-core'; +import { getImportValue, UnionEnum } from '@vality/ng-core'; import { ValueType } from '@vality/thrift-ts'; import { ThriftViewerModule, ViewerKind } from '../../../thrift-viewer'; @@ -15,7 +15,7 @@ import { DomainMetadataViewExtensionsService } from './services/domain-metadata- imports: [CommonModule, ThriftViewerModule], }) export class DomainThriftViewerComponent { - @Input() kind: ViewerKind = ViewerKind.Component; + @Input() kind: UnionEnum = ViewerKind.Component; @Input() value: T; @Input() compared?: T; @Input() type: ValueType; diff --git a/src/app/shared/components/thrift-editor/thrift-editor.component.ts b/src/app/shared/components/thrift-editor/thrift-editor.component.ts index d40fe897..945cf4fc 100644 --- a/src/app/shared/components/thrift-editor/thrift-editor.component.ts +++ b/src/app/shared/components/thrift-editor/thrift-editor.component.ts @@ -9,6 +9,7 @@ import { FormControlSuperclass, } from '@vality/ng-core'; import { toJson } from '@vality/ng-thrift'; +import { ValueType } from '@vality/thrift-ts'; import { merge, defer, of, Subject } from 'rxjs'; import { map, filter, shareReplay } from 'rxjs/operators'; @@ -32,7 +33,7 @@ export class ThriftEditorComponent extends FormControlSuperclass { @Input() metadata: ThriftAstMetadata[]; @Input() namespace: string; - @Input() type: string; + @Input() type: ValueType; @Input() extensions: MetadataFormExtension[]; @Input({ transform: booleanAttribute }) noChangeKind = false; @Input({ transform: booleanAttribute }) noToolbar = false; diff --git a/src/app/shared/components/thrift-viewer/thrift-viewer.component.ts b/src/app/shared/components/thrift-viewer/thrift-viewer.component.ts index c47df368..dfe2fd95 100644 --- a/src/app/shared/components/thrift-viewer/thrift-viewer.component.ts +++ b/src/app/shared/components/thrift-viewer/thrift-viewer.component.ts @@ -1,6 +1,6 @@ import { Component, Input, OnChanges, Output, EventEmitter, booleanAttribute } from '@angular/core'; import { ThriftAstMetadata } from '@vality/domain-proto'; -import { ComponentChanges } from '@vality/ng-core'; +import { ComponentChanges, UnionEnum } from '@vality/ng-core'; import { toJson } from '@vality/ng-thrift'; import { ValueType } from '@vality/thrift-ts'; import { DiffEditorModel } from 'ngx-monaco-editor-v2'; @@ -19,7 +19,7 @@ export enum ViewerKind { styleUrls: ['./thrift-viewer.component.scss'], }) export class ThriftViewerComponent implements OnChanges { - @Input() kind: ViewerKind = ViewerKind.Component; + @Input() kind: UnionEnum = ViewerKind.Component; @Input() value: T; @Input() compared?: T; @Input({ transform: booleanAttribute }) progress: boolean = false; @@ -62,6 +62,6 @@ export class ThriftViewerComponent implements OnChanges { this.kind = ViewerKind.Editor; break; } - this.changeKind.emit(this.kind); + this.changeKind.emit(this.kind as ViewerKind); } } diff --git a/src/app/shared/components/wallet-field/wallet-field.component.ts b/src/app/shared/components/wallet-field/wallet-field.component.ts index 487bef76..0c8a5336 100644 --- a/src/app/shared/components/wallet-field/wallet-field.component.ts +++ b/src/app/shared/components/wallet-field/wallet-field.component.ts @@ -15,6 +15,7 @@ import { createControlProviders, debounceTimeWithFirst, progressTo, + SelectFieldComponent, } from '@vality/ng-core'; import { BehaviorSubject, Observable, of, ReplaySubject, Subject, concat, forkJoin } from 'rxjs'; import { catchError, map, switchMap, tap, distinctUntilChanged } from 'rxjs/operators'; @@ -34,8 +35,8 @@ export class WalletFieldComponent { @Input() label: string; @Input({ transform: booleanAttribute }) required: boolean; - @Input() size?: string; - @Input() appearance?: string; + @Input() size?: SelectFieldComponent['size']; + @Input() appearance?: SelectFieldComponent['appearance']; @Input() hint?: string; @Input({ transform: booleanAttribute }) multiple = false; diff --git a/src/app/shared/utils/table/create-provider-column.ts b/src/app/shared/utils/table/create-provider-column.ts deleted file mode 100644 index 950dfb9d..00000000 --- a/src/app/shared/utils/table/create-provider-column.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Column, PossiblyAsync, getPossiblyAsyncObservable } from '@vality/ng-core'; -import { map } from 'rxjs/operators'; - -import { createDomainObjectColumn } from './create-domain-object-column'; - -export function createProviderColumn( - selectTerminalId: (d: T) => PossiblyAsync, -): Column { - return createDomainObjectColumn('provider', (d) => - getPossiblyAsyncObservable(selectTerminalId(d)).pipe(map((id) => ({ id }))), - ); -} diff --git a/src/app/shared/utils/table2/create-party-column.ts b/src/app/shared/utils/table2/create-party-column.ts index 2fc51a5e..fbacd6a9 100644 --- a/src/app/shared/utils/table2/create-party-column.ts +++ b/src/app/shared/utils/table2/create-party-column.ts @@ -1,5 +1,4 @@ import { inject } from '@angular/core'; -import { Router } from '@angular/router'; import { createColumn } from '@vality/ng-core'; import { of } from 'rxjs'; import { map, startWith } from 'rxjs/operators'; @@ -16,9 +15,7 @@ export const createPartyColumn = createColumn( .pipe(map((party) => party.contact_info.registration_email)); const partyCell = { description: id, - link: () => { - void inject(Router).navigate([`/party/${id}`]); - }, + link: () => `/party/${id}`, }; return partyName$.pipe( map((partyName) => ({