From 05a2359856e8314deab0cba8ee7f5d0a30544f66 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Mon, 17 Feb 2025 11:49:15 +0200 Subject: [PATCH 01/26] Moved save api call to dialog --- .../calculated-fields-table-config.ts | 17 +++-------------- .../dialog/calculated-field-dialog.component.ts | 9 +++++++-- 2 files changed, 10 insertions(+), 16 deletions(-) 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 e1aa7c2ee5..2c96464dda 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 @@ -83,7 +83,7 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig this.fetchCalculatedFields(pageLink); - this.addEntity = this.addCalculatedField.bind(this); + this.addEntity = this.getCalculatedFieldDialog.bind(this); this.deleteEntityTitle = (field: CalculatedField) => this.translate.instant('calculated-fields.delete-title', {title: field.name}); this.deleteEntityContent = () => this.translate.instant('calculated-fields.delete-text'); this.deleteEntitiesTitle = count => this.translate.instant('calculated-fields.delete-multiple-title', {count}); @@ -179,20 +179,8 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig { - return this.getCalculatedFieldDialog() - .pipe( - filter(Boolean), - switchMap(calculatedField => this.calculatedFieldsService.saveCalculatedField({ entityId: this.entityId, ...calculatedField })), - ) - } - private editCalculatedField(calculatedField: CalculatedField, isDirty = false): void { this.getCalculatedFieldDialog(calculatedField, 'action.apply', isDirty) - .pipe( - filter(Boolean), - switchMap((updatedCalculatedField) => this.calculatedFieldsService.saveCalculatedField({ ...calculatedField, ...updatedCalculatedField })), - ) .subscribe((res) => { if (res) { this.updateData(); @@ -217,7 +205,8 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig, + private calculatedFieldsService: CalculatedFieldsService, + private destroyRef: DestroyRef, private fb: FormBuilder) { super(store, router, dialogRef); this.applyDialogData(); @@ -124,7 +127,9 @@ export class CalculatedFieldDialogComponent extends DialogComponent this.dialogRef.close(calculatedField)); } } From e85055076333e9493ea81f6396689153eb6cf25d Mon Sep 17 00:00:00 2001 From: mpetrov Date: Mon, 17 Feb 2025 16:53:13 +0200 Subject: [PATCH 02/26] Reworked test arguments and adjustments --- .../calculated-fields-table-config.ts | 8 +- ...culated-field-arguments-table.component.ts | 8 +- ...ulated-field-test-arguments.component.html | 30 ++++++- ...ulated-field-test-arguments.component.scss | 12 ++- ...lculated-field-test-arguments.component.ts | 79 ++++++++++++++++--- .../json-object-edit-dialog.component.html | 7 +- .../shared/components/js-func.component.ts | 2 +- .../json-object-edit.component.html | 2 +- .../components/value-input.component.html | 2 +- .../components/value-input.component.ts | 4 + .../shared/models/calculated-field.models.ts | 13 ++- .../assets/locale/locale.constant-en_US.json | 1 + ui-ngx/src/styles.scss | 13 +++ 13 files changed, 144 insertions(+), 37 deletions(-) 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 2c96464dda..93fd6d1fd6 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 @@ -36,6 +36,7 @@ import { EntityDebugSettingsPanelComponent } from '@home/components/entity/debug import { CalculatedFieldsService } from '@core/http/calculated-fields.service'; import { catchError, filter, switchMap, tap } from 'rxjs/operators'; import { + ArgumentType, CalculatedField, CalculatedFieldEventArguments, CalculatedFieldDebugDialogData, @@ -122,7 +123,7 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig true, onAction: (_, entity) => this.openDebugEventsDialog(entity), }, @@ -260,7 +261,10 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig { const resultArguments = Object.keys(calculatedField.configuration.arguments).reduce((acc, key) => { - acc[key] = isObject(argumentsObj) && argumentsObj.hasOwnProperty(key) ? argumentsObj[key] : ''; + const type = calculatedField.configuration.arguments[key].refEntityKey.type; + acc[key] = isObject(argumentsObj) && argumentsObj.hasOwnProperty(key) + ? { ...argumentsObj[key], type } + : type === ArgumentType.Rolling ? { values: [], type } : { value: '', type, ts: new Date().getTime() }; return acc; }, {}); return this.dialog.open(CalculatedFieldScriptTestDialogComponent, diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.ts index 3c51dc7f79..2af2e14daa 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.ts @@ -33,7 +33,6 @@ import { NG_VALUE_ACCESSOR, ValidationErrors, Validator, - Validators } from '@angular/forms'; import { ArgumentEntityType, @@ -50,7 +49,6 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { EntityId } from '@shared/models/id/entity-id'; import { EntityType, entityTypeTranslations } from '@shared/models/entity-type.models'; import { isDefinedAndNotNull } from '@core/utils'; -import { charsWithNumRegex } from '@shared/models/regex.constants'; import { TbPopoverComponent } from '@shared/components/popover.component'; @Component({ @@ -143,10 +141,10 @@ export class CalculatedFieldArgumentsTableComponent implements ControlValueAcces buttonTitle: this.argumentsFormArray.at(index)?.value ? 'action.apply' : 'action.add', tenantId: this.tenantId, entityName: this.entityName, - usedArgumentNames: this.argumentsFormArray.value.map(({ argumentName }) => argumentName).filter(name => name !== argumentObj.argumentName), + usedArgumentNames: this.argumentsFormArray.getRawValue().map(({ argumentName }) => argumentName).filter(name => name !== argumentObj.argumentName), }; this.popoverComponent = this.popoverService.displayPopover(trigger, this.renderer, - this.viewContainerRef, CalculatedFieldArgumentPanelComponent, 'left', false, null, + this.viewContainerRef, CalculatedFieldArgumentPanelComponent, index ? 'left' : 'right', false, null, ctx, {}, {}, {}, true); @@ -201,7 +199,7 @@ export class CalculatedFieldArgumentsTableComponent implements ControlValueAcces private getArgumentFormGroup(value: CalculatedFieldArgumentValue): FormGroup { return this.fb.group({ ...value, - argumentName: [value.argumentName, [Validators.required, Validators.maxLength(255), Validators.pattern(charsWithNumRegex)]], + argumentName: [{ value: value.argumentName, disabled: true }], ...(value.refEntityId ? { refEntityId: this.fb.group({ entityType: [{ value: value.refEntityId.entityType, disabled: true }], diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.html b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.html index eea3523d00..9131af966a 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.html +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.html @@ -19,16 +19,38 @@
{{ 'calculated-fields.arguments' | translate }}
-
{{ 'calculated-fields.argument-name' | translate }}
-
{{ 'common.value' | translate }}
+
{{ 'common.name' | translate }}
+
{{ 'common.type' | translate }}
+
{{ 'common.data' | translate }}
@for (group of argumentsFormArray.controls; track group) {
- + - + + + + {{ ArgumentTypeTranslations.get(group.get('type').value) | translate }} + + + +
+ @if (group.get('type').value === ArgumentType.Rolling) { + + + + } @else { + + + + + } + +
}
diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.scss b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.scss index 1b2c8670c1..19046fa254 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.scss +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.scss @@ -15,14 +15,18 @@ */ @use '../../../../../../../scss/constants' as constants; +:host { + .tb-form-table { + min-width: 700px; + } +} + :host::ng-deep { .tb-form-table-row { .argument-value { .tb-value-type.row { - @media #{constants.$mat-lt-sm} { - width: 100px; - min-width: 100px; - } + width: 120px; + min-width: 120px; } } } diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts index c8c9f4e778..e16850008f 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts @@ -26,6 +26,22 @@ import { } from '@angular/forms'; import { PageComponent } from '@shared/components/page.component'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { entityTypeTranslations } from '@shared/models/entity-type.models'; +import { + ArgumentType, + ArgumentTypeTranslations, + CalculatedFieldArgumentEventValue, + CalculatedFieldRollingTelemetryArgumentValue, + CalculatedFieldSingleArgumentValue, + CalculatedFieldEventArguments, + CalculatedFieldType +} from '@shared/models/calculated-field.models'; +import { + JsonObjectEditDialogComponent, + JsonObjectEditDialogData +} from '@shared/components/dialog/json-object-edit-dialog.component'; +import { filter } from 'rxjs/operators'; +import { MatDialog } from '@angular/material/dialog'; @Component({ selector: 'tb-calculated-field-test-arguments', @@ -49,29 +65,35 @@ export class CalculatedFieldTestArgumentsComponent extends PageComponent impleme argumentsFormArray = this.fb.array([]); - private propagateChange: (value: { argumentName: string; value: unknown }) => void; + readonly entityTypeTranslations = entityTypeTranslations; + readonly ArgumentTypeTranslations = ArgumentTypeTranslations; + readonly ArgumentType = ArgumentType; + readonly CalculatedFieldType = CalculatedFieldType; - constructor(private fb: FormBuilder) { + private propagateChange: (value: CalculatedFieldEventArguments) => void; + + constructor(private fb: FormBuilder, private dialog: MatDialog) { super(); this.argumentsFormArray.valueChanges .pipe(takeUntilDestroyed()) .subscribe(() => this.propagateChange(this.getValue())); } - registerOnChange(propagateChange: (value: { argumentName: string; value: unknown }) => void): void { + registerOnChange(propagateChange: (value: CalculatedFieldEventArguments) => void): void { this.propagateChange = propagateChange; } registerOnTouched(_): void { } - writeValue(argumentsObj: Record): void { + writeValue(argumentsObj: CalculatedFieldEventArguments): void { this.argumentsFormArray.clear(); Object.keys(argumentsObj).forEach(key => { - this.argumentsFormArray.push(this.fb.group({ - argumentName: [{ value: key, disabled: true}], - value: [argumentsObj[key]] - }) as FormGroup, {emitEvent: false}); + const value = { ...argumentsObj[key], argumentName: key } as CalculatedFieldArgumentEventValue; + this.argumentsFormArray.push((value).type === ArgumentType.Rolling + ? this.getRollingArgumentFormGroup(value as CalculatedFieldRollingTelemetryArgumentValue) + : this.getSimpleArgumentFormGroup(value as CalculatedFieldSingleArgumentValue), + {emitEvent: false}); }); } @@ -79,11 +101,44 @@ export class CalculatedFieldTestArgumentsComponent extends PageComponent impleme return this.argumentsFormArray.valid ? null : { arguments: { valid: false } }; } - private getValue(): { argumentName: string; value: unknown } { + private getSimpleArgumentFormGroup({ argumentName, type, ts, value }: CalculatedFieldSingleArgumentValue): FormGroup { + return this.fb.group({ + argumentName: [{ value: argumentName, disabled: true}], + type: [{ value: type , disabled: true }], + ts: [ts], + value: [value] + }) as FormGroup; + } + + private getRollingArgumentFormGroup({ argumentName, type, timewindow, values }: CalculatedFieldRollingTelemetryArgumentValue): FormGroup { + return this.fb.group({ + ...timewindow ?? {}, + argumentName: [{ value: argumentName, disabled: true }], + type: [{ value: type , disabled: true }], + values: [values] + }) as FormGroup; + } + + openEditJSONDialog(group: FormGroup): void { + this.dialog.open(JsonObjectEditDialogComponent, { + disableClose: true, + panelClass: ['tb-dialog', 'tb-fullscreen-dialog', 'tb-dialog-min-w-700', 'tb-dialog-h-fill'], + data: { + jsonValue: group.value, + required: true + } + }).afterClosed() + .pipe(filter(Boolean)) + .subscribe(result => group.get('type').value === ArgumentType.Rolling + ? group.patchValue({ timewindow: (result as CalculatedFieldRollingTelemetryArgumentValue).timewindow, values: (result as CalculatedFieldRollingTelemetryArgumentValue).values }) + : group.patchValue({ ts: (result as CalculatedFieldSingleArgumentValue).ts, value: (result as CalculatedFieldSingleArgumentValue).value }) ); + } + + private getValue(): CalculatedFieldEventArguments { return this.argumentsFormArray.getRawValue().reduce((acc, rowItem) => { - const { argumentName, value } = rowItem; - acc[argumentName] = value; + const { argumentName, type, ...value } = rowItem; + acc[argumentName] = { ...value }; return acc; - }, {}) as { argumentName: string; value: unknown }; + }, {}); } } diff --git a/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.html b/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.html index 9cce511a6b..9fcb3a496a 100644 --- a/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.html +++ b/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.html @@ -15,7 +15,7 @@ limitations under the License. --> -
+

{{ title }}

@@ -28,10 +28,11 @@
-
-
+
+
diff --git a/ui-ngx/src/app/shared/components/js-func.component.ts b/ui-ngx/src/app/shared/components/js-func.component.ts index 3f5417c2d0..b1744038c3 100644 --- a/ui-ngx/src/app/shared/components/js-func.component.ts +++ b/ui-ngx/src/app/shared/components/js-func.component.ts @@ -184,7 +184,7 @@ export class JsFuncComponent implements OnInit, OnChanges, OnDestroy, ControlVal this.updateFunctionArgsString(); this.updateFunctionLabel(); } - if (changes.editorCompleter) { + if (changes.editorCompleter?.previousValue) { this.updateCompleters(); } } diff --git a/ui-ngx/src/app/shared/components/json-object-edit.component.html b/ui-ngx/src/app/shared/components/json-object-edit.component.html index 0aa28474d5..bd6e2c06bb 100644 --- a/ui-ngx/src/app/shared/components/json-object-edit.component.html +++ b/ui-ngx/src/app/shared/components/json-object-edit.component.html @@ -15,7 +15,7 @@ limitations under the License. --> -
diff --git a/ui-ngx/src/app/shared/components/value-input.component.html b/ui-ngx/src/app/shared/components/value-input.component.html index a7108f9174..57aed608c5 100644 --- a/ui-ngx/src/app/shared/components/value-input.component.html +++ b/ui-ngx/src/app/shared/components/value-input.component.html @@ -93,7 +93,7 @@ warning -
diff --git a/ui-ngx/src/app/shared/components/value-input.component.ts b/ui-ngx/src/app/shared/components/value-input.component.ts index 93a5a6c8bf..3065dd17c4 100644 --- a/ui-ngx/src/app/shared/components/value-input.component.ts +++ b/ui-ngx/src/app/shared/components/value-input.component.ts @@ -85,6 +85,10 @@ export class ValueInputComponent implements OnInit, OnDestroy, OnChanges, Contro @coerceBoolean() required = true; + @Input() + @coerceBoolean() + hideJsonEdit = false; + @Input() layout: ValueInputLayout | Layout = 'row'; diff --git a/ui-ngx/src/app/shared/models/calculated-field.models.ts b/ui-ngx/src/app/shared/models/calculated-field.models.ts index a718b236bf..5bcc0a4a2a 100644 --- a/ui-ngx/src/app/shared/models/calculated-field.models.ts +++ b/ui-ngx/src/app/shared/models/calculated-field.models.ts @@ -154,7 +154,7 @@ export interface CalculatedFieldTestScriptInputParams { } export interface CalculatedFieldTestScriptDialogData extends CalculatedFieldTestScriptInputParams { - argumentsEditorCompleter: TbEditorCompleter + argumentsEditorCompleter: TbEditorCompleter; openCalculatedFieldEdit?: boolean; } @@ -189,17 +189,22 @@ export const getCalculatedFieldCurrentEntityFilter = (entityName: string, entity } } -export interface CalculatedFieldAttributeArgumentValue { +export interface CalculatedFieldArgumentValueBase { + argumentName: string; + type: ArgumentType; +} + +export interface CalculatedFieldAttributeArgumentValue extends CalculatedFieldArgumentValueBase { ts: number; value: ValueType; } -export interface CalculatedFieldLatestTelemetryArgumentValue { +export interface CalculatedFieldLatestTelemetryArgumentValue extends CalculatedFieldArgumentValueBase { ts: number; value: ValueType; } -export interface CalculatedFieldRollingTelemetryArgumentValue { +export interface CalculatedFieldRollingTelemetryArgumentValue extends CalculatedFieldArgumentValueBase { timewindow: { startTs: number; endTs: number; limit: number }; values: CalculatedFieldSingleArgumentValue[]; } diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 4822d23387..4d19432fe7 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -1100,6 +1100,7 @@ "general": "General", "username": "Username", "password": "Password", + "data": "Data", "enter-username": "Enter username", "enter-password": "Enter password", "enter-search": "Enter search", diff --git a/ui-ngx/src/styles.scss b/ui-ngx/src/styles.scss index dbc69fb9dd..4f38160c0b 100644 --- a/ui-ngx/src/styles.scss +++ b/ui-ngx/src/styles.scss @@ -1058,6 +1058,19 @@ pre.tb-highlight { display: block; } } + + @for $i from 1 through 10 { + &-min-w-#{$i * 100} { + + @media screen and (min-width: #{$i * 100}px) { + --mat-dialog-container-min-width: #{$i * 100}px; + } + } + } + + &-h-fill { + height: 65vh; + } } .tb-fullscreen-dialog-gt-xs { From b01c7d1b1873fc180b49a142c12bca75c0c43a5e Mon Sep 17 00:00:00 2001 From: mpetrov Date: Mon, 17 Feb 2025 17:20:03 +0200 Subject: [PATCH 03/26] added styles --- .../calculated-field-test-arguments.component.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.html b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.html index 9131af966a..6bf600c05a 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.html +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.html @@ -42,10 +42,10 @@ } @else { - + - + }
From b30329be9813711086d01d6da410f131c9edf8ae Mon Sep 17 00:00:00 2001 From: mpetrov Date: Mon, 17 Feb 2025 18:13:20 +0200 Subject: [PATCH 06/26] added isLoading disable form --- .../dialog/calculated-field-dialog.component.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.ts index 6543dead49..4938c0df01 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.ts @@ -97,6 +97,7 @@ export class CalculatedFieldDialogComponent extends DialogComponent { + if (loading) { + this.fieldFormGroup.disable({emitEvent: false}); + } else { + this.fieldFormGroup.enable({emitEvent: false}); + this.toggleScopeByOutputType(this.outputFormGroup.get('type').value); + this.toggleKeyByCalculatedFieldType(this.fieldFormGroup.get('type').value); + } + }); + } } From cf815b39f4c52f3dcd89524ad580fa5bea29f0c9 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Mon, 17 Feb 2025 18:43:24 +0200 Subject: [PATCH 07/26] changed dialog sizing --- .../calculated-field-test-arguments.component.ts | 4 +++- ui-ngx/src/styles.scss | 13 ------------- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts index e16850008f..9ff8d78cba 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts @@ -122,7 +122,9 @@ export class CalculatedFieldTestArgumentsComponent extends PageComponent impleme openEditJSONDialog(group: FormGroup): void { this.dialog.open(JsonObjectEditDialogComponent, { disableClose: true, - panelClass: ['tb-dialog', 'tb-fullscreen-dialog', 'tb-dialog-min-w-700', 'tb-dialog-h-fill'], + height: '65vh', + minWidth: 'min(700px, 100%)', + panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], data: { jsonValue: group.value, required: true diff --git a/ui-ngx/src/styles.scss b/ui-ngx/src/styles.scss index 4f38160c0b..dbc69fb9dd 100644 --- a/ui-ngx/src/styles.scss +++ b/ui-ngx/src/styles.scss @@ -1058,19 +1058,6 @@ pre.tb-highlight { display: block; } } - - @for $i from 1 through 10 { - &-min-w-#{$i * 100} { - - @media screen and (min-width: #{$i * 100}px) { - --mat-dialog-container-min-width: #{$i * 100}px; - } - } - } - - &-h-fill { - height: 65vh; - } } .tb-fullscreen-dialog-gt-xs { From 062fa3a4ed69d315c4d83100e10252052156791d Mon Sep 17 00:00:00 2001 From: mpetrov Date: Mon, 17 Feb 2025 19:03:40 +0200 Subject: [PATCH 08/26] changed dialog sizing --- .../calculated-field-test-arguments.component.ts | 5 +++-- .../components/dialog/json-object-edit-dialog.component.html | 2 +- .../components/dialog/json-object-edit-dialog.component.ts | 1 + .../app/shared/components/json-object-edit.component.html | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts index 9ff8d78cba..4c93d55b7a 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts @@ -122,12 +122,13 @@ export class CalculatedFieldTestArgumentsComponent extends PageComponent impleme openEditJSONDialog(group: FormGroup): void { this.dialog.open(JsonObjectEditDialogComponent, { disableClose: true, - height: '65vh', + height: '760px', minWidth: 'min(700px, 100%)', panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], data: { jsonValue: group.value, - required: true + required: true, + fillHeight: true } }).afterClosed() .pipe(filter(Boolean)) diff --git a/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.html b/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.html index 9fcb3a496a..44f5040010 100644 --- a/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.html +++ b/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.html @@ -35,7 +35,7 @@ class="block h-full" label="{{ 'value.json-value' | translate }}" [jsonRequired]="required" - [fillHeight]="false"> + [fillHeight]="data.fillHeight">
diff --git a/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.ts b/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.ts index a0ffb6b373..d1bc76e194 100644 --- a/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.ts +++ b/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.ts @@ -30,6 +30,7 @@ export interface JsonObjectEditDialogData { title?: string; saveLabel?: string; cancelLabel?: string; + fillHeight?: boolean; } @Component({ diff --git a/ui-ngx/src/app/shared/components/json-object-edit.component.html b/ui-ngx/src/app/shared/components/json-object-edit.component.html index bd6e2c06bb..0aa28474d5 100644 --- a/ui-ngx/src/app/shared/components/json-object-edit.component.html +++ b/ui-ngx/src/app/shared/components/json-object-edit.component.html @@ -15,7 +15,7 @@ limitations under the License. --> -
From 0c71adce914f9ae4833a9143a60c41105d5e1546 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Mon, 17 Feb 2025 19:15:37 +0200 Subject: [PATCH 09/26] added default propagateChange --- .../calculated-field-test-arguments.component.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts index 4c93d55b7a..11246e004f 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts @@ -62,7 +62,6 @@ import { MatDialog } from '@angular/material/dialog'; }) export class CalculatedFieldTestArgumentsComponent extends PageComponent implements ControlValueAccessor, Validator { - argumentsFormArray = this.fb.array([]); readonly entityTypeTranslations = entityTypeTranslations; @@ -70,7 +69,7 @@ export class CalculatedFieldTestArgumentsComponent extends PageComponent impleme readonly ArgumentType = ArgumentType; readonly CalculatedFieldType = CalculatedFieldType; - private propagateChange: (value: CalculatedFieldEventArguments) => void; + private propagateChange: (value: CalculatedFieldEventArguments) => void = () => {}; constructor(private fb: FormBuilder, private dialog: MatDialog) { super(); From 6e0871299b062bd39594eb709c9f7f43c07a2b14 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Mon, 17 Feb 2025 19:42:27 +0200 Subject: [PATCH 10/26] fixes --- ...lculated-field-test-arguments.component.ts | 50 ++++++++++--------- ...ated-field-script-test-dialog.component.ts | 2 +- .../shared/models/calculated-field.models.ts | 2 +- 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts index 11246e004f..e3ab3b560c 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts @@ -14,7 +14,7 @@ /// limitations under the License. /// -import { Component, forwardRef } from '@angular/core'; +import { AfterViewInit, Component, forwardRef } from '@angular/core'; import { ControlValueAccessor, NG_VALIDATORS, @@ -60,7 +60,7 @@ import { MatDialog } from '@angular/material/dialog'; } ] }) -export class CalculatedFieldTestArgumentsComponent extends PageComponent implements ControlValueAccessor, Validator { +export class CalculatedFieldTestArgumentsComponent extends PageComponent implements ControlValueAccessor, Validator, AfterViewInit { argumentsFormArray = this.fb.array([]); @@ -78,6 +78,10 @@ export class CalculatedFieldTestArgumentsComponent extends PageComponent impleme .subscribe(() => this.propagateChange(this.getValue())); } + ngAfterViewInit(): void { + this.argumentsFormArray.updateValueAndValidity(); + } + registerOnChange(propagateChange: (value: CalculatedFieldEventArguments) => void): void { this.propagateChange = propagateChange; } @@ -91,8 +95,8 @@ export class CalculatedFieldTestArgumentsComponent extends PageComponent impleme const value = { ...argumentsObj[key], argumentName: key } as CalculatedFieldArgumentEventValue; this.argumentsFormArray.push((value).type === ArgumentType.Rolling ? this.getRollingArgumentFormGroup(value as CalculatedFieldRollingTelemetryArgumentValue) - : this.getSimpleArgumentFormGroup(value as CalculatedFieldSingleArgumentValue), - {emitEvent: false}); + : this.getSimpleArgumentFormGroup(value as CalculatedFieldSingleArgumentValue) + ); }); } @@ -100,24 +104,6 @@ export class CalculatedFieldTestArgumentsComponent extends PageComponent impleme return this.argumentsFormArray.valid ? null : { arguments: { valid: false } }; } - private getSimpleArgumentFormGroup({ argumentName, type, ts, value }: CalculatedFieldSingleArgumentValue): FormGroup { - return this.fb.group({ - argumentName: [{ value: argumentName, disabled: true}], - type: [{ value: type , disabled: true }], - ts: [ts], - value: [value] - }) as FormGroup; - } - - private getRollingArgumentFormGroup({ argumentName, type, timewindow, values }: CalculatedFieldRollingTelemetryArgumentValue): FormGroup { - return this.fb.group({ - ...timewindow ?? {}, - argumentName: [{ value: argumentName, disabled: true }], - type: [{ value: type , disabled: true }], - values: [values] - }) as FormGroup; - } - openEditJSONDialog(group: FormGroup): void { this.dialog.open(JsonObjectEditDialogComponent, { disableClose: true, @@ -136,10 +122,28 @@ export class CalculatedFieldTestArgumentsComponent extends PageComponent impleme : group.patchValue({ ts: (result as CalculatedFieldSingleArgumentValue).ts, value: (result as CalculatedFieldSingleArgumentValue).value }) ); } + private getSimpleArgumentFormGroup({ argumentName, type, ts, value }: CalculatedFieldSingleArgumentValue): FormGroup { + return this.fb.group({ + argumentName: [{ value: argumentName, disabled: true}], + type: [{ value: type , disabled: true }], + ts: [ts], + value: [value] + }) as FormGroup; + } + + private getRollingArgumentFormGroup({ argumentName, type, timewindow, values }: CalculatedFieldRollingTelemetryArgumentValue): FormGroup { + return this.fb.group({ + ...timewindow ?? {}, + argumentName: [{ value: argumentName, disabled: true }], + type: [{ value: type , disabled: true }], + values: [values] + }) as FormGroup; + } + private getValue(): CalculatedFieldEventArguments { return this.argumentsFormArray.getRawValue().reduce((acc, rowItem) => { const { argumentName, type, ...value } = rowItem; - acc[argumentName] = { ...value }; + acc[argumentName] = value; return acc; }, {}); } 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 83e3625219..ea0164f9b8 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 @@ -81,7 +81,7 @@ export class CalculatedFieldScriptTestDialogComponent extends DialogComponent this.calculatedFieldScriptTestFormGroup.get('expression').patchValue(res, {emitEvent: false}) ); - this.calculatedFieldScriptTestFormGroup.get('arguments').patchValue(this.data.arguments, {emitEvent: false}); + this.calculatedFieldScriptTestFormGroup.get('arguments').patchValue(this.data.arguments); } ngAfterViewInit(): void { diff --git a/ui-ngx/src/app/shared/models/calculated-field.models.ts b/ui-ngx/src/app/shared/models/calculated-field.models.ts index 5bcc0a4a2a..6c816cbb9b 100644 --- a/ui-ngx/src/app/shared/models/calculated-field.models.ts +++ b/ui-ngx/src/app/shared/models/calculated-field.models.ts @@ -149,7 +149,7 @@ export interface CalculatedFieldDebugDialogData { } export interface CalculatedFieldTestScriptInputParams { - arguments: Record, + arguments: CalculatedFieldEventArguments, expression: string; } From 5df33107d361c4f566189a24dc2606d5ebb1254a Mon Sep 17 00:00:00 2001 From: mpetrov Date: Mon, 17 Feb 2025 19:47:23 +0200 Subject: [PATCH 11/26] fixes --- .../dialog/calculated-field-dialog.component.ts | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.ts index 4938c0df01..4a91874b07 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.ts @@ -14,7 +14,7 @@ /// limitations under the License. /// -import { AfterViewInit, Component, DestroyRef, Inject } from '@angular/core'; +import { Component, DestroyRef, Inject } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; @@ -44,7 +44,7 @@ import { CalculatedFieldsService } from '@core/http/calculated-fields.service'; templateUrl: './calculated-field-dialog.component.html', styleUrls: ['./calculated-field-dialog.component.scss'], }) -export class CalculatedFieldDialogComponent extends DialogComponent implements AfterViewInit { +export class CalculatedFieldDialogComponent extends DialogComponent { fieldFormGroup = this.fb.group({ name: ['', [Validators.required, Validators.pattern(noLeadTrailSpacesRegex), Validators.maxLength(255)]], @@ -116,12 +116,6 @@ export class CalculatedFieldDialogComponent extends DialogComponent Date: Tue, 18 Feb 2025 11:17:23 +0200 Subject: [PATCH 12/26] timeseries/rolling cashed search fix --- .../panel/calculated-field-argument-panel.component.html | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-argument-panel.component.html b/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-argument-panel.component.html index c2fe831204..039df61fc6 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-argument-panel.component.html +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/panel/calculated-field-argument-panel.component.html @@ -108,7 +108,14 @@ @if (refEntityKeyFormGroup.get('type').value !== ArgumentType.Attribute) {
{{ 'calculated-fields.timeseries-key' | translate }}
- + @if (refEntityKeyFormGroup.get('type').value === ArgumentType.LatestTelemetry) { + + } @else { + + } + + +
} @else { @if (enableAttributeScopeSelection) { From e7d14df44fa7146e0eef6022263c1a5f4b9e8fd8 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Tue, 18 Feb 2025 11:29:31 +0200 Subject: [PATCH 13/26] datasource truncate fix --- .../calculated-field-arguments-table.component.html | 7 ++++--- .../calculated-field-arguments-table.component.scss | 6 +++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.html b/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.html index 73c3d4df73..a617db5d6d 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.html +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.html @@ -33,7 +33,7 @@
@if (group.get('refEntityId')?.get('id')?.value) { - + {{ entityTypeTranslations.get(group.get('refEntityId').get('entityType').value)?.type | translate }} @@ -41,12 +41,13 @@ + [entityType]="group.get('refEntityId').get('entityType').value" + /> } @else { diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.scss b/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.scss index 28bed75ef7..321cde8dfe 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.scss +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/arguments-table/calculated-field-arguments-table.component.scss @@ -40,9 +40,13 @@ } :host ::ng-deep { - .tb-inline-field { + .entity-field { a { font-size: 14px; + white-space: nowrap; + display: block; + overflow: hidden; + text-overflow: ellipsis; } } From 29a6f1255bc766b6604a7543e74e8aaa342a82ee Mon Sep 17 00:00:00 2001 From: mpetrov Date: Tue, 18 Feb 2025 12:40:09 +0200 Subject: [PATCH 14/26] added test argument type --- ...ulated-field-test-arguments.component.html | 8 ++--- ...lculated-field-test-arguments.component.ts | 18 +++++------ ...ed-field-script-test-dialog.component.html | 2 +- ...ated-field-script-test-dialog.component.ts | 31 +++++++++++++++++-- .../shared/models/calculated-field.models.ts | 13 ++++++++ 5 files changed, 53 insertions(+), 19 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.html b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.html index 6bf600c05a..af51d2ec82 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.html +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.html @@ -30,14 +30,14 @@ - - - {{ ArgumentTypeTranslations.get(group.get('type').value) | translate }} + + + {{ ArgumentTypeTranslations.get(argumentsTypeMap.get(group.get('argumentName').value)) | translate }}
- @if (group.get('type').value === ArgumentType.Rolling) { + @if (argumentsTypeMap.get(group.get('argumentName').value) === ArgumentType.Rolling) { diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts index e3ab3b560c..c493c09e5c 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts @@ -14,7 +14,7 @@ /// limitations under the License. /// -import { AfterViewInit, Component, forwardRef } from '@angular/core'; +import { Component, forwardRef, Input } from '@angular/core'; import { ControlValueAccessor, NG_VALIDATORS, @@ -60,7 +60,9 @@ import { MatDialog } from '@angular/material/dialog'; } ] }) -export class CalculatedFieldTestArgumentsComponent extends PageComponent implements ControlValueAccessor, Validator, AfterViewInit { +export class CalculatedFieldTestArgumentsComponent extends PageComponent implements ControlValueAccessor, Validator { + + @Input() argumentsTypeMap: Map; argumentsFormArray = this.fb.array([]); @@ -78,10 +80,6 @@ export class CalculatedFieldTestArgumentsComponent extends PageComponent impleme .subscribe(() => this.propagateChange(this.getValue())); } - ngAfterViewInit(): void { - this.argumentsFormArray.updateValueAndValidity(); - } - registerOnChange(propagateChange: (value: CalculatedFieldEventArguments) => void): void { this.propagateChange = propagateChange; } @@ -122,27 +120,25 @@ export class CalculatedFieldTestArgumentsComponent extends PageComponent impleme : group.patchValue({ ts: (result as CalculatedFieldSingleArgumentValue).ts, value: (result as CalculatedFieldSingleArgumentValue).value }) ); } - private getSimpleArgumentFormGroup({ argumentName, type, ts, value }: CalculatedFieldSingleArgumentValue): FormGroup { + private getSimpleArgumentFormGroup({ argumentName, ts, value }: CalculatedFieldSingleArgumentValue): FormGroup { return this.fb.group({ argumentName: [{ value: argumentName, disabled: true}], - type: [{ value: type , disabled: true }], ts: [ts], value: [value] }) as FormGroup; } - private getRollingArgumentFormGroup({ argumentName, type, timewindow, values }: CalculatedFieldRollingTelemetryArgumentValue): FormGroup { + private getRollingArgumentFormGroup({ argumentName, timewindow, values }: CalculatedFieldRollingTelemetryArgumentValue): FormGroup { return this.fb.group({ ...timewindow ?? {}, argumentName: [{ value: argumentName, disabled: true }], - type: [{ value: type , disabled: true }], values: [values] }) as FormGroup; } private getValue(): CalculatedFieldEventArguments { return this.argumentsFormArray.getRawValue().reduce((acc, rowItem) => { - const { argumentName, type, ...value } = rowItem; + const { argumentName, ...value } = rowItem; acc[argumentName] = value; return acc; }, {}); diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-dialog/calculated-field-script-test-dialog.component.html b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-dialog/calculated-field-script-test-dialog.component.html index 3f35ecbc0c..6b0a273a51 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-dialog/calculated-field-script-test-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-dialog/calculated-field-script-test-dialog.component.html @@ -52,7 +52,7 @@
{{ 'calculated-fields.arguments' | translate }}
- +
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 ea0164f9b8..b644afa96d 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 @@ -38,7 +38,11 @@ import { beautifyJs } from '@shared/models/beautify.models'; import { CalculatedFieldsService } from '@core/http/calculated-fields.service'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { filter } from 'rxjs/operators'; -import { CalculatedFieldTestScriptDialogData } from '@shared/models/calculated-field.models'; +import { + ArgumentType, CalculatedFieldEventArguments, + CalculatedFieldTestScriptDialogData, + TestArgumentTypeMap +} from '@shared/models/calculated-field.models'; @Component({ selector: 'tb-calculated-field-script-test-dialog', @@ -61,6 +65,7 @@ export class CalculatedFieldScriptTestDialogComponent extends DialogComponent(); readonly ContentType = ContentType; readonly ScriptLanguage = ScriptLanguage; @@ -81,7 +86,7 @@ export class CalculatedFieldScriptTestDialogComponent extends DialogComponent this.calculatedFieldScriptTestFormGroup.get('expression').patchValue(res, {emitEvent: false}) ); - this.calculatedFieldScriptTestFormGroup.get('arguments').patchValue(this.data.arguments); + this.calculatedFieldScriptTestFormGroup.get('arguments').patchValue(this.getArgumentsValue()); } ngAfterViewInit(): void { @@ -117,7 +122,7 @@ export class CalculatedFieldScriptTestDialogComponent extends DialogComponent { if (result.error) { @@ -157,6 +162,26 @@ export class CalculatedFieldScriptTestDialogComponent extends DialogComponent { + acc[key] = argumentsValue[key]; + acc[key].type = TestArgumentTypeMap.get(this.argumentsTypeMap.get(key)); + return acc; + }, {}); + } + + private getArgumentsValue(): CalculatedFieldEventArguments { + return Object.keys(this.data.arguments) + .reduce((acc, key) => { + const { type, ...argumentObj } = this.data.arguments[key]; + this.argumentsTypeMap.set(key, type); + acc[key] = argumentObj; + return acc; + }, {}); + } + private initSplitLayout(smallMode = false): void { const [leftPanel, rightPanel, topRightPanel, bottomRightPanel] = [ this.leftPanelElmRef.nativeElement, diff --git a/ui-ngx/src/app/shared/models/calculated-field.models.ts b/ui-ngx/src/app/shared/models/calculated-field.models.ts index 6c816cbb9b..5229fbe851 100644 --- a/ui-ngx/src/app/shared/models/calculated-field.models.ts +++ b/ui-ngx/src/app/shared/models/calculated-field.models.ts @@ -85,6 +85,19 @@ export enum ArgumentType { Rolling = 'TS_ROLLING', } +export enum TestArgumentType { + Single = 'SINGLE_VALUE', + Rolling = 'TS_ROLLING', +} + +export const TestArgumentTypeMap = new Map( + [ + [ArgumentType.Attribute, TestArgumentType.Single], + [ArgumentType.LatestTelemetry, TestArgumentType.Single], + [ArgumentType.Rolling, TestArgumentType.Rolling], + ] +) + export enum OutputType { Attribute = 'ATTRIBUTES', Timeseries = 'TIME_SERIES', From e766710b95e006a7d3f302200c2974307eb44694 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Tue, 18 Feb 2025 12:59:47 +0200 Subject: [PATCH 15/26] test argument type fixes --- .../calculated-field-test-arguments.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts index c493c09e5c..c1095343cb 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts @@ -91,7 +91,7 @@ export class CalculatedFieldTestArgumentsComponent extends PageComponent impleme this.argumentsFormArray.clear(); Object.keys(argumentsObj).forEach(key => { const value = { ...argumentsObj[key], argumentName: key } as CalculatedFieldArgumentEventValue; - this.argumentsFormArray.push((value).type === ArgumentType.Rolling + this.argumentsFormArray.push(this.argumentsTypeMap.get(key) === ArgumentType.Rolling ? this.getRollingArgumentFormGroup(value as CalculatedFieldRollingTelemetryArgumentValue) : this.getSimpleArgumentFormGroup(value as CalculatedFieldSingleArgumentValue) ); @@ -115,7 +115,7 @@ export class CalculatedFieldTestArgumentsComponent extends PageComponent impleme } }).afterClosed() .pipe(filter(Boolean)) - .subscribe(result => group.get('type').value === ArgumentType.Rolling + .subscribe(result => this.argumentsTypeMap.get(group.get('argumentName').value) === ArgumentType.Rolling ? group.patchValue({ timewindow: (result as CalculatedFieldRollingTelemetryArgumentValue).timewindow, values: (result as CalculatedFieldRollingTelemetryArgumentValue).values }) : group.patchValue({ ts: (result as CalculatedFieldSingleArgumentValue).ts, value: (result as CalculatedFieldSingleArgumentValue).value }) ); } From b5d94fdb0f97e0bc6a5694d03087c034ab39e6ce Mon Sep 17 00:00:00 2001 From: mpetrov Date: Tue, 18 Feb 2025 13:06:53 +0200 Subject: [PATCH 16/26] timewindow align with model --- .../calculated-field-test-arguments.component.ts | 6 +++--- .../calculated-field-script-test-dialog.component.ts | 3 ++- ui-ngx/src/app/shared/models/calculated-field.models.ts | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts index c1095343cb..ea73376c83 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts @@ -116,7 +116,7 @@ export class CalculatedFieldTestArgumentsComponent extends PageComponent impleme }).afterClosed() .pipe(filter(Boolean)) .subscribe(result => this.argumentsTypeMap.get(group.get('argumentName').value) === ArgumentType.Rolling - ? group.patchValue({ timewindow: (result as CalculatedFieldRollingTelemetryArgumentValue).timewindow, values: (result as CalculatedFieldRollingTelemetryArgumentValue).values }) + ? group.patchValue({ timeWindow: (result as CalculatedFieldRollingTelemetryArgumentValue).timeWindow, values: (result as CalculatedFieldRollingTelemetryArgumentValue).values }) : group.patchValue({ ts: (result as CalculatedFieldSingleArgumentValue).ts, value: (result as CalculatedFieldSingleArgumentValue).value }) ); } @@ -128,9 +128,9 @@ export class CalculatedFieldTestArgumentsComponent extends PageComponent impleme }) as FormGroup; } - private getRollingArgumentFormGroup({ argumentName, timewindow, values }: CalculatedFieldRollingTelemetryArgumentValue): FormGroup { + private getRollingArgumentFormGroup({ argumentName, timeWindow, values }: CalculatedFieldRollingTelemetryArgumentValue): FormGroup { return this.fb.group({ - ...timewindow ?? {}, + timeWindow: [timeWindow ?? {}], argumentName: [{ value: argumentName, disabled: true }], values: [values] }) as FormGroup; 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 b644afa96d..769387b3dd 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 @@ -39,7 +39,8 @@ import { CalculatedFieldsService } from '@core/http/calculated-fields.service'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { filter } from 'rxjs/operators'; import { - ArgumentType, CalculatedFieldEventArguments, + ArgumentType, + CalculatedFieldEventArguments, CalculatedFieldTestScriptDialogData, TestArgumentTypeMap } from '@shared/models/calculated-field.models'; diff --git a/ui-ngx/src/app/shared/models/calculated-field.models.ts b/ui-ngx/src/app/shared/models/calculated-field.models.ts index 5229fbe851..8b05cee719 100644 --- a/ui-ngx/src/app/shared/models/calculated-field.models.ts +++ b/ui-ngx/src/app/shared/models/calculated-field.models.ts @@ -218,7 +218,7 @@ export interface CalculatedFieldLatestTelemetryArgumentValue extends CalculatedFieldArgumentValueBase { - timewindow: { startTs: number; endTs: number; limit: number }; + timeWindow: { startTs: number; endTs: number; limit: number }; values: CalculatedFieldSingleArgumentValue[]; } From 08b9c4ed1b7925e559bc19627a122b2d45c72df1 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Tue, 18 Feb 2025 13:14:45 +0200 Subject: [PATCH 17/26] added maxheight for json edit dialog --- .../test-arguments/calculated-field-test-arguments.component.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts index ea73376c83..2411a7fd81 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.ts @@ -106,6 +106,7 @@ export class CalculatedFieldTestArgumentsComponent extends PageComponent impleme this.dialog.open(JsonObjectEditDialogComponent, { disableClose: true, height: '760px', + maxHeight: '70vh', minWidth: 'min(700px, 100%)', panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], data: { From cc89f5fbca6d6c37fef4a926f284eef8a995bbe6 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Tue, 18 Feb 2025 13:19:00 +0200 Subject: [PATCH 18/26] entity version fix --- .../components/dialog/calculated-field-dialog.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.ts index 4a91874b07..5785c62cc9 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.ts @@ -122,7 +122,7 @@ export class CalculatedFieldDialogComponent extends DialogComponent this.dialogRef.close(calculatedField)); } From e39b4673e2c739695eccf503f778cbffbda0a3d9 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Tue, 18 Feb 2025 13:25:29 +0200 Subject: [PATCH 19/26] minor adjustments --- .../calculated-field-test-arguments.component.html | 4 ++-- ui-ngx/src/app/shared/models/calculated-field.models.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.html b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.html index af51d2ec82..3f5c864708 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.html +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-arguments/calculated-field-test-arguments.component.html @@ -20,7 +20,7 @@
{{ 'common.name' | translate }}
-
{{ 'common.type' | translate }}
+
{{ 'common.type' | translate }}
{{ 'common.data' | translate }}
@@ -29,7 +29,7 @@ - + {{ ArgumentTypeTranslations.get(argumentsTypeMap.get(group.get('argumentName').value)) | translate }} diff --git a/ui-ngx/src/app/shared/models/calculated-field.models.ts b/ui-ngx/src/app/shared/models/calculated-field.models.ts index 8b05cee719..b62c287525 100644 --- a/ui-ngx/src/app/shared/models/calculated-field.models.ts +++ b/ui-ngx/src/app/shared/models/calculated-field.models.ts @@ -162,7 +162,7 @@ export interface CalculatedFieldDebugDialogData { } export interface CalculatedFieldTestScriptInputParams { - arguments: CalculatedFieldEventArguments, + arguments: CalculatedFieldEventArguments; expression: string; } From a2560691af42cc74483c8f04f990b995dad2bf2c Mon Sep 17 00:00:00 2001 From: mpetrov Date: Tue, 18 Feb 2025 13:26:23 +0200 Subject: [PATCH 20/26] minor adjustments --- ui-ngx/src/app/shared/models/calculated-field.models.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui-ngx/src/app/shared/models/calculated-field.models.ts b/ui-ngx/src/app/shared/models/calculated-field.models.ts index b62c287525..ba4131147f 100644 --- a/ui-ngx/src/app/shared/models/calculated-field.models.ts +++ b/ui-ngx/src/app/shared/models/calculated-field.models.ts @@ -266,7 +266,7 @@ export const CalculatedFieldAttributeValueArgumentAutocomplete = { export const CalculatedFieldRollingValueArgumentAutocomplete = { meta: 'object', - type: '{ values: { ts: number; value: any; }[]; timewindow: { startTs: number; endTs: number; limit: number } }; }', + type: '{ values: { ts: number; value: any; }[]; timeWindow: { startTs: number; endTs: number; limit: number } }; }', description: 'Calculated field rolling value argument.', children: { values: { @@ -274,7 +274,7 @@ export const CalculatedFieldRollingValueArgumentAutocomplete = { type: '{ ts: number; value: any; }[]', description: 'Values array', }, - timewindow: { + timeWindow: { meta: 'object', type: '{ startTs: number; endTs: number; limit: number }', description: 'Time window configuration', From d8f2cbba8d941c3df5ad874fd038d689bb412a1d Mon Sep 17 00:00:00 2001 From: mpetrov Date: Tue, 18 Feb 2025 13:34:36 +0200 Subject: [PATCH 21/26] Added message type translate --- .../home/components/event/event-table-config.ts | 5 ++++- .../app/shared/models/calculated-field.models.ts | 13 +++++++++++++ ui-ngx/src/assets/locale/locale.constant-en_US.json | 2 ++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/ui-ngx/src/app/modules/home/components/event/event-table-config.ts b/ui-ngx/src/app/modules/home/components/event/event-table-config.ts index 1e9717d5a8..d2e080bbd8 100644 --- a/ui-ngx/src/app/modules/home/components/event/event-table-config.ts +++ b/ui-ngx/src/app/modules/home/components/event/event-table-config.ts @@ -55,6 +55,7 @@ import { DEFAULT_OVERLAY_POSITIONS } from '@shared/models/overlay.models'; import { getCurrentAuthState } from '@core/auth/auth.selectors'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; +import { TestArgumentMessageType, TestArgumentMessageTypeTranslationMap } from '@shared/models/calculated-field.models'; export class EventTableConfig extends EntityTableConfig { @@ -401,7 +402,9 @@ export class EventTableConfig extends EntityTableConfig { } ), new EntityTableColumn('messageType', 'event.message-type', '100px', - (entity) => entity.body.msgType ?? '-', + (entity) => entity.body.msgType + ? this.translate.instant(TestArgumentMessageTypeTranslationMap.get(entity.body.msgType as TestArgumentMessageType)) + : '-', () => ({padding: '0 12px 0 0'}), false ), diff --git a/ui-ngx/src/app/shared/models/calculated-field.models.ts b/ui-ngx/src/app/shared/models/calculated-field.models.ts index ba4131147f..6e243751b3 100644 --- a/ui-ngx/src/app/shared/models/calculated-field.models.ts +++ b/ui-ngx/src/app/shared/models/calculated-field.models.ts @@ -28,6 +28,7 @@ import { EntityType } from '@shared/models/entity-type.models'; import { AliasFilterType } from '@shared/models/alias.models'; import { Observable } from 'rxjs'; import { TbEditorCompleter } from '@shared/models/ace/completion.models'; +import { MessageType } from '@shared/models/rule-node.models'; export interface CalculatedField extends Omit, 'label'>, HasVersion, HasTenantId, ExportableEntity { debugSettings?: EntityDebugSettings; @@ -90,6 +91,18 @@ export enum TestArgumentType { Rolling = 'TS_ROLLING', } +export enum TestArgumentMessageType { + POST_ATTRIBUTES_REQUEST = 'POST_ATTRIBUTES_REQUEST', + POST_TELEMETRY_REQUEST = 'POST_TELEMETRY_REQUEST', +} + +export const TestArgumentMessageTypeTranslationMap = new Map( + [ + [TestArgumentMessageType.POST_ATTRIBUTES_REQUEST, 'calculated-fields.post-attributes'], + [TestArgumentMessageType.POST_TELEMETRY_REQUEST, 'calculated-fields.post-telemetry'], + ] +); + export const TestArgumentTypeMap = new Map( [ [ArgumentType.Attribute, TestArgumentType.Single], diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 4d19432fe7..0a1dad05cc 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -1017,6 +1017,8 @@ "arguments": "Arguments", "debugging": "Calculated field debugging", "argument-name": "Argument name", + "post-telemetry": "Post telemetry", + "post-attributes": "Post attribute", "datasource": "Datasource", "add-argument": "Add argument", "test-script-function": "Test script function", From c406f2af3650c2227c073c12d289165920d6745e Mon Sep 17 00:00:00 2001 From: mpetrov Date: Tue, 18 Feb 2025 13:36:22 +0200 Subject: [PATCH 22/26] Revert "Added message type translate" This reverts commit d8f2cbba8d941c3df5ad874fd038d689bb412a1d. --- .../home/components/event/event-table-config.ts | 5 +---- .../app/shared/models/calculated-field.models.ts | 13 ------------- ui-ngx/src/assets/locale/locale.constant-en_US.json | 2 -- 3 files changed, 1 insertion(+), 19 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/event/event-table-config.ts b/ui-ngx/src/app/modules/home/components/event/event-table-config.ts index d2e080bbd8..1e9717d5a8 100644 --- a/ui-ngx/src/app/modules/home/components/event/event-table-config.ts +++ b/ui-ngx/src/app/modules/home/components/event/event-table-config.ts @@ -55,7 +55,6 @@ import { DEFAULT_OVERLAY_POSITIONS } from '@shared/models/overlay.models'; import { getCurrentAuthState } from '@core/auth/auth.selectors'; import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; -import { TestArgumentMessageType, TestArgumentMessageTypeTranslationMap } from '@shared/models/calculated-field.models'; export class EventTableConfig extends EntityTableConfig { @@ -402,9 +401,7 @@ export class EventTableConfig extends EntityTableConfig { } ), new EntityTableColumn('messageType', 'event.message-type', '100px', - (entity) => entity.body.msgType - ? this.translate.instant(TestArgumentMessageTypeTranslationMap.get(entity.body.msgType as TestArgumentMessageType)) - : '-', + (entity) => entity.body.msgType ?? '-', () => ({padding: '0 12px 0 0'}), false ), diff --git a/ui-ngx/src/app/shared/models/calculated-field.models.ts b/ui-ngx/src/app/shared/models/calculated-field.models.ts index 6e243751b3..ba4131147f 100644 --- a/ui-ngx/src/app/shared/models/calculated-field.models.ts +++ b/ui-ngx/src/app/shared/models/calculated-field.models.ts @@ -28,7 +28,6 @@ import { EntityType } from '@shared/models/entity-type.models'; import { AliasFilterType } from '@shared/models/alias.models'; import { Observable } from 'rxjs'; import { TbEditorCompleter } from '@shared/models/ace/completion.models'; -import { MessageType } from '@shared/models/rule-node.models'; export interface CalculatedField extends Omit, 'label'>, HasVersion, HasTenantId, ExportableEntity { debugSettings?: EntityDebugSettings; @@ -91,18 +90,6 @@ export enum TestArgumentType { Rolling = 'TS_ROLLING', } -export enum TestArgumentMessageType { - POST_ATTRIBUTES_REQUEST = 'POST_ATTRIBUTES_REQUEST', - POST_TELEMETRY_REQUEST = 'POST_TELEMETRY_REQUEST', -} - -export const TestArgumentMessageTypeTranslationMap = new Map( - [ - [TestArgumentMessageType.POST_ATTRIBUTES_REQUEST, 'calculated-fields.post-attributes'], - [TestArgumentMessageType.POST_TELEMETRY_REQUEST, 'calculated-fields.post-telemetry'], - ] -); - export const TestArgumentTypeMap = new Map( [ [ArgumentType.Attribute, TestArgumentType.Single], diff --git a/ui-ngx/src/assets/locale/locale.constant-en_US.json b/ui-ngx/src/assets/locale/locale.constant-en_US.json index 0a1dad05cc..4d19432fe7 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -1017,8 +1017,6 @@ "arguments": "Arguments", "debugging": "Calculated field debugging", "argument-name": "Argument name", - "post-telemetry": "Post telemetry", - "post-attributes": "Post attribute", "datasource": "Datasource", "add-argument": "Add argument", "test-script-function": "Test script function", From ffc88eeb2d0fbfefa6d5dd56f47585c3249e5a10 Mon Sep 17 00:00:00 2001 From: ViacheslavKlimov Date: Tue, 18 Feb 2025 15:28:46 +0200 Subject: [PATCH 23/26] CF Kafka states cleanup --- .../AbstractCalculatedFieldStateService.java | 6 ++- .../KafkaCalculatedFieldStateService.java | 38 +++++++++++++++++-- .../queue/common/AbstractTbQueueTemplate.java | 13 ++++--- .../server/queue/common/TbProtoQueueMsg.java | 3 +- .../provider/KafkaMonolithQueueFactory.java | 2 +- .../KafkaTbRuleEngineQueueFactory.java | 2 +- 6 files changed, 50 insertions(+), 14 deletions(-) diff --git a/application/src/main/java/org/thingsboard/server/service/cf/AbstractCalculatedFieldStateService.java b/application/src/main/java/org/thingsboard/server/service/cf/AbstractCalculatedFieldStateService.java index e390d9e55c..c55ec00379 100644 --- a/application/src/main/java/org/thingsboard/server/service/cf/AbstractCalculatedFieldStateService.java +++ b/application/src/main/java/org/thingsboard/server/service/cf/AbstractCalculatedFieldStateService.java @@ -52,9 +52,11 @@ public abstract class AbstractCalculatedFieldStateService implements CalculatedF protected void processRestoredState(CalculatedFieldStateProto stateMsg) { var id = fromProto(stateMsg.getId()); var state = fromProto(stateMsg); + processRestoredState(id, state); + } + + protected void processRestoredState(CalculatedFieldEntityCtxId id, CalculatedFieldState state) { actorSystemContext.tell(new CalculatedFieldStateRestoreMsg(id, state)); } - - } diff --git a/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/KafkaCalculatedFieldStateService.java b/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/KafkaCalculatedFieldStateService.java index cce7e5ef22..959522ca63 100644 --- a/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/KafkaCalculatedFieldStateService.java +++ b/application/src/main/java/org/thingsboard/server/service/cf/ctx/state/KafkaCalculatedFieldStateService.java @@ -24,10 +24,15 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.stereotype.Service; import org.thingsboard.common.util.ThingsBoardExecutors; import org.thingsboard.common.util.ThingsBoardThreadFactory; +import org.thingsboard.server.common.data.id.CalculatedFieldId; +import org.thingsboard.server.common.data.id.EntityId; +import org.thingsboard.server.common.data.id.EntityIdFactory; +import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.msg.queue.TbCallback; import org.thingsboard.server.common.msg.queue.TopicPartitionInfo; import org.thingsboard.server.gen.transport.TransportProtos.CalculatedFieldStateProto; import org.thingsboard.server.queue.TbQueueCallback; +import org.thingsboard.server.queue.TbQueueMsgHeaders; import org.thingsboard.server.queue.TbQueueMsgMetadata; import org.thingsboard.server.queue.common.TbProtoQueueMsg; import org.thingsboard.server.queue.discovery.PartitionService; @@ -46,6 +51,11 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; +import static org.thingsboard.server.queue.common.AbstractTbQueueTemplate.bytesToString; +import static org.thingsboard.server.queue.common.AbstractTbQueueTemplate.bytesToUuid; +import static org.thingsboard.server.queue.common.AbstractTbQueueTemplate.stringToBytes; +import static org.thingsboard.server.queue.common.AbstractTbQueueTemplate.uuidToBytes; + @Service @RequiredArgsConstructor @Slf4j @@ -81,7 +91,11 @@ public class KafkaCalculatedFieldStateService extends AbstractCalculatedFieldSta .msgPackProcessor((msgs, consumer, config) -> { for (TbProtoQueueMsg msg : msgs) { try { - processRestoredState(msg.getValue()); + if (msg.getValue() != null) { + processRestoredState(msg.getValue()); + } else { + processRestoredState(getStateId(msg.getHeaders()), null); + } } catch (Throwable t) { log.error("Failed to process state message: {}", msg, t); } @@ -103,7 +117,11 @@ public class KafkaCalculatedFieldStateService extends AbstractCalculatedFieldSta @Override protected void doPersist(CalculatedFieldEntityCtxId stateId, CalculatedFieldStateProto stateMsgProto, TbCallback callback) { TopicPartitionInfo tpi = partitionService.resolve(QueueKey.CF_STATES, stateId.entityId()); - stateProducer.send(tpi, stateId.toKey(), new TbProtoQueueMsg<>(stateId.entityId().getId(), stateMsgProto), new TbQueueCallback() { + TbProtoQueueMsg msg = new TbProtoQueueMsg<>(stateId.entityId().getId(), stateMsgProto); + if (stateMsgProto == null) { + putStateId(msg.getHeaders(), stateId); + } + stateProducer.send(tpi, stateId.toKey(), msg, new TbQueueCallback() { @Override public void onSuccess(TbQueueMsgMetadata metadata) { if (callback != null) { @@ -122,7 +140,7 @@ public class KafkaCalculatedFieldStateService extends AbstractCalculatedFieldSta @Override protected void doRemove(CalculatedFieldEntityCtxId stateId, TbCallback callback) { - //TODO: vklimov + doPersist(stateId, null, callback); } @Override @@ -138,6 +156,20 @@ public class KafkaCalculatedFieldStateService extends AbstractCalculatedFieldSta log.info("Restored {} calculated field states in {} ms", counter.get(), System.currentTimeMillis() - startTs); } + private void putStateId(TbQueueMsgHeaders headers, CalculatedFieldEntityCtxId stateId) { + headers.put("tenantId", uuidToBytes(stateId.tenantId().getId())); + headers.put("cfId", uuidToBytes(stateId.cfId().getId())); + headers.put("entityId", uuidToBytes(stateId.entityId().getId())); + headers.put("entityType", stringToBytes(stateId.entityId().getEntityType().name())); + } + + private CalculatedFieldEntityCtxId getStateId(TbQueueMsgHeaders headers) { + TenantId tenantId = TenantId.fromUUID(bytesToUuid(headers.get("tenantId"))); + CalculatedFieldId cfId = new CalculatedFieldId(bytesToUuid(headers.get("cfId"))); + EntityId entityId = EntityIdFactory.getByTypeAndUuid(bytesToString(headers.get("entityType")), bytesToUuid(headers.get("entityId"))); + return new CalculatedFieldEntityCtxId(tenantId, cfId, entityId); + } + @PreDestroy private void preDestroy() { stateConsumer.stop(); diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/common/AbstractTbQueueTemplate.java b/common/queue/src/main/java/org/thingsboard/server/queue/common/AbstractTbQueueTemplate.java index f11eaaef48..51ed1bb05f 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/common/AbstractTbQueueTemplate.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/common/AbstractTbQueueTemplate.java @@ -24,35 +24,36 @@ public class AbstractTbQueueTemplate { protected static final String RESPONSE_TOPIC_HEADER = "responseTopic"; protected static final String EXPIRE_TS_HEADER = "expireTs"; - protected byte[] uuidToBytes(UUID uuid) { + public static byte[] uuidToBytes(UUID uuid) { ByteBuffer buf = ByteBuffer.allocate(16); buf.putLong(uuid.getMostSignificantBits()); buf.putLong(uuid.getLeastSignificantBits()); return buf.array(); } - protected static UUID bytesToUuid(byte[] bytes) { + public static UUID bytesToUuid(byte[] bytes) { ByteBuffer bb = ByteBuffer.wrap(bytes); long firstLong = bb.getLong(); long secondLong = bb.getLong(); return new UUID(firstLong, secondLong); } - protected byte[] stringToBytes(String string) { + public static byte[] stringToBytes(String string) { return string.getBytes(StandardCharsets.UTF_8); } - protected String bytesToString(byte[] data) { + public static String bytesToString(byte[] data) { return new String(data, StandardCharsets.UTF_8); } - protected static byte[] longToBytes(long x) { + public static byte[] longToBytes(long x) { ByteBuffer longBuffer = ByteBuffer.allocate(Long.BYTES); longBuffer.putLong(0, x); return longBuffer.array(); } - protected static long bytesToLong(byte[] bytes) { + public static long bytesToLong(byte[] bytes) { return ByteBuffer.wrap(bytes).getLong(); } + } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/common/TbProtoQueueMsg.java b/common/queue/src/main/java/org/thingsboard/server/queue/common/TbProtoQueueMsg.java index fb7d086daa..6bb72a65fa 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/common/TbProtoQueueMsg.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/common/TbProtoQueueMsg.java @@ -50,6 +50,7 @@ public class TbProtoQueueMsg i @Override public byte[] getData() { - return value.toByteArray(); + return value != null ? value.toByteArray() : null; } + } diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaMonolithQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaMonolithQueueFactory.java index 91ba63427b..d768648aea 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaMonolithQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaMonolithQueueFactory.java @@ -556,7 +556,7 @@ public class KafkaMonolithQueueFactory implements TbCoreQueueFactory, TbRuleEngi .stopWhenRead(true) .clientId("monolith-calculated-field-state-consumer-" + serviceInfoProvider.getServiceId() + "-" + consumerCount.incrementAndGet()) .groupId(topicService.buildTopicName("monolith-calculated-field-state-consumer")) - .decoder(msg -> new TbProtoQueueMsg<>(msg.getKey(), CalculatedFieldStateProto.parseFrom(msg.getData()), msg.getHeaders())) + .decoder(msg -> new TbProtoQueueMsg<>(msg.getKey(), msg.getData() != null ? CalculatedFieldStateProto.parseFrom(msg.getData()) : null, msg.getHeaders())) .admin(cfStateAdmin) .statsService(consumerStatsService) .build(); diff --git a/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbRuleEngineQueueFactory.java b/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbRuleEngineQueueFactory.java index d4076ba67d..45a2290f52 100644 --- a/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbRuleEngineQueueFactory.java +++ b/common/queue/src/main/java/org/thingsboard/server/queue/provider/KafkaTbRuleEngineQueueFactory.java @@ -348,7 +348,7 @@ public class KafkaTbRuleEngineQueueFactory implements TbRuleEngineQueueFactory { .stopWhenRead(true) .clientId("tb-rule-engine-calculated-field-state-consumer-" + serviceInfoProvider.getServiceId() + "-" + consumerCount.incrementAndGet()) .groupId(topicService.buildTopicName("tb-rule-engine-calculated-field-state-consumer")) - .decoder(msg -> new TbProtoQueueMsg<>(msg.getKey(), CalculatedFieldStateProto.parseFrom(msg.getData()), msg.getHeaders())) + .decoder(msg -> new TbProtoQueueMsg<>(msg.getKey(), msg.getData() != null ? CalculatedFieldStateProto.parseFrom(msg.getData()) : null, msg.getHeaders())) .admin(cfStateAdmin) .statsService(consumerStatsService) .build(); From 036cff6a75daddb5d4eb67bcc9e3712660914d5a Mon Sep 17 00:00:00 2001 From: mpetrov Date: Tue, 18 Feb 2025 15:43:24 +0200 Subject: [PATCH 24/26] Deleted json obj dialog fieldset --- .../json-object-edit-dialog.component.html | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.html b/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.html index 44f5040010..2db4f1bf49 100644 --- a/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.html +++ b/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.html @@ -29,15 +29,13 @@
-
- - -
+ +
From 7216719d3e45da6618949fde68fbb17fd097bd61 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Tue, 18 Feb 2025 18:21:59 +0200 Subject: [PATCH 25/26] Added highlight rules --- .../calculated-fields-table-config.ts | 2 + .../calculated-field-dialog.component.html | 2 + .../calculated-field-dialog.component.scss | 18 +++++ .../calculated-field-dialog.component.ts | 7 ++ ...ed-field-script-test-dialog.component.html | 2 + ...ed-field-script-test-dialog.component.scss | 16 +++++ .../shared/components/js-func.component.ts | 37 ++++++---- .../shared/models/calculated-field.models.ts | 71 ++++++++++++++++++- 8 files changed, 139 insertions(+), 16 deletions(-) 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 93fd6d1fd6..783ae6be5c 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 @@ -43,6 +43,7 @@ import { CalculatedFieldDialogData, CalculatedFieldTestScriptDialogData, getCalculatedFieldArgumentsEditorCompleter, + getCalculatedFieldArgumentsHighlights, } from '@shared/models/calculated-field.models'; import { CalculatedFieldDebugDialogComponent, @@ -275,6 +276,7 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.scss b/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.scss index bc49e05e8d..c17dbf8bb5 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.scss +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.scss @@ -20,3 +20,21 @@ max-width: 100%; } } + +:host ::ng-deep { + .expression-edit { + .ace_tb { + &.ace_calculated-field { + &-key { + color: #C52F00; + } + &-ts, &-time-window, &-values, &-value { + color: #7214D0; + } + &-start-ts, &-end-ts, &-limit { + color: #185F2A; + } + } + } + } +} diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.ts index 5785c62cc9..bffb405534 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.ts @@ -28,6 +28,7 @@ import { CalculatedFieldType, CalculatedFieldTypeTranslations, getCalculatedFieldArgumentsEditorCompleter, + getCalculatedFieldArgumentsHighlights, OutputType, OutputTypeTranslations } from '@shared/models/calculated-field.models'; @@ -74,6 +75,12 @@ export class CalculatedFieldDialogComponent extends DialogComponent getCalculatedFieldArgumentsEditorCompleter(argumentsObj)) ); + argumentsHighlightRules$ = this.configFormGroup.get('arguments').valueChanges + .pipe( + startWith(this.data.value?.configuration?.arguments ?? {}), + map(argumentsObj => getCalculatedFieldArgumentsHighlights(argumentsObj)) + ); + additionalDebugActionConfig = this.data.value?.id ? { ...this.data.additionalDebugActionConfig, action: () => this.data.additionalDebugActionConfig.action({ id: this.data.value.id, ...this.fromGroupValue }), diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-dialog/calculated-field-script-test-dialog.component.html b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-dialog/calculated-field-script-test-dialog.component.html index 6b0a273a51..789d290a6d 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-dialog/calculated-field-script-test-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/test-dialog/calculated-field-script-test-dialog.component.html @@ -36,9 +36,11 @@ #expressionContent formControlName="expression" functionName="calculate" + class="expression-edit" [functionArgs]="functionArgs" [disableUndefinedCheck]="true" [fillHeight]="true" + [highlightRules]="data.argumentsHighlightRules" [scriptLanguage]="ScriptLanguage.TBEL" [editorCompleter]="data.argumentsEditorCompleter" resultType="object" 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 eaee8e443d..03ef1c3540 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 @@ -71,4 +71,20 @@ background-image: url("../../../../../../../assets/split.js/grips/vertical.png"); } } + + .expression-edit { + .ace_tb { + &.ace_calculated-field { + &-key { + color: #C52F00; + } + &-ts, &-time-window, &-values, &-value { + color: #7214D0; + } + &-start-ts, &-end-ts, &-limit { + color: #185F2A; + } + } + } + } } diff --git a/ui-ngx/src/app/shared/components/js-func.component.ts b/ui-ngx/src/app/shared/components/js-func.component.ts index b1744038c3..b4898b2377 100644 --- a/ui-ngx/src/app/shared/components/js-func.component.ts +++ b/ui-ngx/src/app/shared/components/js-func.component.ts @@ -187,6 +187,9 @@ export class JsFuncComponent implements OnInit, OnChanges, OnDestroy, ControlVal if (changes.editorCompleter?.previousValue) { this.updateCompleters(); } + if (changes.highlightRules?.previousValue) { + this.updateHighlightRules(); + } } ngOnInit(): void { @@ -247,21 +250,7 @@ export class JsFuncComponent implements OnInit, OnChanges, OnDestroy, ControlVal } }); } - // @ts-ignore - if (!!this.highlightRules && !!this.jsEditor.session.$mode) { - // @ts-ignore - const newMode = new this.jsEditor.session.$mode.constructor(); - newMode.$highlightRules = new newMode.HighlightRules(); - for(const group in this.highlightRules) { - if(!!newMode.$highlightRules.$rules[group]) { - newMode.$highlightRules.$rules[group].unshift(...this.highlightRules[group]); - } else { - newMode.$highlightRules.$rules[group] = this.highlightRules[group]; - } - } - // @ts-ignore - this.jsEditor.session.$onChangeMode(newMode); - } + this.updateHighlightRules(); this.updateJsWorkerGlobals(); this.initialCompleters = this.jsEditor.completers || []; this.updateCompleters(); @@ -282,6 +271,24 @@ export class JsFuncComponent implements OnInit, OnChanges, OnDestroy, ControlVal } } + private updateHighlightRules(): void { + // @ts-ignore + if (!!this.highlightRules && !!this.jsEditor.session.$mode) { + // @ts-ignore + const newMode = new this.jsEditor.session.$mode.constructor(); + newMode.$highlightRules = new newMode.HighlightRules(); + for(const group in this.highlightRules) { + if(!!newMode.$highlightRules.$rules[group]) { + newMode.$highlightRules.$rules[group].unshift(...this.highlightRules[group]); + } else { + newMode.$highlightRules.$rules[group] = this.highlightRules[group]; + } + } + // @ts-ignore + this.jsEditor.session.$onChangeMode(newMode); + } + } + private onAceEditorResize() { if (this.editorsResizeCaf) { this.editorsResizeCaf(); diff --git a/ui-ngx/src/app/shared/models/calculated-field.models.ts b/ui-ngx/src/app/shared/models/calculated-field.models.ts index ba4131147f..5ce1a50d04 100644 --- a/ui-ngx/src/app/shared/models/calculated-field.models.ts +++ b/ui-ngx/src/app/shared/models/calculated-field.models.ts @@ -28,6 +28,7 @@ import { EntityType } from '@shared/models/entity-type.models'; import { AliasFilterType } from '@shared/models/alias.models'; import { Observable } from 'rxjs'; import { TbEditorCompleter } from '@shared/models/ace/completion.models'; +import { AceHighlightRules } from '@shared/models/ace/ace.models'; export interface CalculatedField extends Omit, 'label'>, HasVersion, HasTenantId, ExportableEntity { debugSettings?: EntityDebugSettings; @@ -168,6 +169,7 @@ export interface CalculatedFieldTestScriptInputParams { export interface CalculatedFieldTestScriptDialogData extends CalculatedFieldTestScriptInputParams { argumentsEditorCompleter: TbEditorCompleter; + argumentsHighlightRules: AceHighlightRules; openCalculatedFieldEdit?: boolean; } @@ -313,5 +315,72 @@ export const getCalculatedFieldArgumentsEditorCompleter = (argumentsObj: Record< break; } return acc; - }, {})) + }, {})); +} + +export const getCalculatedFieldArgumentsHighlights = ( + argumentsObj: Record +): AceHighlightRules => { + return { + start: Object.keys(argumentsObj).map(key => ({ + token: 'tb.calculated-field-key', + regex: `\\b${key}\\b`, + next: argumentsObj[key].refEntityKey.type === ArgumentType.Rolling + ? 'calculatedFieldRollingArgumentValue' + : 'calculatedFieldSingleArgumentValue' + })), + ...calculatedFieldSingleArgumentValueHighlightRules, + ...calculatedFieldRollingArgumentValueHighlightRules, + ...calculatedFieldTimeWindowArgumentValueHighlightRules + }; +}; + +const calculatedFieldSingleArgumentValueHighlightRules: AceHighlightRules = { + calculatedFieldSingleArgumentValue: [ + { + token: 'tb.calculated-field-value', + regex: /value/, + next: 'no_regex' + }, + { + token: 'tb.calculated-field-ts', + regex: /ts/, + next: 'no_regex' + } + ], +} + +const calculatedFieldRollingArgumentValueHighlightRules: AceHighlightRules = { + calculatedFieldRollingArgumentValue: [ + { + token: 'tb.calculated-field-values', + regex: /values/, + next: 'no_regex' + }, + { + token: 'tb.calculated-field-time-window', + regex: /timeWindow/, + next: 'calculatedFieldRollingArgumentTimeWindow' + } + ], +} + +const calculatedFieldTimeWindowArgumentValueHighlightRules: AceHighlightRules = { + calculatedFieldRollingArgumentTimeWindow: [ + { + token: 'tb.calculated-field-start-ts', + regex: /startTs/, + next: 'no_regex' + }, + { + token: 'tb.calculated-field-end-ts', + regex: /endTs/, + next: 'no_regex' + }, + { + token: 'tb.calculated-field-limit', + regex: /limit/, + next: 'no_regex' + } + ] } From 4e3e0153382bf71ccab80ae0f8af045b41627f87 Mon Sep 17 00:00:00 2001 From: mpetrov Date: Tue, 18 Feb 2025 18:24:28 +0200 Subject: [PATCH 26/26] Deleted from object edit dialog --- .../dialog/json-object-edit-dialog.component.html | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.html b/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.html index 2db4f1bf49..147c7ed130 100644 --- a/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.html +++ b/ui-ngx/src/app/shared/components/dialog/json-object-edit-dialog.component.html @@ -25,9 +25,7 @@ close - - -
+