diff --git a/ui-ngx/src/app/core/http/calculated-fields.service.ts b/ui-ngx/src/app/core/http/calculated-fields.service.ts index acaf3b2817..3e0e08f8e6 100644 --- a/ui-ngx/src/app/core/http/calculated-fields.service.ts +++ b/ui-ngx/src/app/core/http/calculated-fields.service.ts @@ -22,7 +22,7 @@ import { PageData } from '@shared/models/page/page-data'; import { CalculatedField, CalculatedFieldTestScriptInputParams } from '@shared/models/calculated-field.models'; import { PageLink } from '@shared/models/page/page-link'; import { EntityId } from '@shared/models/id/entity-id'; -import { TestScriptResult } from '@shared/models/entity.models'; +import { EntityTestScriptResult } from '@shared/models/entity.models'; @Injectable({ providedIn: 'root' @@ -50,7 +50,7 @@ export class CalculatedFieldsService { defaultHttpOptionsFromConfig(config)); } - public testScript(inputParams: CalculatedFieldTestScriptInputParams, config?: RequestConfig): Observable { - return this.http.post('/api/calculatedField/testScript', inputParams, defaultHttpOptionsFromConfig(config)); + public testScript(inputParams: CalculatedFieldTestScriptInputParams, config?: RequestConfig): Observable { + return this.http.post('/api/calculatedField/testScript', inputParams, defaultHttpOptionsFromConfig(config)); } } diff --git a/ui-ngx/src/app/core/http/rule-chain.service.ts b/ui-ngx/src/app/core/http/rule-chain.service.ts index c1333df1ac..e3353989cc 100644 --- a/ui-ngx/src/app/core/http/rule-chain.service.ts +++ b/ui-ngx/src/app/core/http/rule-chain.service.ts @@ -35,6 +35,7 @@ import { RuleNodeConfiguration, ScriptLanguage, TestScriptInputParams, + TestScriptResult } from '@app/shared/models/rule-node.models'; import { componentTypeBySelector, ResourcesService } from '../services/resources.service'; 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 { Edge } from '@shared/models/edge.models'; import { IModulesMap } from '@modules/common/modules-map.models'; -import { TestScriptResult } from '@shared/models/entity.models'; @Injectable({ providedIn: 'root' diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/calculated-fields-table-config.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/calculated-fields-table-config.ts index c71eef8de3..63b0fad732 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/calculated-fields-table-config.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/calculated-fields-table-config.ts @@ -34,12 +34,12 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { TbPopoverService } from '@shared/components/popover.service'; import { EntityDebugSettingsPanelComponent } from '@home/components/entity/debug/entity-debug-settings-panel.component'; import { CalculatedFieldsService } from '@core/http/calculated-fields.service'; -import { catchError, filter, switchMap } from 'rxjs/operators'; +import { catchError, filter, switchMap, tap } from 'rxjs/operators'; import { CalculatedField, CalculatedFieldDebugDialogData, CalculatedFieldDialogData, - CalculatedFieldScriptTestDialogData + CalculatedFieldTestScriptInputParams, } from '@shared/models/calculated-field.models'; import { CalculatedFieldDebugDialogComponent, @@ -47,7 +47,6 @@ import { CalculatedFieldScriptTestDialogComponent } from './components/public-api'; import { ImportExportService } from '@shared/import-export/import-export.service'; -import { CalculatedFieldId } from '@shared/models/id/calculated-field-id'; export class CalculatedFieldsTableConfig extends EntityTableConfig { @@ -58,7 +57,7 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig this.openDebugDialog.call(this, id, expression), + action: (calculatedField: CalculatedField) => this.openDebugDialog.call(this, calculatedField), }; constructor(private calculatedFieldsService: CalculatedFieldsService, @@ -139,10 +138,11 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig this.openDebugDialog(id, configuration?.expression) + action: () => this.openDebugDialog(calculatedField) }; const { viewContainerRef } = this.getTable(); if ($event) { @@ -178,8 +178,8 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig this.calculatedFieldsService.saveCalculatedField({ ...calculatedField, ...updatedCalculatedField })), @@ -191,7 +191,7 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig { + private getCalculatedFieldDialog(value?: CalculatedField, buttonTitle = 'action.add', isDirty = false): Observable { return this.dialog.open(CalculatedFieldDialogComponent, { disableClose: true, panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], @@ -204,21 +204,20 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig(CalculatedFieldDebugDialogComponent, { disableClose: true, panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], data: { tenantId: this.tenantId, - entityId: this.entityId, - id, - expression, - testScriptFn: this.getTestScriptDialog.bind(this), + value: calculatedField, + getTestScriptDialogFn: this.getTestScriptDialog.bind(this), } }) .afterClosed() @@ -260,16 +259,21 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig this.updateData()); } - private getTestScriptDialog(argumentsObj: Record, expression: string, withApply = false): Observable { - return this.dialog.open(CalculatedFieldScriptTestDialogComponent, + private getTestScriptDialog(calculatedField: CalculatedField, argumentsObj?: Record): Observable { + return this.dialog.open(CalculatedFieldScriptTestDialogComponent, { disableClose: true, panelClass: ['tb-dialog', 'tb-fullscreen-dialog', 'tb-fullscreen-dialog-gt-xs'], data: { - arguments: argumentsObj, - expression, - withApply, + arguments: argumentsObj ?? Object.keys(calculatedField.configuration.arguments).reduce((acc, key) => ({...acc, [key]: '' }), {}), + expression: calculatedField.configuration.expression, } - }).afterClosed(); + }).afterClosed() + .pipe( + filter(Boolean), + tap(expression => + this.editCalculatedField({...calculatedField, configuration: {...calculatedField.configuration, expression } }, true) + ), + ); } } diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/debug-dialog/calculated-field-debug-dialog.component.html b/ui-ngx/src/app/modules/home/components/calculated-fields/components/debug-dialog/calculated-field-debug-dialog.component.html index f88176be8a..8295a9c892 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/debug-dialog/calculated-field-debug-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/debug-dialog/calculated-field-debug-dialog.component.html @@ -32,7 +32,7 @@ [disabledEventTypes]="[EventType.LC_EVENT, EventType.ERROR, EventType.STATS]" [defaultEventType]="DebugEventType.DEBUG_CALCULATED_FIELD" [active]="true" - [entityId]="data.id" + [entityId]="data.value.id" [functionTestButtonLabel]="'common.test-function' | translate" (debugEventSelected)="onDebugEventSelected($event)" /> diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/debug-dialog/calculated-field-debug-dialog.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/debug-dialog/calculated-field-debug-dialog.component.ts index 5b79476528..be27e277a6 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/debug-dialog/calculated-field-debug-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/debug-dialog/calculated-field-debug-dialog.component.ts @@ -22,14 +22,14 @@ import { Router } from '@angular/router'; import { DialogComponent } from '@shared/components/dialog.component'; import { CalculatedFieldEventBody, DebugEventType, EventType } from '@shared/models/event.models'; 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({ selector: 'tb-calculated-field-debug-dialog', styleUrls: ['calculated-field-debug-dialog.component.scss'], templateUrl: './calculated-field-debug-dialog.component.html', }) -export class CalculatedFieldDebugDialogComponent extends DialogComponent implements AfterViewInit { +export class CalculatedFieldDebugDialogComponent extends DialogComponent implements AfterViewInit { @ViewChild(EventTableComponent, {static: true}) eventsTable: EventTableComponent; @@ -40,12 +40,13 @@ export class CalculatedFieldDebugDialogComponent extends DialogComponent, protected router: Router, @Inject(MAT_DIALOG_DATA) public data: CalculatedFieldDebugDialogData, - protected dialogRef: MatDialogRef) { + protected dialogRef: MatDialogRef) { super(store, router, dialogRef); } ngAfterViewInit(): void { this.eventsTable.entitiesTable.updateData(); + this.eventsTable.entitiesTable.cellActionDescriptors[0].isEnabled = () => this.data.value.type === CalculatedFieldType.SCRIPT; } cancel(): void { @@ -53,6 +54,7 @@ export class CalculatedFieldDebugDialogComponent extends DialogComponent this.dialogRef.close(expression)); } } diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.html b/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.html index ad2d14cbbf..f50c552ec0 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.html @@ -99,7 +99,7 @@ [functionArgs]="functionArgs$ | async" [disableUndefinedCheck]="true" [scriptLanguage]="ScriptLanguage.TBEL" - helpId="[TODO]: [Calculated Fields] add valid link" + helpId="calculated-field/expression_fn" />
- @if (data.withApply) { - - } +
diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-dialog/calculated-field-script-test-dialog.component.scss b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-dialog/calculated-field-script-test-dialog.component.scss index ee0d59b839..2420aa5a50 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-dialog/calculated-field-script-test-dialog.component.scss +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-dialog/calculated-field-script-test-dialog.component.scss @@ -27,6 +27,28 @@ padding-left: 5px; 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; + } + } } } diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-dialog/calculated-field-script-test-dialog.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-dialog/calculated-field-script-test-dialog.component.ts index fa66827eb6..bd19a68045 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-dialog/calculated-field-script-test-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-dialog/calculated-field-script-test-dialog.component.ts @@ -22,7 +22,7 @@ import { Inject, ViewChild, } 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 { AppState } from '@core/core.state'; import { FormBuilder } from '@angular/forms'; @@ -36,8 +36,8 @@ import { ActionNotificationShow } from '@core/notification/notification.actions' import { beautifyJs } from '@shared/models/beautify.models'; import { CalculatedFieldsService } from '@core/http/calculated-fields.service'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; -import { CalculatedFieldScriptTestDialogData } from '@shared/models/calculated-field.models'; import { filter } from 'rxjs/operators'; +import { CalculatedFieldTestScriptInputParams } from '@shared/models/calculated-field.models'; @Component({ selector: 'tb-calculated-field-script-test-dialog', @@ -66,8 +66,9 @@ export class CalculatedFieldScriptTestDialogComponent extends DialogComponent, protected router: Router, - @Inject(MAT_DIALOG_DATA) public data: CalculatedFieldScriptTestDialogData, + @Inject(MAT_DIALOG_DATA) public data: CalculatedFieldTestScriptInputParams, protected dialogRef: MatDialogRef, + private dialog: MatDialog, private fb: FormBuilder, private destroyRef: DestroyRef, private calculatedFieldService: CalculatedFieldsService) { @@ -101,13 +102,13 @@ export class CalculatedFieldScriptTestDialogComponent extends DialogComponent { + this.testScript(true).pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => { this.calculatedFieldScriptTestFormGroup.get('expression').markAsPristine(); this.dialogRef.close(this.calculatedFieldScriptTestFormGroup.get('expression').value); }); } - private testScript(): Observable { + private testScript(onSave = false): Observable { if (this.checkInputParamErrors()) { return this.calculatedFieldService.testScript({ expression: this.calculatedFieldScriptTestFormGroup.get('expression').value, @@ -122,6 +123,9 @@ export class CalculatedFieldScriptTestDialogComponent extends DialogComponent, expression: string, withApply?: boolean) => Observable; +export type CalculatedFieldTestScriptFn = (calculatedField: CalculatedField, argumentsObj?: Record) => Observable; export interface CalculatedFieldDialogData { value?: CalculatedField; @@ -136,20 +136,15 @@ export interface CalculatedFieldDialogData { debugLimitsConfiguration: string; tenantId: string; entityName?: string; - additionalDebugActionConfig: AdditionalDebugActionConfig; + additionalDebugActionConfig: AdditionalDebugActionConfig<(calculatedField: CalculatedField) => void>; testScriptFn: CalculatedFieldTestScriptFn; + isDirty?: boolean; } export interface CalculatedFieldDebugDialogData { - id?: CalculatedFieldId; - entityId: EntityId; tenantId: string; - expression?: string; - testScriptFn: CalculatedFieldTestScriptFn; -} - -export interface CalculatedFieldScriptTestDialogData extends CalculatedFieldTestScriptInputParams { - withApply: boolean; + value: CalculatedField; + getTestScriptDialogFn: CalculatedFieldTestScriptFn; } export interface CalculatedFieldTestScriptInputParams { diff --git a/ui-ngx/src/app/shared/models/entity.models.ts b/ui-ngx/src/app/shared/models/entity.models.ts index 3a8c06f544..472d28f849 100644 --- a/ui-ngx/src/app/shared/models/entity.models.ts +++ b/ui-ngx/src/app/shared/models/entity.models.ts @@ -203,13 +203,13 @@ export interface EntityDebugSettings { allEnabledUntil?: number; } -export interface TestScriptResult { +export interface EntityTestScriptResult { output: string; error: string; } -export interface AdditionalDebugActionConfig { - action?: (id?: EntityId, ...restArguments: unknown[]) => void; +export interface AdditionalDebugActionConfig void> { + action?: Action; title: string; } diff --git a/ui-ngx/src/app/shared/models/rule-node.models.ts b/ui-ngx/src/app/shared/models/rule-node.models.ts index ac08fa38ac..3e1eb70835 100644 --- a/ui-ngx/src/app/shared/models/rule-node.models.ts +++ b/ui-ngx/src/app/shared/models/rule-node.models.ts @@ -27,7 +27,7 @@ import { AppState } from '@core/core.state'; import { AbstractControl, UntypedFormGroup } from '@angular/forms'; import { RuleChainType } from '@shared/models/rule-chain.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'; export interface RuleNodeConfiguration { @@ -374,6 +374,8 @@ export interface TestScriptInputParams { msgType: string; } +export type TestScriptResult = EntityTestScriptResult; + export enum MessageType { POST_ATTRIBUTES_REQUEST = 'POST_ATTRIBUTES_REQUEST', POST_TELEMETRY_REQUEST = 'POST_TELEMETRY_REQUEST', diff --git a/ui-ngx/src/assets/help/en_US/calculated-field/expression_fn.md b/ui-ngx/src/assets/help/en_US/calculated-field/expression_fn.md new file mode 100644 index 0000000000..f8173dc528 --- /dev/null +++ b/ui-ngx/src/assets/help/en_US/calculated-field/expression_fn.md @@ -0,0 +1 @@ + diff --git a/ui-ngx/src/assets/help/en_US/calculated-field/test-expression_fn.md b/ui-ngx/src/assets/help/en_US/calculated-field/test-expression_fn.md new file mode 100644 index 0000000000..f8173dc528 --- /dev/null +++ b/ui-ngx/src/assets/help/en_US/calculated-field/test-expression_fn.md @@ -0,0 +1 @@ +