mirror of
https://github.com/valitydev/control-center.git
synced 2024-11-06 02:25:17 +00:00
IMP-80: Update shop routing rules (#261)
This commit is contained in:
parent
6747d10e4d
commit
8c3f642bee
@ -1,118 +0,0 @@
|
||||
<v-dialog title="Routing rule params">
|
||||
<div [formGroup]="form" fxLayout="column" fxLayoutGap="24px">
|
||||
<div fxLayout="column" fxLayoutGap="16px">
|
||||
<mat-form-field>
|
||||
<input
|
||||
formControlName="description"
|
||||
matInput
|
||||
placeholder="Description (optional)"
|
||||
/>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<input
|
||||
formControlName="weight"
|
||||
matInput
|
||||
placeholder="Weight (optional)"
|
||||
type="number"
|
||||
/>
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<input
|
||||
formControlName="priority"
|
||||
matInput
|
||||
placeholder="Priority"
|
||||
required
|
||||
type="number"
|
||||
/>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<mat-divider></mat-divider>
|
||||
|
||||
<div class="mat-headline-4">Predicate</div>
|
||||
<cc-predicate [formControl]="predicateControl"></cc-predicate>
|
||||
|
||||
<mat-divider></mat-divider>
|
||||
|
||||
<div class="mat-headline-4">Terminal</div>
|
||||
<div fxLayout="column" fxLayoutGap="16px">
|
||||
<mat-radio-group formControlName="terminalType" fxLayout fxLayoutGap="8px">
|
||||
<mat-radio-button [value]="terminalType.New" fxFlex>Create new</mat-radio-button>
|
||||
<mat-radio-button [value]="terminalType.Existent" fxFlex>
|
||||
Select existent
|
||||
</mat-radio-button>
|
||||
</mat-radio-group>
|
||||
<div
|
||||
*ngIf="form.value.terminalType === terminalType.New"
|
||||
formGroupName="newTerminal"
|
||||
fxLayout="column"
|
||||
fxLayoutGap="24px"
|
||||
>
|
||||
<div fxLayout="column" fxLayoutGap="16px">
|
||||
<mat-form-field>
|
||||
<input formControlName="name" matInput placeholder="Name" required />
|
||||
</mat-form-field>
|
||||
<mat-form-field>
|
||||
<input
|
||||
formControlName="description"
|
||||
matInput
|
||||
placeholder="Description"
|
||||
required
|
||||
/>
|
||||
</mat-form-field>
|
||||
<div class="mat-body-1">Risk coverage:</div>
|
||||
<mat-radio-group formControlName="riskCoverage" fxLayout fxLayoutGap="8px">
|
||||
<mat-radio-button [value]="riskScore.low" fxFlex>Low</mat-radio-button>
|
||||
<mat-radio-button [value]="riskScore.high" fxFlex>High</mat-radio-button>
|
||||
<mat-radio-button [value]="riskScore.fatal" fxFlex>Fatal</mat-radio-button>
|
||||
</mat-radio-group>
|
||||
</div>
|
||||
<div formArrayName="options" fxLayout="column" fxLayoutGap="8px">
|
||||
<div class="mat-body-1">Options:</div>
|
||||
<div
|
||||
*ngFor="let optionForm of newTerminalOptionsForm.controls; let idx = index"
|
||||
[formGroup]="optionForm"
|
||||
fxLayout
|
||||
fxLayoutAlign=" center"
|
||||
fxLayoutGap="24px"
|
||||
>
|
||||
<div fxFlex fxLayout>
|
||||
<mat-form-field fxFlex="33">
|
||||
<input formControlName="key" matInput placeholder="Key" required />
|
||||
</mat-form-field>
|
||||
<mat-form-field fxFlex>
|
||||
<input
|
||||
formControlName="value"
|
||||
matInput
|
||||
placeholder="Value"
|
||||
required
|
||||
/>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
<mat-icon class="action" (click)="removeOption(idx)">clear</mat-icon>
|
||||
</div>
|
||||
<mat-icon class="action" fxFlexAlign="end" (click)="addOption()">add</mat-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="form.value.terminalType === terminalType.Existent" fxLayout>
|
||||
<cc-domain-object-field
|
||||
formControlName="existentTerminalID"
|
||||
fxFlex
|
||||
name="terminal"
|
||||
required
|
||||
></cc-domain-object-field>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<v-dialog-actions>
|
||||
<button
|
||||
[disabled]="form.invalid || predicateControl.invalid"
|
||||
color="primary"
|
||||
mat-button
|
||||
(click)="add()"
|
||||
>
|
||||
Add
|
||||
</button>
|
||||
</v-dialog-actions>
|
||||
</v-dialog>
|
@ -1,3 +0,0 @@
|
||||
.action {
|
||||
cursor: pointer;
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
import { Component, Injector } from '@angular/core';
|
||||
import { Validators, FormBuilder } from '@angular/forms';
|
||||
import { UntilDestroy } from '@ngneat/until-destroy';
|
||||
import { domain } from '@vality/domain-proto';
|
||||
import { Predicate } from '@vality/domain-proto/domain';
|
||||
import { DialogSuperclass } from '@vality/ng-core';
|
||||
|
||||
import { AddRoutingRuleDialogService, TerminalType } from './add-routing-rule-dialog.service';
|
||||
|
||||
@UntilDestroy()
|
||||
@Component({
|
||||
templateUrl: 'add-routing-rule-dialog.component.html',
|
||||
styleUrls: ['add-routing-rule-dialog.component.scss'],
|
||||
providers: [AddRoutingRuleDialogService],
|
||||
})
|
||||
export class AddRoutingRuleDialogComponent extends DialogSuperclass<
|
||||
AddRoutingRuleDialogComponent,
|
||||
{ refID: number }
|
||||
> {
|
||||
form = this.addShopRoutingRuleDialogService.form;
|
||||
newTerminalOptionsForm = this.addShopRoutingRuleDialogService.newTerminalOptionsForm;
|
||||
predicateControl = this.fb.control<Predicate>(null, Validators.required);
|
||||
|
||||
terminalType = TerminalType;
|
||||
riskScore = domain.RiskScore;
|
||||
|
||||
constructor(
|
||||
injector: Injector,
|
||||
private addShopRoutingRuleDialogService: AddRoutingRuleDialogService,
|
||||
private fb: FormBuilder,
|
||||
) {
|
||||
super(injector);
|
||||
}
|
||||
|
||||
add() {
|
||||
this.addShopRoutingRuleDialogService.add(
|
||||
this.predicateControl.value,
|
||||
this.dialogData.refID,
|
||||
);
|
||||
}
|
||||
|
||||
addOption() {
|
||||
this.addShopRoutingRuleDialogService.addOption();
|
||||
}
|
||||
|
||||
removeOption(idx: number) {
|
||||
this.addShopRoutingRuleDialogService.removeOption(idx);
|
||||
}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FlexLayoutModule } from '@angular/flex-layout';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { MatDividerModule } from '@angular/material/divider';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatRadioModule } from '@angular/material/radio';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { DialogModule } from '@vality/ng-core';
|
||||
|
||||
import { MetadataFormModule } from '@cc/app/shared/components/metadata-form';
|
||||
|
||||
import { DomainObjectFieldComponent } from '../../../../shared';
|
||||
|
||||
import { AddRoutingRuleDialogComponent } from './add-routing-rule-dialog.component';
|
||||
import { ExpanderComponent } from './expander';
|
||||
import { PredicateComponent } from './predicate';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
MatButtonModule,
|
||||
FlexLayoutModule,
|
||||
MatDialogModule,
|
||||
MatDividerModule,
|
||||
ReactiveFormsModule,
|
||||
MatFormFieldModule,
|
||||
MatInputModule,
|
||||
MatIconModule,
|
||||
MatSelectModule,
|
||||
MatRadioModule,
|
||||
MatAutocompleteModule,
|
||||
MetadataFormModule,
|
||||
DialogModule,
|
||||
DomainObjectFieldComponent,
|
||||
],
|
||||
declarations: [AddRoutingRuleDialogComponent, PredicateComponent, ExpanderComponent],
|
||||
exports: [AddRoutingRuleDialogComponent],
|
||||
})
|
||||
export class AddRoutingRuleDialogModule {}
|
@ -1,104 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { UntypedFormArray, UntypedFormBuilder, Validators } from '@angular/forms';
|
||||
import { MatDialogRef } from '@angular/material/dialog';
|
||||
import { Predicate } from '@vality/domain-proto/domain';
|
||||
import { DialogResponseStatus } from '@vality/ng-core';
|
||||
import { of } from 'rxjs';
|
||||
import { startWith, take, switchMap } from 'rxjs/operators';
|
||||
|
||||
import { RoutingRulesService } from '../../services/routing-rules';
|
||||
|
||||
import { AddRoutingRuleDialogComponent } from './add-routing-rule-dialog.component';
|
||||
|
||||
export enum TerminalType {
|
||||
New = 'new',
|
||||
Existent = 'existent',
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class AddRoutingRuleDialogService {
|
||||
form = this.fb.group({
|
||||
description: '',
|
||||
weight: '',
|
||||
priority: 1000,
|
||||
terminalType: [null, Validators.required],
|
||||
existentTerminalID: [null, Validators.required],
|
||||
newTerminal: this.fb.group({
|
||||
name: ['', Validators.required],
|
||||
description: ['', Validators.required],
|
||||
riskCoverage: [null, Validators.required],
|
||||
options: this.fb.array([this.createOption()]),
|
||||
}),
|
||||
});
|
||||
|
||||
get newTerminalOptionsForm() {
|
||||
return this.form.get('newTerminal').get('options') as UntypedFormArray;
|
||||
}
|
||||
|
||||
constructor(
|
||||
private fb: UntypedFormBuilder,
|
||||
private dialogRef: MatDialogRef<AddRoutingRuleDialogComponent>,
|
||||
private routingRulesService: RoutingRulesService,
|
||||
) {
|
||||
this.form
|
||||
.get('terminalType')
|
||||
.valueChanges.pipe(startWith(this.form.value.terminalType))
|
||||
.subscribe((type) => {
|
||||
const { newTerminal, existentTerminalID } = this.form.controls;
|
||||
switch (type) {
|
||||
case TerminalType.New:
|
||||
newTerminal.enable();
|
||||
existentTerminalID.disable();
|
||||
return;
|
||||
case TerminalType.Existent:
|
||||
newTerminal.disable();
|
||||
existentTerminalID.enable();
|
||||
return;
|
||||
default:
|
||||
newTerminal.disable();
|
||||
existentTerminalID.disable();
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
add(predicate: Predicate, refID: number) {
|
||||
const { description, weight, priority, terminalType, existentTerminalID, newTerminal } =
|
||||
this.form.value;
|
||||
(terminalType === TerminalType.New
|
||||
? this.routingRulesService.createTerminal({
|
||||
name: newTerminal.name,
|
||||
description: newTerminal.description,
|
||||
risk_coverage: newTerminal.riskCoverage,
|
||||
options: newTerminal.options,
|
||||
})
|
||||
: of(existentTerminalID)
|
||||
)
|
||||
.pipe(
|
||||
take(1),
|
||||
switchMap((terminalID) =>
|
||||
this.routingRulesService.addShopRule({
|
||||
description,
|
||||
weight,
|
||||
priority,
|
||||
terminalID,
|
||||
refID,
|
||||
predicate,
|
||||
}),
|
||||
),
|
||||
)
|
||||
.subscribe(() => this.dialogRef.close({ status: DialogResponseStatus.Success }));
|
||||
}
|
||||
|
||||
addOption() {
|
||||
this.newTerminalOptionsForm.push(this.createOption());
|
||||
}
|
||||
|
||||
removeOption(idx: number) {
|
||||
this.newTerminalOptionsForm.removeAt(idx);
|
||||
}
|
||||
|
||||
private createOption() {
|
||||
return this.fb.group({ key: ['', Validators.required], value: ['', Validators.required] });
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
<div fxLayout="column" fxLayoutGap="24px">
|
||||
<div fxLayout fxLayoutAlign="space-between center">
|
||||
<div class="mat-h3">
|
||||
{{ title }}
|
||||
</div>
|
||||
<div fxLayout fxLayoutGap="16px">
|
||||
<mat-icon class="action" fxFlexAlign="end" (click)="remove.emit()">clear</mat-icon>
|
||||
<mat-icon class="action" fxFlexAlign="end" (click)="toggle()">{{
|
||||
expanded ? 'expand_less' : 'expand_more'
|
||||
}}</mat-icon>
|
||||
</div>
|
||||
</div>
|
||||
<ng-content *ngIf="expanded"></ng-content>
|
||||
</div>
|
@ -1,3 +0,0 @@
|
||||
.action {
|
||||
cursor: pointer;
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'cc-expander',
|
||||
templateUrl: 'expander.component.html',
|
||||
styleUrls: ['expander.component.scss'],
|
||||
})
|
||||
export class ExpanderComponent {
|
||||
@Input() title: string;
|
||||
@Output() remove = new EventEmitter<void>();
|
||||
|
||||
expanded = true;
|
||||
|
||||
toggle() {
|
||||
this.expanded = !this.expanded;
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
export * from './expander.component';
|
@ -1,2 +0,0 @@
|
||||
export * from './add-routing-rule-dialog.component';
|
||||
export * from './add-routing-rule-dialog.module';
|
@ -1 +0,0 @@
|
||||
export * from './predicate.component';
|
@ -1,7 +0,0 @@
|
||||
<cc-metadata-form
|
||||
[extensions]="extensions$ | async"
|
||||
[formControl]="control"
|
||||
[metadata]="metadata$ | async"
|
||||
namespace="domain"
|
||||
type="Predicate"
|
||||
></cc-metadata-form>
|
@ -1,23 +0,0 @@
|
||||
import { Component, OnChanges } from '@angular/core';
|
||||
import { Predicate } from '@vality/domain-proto/domain';
|
||||
import { from } from 'rxjs';
|
||||
|
||||
import { DomainMetadataFormExtensionsService } from '@cc/app/shared/services';
|
||||
import { createControlProviders, ValidatedFormControlSuperclass } from '@cc/utils';
|
||||
|
||||
@Component({
|
||||
selector: 'cc-predicate',
|
||||
templateUrl: 'predicate.component.html',
|
||||
providers: createControlProviders(() => PredicateComponent),
|
||||
})
|
||||
export class PredicateComponent
|
||||
extends ValidatedFormControlSuperclass<Predicate>
|
||||
implements OnChanges
|
||||
{
|
||||
metadata$ = from(import('@vality/domain-proto/metadata.json').then((m) => m.default));
|
||||
extensions$ = this.domainMetadataFormExtensionsService.extensions$;
|
||||
|
||||
constructor(private domainMetadataFormExtensionsService: DomainMetadataFormExtensionsService) {
|
||||
super();
|
||||
}
|
||||
}
|
@ -39,14 +39,6 @@
|
||||
<div class="mat-caption cc-routing-rules-caption">Description</div>
|
||||
<div>{{ c.candidate.description }}</div>
|
||||
</div>
|
||||
<div fxFlex fxLayout="column" fxLayoutGap="8px">
|
||||
<div class="mat-caption cc-routing-rules-caption">Weight</div>
|
||||
<div>{{ c.candidate.weight }}</div>
|
||||
</div>
|
||||
<div fxFlex fxLayout="column" fxLayoutGap="8px">
|
||||
<div class="mat-caption cc-routing-rules-caption">Priority</div>
|
||||
<div>{{ c.candidate.priority }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div fxLayout="column" fxLayoutGap="16px">
|
||||
<div class="mat-headline-4">Predicate</div>
|
||||
@ -64,7 +56,8 @@
|
||||
></cc-pretty-json>
|
||||
</div>
|
||||
</div>
|
||||
<mat-action-row fxLayoutAlign="start">
|
||||
<mat-action-row>
|
||||
<button mat-button (click)="editShopRule(c.idx)">Edit</button>
|
||||
<button color="warn" mat-button (click)="removeShopRule(c.idx)">Remove</button>
|
||||
</mat-action-row>
|
||||
</mat-expansion-panel>
|
||||
|
@ -2,17 +2,18 @@ import { Component } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
|
||||
import { Predicate, TerminalObject } from '@vality/domain-proto/domain';
|
||||
import { DialogResponseStatus, DialogService } from '@vality/ng-core';
|
||||
import { RoutingCandidate } from '@vality/domain-proto/internal/domain';
|
||||
import { DialogResponseStatus, DialogService, NotifyLogService } from '@vality/ng-core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { first, map, pluck, shareReplay, switchMap } from 'rxjs/operators';
|
||||
import { first, map, pluck, shareReplay, switchMap, withLatestFrom } from 'rxjs/operators';
|
||||
|
||||
import { DomainStoreService } from '@cc/app/api/deprecated-damsel';
|
||||
import { RoutingRulesType } from '@cc/app/sections/routing-rules/types/routing-rules-type';
|
||||
import { NotificationService } from '@cc/app/shared/services/notification';
|
||||
import { NotificationErrorService } from '@cc/app/shared/services/notification-error';
|
||||
import { objectToJSON } from '@cc/utils/thrift-instance';
|
||||
|
||||
import { AddRoutingRuleDialogComponent } from './add-routing-rule-dialog';
|
||||
import { DomainThriftFormDialogComponent } from '../../../shared/components/thrift-forms-dialogs';
|
||||
import { RoutingRulesService } from '../services/routing-rules';
|
||||
|
||||
import { RoutingRulesetService } from './routing-ruleset.service';
|
||||
|
||||
@UntilDestroy()
|
||||
@ -47,11 +48,11 @@ export class RoutingRulesetComponent {
|
||||
isLoading$ = this.domainStoreService.isLoading$;
|
||||
|
||||
constructor(
|
||||
private dialogService: DialogService,
|
||||
private dialog: DialogService,
|
||||
private routingRulesetService: RoutingRulesetService,
|
||||
private routingRulesService: RoutingRulesService,
|
||||
private domainStoreService: DomainStoreService,
|
||||
private notificationErrorService: NotificationErrorService,
|
||||
private notificationService: NotificationService,
|
||||
private log: NotifyLogService,
|
||||
private route: ActivatedRoute,
|
||||
) {}
|
||||
|
||||
@ -59,8 +60,14 @@ export class RoutingRulesetComponent {
|
||||
this.routingRulesetService.refID$
|
||||
.pipe(
|
||||
first(),
|
||||
switchMap((refID) =>
|
||||
this.dialogService.open(AddRoutingRuleDialogComponent, { refID }).afterClosed(),
|
||||
switchMap((refId) =>
|
||||
this.dialog
|
||||
.open(DomainThriftFormDialogComponent<RoutingCandidate>, {
|
||||
type: 'RoutingCandidate',
|
||||
title: 'Add shop routing candidate',
|
||||
action: (params) => this.routingRulesService.addShopRule(refId, params),
|
||||
})
|
||||
.afterClosed(),
|
||||
),
|
||||
)
|
||||
.pipe(untilDestroyed(this))
|
||||
@ -68,12 +75,43 @@ export class RoutingRulesetComponent {
|
||||
next: (res) => {
|
||||
if (res.status === DialogResponseStatus.Success) {
|
||||
this.domainStoreService.forceReload();
|
||||
this.notificationService.success('Routing rule successfully added');
|
||||
this.log.successOperation('update', 'Routing rule');
|
||||
}
|
||||
},
|
||||
error: (err) => {
|
||||
this.notificationErrorService.error(err);
|
||||
this.notificationService.success('Error while adding routing rule');
|
||||
this.log.error(err, 'Error while adding routing rule');
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
editShopRule(idx: number) {
|
||||
this.routingRulesetService.refID$
|
||||
.pipe(
|
||||
first(),
|
||||
switchMap((refId) => this.routingRulesService.getShopCandidate(refId, idx)),
|
||||
withLatestFrom(this.routingRulesetService.refID$),
|
||||
switchMap(([shopCandidate, refId]) =>
|
||||
this.dialog
|
||||
.open(DomainThriftFormDialogComponent<RoutingCandidate>, {
|
||||
type: 'RoutingCandidate',
|
||||
title: `Edit shop routing candidate #${idx + 1}`,
|
||||
object: shopCandidate,
|
||||
action: (params) =>
|
||||
this.routingRulesService.updateShopRule(refId, idx, params),
|
||||
})
|
||||
.afterClosed(),
|
||||
),
|
||||
)
|
||||
.pipe(untilDestroyed(this))
|
||||
.subscribe({
|
||||
next: (res) => {
|
||||
if (res.status === DialogResponseStatus.Success) {
|
||||
this.domainStoreService.forceReload();
|
||||
this.log.successOperation('update', 'Routing rule');
|
||||
}
|
||||
},
|
||||
error: (err) => {
|
||||
this.log.error(err);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -23,7 +23,6 @@ import { PrettyJsonModule } from '@cc/components/pretty-json';
|
||||
|
||||
import { RoutingRulesetHeaderModule } from '../routing-ruleset-header';
|
||||
|
||||
import { AddRoutingRuleDialogModule } from './add-routing-rule-dialog';
|
||||
import { RoutingRulesetRoutingModule } from './routing-ruleset-routing.module';
|
||||
import { RoutingRulesetComponent } from './routing-ruleset.component';
|
||||
|
||||
@ -49,7 +48,6 @@ import { RoutingRulesetComponent } from './routing-ruleset.component';
|
||||
MatExpansionModule,
|
||||
RoutingRulesetHeaderModule,
|
||||
MatAutocompleteModule,
|
||||
AddRoutingRuleDialogModule,
|
||||
PrettyJsonModule,
|
||||
MatProgressBarModule,
|
||||
],
|
||||
|
@ -1,24 +1,33 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { combineLatest, Observable } from 'rxjs';
|
||||
import { map, pluck, shareReplay, switchMap, take } from 'rxjs/operators';
|
||||
import { untilDestroyed, UntilDestroy } from '@ngneat/until-destroy';
|
||||
import {
|
||||
DialogService,
|
||||
ConfirmDialogComponent,
|
||||
DialogResponseStatus,
|
||||
NotifyLogService,
|
||||
} from '@vality/ng-core';
|
||||
import { combineLatest, Observable, filter } from 'rxjs';
|
||||
import { map, shareReplay, switchMap, take, withLatestFrom } from 'rxjs/operators';
|
||||
|
||||
import { PartyManagementService } from '@cc/app/api/payment-processing';
|
||||
import { NotificationErrorService } from '@cc/app/shared/services/notification-error';
|
||||
|
||||
import { handleError } from '../../../../utils/operators/handle-error';
|
||||
import { RoutingRulesService as RoutingRulesDamselService } from '../services/routing-rules';
|
||||
|
||||
@UntilDestroy()
|
||||
@Injectable()
|
||||
export class RoutingRulesetService {
|
||||
partyID$: Observable<string> = this.route.params.pipe(pluck('partyID'), shareReplay(1));
|
||||
partyID$: Observable<string> = this.route.params.pipe(
|
||||
map((r) => r.partyID),
|
||||
shareReplay(1),
|
||||
);
|
||||
partyRulesetRefID$: Observable<number> = this.route.params.pipe(
|
||||
pluck('partyRefID'),
|
||||
map((r) => r.partyRefID),
|
||||
map((p) => +p),
|
||||
shareReplay(1),
|
||||
);
|
||||
refID$: Observable<number> = this.route.params.pipe(
|
||||
pluck('refID'),
|
||||
map((r) => r.refID),
|
||||
map((p) => +p),
|
||||
shareReplay(1),
|
||||
);
|
||||
@ -46,21 +55,33 @@ export class RoutingRulesetService {
|
||||
private routingRulesService: RoutingRulesDamselService,
|
||||
private route: ActivatedRoute,
|
||||
private partyManagementService: PartyManagementService,
|
||||
private notificationErrorService: NotificationErrorService,
|
||||
private log: NotifyLogService,
|
||||
private dialog: DialogService,
|
||||
) {}
|
||||
|
||||
removeShopRule(candidateIdx: number) {
|
||||
this.refID$
|
||||
this.dialog
|
||||
.open(ConfirmDialogComponent)
|
||||
.afterClosed()
|
||||
.pipe(
|
||||
filter((r) => r.status === DialogResponseStatus.Success),
|
||||
withLatestFrom(this.refID$),
|
||||
take(1),
|
||||
switchMap((refID) =>
|
||||
switchMap(([, refID]) =>
|
||||
this.routingRulesService.removeShopRule({
|
||||
refID,
|
||||
candidateIdx,
|
||||
}),
|
||||
),
|
||||
handleError(this.notificationErrorService.error),
|
||||
untilDestroyed(this),
|
||||
)
|
||||
.subscribe();
|
||||
.subscribe({
|
||||
next: () => {
|
||||
this.log.successOperation('delete', 'Shop routing candidate');
|
||||
},
|
||||
error: (err) => {
|
||||
this.log.error(err);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,9 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import {
|
||||
Terminal,
|
||||
Predicate,
|
||||
RoutingCandidate,
|
||||
RoutingDelegate,
|
||||
RoutingRulesObject,
|
||||
} from '@vality/domain-proto/domain';
|
||||
import { RoutingCandidate, RoutingDelegate, RoutingRulesObject } from '@vality/domain-proto/domain';
|
||||
import { Version } from '@vality/domain-proto/domain_config';
|
||||
import cloneDeep from 'lodash-es/cloneDeep';
|
||||
import { combineLatest, concat, Observable } from 'rxjs';
|
||||
import { first, map, pluck, shareReplay, switchMap, take } from 'rxjs/operators';
|
||||
import { map, pluck, shareReplay, switchMap, take } from 'rxjs/operators';
|
||||
|
||||
import { DomainStoreService } from '@cc/app/api/deprecated-damsel';
|
||||
import { createNextId } from '@cc/utils/create-next-id';
|
||||
@ -210,33 +204,35 @@ export class RoutingRulesService {
|
||||
);
|
||||
}
|
||||
|
||||
addShopRule({
|
||||
refID,
|
||||
terminalID,
|
||||
description,
|
||||
weight,
|
||||
priority,
|
||||
predicate,
|
||||
}: {
|
||||
refID: number;
|
||||
terminalID: number;
|
||||
description: string;
|
||||
weight: number;
|
||||
priority: number;
|
||||
predicate: Predicate;
|
||||
}): Observable<Version> {
|
||||
addShopRule(refID: number, params: RoutingCandidate): Observable<Version> {
|
||||
return this.getRuleset(refID).pipe(
|
||||
take(1),
|
||||
switchMap((ruleset) => {
|
||||
const newShopRuleset = this.cloneRulesetAndPushCandidate(ruleset, {
|
||||
description,
|
||||
allowed: predicate,
|
||||
terminal: {
|
||||
id: terminalID,
|
||||
},
|
||||
weight,
|
||||
priority,
|
||||
const newShopRuleset = this.cloneRulesetAndPushCandidate(ruleset, params);
|
||||
return this.domainStoreService.commit({
|
||||
ops: [
|
||||
{
|
||||
update: {
|
||||
old_object: { routing_rules: ruleset },
|
||||
new_object: { routing_rules: newShopRuleset },
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
updateShopRule(
|
||||
refID: number,
|
||||
candidateIdx: number,
|
||||
shopCandidate: RoutingCandidate,
|
||||
): Observable<Version> {
|
||||
return this.getRuleset(refID).pipe(
|
||||
take(1),
|
||||
switchMap((ruleset) => {
|
||||
const newShopRuleset = cloneDeep(ruleset);
|
||||
newShopRuleset.data.decisions.candidates.splice(candidateIdx, 1, shopCandidate);
|
||||
return this.domainStoreService.commit({
|
||||
ops: [
|
||||
{
|
||||
@ -299,6 +295,13 @@ export class RoutingRulesService {
|
||||
);
|
||||
}
|
||||
|
||||
getShopCandidate(refID: number, candidateIdx: number) {
|
||||
return this.getRuleset(refID).pipe(
|
||||
take(1),
|
||||
map((shopRuleset) => cloneDeep(shopRuleset.data.decisions.candidates.at(candidateIdx))),
|
||||
);
|
||||
}
|
||||
|
||||
removeShopRule({
|
||||
refID,
|
||||
candidateIdx,
|
||||
@ -435,27 +438,6 @@ export class RoutingRulesService {
|
||||
);
|
||||
}
|
||||
|
||||
createTerminal(terminal: Terminal): Observable<Version> {
|
||||
return this.domainStoreService.getObjects('terminal').pipe(
|
||||
first(),
|
||||
map((objs) => objs.map(({ ref }) => ref.id)),
|
||||
map(createNextId),
|
||||
switchMap((id) => {
|
||||
return this.domainStoreService.commit({
|
||||
ops: [
|
||||
{
|
||||
insert: {
|
||||
object: {
|
||||
terminal: { ref: { id }, data: terminal },
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
cloneDelegateRuleset({
|
||||
mainRulesetRefID,
|
||||
delegateIdx,
|
||||
|
@ -0,0 +1,13 @@
|
||||
<v-dialog [title]="dialogData.title">
|
||||
<cc-domain-thrift-form
|
||||
[formControl]="control"
|
||||
[namespace]="dialogData.namespace"
|
||||
[type]="dialogData.type"
|
||||
></cc-domain-thrift-form>
|
||||
|
||||
<v-dialog-actions>
|
||||
<button [disabled]="control.invalid" color="primary" mat-button (click)="upsert()">
|
||||
{{ isUpdate ? 'Update' : 'Add' }}
|
||||
</button>
|
||||
</v-dialog-actions>
|
||||
</v-dialog>
|
@ -0,0 +1,54 @@
|
||||
import { Component, Injector } from '@angular/core';
|
||||
import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
|
||||
import { DialogSuperclass, DialogModule } from '@vality/ng-core';
|
||||
import { ValueType } from '@vality/thrift-ts';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { DomainThriftFormComponent } from '../../thrift-forms/domain-thrift-form';
|
||||
|
||||
@UntilDestroy()
|
||||
@Component({
|
||||
standalone: true,
|
||||
templateUrl: 'domain-thrift-form-dialog.component.html',
|
||||
imports: [DialogModule, DomainThriftFormComponent, MatButtonModule, ReactiveFormsModule],
|
||||
})
|
||||
export class DomainThriftFormDialogComponent<T = unknown, R = unknown> extends DialogSuperclass<
|
||||
DomainThriftFormDialogComponent<T, R>,
|
||||
{
|
||||
type: ValueType;
|
||||
title: string;
|
||||
action: (object: T) => Observable<R>;
|
||||
namespace?: string;
|
||||
object?: T;
|
||||
},
|
||||
{ object?: T; result?: R; error?: unknown }
|
||||
> {
|
||||
control = this.fb.control(this.dialogData.object ?? null);
|
||||
|
||||
get isUpdate() {
|
||||
return this.dialogData.object !== undefined;
|
||||
}
|
||||
|
||||
constructor(
|
||||
injector: Injector,
|
||||
private fb: FormBuilder,
|
||||
) {
|
||||
super(injector);
|
||||
}
|
||||
|
||||
upsert() {
|
||||
this.dialogData
|
||||
.action(this.control.value)
|
||||
.pipe(untilDestroyed(this))
|
||||
.subscribe({
|
||||
next: (result) => {
|
||||
this.closeWithSuccess({ object: this.control.value, result });
|
||||
},
|
||||
error: (error) => {
|
||||
this.closeWithError({ error });
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
export * from './domain-thrift-form-dialog.component';
|
1
src/app/shared/components/thrift-forms-dialogs/index.ts
Normal file
1
src/app/shared/components/thrift-forms-dialogs/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './domain-thrift-form-dialog';
|
@ -1,5 +1,5 @@
|
||||
<cc-metadata-form
|
||||
[extensions]="extensions"
|
||||
[extensions]="extensions$ | async"
|
||||
[formControl]="control"
|
||||
[metadata]="metadata$ | async"
|
||||
[namespace]="namespace ?? defaultNamespace"
|
||||
|
@ -5,6 +5,9 @@ import { ErrorService } from './types/error-service';
|
||||
|
||||
const DEFAULT_DURATION_MS = 6000;
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
*/
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class NotificationErrorService implements ErrorService {
|
||||
constructor(private snackBar: MatSnackBar) {}
|
||||
|
Loading…
Reference in New Issue
Block a user