IMP-80: Update shop routing rules (#261)

This commit is contained in:
Rinat Arsaev 2023-09-28 16:29:37 +05:30 committed by GitHub
parent 6747d10e4d
commit 8c3f642bee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 193 additions and 476 deletions

View File

@ -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>

View File

@ -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);
}
}

View File

@ -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 {}

View File

@ -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] });
}
}

View File

@ -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>

View File

@ -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;
}
}

View File

@ -1 +0,0 @@
export * from './expander.component';

View File

@ -1,2 +0,0 @@
export * from './add-routing-rule-dialog.component';
export * from './add-routing-rule-dialog.module';

View File

@ -1 +0,0 @@
export * from './predicate.component';

View File

@ -1,7 +0,0 @@
<cc-metadata-form
[extensions]="extensions$ | async"
[formControl]="control"
[metadata]="metadata$ | async"
namespace="domain"
type="Predicate"
></cc-metadata-form>

View File

@ -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();
}
}

View File

@ -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>

View File

@ -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);
},
});
}

View File

@ -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,
],

View File

@ -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);
},
});
}
}

View File

@ -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,
const newShopRuleset = this.cloneRulesetAndPushCandidate(ruleset, params);
return this.domainStoreService.commit({
ops: [
{
update: {
old_object: { routing_rules: ruleset },
new_object: { routing_rules: newShopRuleset },
},
weight,
priority,
},
],
});
}),
);
}
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,

View File

@ -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>

View File

@ -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 });
},
});
}
}

View File

@ -0,0 +1 @@
export * from './domain-thrift-form-dialog.component';

View File

@ -0,0 +1 @@
export * from './domain-thrift-form-dialog';

View File

@ -1,5 +1,5 @@
<cc-metadata-form
[extensions]="extensions"
[extensions]="extensions$ | async"
[formControl]="control"
[metadata]="metadata$ | async"
[namespace]="namespace ?? defaultNamespace"

View File

@ -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) {}