Review comments resolving and refactoring

This commit is contained in:
mpetrov 2025-02-11 15:43:13 +02:00
parent 84b9bde577
commit 9e19fab11d
15 changed files with 109 additions and 73 deletions

View File

@ -22,7 +22,7 @@ import { PageData } from '@shared/models/page/page-data';
import { CalculatedField, CalculatedFieldTestScriptInputParams } from '@shared/models/calculated-field.models'; import { CalculatedField, CalculatedFieldTestScriptInputParams } from '@shared/models/calculated-field.models';
import { PageLink } from '@shared/models/page/page-link'; import { PageLink } from '@shared/models/page/page-link';
import { EntityId } from '@shared/models/id/entity-id'; import { EntityId } from '@shared/models/id/entity-id';
import { TestScriptResult } from '@shared/models/entity.models'; import { EntityTestScriptResult } from '@shared/models/entity.models';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@ -50,7 +50,7 @@ export class CalculatedFieldsService {
defaultHttpOptionsFromConfig(config)); defaultHttpOptionsFromConfig(config));
} }
public testScript(inputParams: CalculatedFieldTestScriptInputParams, config?: RequestConfig): Observable<TestScriptResult> { public testScript(inputParams: CalculatedFieldTestScriptInputParams, config?: RequestConfig): Observable<EntityTestScriptResult> {
return this.http.post<TestScriptResult>('/api/calculatedField/testScript', inputParams, defaultHttpOptionsFromConfig(config)); return this.http.post<EntityTestScriptResult>('/api/calculatedField/testScript', inputParams, defaultHttpOptionsFromConfig(config));
} }
} }

View File

@ -35,6 +35,7 @@ import {
RuleNodeConfiguration, RuleNodeConfiguration,
ScriptLanguage, ScriptLanguage,
TestScriptInputParams, TestScriptInputParams,
TestScriptResult
} from '@app/shared/models/rule-node.models'; } from '@app/shared/models/rule-node.models';
import { componentTypeBySelector, ResourcesService } from '../services/resources.service'; import { componentTypeBySelector, ResourcesService } from '../services/resources.service';
import { catchError, map, mergeMap } from 'rxjs/operators'; import { catchError, map, mergeMap } from 'rxjs/operators';
@ -43,7 +44,6 @@ import { deepClone, snakeCase } from '@core/utils';
import { DebugRuleNodeEventBody } from '@app/shared/models/event.models'; import { DebugRuleNodeEventBody } from '@app/shared/models/event.models';
import { Edge } from '@shared/models/edge.models'; import { Edge } from '@shared/models/edge.models';
import { IModulesMap } from '@modules/common/modules-map.models'; import { IModulesMap } from '@modules/common/modules-map.models';
import { TestScriptResult } from '@shared/models/entity.models';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'

View File

@ -34,12 +34,12 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { TbPopoverService } from '@shared/components/popover.service'; import { TbPopoverService } from '@shared/components/popover.service';
import { EntityDebugSettingsPanelComponent } from '@home/components/entity/debug/entity-debug-settings-panel.component'; import { EntityDebugSettingsPanelComponent } from '@home/components/entity/debug/entity-debug-settings-panel.component';
import { CalculatedFieldsService } from '@core/http/calculated-fields.service'; import { CalculatedFieldsService } from '@core/http/calculated-fields.service';
import { catchError, filter, switchMap } from 'rxjs/operators'; import { catchError, filter, switchMap, tap } from 'rxjs/operators';
import { import {
CalculatedField, CalculatedField,
CalculatedFieldDebugDialogData, CalculatedFieldDebugDialogData,
CalculatedFieldDialogData, CalculatedFieldDialogData,
CalculatedFieldScriptTestDialogData CalculatedFieldTestScriptInputParams,
} from '@shared/models/calculated-field.models'; } from '@shared/models/calculated-field.models';
import { import {
CalculatedFieldDebugDialogComponent, CalculatedFieldDebugDialogComponent,
@ -47,7 +47,6 @@ import {
CalculatedFieldScriptTestDialogComponent CalculatedFieldScriptTestDialogComponent
} from './components/public-api'; } from './components/public-api';
import { ImportExportService } from '@shared/import-export/import-export.service'; import { ImportExportService } from '@shared/import-export/import-export.service';
import { CalculatedFieldId } from '@shared/models/id/calculated-field-id';
export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedField, PageLink> { export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedField, PageLink> {
@ -58,7 +57,7 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
readonly tenantId = getCurrentAuthUser(this.store).tenantId; readonly tenantId = getCurrentAuthUser(this.store).tenantId;
additionalDebugActionConfig = { additionalDebugActionConfig = {
title: this.translate.instant('calculated-fields.see-debug-events'), title: this.translate.instant('calculated-fields.see-debug-events'),
action: (id?: CalculatedFieldId, expression?: string) => this.openDebugDialog.call(this, id, expression), action: (calculatedField: CalculatedField) => this.openDebugDialog.call(this, calculatedField),
}; };
constructor(private calculatedFieldsService: CalculatedFieldsService, constructor(private calculatedFieldsService: CalculatedFieldsService,
@ -139,10 +138,11 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
return this.calculatedFieldsService.getCalculatedFields(this.entityId, pageLink); return this.calculatedFieldsService.getCalculatedFields(this.entityId, pageLink);
} }
onOpenDebugConfig($event: Event, { debugSettings = {}, configuration, id }: CalculatedField): void { onOpenDebugConfig($event: Event, calculatedField: CalculatedField): void {
const { debugSettings = {}, id } = calculatedField;
const additionalActionConfig = { const additionalActionConfig = {
...this.additionalDebugActionConfig, ...this.additionalDebugActionConfig,
action: () => this.openDebugDialog(id, configuration?.expression) action: () => this.openDebugDialog(calculatedField)
}; };
const { viewContainerRef } = this.getTable(); const { viewContainerRef } = this.getTable();
if ($event) { if ($event) {
@ -178,8 +178,8 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
) )
} }
private editCalculatedField(calculatedField: CalculatedField): void { private editCalculatedField(calculatedField: CalculatedField, isDirty = false): void {
this.getCalculatedFieldDialog(calculatedField, 'action.apply') this.getCalculatedFieldDialog(calculatedField, 'action.apply', isDirty)
.pipe( .pipe(
filter(Boolean), filter(Boolean),
switchMap((updatedCalculatedField) => this.calculatedFieldsService.saveCalculatedField({ ...calculatedField, ...updatedCalculatedField })), switchMap((updatedCalculatedField) => this.calculatedFieldsService.saveCalculatedField({ ...calculatedField, ...updatedCalculatedField })),
@ -191,7 +191,7 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
}); });
} }
private getCalculatedFieldDialog(value?: CalculatedField, buttonTitle = 'action.add'): Observable<CalculatedField> { private getCalculatedFieldDialog(value?: CalculatedField, buttonTitle = 'action.add', isDirty = false): Observable<CalculatedField> {
return this.dialog.open<CalculatedFieldDialogComponent, CalculatedFieldDialogData, CalculatedField>(CalculatedFieldDialogComponent, { return this.dialog.open<CalculatedFieldDialogComponent, CalculatedFieldDialogData, CalculatedField>(CalculatedFieldDialogComponent, {
disableClose: true, disableClose: true,
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
@ -204,21 +204,20 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
entityName: this.entityName, entityName: this.entityName,
additionalDebugActionConfig: this.additionalDebugActionConfig, additionalDebugActionConfig: this.additionalDebugActionConfig,
testScriptFn: this.getTestScriptDialog.bind(this), testScriptFn: this.getTestScriptDialog.bind(this),
isDirty
} }
}) })
.afterClosed(); .afterClosed();
} }
private openDebugDialog(id: CalculatedFieldId, expression: string): void { private openDebugDialog(calculatedField: CalculatedField): void {
this.dialog.open<CalculatedFieldDebugDialogComponent, CalculatedFieldDebugDialogData, null>(CalculatedFieldDebugDialogComponent, { this.dialog.open<CalculatedFieldDebugDialogComponent, CalculatedFieldDebugDialogData, null>(CalculatedFieldDebugDialogComponent, {
disableClose: true, disableClose: true,
panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], panelClass: ['tb-dialog', 'tb-fullscreen-dialog'],
data: { data: {
tenantId: this.tenantId, tenantId: this.tenantId,
entityId: this.entityId, value: calculatedField,
id, getTestScriptDialogFn: this.getTestScriptDialog.bind(this),
expression,
testScriptFn: this.getTestScriptDialog.bind(this),
} }
}) })
.afterClosed() .afterClosed()
@ -260,16 +259,21 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig<CalculatedFie
).subscribe(() => this.updateData()); ).subscribe(() => this.updateData());
} }
private getTestScriptDialog(argumentsObj: Record<string, unknown>, expression: string, withApply = false): Observable<string> { private getTestScriptDialog(calculatedField: CalculatedField, argumentsObj?: Record<string, unknown>): Observable<string> {
return this.dialog.open<CalculatedFieldScriptTestDialogComponent, CalculatedFieldScriptTestDialogData, string>(CalculatedFieldScriptTestDialogComponent, return this.dialog.open<CalculatedFieldScriptTestDialogComponent, CalculatedFieldTestScriptInputParams, string>(CalculatedFieldScriptTestDialogComponent,
{ {
disableClose: true, disableClose: true,
panelClass: ['tb-dialog', 'tb-fullscreen-dialog', 'tb-fullscreen-dialog-gt-xs'], panelClass: ['tb-dialog', 'tb-fullscreen-dialog', 'tb-fullscreen-dialog-gt-xs'],
data: { data: {
arguments: argumentsObj, arguments: argumentsObj ?? Object.keys(calculatedField.configuration.arguments).reduce((acc, key) => ({...acc, [key]: '' }), {}),
expression, expression: calculatedField.configuration.expression,
withApply,
} }
}).afterClosed(); }).afterClosed()
.pipe(
filter(Boolean),
tap(expression =>
this.editCalculatedField({...calculatedField, configuration: {...calculatedField.configuration, expression } }, true)
),
);
} }
} }

View File

@ -32,7 +32,7 @@
[disabledEventTypes]="[EventType.LC_EVENT, EventType.ERROR, EventType.STATS]" [disabledEventTypes]="[EventType.LC_EVENT, EventType.ERROR, EventType.STATS]"
[defaultEventType]="DebugEventType.DEBUG_CALCULATED_FIELD" [defaultEventType]="DebugEventType.DEBUG_CALCULATED_FIELD"
[active]="true" [active]="true"
[entityId]="data.id" [entityId]="data.value.id"
[functionTestButtonLabel]="'common.test-function' | translate" [functionTestButtonLabel]="'common.test-function' | translate"
(debugEventSelected)="onDebugEventSelected($event)" (debugEventSelected)="onDebugEventSelected($event)"
/> />

View File

@ -22,14 +22,14 @@ import { Router } from '@angular/router';
import { DialogComponent } from '@shared/components/dialog.component'; import { DialogComponent } from '@shared/components/dialog.component';
import { CalculatedFieldEventBody, DebugEventType, EventType } from '@shared/models/event.models'; import { CalculatedFieldEventBody, DebugEventType, EventType } from '@shared/models/event.models';
import { EventTableComponent } from '@home/components/event/event-table.component'; import { EventTableComponent } from '@home/components/event/event-table.component';
import { CalculatedFieldDebugDialogData } from '@shared/models/calculated-field.models'; import { CalculatedFieldDebugDialogData, CalculatedFieldType } from '@shared/models/calculated-field.models';
@Component({ @Component({
selector: 'tb-calculated-field-debug-dialog', selector: 'tb-calculated-field-debug-dialog',
styleUrls: ['calculated-field-debug-dialog.component.scss'], styleUrls: ['calculated-field-debug-dialog.component.scss'],
templateUrl: './calculated-field-debug-dialog.component.html', templateUrl: './calculated-field-debug-dialog.component.html',
}) })
export class CalculatedFieldDebugDialogComponent extends DialogComponent<CalculatedFieldDebugDialogComponent, null> implements AfterViewInit { export class CalculatedFieldDebugDialogComponent extends DialogComponent<CalculatedFieldDebugDialogComponent, string> implements AfterViewInit {
@ViewChild(EventTableComponent, {static: true}) eventsTable: EventTableComponent; @ViewChild(EventTableComponent, {static: true}) eventsTable: EventTableComponent;
@ -40,12 +40,13 @@ export class CalculatedFieldDebugDialogComponent extends DialogComponent<Calcula
constructor(protected store: Store<AppState>, constructor(protected store: Store<AppState>,
protected router: Router, protected router: Router,
@Inject(MAT_DIALOG_DATA) public data: CalculatedFieldDebugDialogData, @Inject(MAT_DIALOG_DATA) public data: CalculatedFieldDebugDialogData,
protected dialogRef: MatDialogRef<CalculatedFieldDebugDialogComponent, null>) { protected dialogRef: MatDialogRef<CalculatedFieldDebugDialogComponent, string>) {
super(store, router, dialogRef); super(store, router, dialogRef);
} }
ngAfterViewInit(): void { ngAfterViewInit(): void {
this.eventsTable.entitiesTable.updateData(); this.eventsTable.entitiesTable.updateData();
this.eventsTable.entitiesTable.cellActionDescriptors[0].isEnabled = () => this.data.value.type === CalculatedFieldType.SCRIPT;
} }
cancel(): void { cancel(): void {
@ -53,6 +54,7 @@ export class CalculatedFieldDebugDialogComponent extends DialogComponent<Calcula
} }
onDebugEventSelected(event: CalculatedFieldEventBody): void { onDebugEventSelected(event: CalculatedFieldEventBody): void {
this.data.testScriptFn(JSON.parse(event.arguments), this.data.expression); this.data.getTestScriptDialogFn(this.data.value, JSON.parse(event.arguments))
.subscribe(expression => this.dialogRef.close(expression));
} }
} }

View File

@ -99,7 +99,7 @@
[functionArgs]="functionArgs$ | async" [functionArgs]="functionArgs$ | async"
[disableUndefinedCheck]="true" [disableUndefinedCheck]="true"
[scriptLanguage]="ScriptLanguage.TBEL" [scriptLanguage]="ScriptLanguage.TBEL"
helpId="[TODO]: [Calculated Fields] add valid link" helpId="calculated-field/expression_fn"
/> />
<div> <div>
<button mat-button mat-raised-button color="primary" <button mat-button mat-raised-button color="primary"

View File

@ -14,7 +14,7 @@
/// limitations under the License. /// limitations under the License.
/// ///
import { Component, Inject } from '@angular/core'; import { AfterViewInit, Component, Inject } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
@ -41,7 +41,7 @@ import { ScriptLanguage } from '@shared/models/rule-node.models';
selector: 'tb-calculated-field-dialog', selector: 'tb-calculated-field-dialog',
templateUrl: './calculated-field-dialog.component.html', templateUrl: './calculated-field-dialog.component.html',
}) })
export class CalculatedFieldDialogComponent extends DialogComponent<CalculatedFieldDialogComponent, CalculatedField> { export class CalculatedFieldDialogComponent extends DialogComponent<CalculatedFieldDialogComponent, CalculatedField> implements AfterViewInit {
fieldFormGroup = this.fb.group({ fieldFormGroup = this.fb.group({
name: ['', [Validators.required, Validators.pattern(noLeadTrailSpacesRegex), Validators.maxLength(255)]], name: ['', [Validators.required, Validators.pattern(noLeadTrailSpacesRegex), Validators.maxLength(255)]],
@ -67,7 +67,7 @@ export class CalculatedFieldDialogComponent extends DialogComponent<CalculatedFi
additionalDebugActionConfig = this.data.value?.id ? { additionalDebugActionConfig = this.data.value?.id ? {
...this.data.additionalDebugActionConfig, ...this.data.additionalDebugActionConfig,
action: () => this.data.additionalDebugActionConfig.action(this.data.value.id, this.data.value.configuration.expression) action: () => this.data.additionalDebugActionConfig.action({ id: this.data.value.id, ...this.fromGroupValue }),
} : null; } : null;
readonly OutputTypeTranslations = OutputTypeTranslations; readonly OutputTypeTranslations = OutputTypeTranslations;
@ -98,24 +98,31 @@ export class CalculatedFieldDialogComponent extends DialogComponent<CalculatedFi
return this.fieldFormGroup.get('configuration').get('output') as FormGroup; return this.fieldFormGroup.get('configuration').get('output') as FormGroup;
} }
get fromGroupValue(): CalculatedField {
const { configuration, type, ...rest } = this.fieldFormGroup.value;
const { expressionSIMPLE, expressionSCRIPT, ...restConfig } = configuration;
return { configuration: { ...restConfig, type, expression: configuration['expression'+type] }, ...rest, type } as CalculatedField;
}
ngAfterViewInit(): void {
if (this.data.isDirty) {
this.fieldFormGroup.markAsDirty();
}
}
cancel(): void { cancel(): void {
this.dialogRef.close(null); this.dialogRef.close(null);
} }
add(): void { add(): void {
if (this.fieldFormGroup.valid) { if (this.fieldFormGroup.valid) {
const { configuration, type, ...rest } = this.fieldFormGroup.value; this.dialogRef.close(this.fromGroupValue);
const { expressionSIMPLE, expressionSCRIPT, ...restConfig } = configuration;
this.dialogRef.close({ configuration: { ...restConfig, type, expression: configuration['expression'+type] }, ...rest, type } as CalculatedField);
} }
} }
onTestScript(): void { onTestScript(): void {
this.data.testScriptFn( this.data.testScriptFn(this.fromGroupValue)
Object.fromEntries(Object.keys(this.configFormGroup.get('arguments').value).map(k => [k, ''])), .pipe(filter(Boolean)).subscribe((expression: string) => {
this.configFormGroup.get('expressionSCRIPT').value,
true
).pipe(filter(Boolean)).subscribe((expression: string) => {
this.configFormGroup.get('expressionSCRIPT').setValue(expression); this.configFormGroup.get('expressionSCRIPT').setValue(expression);
this.configFormGroup.get('expressionSCRIPT').markAsDirty(); this.configFormGroup.get('expressionSCRIPT').markAsDirty();
}); });

View File

@ -17,7 +17,7 @@
--> -->
<form class="test-dialog-container size-full" [formGroup]="calculatedFieldScriptTestFormGroup"> <form class="test-dialog-container size-full" [formGroup]="calculatedFieldScriptTestFormGroup">
<mat-toolbar class="flex justify-between" color="primary"> <mat-toolbar class="flex justify-between" color="primary">
<h2>{{ 'calculated-fields.test-script-function' | translate }} ({{ 'TBEL' }})</h2> <h2>{{ 'calculated-fields.test-script-function' | translate }} ({{ 'api-usage.tbel' | translate }})</h2>
<button mat-icon-button <button mat-icon-button
(click)="cancel()" (click)="cancel()"
type="button"> type="button">
@ -29,7 +29,7 @@
<div class="tb-fullscreen-panel flex size-full flex-row"> <div class="tb-fullscreen-panel flex size-full flex-row">
<div #leftPanel class="test-block-content overflow-hidden"> <div #leftPanel class="test-block-content overflow-hidden">
<div class="relative size-full min-w-64"> <div class="relative size-full min-w-64">
<div class="absolute right-28 top-[9px] z-10 text-[12px] font-bold"> <div class="block-label-container left">
<span class="block-label">{{ 'calculated-fields.expression' | translate }}</span> <span class="block-label">{{ 'calculated-fields.expression' | translate }}</span>
</div> </div>
<tb-js-func <tb-js-func
@ -41,14 +41,14 @@
[fillHeight]="true" [fillHeight]="true"
[scriptLanguage]="ScriptLanguage.TBEL" [scriptLanguage]="ScriptLanguage.TBEL"
resultType="object" resultType="object"
helpId="[TODO]: [Calculated Fields] add valid link" helpId="calculated-field/test-expression_fn"
/> />
</div> </div>
</div> </div>
<div #rightPanel> <div #rightPanel>
<div #topRightPanel class="test-block-content"> <div #topRightPanel class="test-block-content">
<div class="relative flex size-full min-w-96 gap-2"> <div class="relative flex size-full min-w-96 gap-2">
<div class="absolute right-2 top-[6px] z-10 text-[12px] font-bold"> <div class="block-label-container right-top">
<span class="block-label">{{ 'calculated-fields.arguments' | translate }}</span> <span class="block-label">{{ 'calculated-fields.arguments' | translate }}</span>
</div> </div>
<tb-calculated-field-test-arguments class="size-full" formControlName="arguments"/> <tb-calculated-field-test-arguments class="size-full" formControlName="arguments"/>
@ -56,7 +56,7 @@
</div> </div>
<div #bottomRightPanel class="test-block-content"> <div #bottomRightPanel class="test-block-content">
<div class="relative size-full"> <div class="relative size-full">
<div class="absolute right-10 top-[6px] z-10 text-[12px] font-bold"> <div class="block-label-container right-bottom">
<span class="block-label" translate>common.output</span> <span class="block-label" translate>common.output</span>
</div> </div>
<tb-json-content <tb-json-content
@ -89,13 +89,11 @@
(click)="cancel()"> (click)="cancel()">
{{ 'action.cancel' | translate }} {{ 'action.cancel' | translate }}
</button> </button>
@if (data.withApply) { <button mat-button mat-raised-button color="primary"
<button mat-button mat-raised-button color="primary" type="submit"
type="submit" (click)="save()"
(click)="save()" [disabled]="(isLoading$ | async) || calculatedFieldScriptTestFormGroup.get('expression').invalid || !calculatedFieldScriptTestFormGroup.get('expression').dirty">
[disabled]="(isLoading$ | async) || calculatedFieldScriptTestFormGroup.get('expression').invalid || !calculatedFieldScriptTestFormGroup.get('expression').dirty"> {{ 'action.save' | translate }}
{{ 'action.save' | translate }} </button>
</button>
}
</div> </div>
</form> </form>

View File

@ -27,6 +27,28 @@
padding-left: 5px; padding-left: 5px;
border: 1px solid #c0c0c0; border: 1px solid #c0c0c0;
} }
.block-label-container {
position: absolute;
z-index: 10;
font-size: 12px;
font-weight: bold;
&.left {
right: 112px;
top: 9px;
}
&.right-bottom {
right: 40px;
top: 6px;
}
&.right-top {
right: 8px;
top: 2px;
}
}
} }
} }

View File

@ -22,7 +22,7 @@ import {
Inject, Inject,
ViewChild, ViewChild,
} from '@angular/core'; } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { MAT_DIALOG_DATA, MatDialog, MatDialogRef } from '@angular/material/dialog';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state'; import { AppState } from '@core/core.state';
import { FormBuilder } from '@angular/forms'; import { FormBuilder } from '@angular/forms';
@ -36,8 +36,8 @@ import { ActionNotificationShow } from '@core/notification/notification.actions'
import { beautifyJs } from '@shared/models/beautify.models'; import { beautifyJs } from '@shared/models/beautify.models';
import { CalculatedFieldsService } from '@core/http/calculated-fields.service'; import { CalculatedFieldsService } from '@core/http/calculated-fields.service';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { CalculatedFieldScriptTestDialogData } from '@shared/models/calculated-field.models';
import { filter } from 'rxjs/operators'; import { filter } from 'rxjs/operators';
import { CalculatedFieldTestScriptInputParams } from '@shared/models/calculated-field.models';
@Component({ @Component({
selector: 'tb-calculated-field-script-test-dialog', selector: 'tb-calculated-field-script-test-dialog',
@ -66,8 +66,9 @@ export class CalculatedFieldScriptTestDialogComponent extends DialogComponent<Ca
constructor(protected store: Store<AppState>, constructor(protected store: Store<AppState>,
protected router: Router, protected router: Router,
@Inject(MAT_DIALOG_DATA) public data: CalculatedFieldScriptTestDialogData, @Inject(MAT_DIALOG_DATA) public data: CalculatedFieldTestScriptInputParams,
protected dialogRef: MatDialogRef<CalculatedFieldScriptTestDialogComponent, string>, protected dialogRef: MatDialogRef<CalculatedFieldScriptTestDialogComponent, string>,
private dialog: MatDialog,
private fb: FormBuilder, private fb: FormBuilder,
private destroyRef: DestroyRef, private destroyRef: DestroyRef,
private calculatedFieldService: CalculatedFieldsService) { private calculatedFieldService: CalculatedFieldsService) {
@ -101,13 +102,13 @@ export class CalculatedFieldScriptTestDialogComponent extends DialogComponent<Ca
} }
save(): void { save(): void {
this.testScript().pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => { this.testScript(true).pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => {
this.calculatedFieldScriptTestFormGroup.get('expression').markAsPristine(); this.calculatedFieldScriptTestFormGroup.get('expression').markAsPristine();
this.dialogRef.close(this.calculatedFieldScriptTestFormGroup.get('expression').value); this.dialogRef.close(this.calculatedFieldScriptTestFormGroup.get('expression').value);
}); });
} }
private testScript(): Observable<string> { private testScript(onSave = false): Observable<string> {
if (this.checkInputParamErrors()) { if (this.checkInputParamErrors()) {
return this.calculatedFieldService.testScript({ return this.calculatedFieldService.testScript({
expression: this.calculatedFieldScriptTestFormGroup.get('expression').value, expression: this.calculatedFieldScriptTestFormGroup.get('expression').value,
@ -122,6 +123,9 @@ export class CalculatedFieldScriptTestDialogComponent extends DialogComponent<Ca
})); }));
return NEVER; return NEVER;
} else { } else {
if (onSave) {
this.dialog.closeAll();
}
return of(result.output); return of(result.output);
} }
}), }),

View File

@ -127,7 +127,7 @@ export interface CalculatedFieldArgumentValue extends CalculatedFieldArgument {
argumentName: string; argumentName: string;
} }
export type CalculatedFieldTestScriptFn = (argumentsObj: Record<string, unknown>, expression: string, withApply?: boolean) => Observable<string>; export type CalculatedFieldTestScriptFn = (calculatedField: CalculatedField, argumentsObj?: Record<string, unknown>) => Observable<string>;
export interface CalculatedFieldDialogData { export interface CalculatedFieldDialogData {
value?: CalculatedField; value?: CalculatedField;
@ -136,20 +136,15 @@ export interface CalculatedFieldDialogData {
debugLimitsConfiguration: string; debugLimitsConfiguration: string;
tenantId: string; tenantId: string;
entityName?: string; entityName?: string;
additionalDebugActionConfig: AdditionalDebugActionConfig; additionalDebugActionConfig: AdditionalDebugActionConfig<(calculatedField: CalculatedField) => void>;
testScriptFn: CalculatedFieldTestScriptFn; testScriptFn: CalculatedFieldTestScriptFn;
isDirty?: boolean;
} }
export interface CalculatedFieldDebugDialogData { export interface CalculatedFieldDebugDialogData {
id?: CalculatedFieldId;
entityId: EntityId;
tenantId: string; tenantId: string;
expression?: string; value: CalculatedField;
testScriptFn: CalculatedFieldTestScriptFn; getTestScriptDialogFn: CalculatedFieldTestScriptFn;
}
export interface CalculatedFieldScriptTestDialogData extends CalculatedFieldTestScriptInputParams {
withApply: boolean;
} }
export interface CalculatedFieldTestScriptInputParams { export interface CalculatedFieldTestScriptInputParams {

View File

@ -203,13 +203,13 @@ export interface EntityDebugSettings {
allEnabledUntil?: number; allEnabledUntil?: number;
} }
export interface TestScriptResult { export interface EntityTestScriptResult {
output: string; output: string;
error: string; error: string;
} }
export interface AdditionalDebugActionConfig { export interface AdditionalDebugActionConfig<Action = (...args: unknown[]) => void> {
action?: (id?: EntityId, ...restArguments: unknown[]) => void; action?: Action;
title: string; title: string;
} }

View File

@ -27,7 +27,7 @@ import { AppState } from '@core/core.state';
import { AbstractControl, UntypedFormGroup } from '@angular/forms'; import { AbstractControl, UntypedFormGroup } from '@angular/forms';
import { RuleChainType } from '@shared/models/rule-chain.models'; import { RuleChainType } from '@shared/models/rule-chain.models';
import { DebugRuleNodeEventBody } from '@shared/models/event.models'; import { DebugRuleNodeEventBody } from '@shared/models/event.models';
import { HasEntityDebugSettings } from '@shared/models/entity.models'; import { EntityTestScriptResult, HasEntityDebugSettings } from '@shared/models/entity.models';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
export interface RuleNodeConfiguration { export interface RuleNodeConfiguration {
@ -374,6 +374,8 @@ export interface TestScriptInputParams {
msgType: string; msgType: string;
} }
export type TestScriptResult = EntityTestScriptResult;
export enum MessageType { export enum MessageType {
POST_ATTRIBUTES_REQUEST = 'POST_ATTRIBUTES_REQUEST', POST_ATTRIBUTES_REQUEST = 'POST_ATTRIBUTES_REQUEST',
POST_TELEMETRY_REQUEST = 'POST_TELEMETRY_REQUEST', POST_TELEMETRY_REQUEST = 'POST_TELEMETRY_REQUEST',

View File

@ -0,0 +1 @@
<!-- [TODO]: [Calculated Fields] add content -->

View File

@ -0,0 +1 @@
<!-- [TODO]: [Calculated Fields] add content -->