IMP-159: Add filters to withdrawals search (#322)

This commit is contained in:
Rinat Arsaev 2024-02-01 12:10:41 +07:00 committed by GitHub
parent 115de955b4
commit 31f887a6b8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 225 additions and 153 deletions

96
package-lock.json generated
View File

@ -22,15 +22,15 @@
"@ngneat/input-mask": "6.0.0",
"@vality/deanonimus-proto": "2.0.1-2a02d87.0",
"@vality/domain-proto": "2.0.1-23211ff.0",
"@vality/fistful-proto": "2.0.1-f2ca9b5.0",
"@vality/fistful-proto": "2.0.1-23e9ba3.0",
"@vality/machinegun-proto": "1.0.0",
"@vality/magista-proto": "2.0.2-28d11b9.0",
"@vality/ng-core": "^17.1.1-pr-57-8ca06c2.0",
"@vality/ng-core": "^17.1.1-pr-57-4da820a.0",
"@vality/payout-manager-proto": "2.0.1-eb4091a.0",
"@vality/repairer-proto": "2.0.2-07b73e9.0",
"@vality/thrift-ts": "2.4.1-8ad5123.0",
"@vality/woody": "0.1.3",
"date-fns": "2.30.0",
"date-fns": "^3.3.1",
"inputmask": "5.0.7",
"keycloak-angular": "^15.0.0",
"keycloak-js": "^20.0.5",
@ -2571,6 +2571,7 @@
"version": "7.23.7",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.7.tgz",
"integrity": "sha512-w06OXVOFso7LcbzMiDGt+3X7Rh7Ho8MmgPoWU3rarH+8upf+wSU/grlGbWzQyr3DkdN6ZeuMFjpdwW0Q+HxobA==",
"dev": true,
"dependencies": {
"regenerator-runtime": "^0.14.0"
},
@ -5354,50 +5355,50 @@
]
},
"node_modules/@s-libs/js-core": {
"version": "17.0.0",
"resolved": "https://registry.npmjs.org/@s-libs/js-core/-/js-core-17.0.0.tgz",
"integrity": "sha512-+q9ZavPgKQTb0Wj0ST+BexJx2/wBYL7O5ONS0I1AKQ7cObAdfTi6cUjZKfvCpdjUEqFdFtGeoI8yRmn0Lpt87A==",
"version": "17.1.0",
"resolved": "https://registry.npmjs.org/@s-libs/js-core/-/js-core-17.1.0.tgz",
"integrity": "sha512-HsHs7gl0XYJVjRCd2yxf5lHmrUAZ65HsGCdyr++cfZN3cmGRDhuriwuu6hI1AfNHBIWVTF4YPrTKxVTaNXjmUA==",
"dependencies": {
"tslib": "^2.3.0"
},
"peerDependencies": {
"@s-libs/micro-dash": "^17.0.0"
"@s-libs/micro-dash": "^17.1.0"
}
},
"node_modules/@s-libs/micro-dash": {
"version": "17.0.0",
"resolved": "https://registry.npmjs.org/@s-libs/micro-dash/-/micro-dash-17.0.0.tgz",
"integrity": "sha512-pXrQItHMZIaqmm6aPlYrqUUhPSl+fxO0eqxDd5QiBH+NqEXiYYhtcy8oLKPlWau+8HBB2PkQ5IzXh+dReGe1YA==",
"version": "17.1.0",
"resolved": "https://registry.npmjs.org/@s-libs/micro-dash/-/micro-dash-17.1.0.tgz",
"integrity": "sha512-vnrChv6KQG/kgRSNmxH0IqcGx4gYlvnmkfzuKotQNZZMBTnDZOzHYr487LPRq1Rr0ohRDuDsz6WssSolyoowQg==",
"dependencies": {
"tslib": "^2.3.0",
"utility-types": "^3.10.0"
}
},
"node_modules/@s-libs/ng-core": {
"version": "17.0.0",
"resolved": "https://registry.npmjs.org/@s-libs/ng-core/-/ng-core-17.0.0.tgz",
"integrity": "sha512-IgMquST4EEgC/C5sAbviQ523ohJ1LXCfiPKzZ1S2JdEsTfDxdzCEeoUfi2dff3vVCvC4ZEJ7TrWmoRnJq4jM9g==",
"version": "17.1.0",
"resolved": "https://registry.npmjs.org/@s-libs/ng-core/-/ng-core-17.1.0.tgz",
"integrity": "sha512-GqwmW12vV9KVWCG8NMnHS6TqxM285edBO1iVDSNzCs5Ot+aHBKuX5ThUfgbpNqN5uUtgQP3VHMX09gxUufejqg==",
"dependencies": {
"tslib": "^2.3.0"
},
"peerDependencies": {
"@angular/common": "^17.0.0",
"@angular/core": "^17.0.0",
"@s-libs/js-core": "^17.0.0",
"@s-libs/micro-dash": "^17.0.0",
"@s-libs/rxjs-core": "^17.0.0"
"@s-libs/js-core": "^17.1.0",
"@s-libs/micro-dash": "^17.1.0",
"@s-libs/rxjs-core": "^17.1.0"
}
},
"node_modules/@s-libs/rxjs-core": {
"version": "17.0.0",
"resolved": "https://registry.npmjs.org/@s-libs/rxjs-core/-/rxjs-core-17.0.0.tgz",
"integrity": "sha512-H5cBRDDSPhn7gDXBo3VNtZzOmFScekg7o6PbV/6suyJtmT0Ke0UQFhoqxiZyVHChlJQbfOTWf2eh8RUpySPnJg==",
"version": "17.1.0",
"resolved": "https://registry.npmjs.org/@s-libs/rxjs-core/-/rxjs-core-17.1.0.tgz",
"integrity": "sha512-PYDoLh6SIwsMWnmz4bZfAmQQl9MyywBfsvE1qJEvo3BzHQpAV6U/RfugMzXcMWQDrs5hIGjxS0xMfMZXp6u/gQ==",
"dependencies": {
"tslib": "^2.3.0"
},
"peerDependencies": {
"@s-libs/js-core": "^17.0.0",
"@s-libs/micro-dash": "^17.0.0",
"@s-libs/js-core": "^17.1.0",
"@s-libs/micro-dash": "^17.1.0",
"rxjs": "^7.8.0"
}
},
@ -6429,9 +6430,9 @@
}
},
"node_modules/@vality/fistful-proto": {
"version": "2.0.1-f2ca9b5.0",
"resolved": "https://registry.npmjs.org/@vality/fistful-proto/-/fistful-proto-2.0.1-f2ca9b5.0.tgz",
"integrity": "sha512-rH5vYC2yxSgUcfXlG6ZLbE0TZBazO0Q2fkoShTBVQoXh8hvGcaJU0KpRPc2z4NEKZRFqhKicDQODgs719mpVwA=="
"version": "2.0.1-23e9ba3.0",
"resolved": "https://registry.npmjs.org/@vality/fistful-proto/-/fistful-proto-2.0.1-23e9ba3.0.tgz",
"integrity": "sha512-yOEV1tR7977GWLVUKThSYmC7KnwaswIqQpIacW5ffUdKMCvp+uv9LZZHpTd812k6WZXcj/NbGMIdEteQHqCLXA=="
},
"node_modules/@vality/machinegun-proto": {
"version": "1.0.0",
@ -6444,27 +6445,27 @@
"integrity": "sha512-BsDy5ejotfTtUlwuoX3kz+PYJ5NSTW6m5ZRGv+p5HaKXSjR7tserPdv0q133Wp4T+sg0ED0Qr9Peqsrn+9XlDQ=="
},
"node_modules/@vality/ng-core": {
"version": "17.1.1-pr-57-8ca06c2.0",
"resolved": "https://registry.npmjs.org/@vality/ng-core/-/ng-core-17.1.1-pr-57-8ca06c2.0.tgz",
"integrity": "sha512-io0j/knhIGgqmi8HxfuTZMGycVSO8qE9EYq5KN7lP7ectNeDrpvZdKcsJUg2kfTtWWaG9p8DSR5CHbe36tDxYA==",
"version": "17.1.1-pr-57-4da820a.0",
"resolved": "https://registry.npmjs.org/@vality/ng-core/-/ng-core-17.1.1-pr-57-4da820a.0.tgz",
"integrity": "sha512-8SFOKgGjWDEZZW6f1Nv10gUUrmqb18OQyNGHRHyU77WLKQ3k+qW9nuaWWmxywMmDSFvaposg7WaDpH1+5INDoA==",
"dependencies": {
"@angular/material-date-fns-adapter": "^17.0.0",
"@ng-matero/extensions": "^17.0.0",
"@s-libs/js-core": "^17.0.0",
"@s-libs/micro-dash": "^17.0.0",
"@s-libs/ng-core": "^17.0.0",
"@s-libs/rxjs-core": "^17.0.0",
"@angular/material-date-fns-adapter": "^17.1.1",
"@ng-matero/extensions": "^17.1.0",
"@s-libs/js-core": "^17.1.0",
"@s-libs/micro-dash": "^17.1.0",
"@s-libs/ng-core": "^17.1.0",
"@s-libs/rxjs-core": "^17.1.0",
"dinero.js": "^2.0.0-alpha.14",
"fuse.js": "^7.0.0",
"tslib": "^2.3.0"
},
"peerDependencies": {
"@angular/cdk": "^17.0.0",
"@angular/common": "^17.0.0",
"@angular/core": "^17.0.0",
"@angular/material": "^17.0.0",
"@angular/cdk": "^17.1.0",
"@angular/common": "^17.1.0",
"@angular/core": "^17.1.0",
"@angular/material": "^17.1.0",
"@types/lodash-es": "^4.0.0",
"date-fns": "^2.30.0",
"date-fns": "^3.0.0",
"lodash-es": "^4.0.0",
"rxjs": "^7.0.0",
"utility-types": "^3.0.0"
@ -8946,18 +8947,12 @@
"dev": true
},
"node_modules/date-fns": {
"version": "2.30.0",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
"integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
"dependencies": {
"@babel/runtime": "^7.21.0"
},
"engines": {
"node": ">=0.11"
},
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.3.1.tgz",
"integrity": "sha512-y8e109LYGgoQDveiEBD3DYXKba1jWf5BA8YU1FL5Tvm0BTdEfy54WLCwnuYWZNnzzvALy/QQ4Hov+Q9RVRv+Zw==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/date-fns"
"type": "github",
"url": "https://github.com/sponsors/kossnocorp"
}
},
"node_modules/date-format": {
@ -15797,7 +15792,8 @@
"node_modules/regenerator-runtime": {
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
"integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
"dev": true
},
"node_modules/regenerator-transform": {
"version": "0.15.2",

View File

@ -30,15 +30,15 @@
"@ngneat/input-mask": "6.0.0",
"@vality/deanonimus-proto": "2.0.1-2a02d87.0",
"@vality/domain-proto": "2.0.1-23211ff.0",
"@vality/fistful-proto": "2.0.1-f2ca9b5.0",
"@vality/fistful-proto": "2.0.1-23e9ba3.0",
"@vality/machinegun-proto": "1.0.0",
"@vality/magista-proto": "2.0.2-28d11b9.0",
"@vality/ng-core": "^17.1.1-pr-57-8ca06c2.0",
"@vality/ng-core": "^17.1.1-pr-57-4da820a.0",
"@vality/payout-manager-proto": "2.0.1-eb4091a.0",
"@vality/repairer-proto": "2.0.2-07b73e9.0",
"@vality/thrift-ts": "2.4.1-8ad5123.0",
"@vality/woody": "0.1.3",
"date-fns": "2.30.0",
"date-fns": "^3.3.1",
"inputmask": "5.0.7",
"keycloak-angular": "^15.0.0",
"keycloak-js": "^20.0.5",
@ -82,4 +82,4 @@
"typescript": "~5.2.2",
"typescript-memoize": "1.1.1"
}
}
}

View File

@ -57,9 +57,9 @@ export class DomainStoreService {
);
}
getObject(ref: Reference): Observable<DomainObject> {
return this.getDomain().pipe(
map((domain) => Array.from(domain).find(([r]) => isEqual(ref, r))[1]),
getObject(ref: Reference, raw = false): Observable<DomainObject> {
return this.getDomain(raw).pipe(
map((domain) => Array.from(domain).find(([r]) => isEqual(ref, r))?.[1]),
);
}

View File

@ -18,4 +18,6 @@ export interface WithdrawalParams extends PagedBaseParameters {
from_time?: string;
to_time?: string;
error_message?: string;
withdrawal_provider_id?: string;
withdrawal_terminal_id?: string;
}

View File

@ -27,7 +27,7 @@ import {
getDomainObjectDetails,
DomainThriftViewerComponent,
DomainObjectCardComponent,
DomainObjectService,
DeleteDomainObjectService,
EditDomainObjectDialogComponent,
} from '../../../../shared/components/thrift-api-crud';
import { MetadataService } from '../../services/metadata.service';
@ -121,7 +121,7 @@ export class DomainObjectsTableComponent implements OnInit {
{
label: 'Delete',
click: (d) => {
this.domainObjectService.delete(d.obj);
this.deleteDomainObjectService.delete(d.ref);
},
},
]),
@ -147,7 +147,7 @@ export class DomainObjectsTableComponent implements OnInit {
private metadataService: MetadataService,
private qp: QueryParamsService<{ types?: string[] }>,
private sidenavInfoService: SidenavInfoService,
private domainObjectService: DomainObjectService,
private deleteDomainObjectService: DeleteDomainObjectService,
private destroyRef: DestroyRef,
private dialogService: DialogService,
) {}

View File

@ -11,6 +11,8 @@ import { AmountCurrencyService } from '@cc/app/shared/services';
import { getUnionKey } from '@cc/utils';
import { createFailureColumn } from '../../../../shared';
import { createProviderColumn } from '../../../../shared/utils/table/create-provider-column';
import { createTerminalColumn } from '../../../../shared/utils/table/create-terminal-column';
@Component({
selector: 'cc-payments-table',
@ -82,8 +84,8 @@ export class PaymentsTableComponent {
header: 'Shop',
},
'domain_revision',
{ field: 'terminal_id.id', header: 'Terminal' },
{ field: 'provider_id.id', header: 'Provider' },
createTerminalColumn((d) => d.terminal_id.id),
createProviderColumn((d) => d.provider_id.id),
createFailureColumn<StatPayment>(
(d) => d.status?.failed?.failure?.failure,
(d) =>

View File

@ -22,7 +22,7 @@
*ngFor="let statusName of status | enumKeys"
[value]="status[statusName]"
>
{{ statusName }}
{{ statusName | keyTitle | titlecase }}
</mat-option>
</mat-select>
</mat-form-field>

View File

@ -16,14 +16,15 @@ import { repairer } from '@vality/repairer-proto';
import { Namespace, ProviderID, RepairStatus, Machine } from '@vality/repairer-proto/repairer';
import { endOfDay } from 'date-fns';
import isNil from 'lodash-es/isNil';
import startCase from 'lodash-es/startCase';
import { BehaviorSubject } from 'rxjs';
import { filter, map, switchMap } from 'rxjs/operators';
import { DomainStoreService } from '@cc/app/api/domain-config';
import { getEnumKey } from '@cc/utils';
import { RepairManagementService } from '../../api/repairer';
import { NotificationService } from '../../shared/services/notification';
import { createProviderColumn } from '../../shared/utils/table/create-provider-column';
import { RepairByScenarioDialogComponent } from './components/repair-by-scenario-dialog/repair-by-scenario-dialog.component';
import { MachinesService } from './services/machines.service';
@ -60,30 +61,28 @@ export class RepairingComponent implements OnInit {
{ field: 'id' },
{ header: 'Namespace', field: 'ns' },
{ field: 'created_at', type: 'datetime' },
{
field: 'provider',
formatter: (data) =>
this.domainStoreService
.getObjects('provider')
.pipe(
map(
(providers) =>
providers.find((p) => String(p.ref.id) === data.provider_id)?.data
?.name,
),
),
description: 'provider_id',
},
createProviderColumn((d) => Number(d.provider_id)),
{
field: 'status',
formatter: (data) => getEnumKey(repairer.RepairStatus, data.status),
tooltip: 'error_message',
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' },
},
},
},
{
field: 'history',
formatter: (data) => (data.history?.length ? String(data.history.length) : ''),
tooltip: 'history',
},
{
field: 'error_message',
},
];
constructor(
@ -94,7 +93,6 @@ export class RepairingComponent implements OnInit {
private repairManagementService: RepairManagementService,
private notificationService: NotificationService,
private log: NotifyLogService,
private domainStoreService: DomainStoreService,
private destroyRef: DestroyRef,
) {}

View File

@ -21,7 +21,7 @@ import {
EnumKeysPipe,
} from '@vality/ng-core';
import { PageLayoutModule } from '@cc/app/shared';
import { PageLayoutModule, ThriftPipesModule } from '@cc/app/shared';
import { MetadataFormModule } from '@cc/app/shared/components/metadata-form';
import { DomainObjectFieldComponent } from '@cc/app/shared/components/thrift-api-crud';
@ -54,6 +54,7 @@ import { RepairingComponent } from './repairing.component';
DomainObjectFieldComponent,
PageLayoutModule,
ListFieldModule,
ThriftPipesModule,
],
declarations: [RepairingComponent, RepairByScenarioDialogComponent],
})

View File

@ -17,15 +17,13 @@ import { first, map, switchMap, withLatestFrom } from 'rxjs/operators';
import { DomainStoreService } from '@cc/app/api/domain-config';
import { RoutingRulesType } from '@cc/app/sections/routing-rules/types/routing-rules-type';
import {
DomainThriftFormDialogComponent,
DomainObjectCardComponent,
} from '@cc/app/shared/components/thrift-api-crud';
import { DomainThriftFormDialogComponent } from '@cc/app/shared/components/thrift-api-crud';
import { objectToJSON } from '../../../../utils';
import { createPredicateColumn } from '../../../shared';
import { CandidateCardComponent } from '../../../shared/components/candidate-card/candidate-card.component';
import { SidenavInfoService } from '../../../shared/components/sidenav-info';
import { createTerminalColumn } from '../../../shared/utils/table/create-terminal-column';
import { RoutingRulesService } from '../services/routing-rules';
import { ChangeCandidatesPrioritiesDialogComponent } from './components/change-candidates-priorities-dialog/change-candidates-priorities-dialog.component';
@ -63,24 +61,7 @@ export class RoutingRulesetComponent {
});
},
},
{
field: 'terminal',
description: 'terminal.id',
formatter: (d) =>
this.domainStoreService
.getObjects('terminal')
.pipe(
map(
(terminals) =>
terminals.find((t) => t.ref.id === d.terminal.id).data.name,
),
),
click: (d) => {
this.sidenavInfoService.toggle(DomainObjectCardComponent, {
ref: { terminal: { id: d.terminal.id } },
});
},
},
createTerminalColumn((d) => d.terminal.id),
createPredicateColumn('global_allow', (d) =>
combineLatest([
this.domainStoreService.getObjects('terminal'),

View File

@ -22,6 +22,8 @@
</mat-form-field>
<v-number-range-field formControlName="amount" label="Amount"></v-number-range-field>
<v-input-field formControlName="errorMessage" label="Error message"></v-input-field>
<v-input-field formControlName="terminalId" label="Terminal ID"></v-input-field>
<v-input-field formControlName="providerId" label="Provider ID"></v-input-field>
</ng-template>
</v-filters>

View File

@ -25,6 +25,8 @@ import { getUnionKey } from '../../../utils';
import { createFailureColumn } from '../../shared';
import { FailMachinesDialogComponent, Type } from '../../shared/components/fail-machines-dialog';
import { AmountCurrencyService } from '../../shared/services';
import { createProviderColumn } from '../../shared/utils/table/create-provider-column';
import { createTerminalColumn } from '../../shared/utils/table/create-terminal-column';
import { CreateAdjustmentDialogComponent } from './components/create-adjustment-dialog/create-adjustment-dialog.component';
import { FetchWithdrawalsService } from './services/fetch-withdrawals.service';
@ -37,6 +39,8 @@ interface WithdrawalsForm {
withdrawalIds: WithdrawalParams['withdrawal_ids'];
walletId: WithdrawalParams['wallet_id'];
errorMessage: WithdrawalParams['error_message'];
providerId: WithdrawalParams['withdrawal_provider_id'];
terminalId: WithdrawalParams['withdrawal_terminal_id'];
}
@Component({
@ -53,6 +57,8 @@ export class WithdrawalsComponent implements OnInit {
withdrawalIds: null,
walletId: null,
errorMessage: null,
providerId: null,
terminalId: null,
...this.qp.params,
});
active = 0;
@ -96,6 +102,8 @@ export class WithdrawalsComponent implements OnInit {
},
},
},
createTerminalColumn((d) => d.terminal_id),
createProviderColumn((d) => d.provider_id),
createFailureColumn<StatWithdrawal>((d) => d.status?.failed?.base_failure),
];
selected: StatWithdrawal[] = [];
@ -120,8 +128,17 @@ export class WithdrawalsComponent implements OnInit {
}
update(options?: UpdateOptions) {
const { dateRange, merchant, status, amount, withdrawalIds, walletId, errorMessage } =
this.qp.params;
const {
dateRange,
merchant,
status,
amount,
withdrawalIds,
walletId,
errorMessage,
providerId,
terminalId,
} = this.qp.params;
const params = clean({
party_id: merchant,
from_time: dateRange?.start && getNoTimeZoneIsoString(dateRange?.start),
@ -132,6 +149,8 @@ export class WithdrawalsComponent implements OnInit {
withdrawal_ids: withdrawalIds,
wallet_id: walletId,
error_message: errorMessage,
withdrawal_terminal_id: terminalId,
withdrawal_provider_id: providerId,
});
this.fetchWithdrawalsService.load(params, options);
this.active = countProps(params);

View File

@ -72,7 +72,10 @@ export class UnionFieldComponent<T extends { [N in string]: unknown }>
}
validate(): ValidationErrors | null {
return this.fieldControl.errors || getErrorsTree(this.internalControl);
return (
this.fieldControl.errors ||
(this.fieldControl.value ? getErrorsTree(this.internalControl) : null)
);
}
handleIncomingValue(value: T) {

View File

@ -9,13 +9,13 @@ import { combineLatest, ReplaySubject, switchMap } from 'rxjs';
import { map, shareReplay, first } from 'rxjs/operators';
import { DomainStoreService } from '@cc/app/api/domain-config';
import { toJson } from '@cc/utils';
import { isEqualThrift } from '@cc/utils';
import { SidenavInfoModule } from '../../../sidenav-info';
import { CardComponent } from '../../../sidenav-info/components/card/card.component';
import { DomainThriftViewerComponent } from '../domain-thrift-viewer';
import { EditDomainObjectDialogComponent } from '../edit-domain-object-dialog';
import { DomainObjectService } from '../services';
import { DeleteDomainObjectService } from '../services';
import { getDomainObjectDetails } from '../utils';
@Component({
@ -36,12 +36,9 @@ export class DomainObjectCardComponent implements OnChanges {
ref$ = new ReplaySubject<Reference>(1);
progress$ = this.domainStoreService.isLoading$;
domainObject$ = combineLatest([this.domainStoreService.getDomain(), this.ref$]).pipe(
map(([domain, ref]) => {
const searchRef = JSON.stringify(ref);
return domain.get(
Array.from(domain.keys()).find((k) => JSON.stringify(toJson(k)) === searchRef),
);
}),
map(([domain, ref]) =>
domain.get(Array.from(domain.keys()).find((k) => isEqualThrift(k, ref))),
),
shareReplay({ refCount: true, bufferSize: 1 }),
);
title$ = this.domainObject$.pipe(
@ -49,7 +46,7 @@ export class DomainObjectCardComponent implements OnChanges {
);
constructor(
private domainObjectService: DomainObjectService,
private deleteDomainObjectService: DeleteDomainObjectService,
private domainStoreService: DomainStoreService,
private destroyRef: DestroyRef,
private dialogService: DialogService,
@ -77,11 +74,7 @@ export class DomainObjectCardComponent implements OnChanges {
}
delete() {
this.domainObject$
.pipe(first(), takeUntilDestroyed(this.destroyRef))
.subscribe((domainObject) => {
this.domainObjectService.delete(domainObject);
});
this.deleteDomainObjectService.delete(this.ref);
}
oldEdit() {

View File

@ -70,7 +70,15 @@ export class DomainMetadataViewExtensionsService {
).ast;
const refType = objectFields.find((n) => n.name === 'ref').type as string;
return {
determinant: (data) => of(isTypeWithAliases(data, refType, 'domain')),
determinant: (data) =>
of(
isTypeWithAliases(data, refType, 'domain') &&
!isTypeWithAliases(
data?.trueParent?.trueParent,
'DomainObject',
'domain',
),
),
extension: (_, value) =>
this.domainStoreService.getObjectsRefs(objectKey).pipe(
map((refObjs) => refObjs.find(([, o]) => isEqual(o[objectKey].ref, value))),

View File

@ -13,8 +13,9 @@ import {
NotifyLogService,
getValueChanges,
progressTo,
inProgressFrom,
} from '@vality/ng-core';
import { BehaviorSubject, switchMap, EMPTY, combineLatest, defer, Observable } from 'rxjs';
import { BehaviorSubject, switchMap, EMPTY, combineLatest, Observable } from 'rxjs';
import { first, map, shareReplay, catchError, distinctUntilChanged } from 'rxjs/operators';
import { ValuesType } from 'utility-types';
@ -23,6 +24,7 @@ import { DomainStoreService } from '../../../../../api/domain-config';
import { DomainNavigateService } from '../../../../../sections/domain/services/domain-navigate.service';
import { MetadataService } from '../../../../../sections/domain/services/metadata.service';
import { ThriftPipesModule } from '../../../../pipes';
import { DomainSecretService } from '../../../../services';
import { DomainThriftFormComponent } from '../domain-thrift-form';
import { DomainThriftViewerComponent } from '../domain-thrift-viewer';
@ -88,13 +90,7 @@ export class EditDomainObjectDialogComponent extends DialogSuperclass<
distinctUntilChanged(),
shareReplay({ refCount: true, bufferSize: 1 }),
);
isLoading$ = combineLatest([
this.domainStoreService.isLoading$,
defer(() => this.progress$),
]).pipe(
map((progresses) => progresses.some((p) => !!p)),
shareReplay({ refCount: true, bufferSize: 1 }),
);
isLoading$ = inProgressFrom([this.domainStoreService.isLoading$, () => this.progress$]);
private progress$ = new BehaviorSubject(0);
@ -104,15 +100,16 @@ export class EditDomainObjectDialogComponent extends DialogSuperclass<
private log: NotifyLogService,
private domainNavigateService: DomainNavigateService,
private metadataService: MetadataService,
private domainSecretService: DomainSecretService,
) {
super();
}
update(isRepeat = false) {
this.getCurrentObject()
combineLatest([this.getCurrentObject(), this.getCurrentObject(true)])
.pipe(
first(),
switchMap((currentObject) => {
switchMap(([currentObject, currentObjectRaw]) => {
if (isRepeat && !isEqualThrift(currentObject, this.dialogData.domainObject)) {
this.log.error(
new Error('The object has changed'),
@ -125,8 +122,11 @@ export class EditDomainObjectDialogComponent extends DialogSuperclass<
ops: [
{
update: {
old_object: currentObject,
new_object: this.getNewObject(),
old_object: currentObjectRaw,
new_object: this.domainSecretService.restoreDomain(
currentObjectRaw,
this.getNewObject(),
),
},
},
],
@ -164,11 +164,15 @@ export class EditDomainObjectDialogComponent extends DialogSuperclass<
});
}
private getCurrentObject(): Observable<DomainObject> {
return this.domainStoreService.getObject({
[getUnionKey(this.dialogData.domainObject)]: getUnionValue(this.dialogData.domainObject)
.ref,
});
private getCurrentObject(raw = false): Observable<DomainObject> {
return this.domainStoreService.getObject(
{
[getUnionKey(this.dialogData.domainObject)]: getUnionValue(
this.dialogData.domainObject,
).ref,
},
raw,
);
}
private getNewObject(): DomainObject {

View File

@ -1,35 +1,34 @@
import { Injectable } from '@angular/core';
import { DomainObject } from '@vality/domain-proto/domain';
import { Reference } from '@vality/domain-proto/domain';
import {
ConfirmDialogComponent,
DialogResponseStatus,
DialogService,
NotifyLogService,
} from '@vality/ng-core';
import { filter, switchMap } from 'rxjs/operators';
import { filter, switchMap, first } from 'rxjs/operators';
import { DomainStoreService } from '../../../../../api/domain-config';
@Injectable({
providedIn: 'root',
})
export class DomainObjectService {
export class DeleteDomainObjectService {
constructor(
private dialogService: DialogService,
private domainStoreService: DomainStoreService,
private log: NotifyLogService,
) {}
delete(domainObject: DomainObject) {
delete(domainRef: Reference) {
return this.dialogService
.open(ConfirmDialogComponent, { title: 'Delete object' })
.afterClosed()
.pipe(
filter(({ status }) => status === DialogResponseStatus.Success),
switchMap(() =>
this.domainStoreService.commit({
ops: [{ remove: { object: domainObject } }],
}),
filter((r) => r.status === DialogResponseStatus.Success),
switchMap(() => this.domainStoreService.getObject(domainRef, true).pipe(first())),
switchMap((obj) =>
this.domainStoreService.commit({ ops: [{ remove: { object: obj } }] }),
),
)
.subscribe({

View File

@ -1 +1 @@
export * from './domain-object.service';
export * from './delete-domain-object.service';

View File

@ -76,7 +76,7 @@ export function getDomainObjectValueDetailsFn(key: keyof DomainObject): GetDomai
}
export function getDomainObjectDetails(o: DomainObject): DomainObjectDetails {
if (!o) {
if (!o || !getUnionValue(o)) {
return { id: null, label: '', description: '', type: '' };
}
const result = getDomainObjectValueDetailsFn(getUnionKey(o))(getUnionValue(o));

View File

@ -14,7 +14,7 @@ const EXCLUDE_OBJECTS = ['terminal', 'provider', 'proxy'];
providedIn: 'root',
})
export class DomainSecretService {
private isDominantSecret = isDominantSecretRole(
private hasDominantSecretRole = isDominantSecretRole(
this.keycloakService.getUserRoles(),
DOMINANT_SECRETS_ROLE,
);
@ -22,7 +22,7 @@ export class DomainSecretService {
constructor(private keycloakService: KeycloakService) {}
reduceDomain(domain: Domain): Domain {
if (this.isDominantSecret) {
if (this.hasDominantSecretRole) {
return domain;
}
const result = new Map(domain);
@ -36,7 +36,7 @@ export class DomainSecretService {
}
restoreDomain(oldObject: DomainObject, newObject: DomainObject): DomainObject {
if (this.isDominantSecret) {
if (this.hasDominantSecretRole) {
return newObject;
}
let result = newObject;

View File

@ -0,0 +1,40 @@
import { inject } from '@angular/core';
import { Reference } from '@vality/domain-proto/domain';
import { Column, PossiblyAsync, getPossiblyAsyncObservable } from '@vality/ng-core';
import startCase from 'lodash-es/startCase';
import { map, switchMap, first } from 'rxjs/operators';
import { ValuesType } from 'utility-types';
import { DomainStoreService } from '../../../api/domain-config';
import { SidenavInfoService } from '../../components/sidenav-info';
import {
getDomainObjectDetails,
DomainObjectCardComponent,
} from '../../components/thrift-api-crud';
export function createDomainObjectColumn<T extends object>(
objectKey: keyof Reference,
selectDomainObjectRef: (d: T) => PossiblyAsync<ValuesType<Reference>>,
): Column<T> {
const domainStoreService = inject(DomainStoreService);
const sidenavInfoService = inject(SidenavInfoService);
const getObjectRef = (d: T) =>
getPossiblyAsyncObservable(selectDomainObjectRef(d)).pipe(
map((ref): Reference => ({ [objectKey]: ref })),
);
const getObject = (d: T) =>
getObjectRef(d).pipe(switchMap((ref) => domainStoreService.getObject(ref)));
return {
field: `domain_object_${objectKey}`,
header: startCase(objectKey),
description: (d) => getObject(d).pipe(map((o) => getDomainObjectDetails(o)?.id)),
formatter: (d) => getObject(d).pipe(map((o) => getDomainObjectDetails(o)?.label)),
click: (d) => {
getObjectRef(d)
.pipe(first())
.subscribe((ref) => {
sidenavInfoService.toggle(DomainObjectCardComponent, { ref });
});
},
};
}

View File

@ -0,0 +1,12 @@
import { Column, PossiblyAsync, getPossiblyAsyncObservable } from '@vality/ng-core';
import { map } from 'rxjs/operators';
import { createDomainObjectColumn } from './create-domain-object-column';
export function createProviderColumn<T extends object>(
selectTerminalId: (d: T) => PossiblyAsync<number>,
): Column<T> {
return createDomainObjectColumn('provider', (d) =>
getPossiblyAsyncObservable(selectTerminalId(d)).pipe(map((id) => ({ id }))),
);
}

View File

@ -0,0 +1,12 @@
import { Column, PossiblyAsync, getPossiblyAsyncObservable } from '@vality/ng-core';
import { map } from 'rxjs/operators';
import { createDomainObjectColumn } from './create-domain-object-column';
export function createTerminalColumn<T extends object>(
selectTerminalId: (d: T) => PossiblyAsync<number>,
): Column<T> {
return createDomainObjectColumn('terminal', (d) =>
getPossiblyAsyncObservable(selectTerminalId(d)).pipe(map((id) => ({ id }))),
);
}