From ba19ebd6acf86e749c5da1fbe2156b0683e3a731 Mon Sep 17 00:00:00 2001 From: Maksym Tsymbarov Date: Fri, 5 Dec 2025 12:11:57 +0200 Subject: [PATCH 1/6] added debug events modal to rule chain elements --- .../rule-node-debug-dialog.component.html | 47 ++++++++++++++ .../rule-node-debug-dialog.component.scss | 26 ++++++++ .../rule-node-debug-dialog.component.ts | 65 +++++++++++++++++++ .../rule-node-details.component.html | 1 + .../rulechain/rule-node-details.component.ts | 4 ++ .../rulechain/rulechain-page.component.html | 1 + .../rulechain/rulechain-page.component.ts | 35 +++++++++- .../pages/rulechain/rulechain-page.module.ts | 4 +- 8 files changed, 181 insertions(+), 2 deletions(-) create mode 100644 ui-ngx/src/app/modules/home/pages/rulechain/rule-node-debug-dialog.component.html create mode 100644 ui-ngx/src/app/modules/home/pages/rulechain/rule-node-debug-dialog.component.scss create mode 100644 ui-ngx/src/app/modules/home/pages/rulechain/rule-node-debug-dialog.component.ts diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-debug-dialog.component.html b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-debug-dialog.component.html new file mode 100644 index 0000000000..b2bd40aa1a --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-debug-dialog.component.html @@ -0,0 +1,47 @@ + +
+ +

{{ 'rulenode.events' | translate}}

+ + +
+
+ +
+
+ +
+
diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-debug-dialog.component.scss b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-debug-dialog.component.scss new file mode 100644 index 0000000000..c4798d06f9 --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-debug-dialog.component.scss @@ -0,0 +1,26 @@ +/** + * Copyright © 2016-2025 The Thingsboard Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +:host { + .debug-dialog-container { + width: 1080px; + max-width: 100%; + + .debug-dialog-content { + height: 65vh; + border-radius: 0; + } + } +} diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-debug-dialog.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-debug-dialog.component.ts new file mode 100644 index 0000000000..e7a7947009 --- /dev/null +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-debug-dialog.component.ts @@ -0,0 +1,65 @@ +/// +/// Copyright © 2016-2025 The Thingsboard Authors +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// + +import { AfterViewInit, Component, Inject, ViewChild } from '@angular/core'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { DialogComponent } from '@shared/components/dialog.component'; +import { EventTableComponent } from '@home/components/event/event-table.component'; +import { Store } from '@ngrx/store'; +import { AppState } from '@core/core.state'; +import { Router } from '@angular/router'; +import { DebugEventType, EventType } from '@shared/models/event.models'; +import { TenantId } from '@shared/models/id/tenant-id'; +import { EntityId } from '@shared/models/id/entity-id'; + +export interface RuleNodeDebugDialogData { + isActive: boolean; + tenantId: TenantId; + ruleNodeId: EntityId; + ruleNodeTestButtonLabel: string; + onDebugEventSelected: ()=> void; +} + +@Component({ + selector: 'tb-rule-node-debug-dialog', + templateUrl: './rule-node-debug-dialog.component.html', + styleUrl: './rule-node-debug-dialog.component.scss' +}) +export class RuleNodeDebugDialogComponent extends DialogComponent implements AfterViewInit{ + + @ViewChild(EventTableComponent, {static: true}) eventsTable: EventTableComponent; + + readonly DebugEventType = DebugEventType; + readonly debugEventTypes = DebugEventType; + readonly EventType = EventType; + + dialogTitle: string; + + constructor(protected store: Store, + protected router: Router, + @Inject(MAT_DIALOG_DATA) public data: RuleNodeDebugDialogData, + protected dialogRef: MatDialogRef) { + super(store, router, dialogRef); + } + + ngAfterViewInit() { + this.eventsTable.entitiesTable.updateData(); + } + + cancel(): void { + this.dialogRef.close(null); + } +} diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.html b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.html index b55dcdaa73..a66819a49b 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.html +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-details.component.html @@ -36,6 +36,7 @@
(); diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.html b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.html index 423bde7da3..c31f24c0ea 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.html +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.html @@ -106,6 +106,7 @@ (RuleNodeDebugDialogComponent, { + disableClose: true, + panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], + data: { + active: true, + tenantId: this.ruleChain.tenantId, + ruleNodeId: this.editingRuleNode.ruleNodeId, + functionTestButtonLabel: this.ruleNodeTestButtonLabel, + debugEventSelected: this.onDebugEventSelected.bind(this) + } + }) + .afterClosed() + .subscribe(); + } + private updateNodeErrorTooltip(node: FcRuleNode) { if (node.error) { const element = $('#' + node.id); diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.module.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.module.ts index 34518e2b70..51197e1073 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.module.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.module.ts @@ -33,6 +33,7 @@ import { RuleNodeDetailsComponent } from '@home/pages/rulechain/rule-node-detail import { RuleNodeConfigComponent } from '@home/pages/rulechain/rule-node-config.component'; import { LinkLabelsComponent } from '@home/pages/rulechain/link-labels.component'; import { RuleNodeLinkComponent } from '@home/pages/rulechain/rule-node-link.component'; +import { RuleNodeDebugDialogComponent } from '@home/pages/rulechain/rule-node-debug-dialog.component'; @NgModule({ declarations: [ @@ -43,7 +44,8 @@ import { RuleNodeLinkComponent } from '@home/pages/rulechain/rule-node-link.comp RuleNodeConfigComponent, AddRuleNodeLinkDialogComponent, AddRuleNodeDialogComponent, - CreateNestedRuleChainDialogComponent + CreateNestedRuleChainDialogComponent, + RuleNodeDebugDialogComponent ], imports: [ CommonModule, From 185ef9b53b31de8632d5d34105ada22b3fcbe6d4 Mon Sep 17 00:00:00 2001 From: Maksym Tsymbarov Date: Fri, 5 Dec 2025 12:46:27 +0200 Subject: [PATCH 2/6] move events modal to reusable component --- .../event/events-dialog.component.html} | 8 ++++---- .../event/events-dialog.component.scss} | 0 .../event/events-dialog.component.ts} | 19 ++++++++----------- .../home/components/home-components.module.ts | 5 ++++- .../rulechain/rulechain-page.component.ts | 8 ++++---- .../pages/rulechain/rulechain-page.module.ts | 4 +--- 6 files changed, 21 insertions(+), 23 deletions(-) rename ui-ngx/src/app/modules/home/{pages/rulechain/rule-node-debug-dialog.component.html => components/event/events-dialog.component.html} (89%) rename ui-ngx/src/app/modules/home/{pages/rulechain/rule-node-debug-dialog.component.scss => components/event/events-dialog.component.scss} (100%) rename ui-ngx/src/app/modules/home/{pages/rulechain/rule-node-debug-dialog.component.ts => components/event/events-dialog.component.ts} (78%) diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-debug-dialog.component.html b/ui-ngx/src/app/modules/home/components/event/events-dialog.component.html similarity index 89% rename from ui-ngx/src/app/modules/home/pages/rulechain/rule-node-debug-dialog.component.html rename to ui-ngx/src/app/modules/home/components/event/events-dialog.component.html index b2bd40aa1a..65040bcf60 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-debug-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/event/events-dialog.component.html @@ -17,7 +17,7 @@ -->
-

{{ 'rulenode.events' | translate}}

+

{{ data.title | translate}}

diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-debug-dialog.component.scss b/ui-ngx/src/app/modules/home/components/event/events-dialog.component.scss similarity index 100% rename from ui-ngx/src/app/modules/home/pages/rulechain/rule-node-debug-dialog.component.scss rename to ui-ngx/src/app/modules/home/components/event/events-dialog.component.scss diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-debug-dialog.component.ts b/ui-ngx/src/app/modules/home/components/event/events-dialog.component.ts similarity index 78% rename from ui-ngx/src/app/modules/home/pages/rulechain/rule-node-debug-dialog.component.ts rename to ui-ngx/src/app/modules/home/components/event/events-dialog.component.ts index e7a7947009..5a21241868 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rule-node-debug-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/event/events-dialog.component.ts @@ -26,32 +26,29 @@ import { TenantId } from '@shared/models/id/tenant-id'; import { EntityId } from '@shared/models/id/entity-id'; export interface RuleNodeDebugDialogData { - isActive: boolean; + title: string; tenantId: TenantId; - ruleNodeId: EntityId; - ruleNodeTestButtonLabel: string; + entityId: EntityId; + functionTestButtonLabel: string; onDebugEventSelected: ()=> void; } @Component({ - selector: 'tb-rule-node-debug-dialog', - templateUrl: './rule-node-debug-dialog.component.html', - styleUrl: './rule-node-debug-dialog.component.scss' + selector: 'tb-debug-dialog', + templateUrl: './events-dialog.component.html', + styleUrl: './events-dialog.component.scss' }) -export class RuleNodeDebugDialogComponent extends DialogComponent implements AfterViewInit{ +export class EventsDialogComponent extends DialogComponent implements AfterViewInit{ @ViewChild(EventTableComponent, {static: true}) eventsTable: EventTableComponent; - readonly DebugEventType = DebugEventType; readonly debugEventTypes = DebugEventType; readonly EventType = EventType; - dialogTitle: string; - constructor(protected store: Store, protected router: Router, @Inject(MAT_DIALOG_DATA) public data: RuleNodeDebugDialogData, - protected dialogRef: MatDialogRef) { + protected dialogRef: MatDialogRef) { super(store, router, dialogRef); } diff --git a/ui-ngx/src/app/modules/home/components/home-components.module.ts b/ui-ngx/src/app/modules/home/components/home-components.module.ts index 6da26fb2c3..8a90c28878 100644 --- a/ui-ngx/src/app/modules/home/components/home-components.module.ts +++ b/ui-ngx/src/app/modules/home/components/home-components.module.ts @@ -204,6 +204,7 @@ import { EditApiKeyDescriptionPanelComponent } from '@home/components/api-key/ed import { ApiKeyGeneratedDialogComponent } from '@home/components/api-key/api-key-generated-dialog.component'; import { ApiKeysTableDialogComponent } from '@home/components/api-key/api-keys-table-dialog.component'; import { AuditLogFilterComponent } from "@home/components/audit-log/audit-log-filter.component"; +import { EventsDialogComponent } from '@home/components/event/events-dialog.component'; @NgModule({ declarations: @@ -361,7 +362,8 @@ import { AuditLogFilterComponent } from "@home/components/audit-log/audit-log-fi EditApiKeyDescriptionPanelComponent, ApiKeyGeneratedDialogComponent, AuditLogHeaderComponent, - AuditLogFilterComponent + AuditLogFilterComponent, + EventsDialogComponent ], imports: [ CommonModule, @@ -510,6 +512,7 @@ import { AuditLogFilterComponent } from "@home/components/audit-log/audit-log-fi ResourcesLibraryComponent, ApiKeysTableComponent, ApiKeysTableDialogComponent, + EventsDialogComponent ], providers: [ WidgetComponentService, diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts index 53e2563ee2..3123719f22 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts @@ -100,7 +100,7 @@ import { EntityDebugSettings } from '@shared/models/entity.models'; import Timeout = NodeJS.Timeout; import { DomSanitizer } from '@angular/platform-browser'; import { AdditionalDebugActionConfig } from '@home/components/entity/debug/entity-debug-settings.model'; -import { RuleNodeDebugDialogComponent } from '@home/pages/rulechain/rule-node-debug-dialog.component'; +import { EventsDialogComponent } from '@home/components/event/events-dialog.component'; @Component({ selector: 'tb-rulechain-page', @@ -1674,13 +1674,13 @@ export class RuleChainPageComponent extends PageComponent } private openDebugEventsDialog(): void { - this.dialog.open(RuleNodeDebugDialogComponent, { + this.dialog.open(EventsDialogComponent, { disableClose: true, panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], data: { - active: true, + title: 'rulenode.events', tenantId: this.ruleChain.tenantId, - ruleNodeId: this.editingRuleNode.ruleNodeId, + entityId: this.editingRuleNode.ruleNodeId, functionTestButtonLabel: this.ruleNodeTestButtonLabel, debugEventSelected: this.onDebugEventSelected.bind(this) } diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.module.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.module.ts index 51197e1073..34518e2b70 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.module.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.module.ts @@ -33,7 +33,6 @@ import { RuleNodeDetailsComponent } from '@home/pages/rulechain/rule-node-detail import { RuleNodeConfigComponent } from '@home/pages/rulechain/rule-node-config.component'; import { LinkLabelsComponent } from '@home/pages/rulechain/link-labels.component'; import { RuleNodeLinkComponent } from '@home/pages/rulechain/rule-node-link.component'; -import { RuleNodeDebugDialogComponent } from '@home/pages/rulechain/rule-node-debug-dialog.component'; @NgModule({ declarations: [ @@ -44,8 +43,7 @@ import { RuleNodeDebugDialogComponent } from '@home/pages/rulechain/rule-node-de RuleNodeConfigComponent, AddRuleNodeLinkDialogComponent, AddRuleNodeDialogComponent, - CreateNestedRuleChainDialogComponent, - RuleNodeDebugDialogComponent + CreateNestedRuleChainDialogComponent ], imports: [ CommonModule, From 0d66c6b33e72877270a5aece61e850ac5c4e396b Mon Sep 17 00:00:00 2001 From: Maksym Tsymbarov Date: Fri, 5 Dec 2025 12:51:08 +0200 Subject: [PATCH 3/6] adjustments --- .../home/components/event/events-dialog.component.html | 4 ++-- .../home/components/event/events-dialog.component.ts | 6 ++---- .../home/pages/rulechain/rulechain-page.component.ts | 1 + 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/event/events-dialog.component.html b/ui-ngx/src/app/modules/home/components/event/events-dialog.component.html index 65040bcf60..7aa1f3dd7f 100644 --- a/ui-ngx/src/app/modules/home/components/event/events-dialog.component.html +++ b/ui-ngx/src/app/modules/home/components/event/events-dialog.component.html @@ -27,8 +27,8 @@
void; } @@ -42,9 +43,6 @@ export class EventsDialogComponent extends DialogComponent, protected router: Router, @Inject(MAT_DIALOG_DATA) public data: RuleNodeDebugDialogData, diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts index 3123719f22..163b4ff1f6 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts @@ -1679,6 +1679,7 @@ export class RuleChainPageComponent extends PageComponent panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], data: { title: 'rulenode.events', + debugEventType: DebugEventType.DEBUG_RULE_CHAIN, tenantId: this.ruleChain.tenantId, entityId: this.editingRuleNode.ruleNodeId, functionTestButtonLabel: this.ruleNodeTestButtonLabel, From 30e3c447f37d6072a8d445aae5c9fa76cc6bfa22 Mon Sep 17 00:00:00 2001 From: Maksym Tsymbarov Date: Mon, 8 Dec 2025 15:03:13 +0200 Subject: [PATCH 4/6] moved calculated-fields-table to use debug event modal --- .../alarm-rules/alarm-rules-table-config.ts | 24 ++++-- .../calculated-fields-table-config.ts | 29 +++++-- ...lculated-field-debug-dialog.component.html | 47 ----------- ...lculated-field-debug-dialog.component.scss | 26 ------- ...calculated-field-debug-dialog.component.ts | 77 ------------------- .../components/public-api.ts | 1 - .../home/components/home-components.module.ts | 6 +- .../events-dialog.component.html | 13 ++-- .../events-dialog.component.scss | 0 .../events-dialog.component.ts | 30 +++++--- .../rulechain/rulechain-page.component.ts | 11 +-- 11 files changed, 75 insertions(+), 189 deletions(-) delete mode 100644 ui-ngx/src/app/modules/home/components/calculated-fields/components/debug-dialog/calculated-field-debug-dialog.component.html delete mode 100644 ui-ngx/src/app/modules/home/components/calculated-fields/components/debug-dialog/calculated-field-debug-dialog.component.scss delete mode 100644 ui-ngx/src/app/modules/home/components/calculated-fields/components/debug-dialog/calculated-field-debug-dialog.component.ts rename ui-ngx/src/app/modules/home/{components/event => dialogs}/events-dialog.component.html (79%) rename ui-ngx/src/app/modules/home/{components/event => dialogs}/events-dialog.component.scss (100%) rename ui-ngx/src/app/modules/home/{components/event => dialogs}/events-dialog.component.ts (64%) diff --git a/ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rules-table-config.ts b/ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rules-table-config.ts index f73633ad8e..15c7cdaeb1 100644 --- a/ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rules-table-config.ts +++ b/ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rules-table-config.ts @@ -55,14 +55,12 @@ import { AlarmRuleDialogComponent, AlarmRuleDialogData } from "@home/components/alarm-rules/alarm-rule-dialog.component"; -import { - CalculatedFieldDebugDialogComponent, - CalculatedFieldDebugDialogData -} from "@home/components/calculated-fields/components/debug-dialog/calculated-field-debug-dialog.component"; import { AlarmSeverity, alarmSeverityTranslations } from "@shared/models/alarm.models"; import { UtilsService } from "@core/services/utils.service"; import { deepClone, getEntityDetailsPageURL, isObject } from "@core/utils"; import { AlarmRuleTableHeaderComponent } from "@home/components/alarm-rules/alarm-rule-table-header.component"; +import { EventsDialogComponent, EventsDialogData } from '@home/dialogs/events-dialog.component'; +import { DebugEventType, Event as DebugEvent, EventType } from '@shared/models/event.models'; import { ActionNotificationShow } from "@core/notification/notification.actions"; import { CalculatedFieldScriptTestDialogComponent, @@ -266,13 +264,25 @@ export class AlarmRulesTableConfig extends EntityTableConfig { } private openDebugEventsDialog(calculatedField: CalculatedField): void { - this.dialog.open(CalculatedFieldDebugDialogComponent, { + const customCellActionEnabledFn = (event: DebugEvent) => { + return (calculatedField.type === CalculatedFieldType.SCRIPT || + (calculatedField.type === CalculatedFieldType.PROPAGATION && + calculatedField.configuration.applyExpressionToResolvedArguments) + ) && !!(event as DebugEvent).body.arguments; + }; + + this.dialog.open(EventsDialogComponent, { disableClose: true, panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], data: { + title: 'alarm-rule.debugging', tenantId: this.tenantId, - value: calculatedField, - getTestScriptDialogFn: null, + value: calculatedField.id, + debugEventTypes:[DebugEventType.DEBUG_CALCULATED_FIELD], + disabledEventTypes:[EventType.LC_EVENT, EventType.ERROR, EventType.STATS], + defaultEventType: DebugEventType.DEBUG_CALCULATED_FIELD, + onDebugEventSelected: null, + customCellActionEnabledFn: customCellActionEnabledFn } }) .afterClosed() 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 98e4a29549..f024e1c88c 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 @@ -22,7 +22,7 @@ import { import { EntityType, entityTypeTranslations } from '@shared/models/entity-type.models'; import { TranslateService } from '@ngx-translate/core'; import { Direction } from '@shared/models/page/sort-order'; -import { MatDialog } from '@angular/material/dialog'; +import { MatDialog, MatDialogRef } from '@angular/material/dialog'; import { PageLink } from '@shared/models/page/page-link'; import { EMPTY, Observable, of } from 'rxjs'; import { PageData } from '@shared/models/page/page-data'; @@ -48,8 +48,6 @@ import { PropagationWithExpression, } from '@shared/models/calculated-field.models'; import { - CalculatedFieldDebugDialogComponent, - CalculatedFieldDebugDialogData, CalculatedFieldDialogComponent, CalculatedFieldDialogData, CalculatedFieldScriptTestDialogComponent, @@ -61,6 +59,8 @@ import { EntityDebugSettingsService } from '@home/components/entity/debug/entity import { DatePipe } from '@angular/common'; import { UtilsService } from "@core/services/utils.service"; import { ActionNotificationShow } from "@core/notification/notification.actions"; +import { CalculatedFieldEventBody, DebugEventType, Event as DebugEvent, EventType } from '@shared/models/event.models'; +import { EventsDialogComponent, EventsDialogData } from '@home/dialogs/events-dialog.component'; export class CalculatedFieldsTableConfig extends EntityTableConfig { @@ -233,13 +233,30 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig(CalculatedFieldDebugDialogComponent, { + const customCellActionEnabledFn = (event: DebugEvent) => { + return (calculatedField.type === CalculatedFieldType.SCRIPT || + (calculatedField.type === CalculatedFieldType.PROPAGATION && + calculatedField.configuration.applyExpressionToResolvedArguments) + ) && !!(event as DebugEvent).body.arguments; + }; + + const onDebugEventSelected = (event: CalculatedFieldEventBody, dialogRef: MatDialogRef) => { + this.getTestScriptDialog(calculatedField, JSON.parse(event.arguments)) + .subscribe(expression => dialogRef.close(expression)); + }; + + this.dialog.open(EventsDialogComponent, { disableClose: true, panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], data: { + title: 'alarm-rule.debugging', tenantId: this.tenantId, - value: calculatedField, - getTestScriptDialogFn: this.getTestScriptDialog.bind(this), + value: calculatedField.id, + debugEventTypes:[DebugEventType.DEBUG_CALCULATED_FIELD], + disabledEventTypes:[EventType.LC_EVENT, EventType.ERROR, EventType.STATS], + defaultEventType: DebugEventType.DEBUG_CALCULATED_FIELD, + onDebugEventSelected: onDebugEventSelected, + customCellActionEnabledFn: customCellActionEnabledFn } }) .afterClosed() 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 deleted file mode 100644 index 168657b8cb..0000000000 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/debug-dialog/calculated-field-debug-dialog.component.html +++ /dev/null @@ -1,47 +0,0 @@ - -
- -

{{ dialogTitle | translate}}

- - -
-
- -
-
- -
-
diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/debug-dialog/calculated-field-debug-dialog.component.scss b/ui-ngx/src/app/modules/home/components/calculated-fields/components/debug-dialog/calculated-field-debug-dialog.component.scss deleted file mode 100644 index c4798d06f9..0000000000 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/debug-dialog/calculated-field-debug-dialog.component.scss +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright © 2016-2025 The Thingsboard Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -:host { - .debug-dialog-container { - width: 1080px; - max-width: 100%; - - .debug-dialog-content { - height: 65vh; - border-radius: 0; - } - } -} 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 deleted file mode 100644 index 70bfa43c63..0000000000 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/debug-dialog/calculated-field-debug-dialog.component.ts +++ /dev/null @@ -1,77 +0,0 @@ -/// -/// Copyright © 2016-2025 The Thingsboard Authors -/// -/// Licensed under the Apache License, Version 2.0 (the "License"); -/// you may not use this file except in compliance with the License. -/// You may obtain a copy of the License at -/// -/// http://www.apache.org/licenses/LICENSE-2.0 -/// -/// Unless required by applicable law or agreed to in writing, software -/// distributed under the License is distributed on an "AS IS" BASIS, -/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -/// See the License for the specific language governing permissions and -/// limitations under the License. -/// - -import { AfterViewInit, Component, Inject, ViewChild } from '@angular/core'; -import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; -import { Store } from '@ngrx/store'; -import { AppState } from '@core/core.state'; -import { Router } from '@angular/router'; -import { DialogComponent } from '@shared/components/dialog.component'; -import { CalculatedFieldEventBody, DebugEventType, Event, EventType } from '@shared/models/event.models'; -import { EventTableComponent } from '@home/components/event/event-table.component'; -import { - CalculatedField, - CalculatedFieldTestScriptFn, - CalculatedFieldType -} from '@shared/models/calculated-field.models'; - -export interface CalculatedFieldDebugDialogData { - tenantId: string; - value: CalculatedField; - getTestScriptDialogFn: CalculatedFieldTestScriptFn; -} - -@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 { - - @ViewChild(EventTableComponent, {static: true}) eventsTable: EventTableComponent; - - readonly DebugEventType = DebugEventType; - readonly debugEventTypes = DebugEventType; - readonly EventType = EventType; - - dialogTitle: string; - - constructor(protected store: Store, - protected router: Router, - @Inject(MAT_DIALOG_DATA) public data: CalculatedFieldDebugDialogData, - protected dialogRef: MatDialogRef) { - super(store, router, dialogRef); - this.dialogTitle = this.data.value.type === CalculatedFieldType.ALARM ? 'alarm-rule.debugging' : 'calculated-fields.debugging'; - } - - ngAfterViewInit(): void { - this.eventsTable.entitiesTable.cellActionDescriptors[0].isEnabled = (event => { - return (this.data.value.type === CalculatedFieldType.SCRIPT || - (this.data.value.type === CalculatedFieldType.PROPAGATION && this.data.value.configuration.applyExpressionToResolvedArguments) - ) && !!(event as Event).body.arguments - }); - this.eventsTable.entitiesTable.updateData(); - } - - cancel(): void { - this.dialogRef.close(null); - } - - onDebugEventSelected(event: CalculatedFieldEventBody): void { - this.data.getTestScriptDialogFn(this.data.value, JSON.parse(event.arguments)) - .subscribe(expression => this.dialogRef.close(expression)); - } -} diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/public-api.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/components/public-api.ts index d4d4f9d1da..f114fd4d67 100644 --- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/public-api.ts +++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/public-api.ts @@ -15,5 +15,4 @@ /// export * from './dialog/calculated-field-dialog.component'; -export * from './debug-dialog/calculated-field-debug-dialog.component'; export * from './test-dialog/calculated-field-script-test-dialog.component'; diff --git a/ui-ngx/src/app/modules/home/components/home-components.module.ts b/ui-ngx/src/app/modules/home/components/home-components.module.ts index 8a90c28878..b159b9240c 100644 --- a/ui-ngx/src/app/modules/home/components/home-components.module.ts +++ b/ui-ngx/src/app/modules/home/components/home-components.module.ts @@ -192,9 +192,6 @@ import { AIModelDialogComponent } from '@home/components/ai-model/ai-model-dialo import { ResourcesDialogComponent } from "@home/components/resources/resources-dialog.component"; import { ResourcesLibraryComponent } from "@home/components/resources/resources-library.component"; import { CalculatedFieldsTableComponent } from '@home/components/calculated-fields/calculated-fields-table.component'; -import { - CalculatedFieldDebugDialogComponent -} from '@home/components/calculated-fields/components/debug-dialog/calculated-field-debug-dialog.component'; import { CalculatedFieldsModule } from '@home/components/calculated-fields/calculated-field.module'; import { AlarmRuleModule } from "@home/components/alarm-rules/alarm-rule.module"; import { AlarmRulesTableComponent } from "@home/components/alarm-rules/alarm-rules-table.component"; @@ -204,7 +201,7 @@ import { EditApiKeyDescriptionPanelComponent } from '@home/components/api-key/ed import { ApiKeyGeneratedDialogComponent } from '@home/components/api-key/api-key-generated-dialog.component'; import { ApiKeysTableDialogComponent } from '@home/components/api-key/api-keys-table-dialog.component'; import { AuditLogFilterComponent } from "@home/components/audit-log/audit-log-filter.component"; -import { EventsDialogComponent } from '@home/components/event/events-dialog.component'; +import { EventsDialogComponent } from '@home/dialogs/events-dialog.component'; @NgModule({ declarations: @@ -218,7 +215,6 @@ import { EventsDialogComponent } from '@home/components/event/events-dialog.comp AuditLogTableComponent, AuditLogDetailsDialogComponent, CalculatedFieldsTableComponent, - CalculatedFieldDebugDialogComponent, AlarmRulesTableComponent, EventContentDialogComponent, EventTableHeaderComponent, diff --git a/ui-ngx/src/app/modules/home/components/event/events-dialog.component.html b/ui-ngx/src/app/modules/home/dialogs/events-dialog.component.html similarity index 79% rename from ui-ngx/src/app/modules/home/components/event/events-dialog.component.html rename to ui-ngx/src/app/modules/home/dialogs/events-dialog.component.html index 7aa1f3dd7f..5197f6bb4e 100644 --- a/ui-ngx/src/app/modules/home/components/event/events-dialog.component.html +++ b/ui-ngx/src/app/modules/home/dialogs/events-dialog.component.html @@ -27,13 +27,14 @@
diff --git a/ui-ngx/src/app/modules/home/components/event/events-dialog.component.scss b/ui-ngx/src/app/modules/home/dialogs/events-dialog.component.scss similarity index 100% rename from ui-ngx/src/app/modules/home/components/event/events-dialog.component.scss rename to ui-ngx/src/app/modules/home/dialogs/events-dialog.component.scss diff --git a/ui-ngx/src/app/modules/home/components/event/events-dialog.component.ts b/ui-ngx/src/app/modules/home/dialogs/events-dialog.component.ts similarity index 64% rename from ui-ngx/src/app/modules/home/components/event/events-dialog.component.ts rename to ui-ngx/src/app/modules/home/dialogs/events-dialog.component.ts index 30e8a0f4f1..613f4e9c15 100644 --- a/ui-ngx/src/app/modules/home/components/event/events-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/dialogs/events-dialog.component.ts @@ -21,17 +21,20 @@ import { EventTableComponent } from '@home/components/event/event-table.componen import { Store } from '@ngrx/store'; import { AppState } from '@core/core.state'; import { Router } from '@angular/router'; -import { DebugEventType } from '@shared/models/event.models'; -import { TenantId } from '@shared/models/id/tenant-id'; +import { DebugEventType, EventType } from '@shared/models/event.models'; import { EntityId } from '@shared/models/id/entity-id'; +import { BaseData, HasId } from '@shared/models/base-data'; -export interface RuleNodeDebugDialogData { +export interface EventsDialogData { title: string; - tenantId: TenantId; - entityId: EntityId; - debugEventType: DebugEventType; - functionTestButtonLabel: string; - onDebugEventSelected: ()=> void; + tenantId: string; + value: EntityId; + debugEventTypes: Array; + defaultEventType: DebugEventType; + disabledEventTypes?: Array; + functionTestButtonLabel?: string; + onDebugEventSelected?: (event: any, dialogRef: MatDialogRef) => void; + customCellActionEnabledFn?: (event: BaseData) => boolean; } @Component({ @@ -45,16 +48,25 @@ export class EventsDialogComponent extends DialogComponent, protected router: Router, - @Inject(MAT_DIALOG_DATA) public data: RuleNodeDebugDialogData, + @Inject(MAT_DIALOG_DATA) public data: EventsDialogData, protected dialogRef: MatDialogRef) { super(store, router, dialogRef); } ngAfterViewInit() { + if (this.data.customCellActionEnabledFn && this.eventsTable.entitiesTable.cellActionDescriptors?.length > 0) { + this.eventsTable.entitiesTable.cellActionDescriptors[0].isEnabled = this.data.customCellActionEnabledFn; + } this.eventsTable.entitiesTable.updateData(); } cancel(): void { this.dialogRef.close(null); } + + onDebugEventSelected(event: any): void { + if(this.data.onDebugEventSelected) { + this.data.onDebugEventSelected(event, this.dialogRef); + } + } } diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts index 163b4ff1f6..aa2b4fd3eb 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts @@ -100,7 +100,7 @@ import { EntityDebugSettings } from '@shared/models/entity.models'; import Timeout = NodeJS.Timeout; import { DomSanitizer } from '@angular/platform-browser'; import { AdditionalDebugActionConfig } from '@home/components/entity/debug/entity-debug-settings.model'; -import { EventsDialogComponent } from '@home/components/event/events-dialog.component'; +import { EventsDialogComponent } from '@home/dialogs/events-dialog.component'; @Component({ selector: 'tb-rulechain-page', @@ -1679,11 +1679,12 @@ export class RuleChainPageComponent extends PageComponent panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], data: { title: 'rulenode.events', - debugEventType: DebugEventType.DEBUG_RULE_CHAIN, - tenantId: this.ruleChain.tenantId, - entityId: this.editingRuleNode.ruleNodeId, + debugEventTypes: [DebugEventType.DEBUG_RULE_CHAIN], + defaultEventType: DebugEventType.DEBUG_RULE_CHAIN, + tenantId: this.ruleChain.tenantId.id, + value: this.editingRuleNode.ruleNodeId, functionTestButtonLabel: this.ruleNodeTestButtonLabel, - debugEventSelected: this.onDebugEventSelected.bind(this) + onDebugEventSelected: this.onDebugEventSelected.bind(this) } }) .afterClosed() From ece81a14770c2028d75182a4af666a3685cd1c67 Mon Sep 17 00:00:00 2001 From: Maksym Tsymbarov Date: Mon, 8 Dec 2025 17:01:22 +0200 Subject: [PATCH 5/6] moved fixed rulenode DebugEventType --- .../calculated-fields/calculated-fields-table-config.ts | 2 +- .../modules/home/pages/rulechain/rulechain-page.component.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 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 f024e1c88c..18dcb28a2e 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 @@ -249,7 +249,7 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig Date: Mon, 8 Dec 2025 18:13:30 +0200 Subject: [PATCH 6/6] fixes --- .../alarm-rules/alarm-rules-table-config.ts | 12 ++---------- .../calculated-fields-table-config.ts | 8 ++++---- .../home/dialogs/events-dialog.component.html | 2 +- .../modules/home/dialogs/events-dialog.component.ts | 8 ++++---- .../home/pages/rulechain/rulechain-page.component.ts | 2 +- 5 files changed, 12 insertions(+), 20 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rules-table-config.ts b/ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rules-table-config.ts index 15c7cdaeb1..0cb6069ee9 100644 --- a/ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rules-table-config.ts +++ b/ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rules-table-config.ts @@ -264,25 +264,17 @@ export class AlarmRulesTableConfig extends EntityTableConfig { } private openDebugEventsDialog(calculatedField: CalculatedField): void { - const customCellActionEnabledFn = (event: DebugEvent) => { - return (calculatedField.type === CalculatedFieldType.SCRIPT || - (calculatedField.type === CalculatedFieldType.PROPAGATION && - calculatedField.configuration.applyExpressionToResolvedArguments) - ) && !!(event as DebugEvent).body.arguments; - }; - this.dialog.open(EventsDialogComponent, { disableClose: true, panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], data: { title: 'alarm-rule.debugging', tenantId: this.tenantId, - value: calculatedField.id, + entityId: calculatedField.id, debugEventTypes:[DebugEventType.DEBUG_CALCULATED_FIELD], disabledEventTypes:[EventType.LC_EVENT, EventType.ERROR, EventType.STATS], defaultEventType: DebugEventType.DEBUG_CALCULATED_FIELD, - onDebugEventSelected: null, - customCellActionEnabledFn: customCellActionEnabledFn + debugActionEnabledFn: () => false } }) .afterClosed() 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 18dcb28a2e..60c2878802 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 @@ -233,7 +233,7 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig { + const debugActionEnabledFn = (event: DebugEvent) => { return (calculatedField.type === CalculatedFieldType.SCRIPT || (calculatedField.type === CalculatedFieldType.PROPAGATION && calculatedField.configuration.applyExpressionToResolvedArguments) @@ -251,12 +251,12 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig diff --git a/ui-ngx/src/app/modules/home/dialogs/events-dialog.component.ts b/ui-ngx/src/app/modules/home/dialogs/events-dialog.component.ts index 613f4e9c15..d5339de3b2 100644 --- a/ui-ngx/src/app/modules/home/dialogs/events-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/dialogs/events-dialog.component.ts @@ -28,13 +28,13 @@ import { BaseData, HasId } from '@shared/models/base-data'; export interface EventsDialogData { title: string; tenantId: string; - value: EntityId; + entityId: EntityId; debugEventTypes: Array; defaultEventType: DebugEventType; disabledEventTypes?: Array; functionTestButtonLabel?: string; onDebugEventSelected?: (event: any, dialogRef: MatDialogRef) => void; - customCellActionEnabledFn?: (event: BaseData) => boolean; + debugActionEnabledFn?: (event: BaseData) => boolean; } @Component({ @@ -54,8 +54,8 @@ export class EventsDialogComponent extends DialogComponent 0) { - this.eventsTable.entitiesTable.cellActionDescriptors[0].isEnabled = this.data.customCellActionEnabledFn; + if (this.data.debugActionEnabledFn && this.eventsTable.entitiesTable.cellActionDescriptors?.length > 0) { + this.eventsTable.entitiesTable.cellActionDescriptors[0].isEnabled = this.data.debugActionEnabledFn; } this.eventsTable.entitiesTable.updateData(); } diff --git a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts index b1cf2eddf2..7f751a0bfe 100644 --- a/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts +++ b/ui-ngx/src/app/modules/home/pages/rulechain/rulechain-page.component.ts @@ -1682,7 +1682,7 @@ export class RuleChainPageComponent extends PageComponent debugEventTypes: [DebugEventType.DEBUG_RULE_NODE], defaultEventType: DebugEventType.DEBUG_RULE_NODE, tenantId: this.ruleChain.tenantId.id, - value: this.editingRuleNode.ruleNodeId, + entityId: this.editingRuleNode.ruleNodeId, functionTestButtonLabel: this.ruleNodeTestButtonLabel, onDebugEventSelected: this.onDebugEventSelected.bind(this) }