From 706b02295de2c36fcb68648df67d412cfc1a0e75 Mon Sep 17 00:00:00 2001 From: Vladyslav Prykhodko Date: Fri, 19 Dec 2025 23:52:57 +0200 Subject: [PATCH] UI: Fixed edit cf and refactor cf models and service --- .../core/http/calculated-fields.service.ts | 16 +++--- .../alarm-rules/alarm-rules-table-config.ts | 43 +++++++++------- .../calculated-fields-table-config.ts | 50 ++++++++++--------- .../entity/entity-subtype-list.component.ts | 11 ++-- .../shared/models/calculated-field.models.ts | 2 + 5 files changed, 63 insertions(+), 59 deletions(-) diff --git a/ui-ngx/src/app/core/http/calculated-fields.service.ts b/ui-ngx/src/app/core/http/calculated-fields.service.ts index 0fba704277..f3bab62cd2 100644 --- a/ui-ngx/src/app/core/http/calculated-fields.service.ts +++ b/ui-ngx/src/app/core/http/calculated-fields.service.ts @@ -15,17 +15,13 @@ /// import { Injectable } from '@angular/core'; -import { - createDefaultHttpOptions, - defaultHttpOptionsFromConfig, - defaultHttpOptionsFromParams, - RequestConfig -} from './http-utils'; +import { defaultHttpOptionsFromConfig, defaultHttpOptionsFromParams, RequestConfig } from './http-utils'; import { Observable } from 'rxjs'; import { HttpClient } from '@angular/common/http'; import { PageData } from '@shared/models/page/page-data'; import { CalculatedField, + CalculatedFieldInfo, CalculatedFieldsQuery, CalculatedFieldTestScriptInputParams, CalculatedFieldType @@ -56,11 +52,11 @@ export class CalculatedFieldsService { return this.http.delete(`/api/calculatedField/${calculatedFieldId}`, defaultHttpOptionsFromConfig(config)); } - public getCalculatedFieldsFilter(pageLink: PageLink, query: CalculatedFieldsQuery, config?: RequestConfig): Observable> { - return this.http.get>(`/api/calculatedFields${pageLink.toQuery()}`, defaultHttpOptionsFromParams(query, config)); + public getCalculatedFields(pageLink: PageLink, query: CalculatedFieldsQuery, config?: RequestConfig): Observable> { + return this.http.get>(`/api/calculatedFields${pageLink.toQuery()}`, defaultHttpOptionsFromParams(query, config)); } - public getCalculatedFields({ entityType, id }: EntityId, pageLink: PageLink, type?: CalculatedFieldType, config?: RequestConfig): Observable> { + public getCalculatedFieldsByEntityId({ entityType, id }: EntityId, pageLink: PageLink, type?: CalculatedFieldType, config?: RequestConfig): Observable> { return this.http.get>(`/api/${entityType}/${id}/calculatedFields${pageLink.toQuery()}`, defaultHttpOptionsFromParams({type} , config)); } @@ -72,7 +68,7 @@ export class CalculatedFieldsService { return this.http.get(`/api/calculatedField/${id}/debug`, defaultHttpOptionsFromConfig(config)); } - public getAlarmRuleNames(pageLink: PageLink, type: CalculatedFieldType, config?: RequestConfig): Observable> { + public getCalculatedFieldNames(pageLink: PageLink, type: CalculatedFieldType, config?: RequestConfig): Observable> { return this.http.get>(`/api/calculatedFields/names${pageLink.toQuery()}`, defaultHttpOptionsFromParams({type}, config)); } } 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 f1bd30d853..46d43f2921 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 @@ -43,6 +43,7 @@ import { CalculatedField, CalculatedFieldAlarmRule, CalculatedFieldEventArguments, + CalculatedFieldInfo, CalculatedFieldsQuery, CalculatedFieldType, getCalculatedFieldArgumentsEditorCompleter, @@ -67,12 +68,14 @@ import { CalculatedFieldTestScriptDialogData } from "@home/components/calculated-fields/components/test-dialog/calculated-field-script-test-dialog.component"; -export class AlarmRulesTableConfig extends EntityTableConfig { +type AlarmRuleTableEntity = CalculatedField | CalculatedFieldInfo; + +export class AlarmRulesTableConfig extends EntityTableConfig { readonly tenantId = getCurrentAuthUser(this.store).tenantId; additionalDebugActionConfig = { title: this.translate.instant('action.see-debug-events'), - action: (calculatedField: CalculatedField) => this.openDebugEventsDialog.call(this, calculatedField), + action: (calculatedField: AlarmRuleTableEntity) => this.openDebugEventsDialog.call(this, calculatedField), }; alarmRuleFilterConfig: CalculatedFieldsQuery; @@ -81,11 +84,11 @@ export class AlarmRulesTableConfig extends EntityTableConfig { private translate: TranslateService, private dialog: MatDialog, private datePipe: DatePipe, - public entityId: EntityId = null, + private entityId: EntityId = null, private store: Store, private destroyRef: DestroyRef, private renderer: Renderer2, - public entityName: string, + private entityName: string, private ownerId: EntityId = null, private importExportService: ImportExportService, private entityDebugSettingsService: EntityDebugSettingsService, @@ -118,7 +121,7 @@ export class AlarmRulesTableConfig extends EntityTableConfig { this.entitiesFetchFunction = (pageLink: PageLink) => this.fetchCalculatedFields(pageLink); this.addEntity = this.getCalculatedAlarmDialog.bind(this); - this.deleteEntityTitle = (field: CalculatedField) => this.translate.instant('alarm-rule.delete-title', {title: field.name}); + this.deleteEntityTitle = (field) => this.translate.instant('alarm-rule.delete-title', {title: field.name}); this.deleteEntityContent = () => this.translate.instant('alarm-rule.delete-text'); this.deleteEntitiesTitle = count => this.translate.instant('alarm-rule.delete-multiple-title', {count}); this.deleteEntitiesContent = () => this.translate.instant('alarm-rule.delete-multiple-text'); @@ -143,10 +146,10 @@ export class AlarmRulesTableConfig extends EntityTableConfig { this.columns.push(new EntityTableColumn('name', 'alarm-rule.alarm-type', '33%', entity => this.utilsService.customTranslation(entity.name, entity.name))); if (this.pageMode) { - this.columns.push(new EntityTableColumn('entityType', 'entity.entity-type', '10%', + this.columns.push(new EntityTableColumn('entityType', 'entity.entity-type', '10%', entity => this.translate.instant(entityTypeTranslations.get(entity.entityId.entityType).type))); - this.columns.push(new EntityLinkTableColumn('entityName', 'entity.entity', '33%', - entity => this.utilsService.customTranslation(entity['entityName'], entity['entityName']), + this.columns.push(new EntityLinkTableColumn('entityName', 'entity.entity', '33%', + entity => this.utilsService.customTranslation(entity.entityName, entity.entityName), entity => getEntityDetailsPageURL(entity.entityId?.id, entity.entityId?.entityType as EntityType), false)); } this.columns.push(new EntityTableColumn('createRule', 'alarm-rule.severities', this.pageMode ? '23%' : '67%', @@ -193,13 +196,13 @@ export class AlarmRulesTableConfig extends EntityTableConfig { ); } - fetchCalculatedFields(pageLink: PageLink): Observable> { + fetchCalculatedFields(pageLink: PageLink): Observable> { return this.pageMode ? - this.calculatedFieldsService.getCalculatedFieldsFilter(pageLink, {types: [CalculatedFieldType.ALARM], ...this.alarmRuleFilterConfig}) : - this.calculatedFieldsService.getCalculatedFields(this.entityId, pageLink, CalculatedFieldType.ALARM); + this.calculatedFieldsService.getCalculatedFields(pageLink, {types: [CalculatedFieldType.ALARM], ...this.alarmRuleFilterConfig}) : + this.calculatedFieldsService.getCalculatedFieldsByEntityId(this.entityId, pageLink, CalculatedFieldType.ALARM); } - onOpenDebugConfig($event: Event, calculatedField: CalculatedField): void { + onOpenDebugConfig($event: Event, calculatedField: AlarmRuleTableEntity): void { $event?.stopPropagation(); const { debugSettings = {}, id } = calculatedField; const additionalActionConfig = { @@ -224,7 +227,7 @@ export class AlarmRulesTableConfig extends EntityTableConfig { }, $event.target as Element); } - private editCalculatedField($event: Event, calculatedField: CalculatedField, isDirty = false): void { + private editCalculatedField($event: Event, calculatedField: AlarmRuleTableEntity, isDirty = false): void { $event?.stopPropagation(); this.getCalculatedAlarmDialog(calculatedField, 'action.apply', isDirty) .subscribe((res) => { @@ -234,11 +237,12 @@ export class AlarmRulesTableConfig extends EntityTableConfig { }); } - private copyCalculatedField($event: Event, calculatedField: CalculatedField, isDirty = false): void { + private copyCalculatedField($event: Event, calculatedField: AlarmRuleTableEntity, isDirty = false): void { $event?.stopPropagation(); const copyCalculatedAlarmRule = deepClone(calculatedField); if (this.pageMode) { copyCalculatedAlarmRule.entityId = null; + delete (copyCalculatedAlarmRule as CalculatedFieldInfo).entityName; } delete copyCalculatedAlarmRule.id; this.getCalculatedAlarmDialog(copyCalculatedAlarmRule, 'action.apply', isDirty) @@ -249,8 +253,9 @@ export class AlarmRulesTableConfig extends EntityTableConfig { }); } - private getCalculatedAlarmDialog(value?: CalculatedField, buttonTitle = 'action.add', isDirty = false): Observable { + private getCalculatedAlarmDialog(value?: AlarmRuleTableEntity, buttonTitle = 'action.add', isDirty = false): Observable { const entityId = this.entityId || value?.entityId; + const entityName = this.entityName || (value as CalculatedFieldInfo)?.entityName; return this.dialog.open(AlarmRuleDialogComponent, { disableClose: true, panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], @@ -258,8 +263,8 @@ export class AlarmRulesTableConfig extends EntityTableConfig { value, buttonTitle, entityId, + entityName, tenantId: this.tenantId, - entityName: this.entityName, ownerId: this.ownerId ?? {entityType: EntityType.TENANT, id: this.tenantId}, additionalDebugActionConfig: this.additionalDebugActionConfig, isDirty, @@ -271,7 +276,7 @@ export class AlarmRulesTableConfig extends EntityTableConfig { .pipe(filter(Boolean)); } - private openDebugEventsDialog($event: Event, calculatedField: CalculatedField): void { + private openDebugEventsDialog($event: Event, calculatedField: AlarmRuleTableEntity): void { $event?.stopPropagation(); this.dialog.open(EventsDialogComponent, { disableClose: true, @@ -290,7 +295,7 @@ export class AlarmRulesTableConfig extends EntityTableConfig { .subscribe(); } - private exportAlarmRule($event: Event, calculatedField: CalculatedField): void { + private exportAlarmRule($event: Event, calculatedField: AlarmRuleTableEntity): void { $event?.stopPropagation(); this.importExportService.exportCalculatedField(calculatedField.id.id); } @@ -343,7 +348,7 @@ export class AlarmRulesTableConfig extends EntityTableConfig { ).subscribe(() => this.updateData()); } - private getTestScriptDialog(calculatedField: CalculatedField, expression: string, argumentsObj?: CalculatedFieldEventArguments, openCalculatedFieldEdit = true): Observable { + private getTestScriptDialog(calculatedField: AlarmRuleTableEntity, expression: string, argumentsObj?: CalculatedFieldEventArguments, openCalculatedFieldEdit = true): Observable { if (calculatedField.type === CalculatedFieldType.ALARM) { const resultArguments = Object.keys(calculatedField.configuration.arguments).reduce((acc, key) => { const type = calculatedField.configuration.arguments[key].refEntityKey.type; 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 e5c57aae2e..8385b5cb45 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 @@ -40,8 +40,8 @@ import { ArgumentEntityType, ArgumentType, CalculatedField, - CalculatedFieldAlarmRule, CalculatedFieldEventArguments, + CalculatedFieldInfo, CalculatedFieldScriptConfiguration, CalculatedFieldsQuery, CalculatedFieldType, @@ -68,12 +68,14 @@ import { CalculatedFieldsHeaderComponent } from '@home/components/calculated-fields/table-header/calculated-fields-header.component'; -export class CalculatedFieldsTableConfig extends EntityTableConfig { +type CalculatedFieldsTableEntity = CalculatedField | CalculatedFieldInfo; + +export class CalculatedFieldsTableConfig extends EntityTableConfig { readonly tenantId = getCurrentAuthUser(this.store).tenantId; additionalDebugActionConfig = { title: this.translate.instant('action.see-debug-events'), - action: (calculatedField: CalculatedField) => this.openDebugEventsDialog.call(this, null, calculatedField), + action: (calculatedField: CalculatedFieldsTableEntity) => this.openDebugEventsDialog.call(this, null, calculatedField), }; calculatedFieldFilterConfig: CalculatedFieldsQuery; @@ -82,11 +84,11 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig, private destroyRef: DestroyRef, private renderer: Renderer2, - public entityName: string, + private entityName: string, private ownerId: EntityId = null, private importExportService: ImportExportService, private entityDebugSettingsService: EntityDebugSettingsService, @@ -110,7 +112,7 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig this.fetchCalculatedFields(pageLink); this.addEntity = this.getCalculatedFieldDialog.bind(this); - this.deleteEntityTitle = (field: CalculatedField) => this.translate.instant('calculated-fields.delete-title', {title: field.name}); + this.deleteEntityTitle = (field) => 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}); this.deleteEntitiesContent = () => this.translate.instant('calculated-fields.delete-multiple-text'); @@ -136,10 +138,10 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig('name', 'common.name', this.pageMode ? '33%' : '60%', entity => this.utilsService.customTranslation(entity.name, entity.name))); if (this.pageMode) { - this.columns.push(new EntityTableColumn('entityType', 'entity.entity-type', '10%', + this.columns.push(new EntityTableColumn('entityType', 'entity.entity-type', '10%', entity => this.translate.instant(entityTypeTranslations.get(entity.entityId.entityType).type))); - this.columns.push(new EntityLinkTableColumn('entityName', 'entity.entity', '33%', - entity => this.utilsService.customTranslation(entity['entityName'], entity['entityName']), + this.columns.push(new EntityLinkTableColumn('entityName', 'entity.entity', '33%', + entity => this.utilsService.customTranslation(entity.entityName, entity.entityName), entity => getEntityDetailsPageURL(entity.entityId?.id, entity.entityId?.entityType as EntityType), false)); } this.columns.push(new EntityTableColumn('type', 'common.type', this.pageMode ? '23%' : '40%', entity => this.translate.instant(CalculatedFieldTypeTranslations.get(entity.type).name), () => ({whiteSpace: 'nowrap' }))); @@ -180,13 +182,13 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig> { + fetchCalculatedFields(pageLink: PageLink): Observable> { return this.pageMode ? - this.calculatedFieldsService.getCalculatedFieldsFilter(pageLink, this.calculatedFieldFilterConfig): - this.calculatedFieldsService.getCalculatedFields(this.entityId, pageLink); + this.calculatedFieldsService.getCalculatedFields(pageLink, this.calculatedFieldFilterConfig): + this.calculatedFieldsService.getCalculatedFieldsByEntityId(this.entityId, pageLink); } - onOpenDebugConfig($event: Event, calculatedField: CalculatedField): void { + onOpenDebugConfig($event: Event, calculatedField: CalculatedFieldsTableEntity): void { $event?.stopPropagation(); const { debugSettings = {}, id } = calculatedField; const additionalActionConfig = { @@ -210,7 +212,7 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig { @@ -220,8 +222,9 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig { + private getCalculatedFieldDialog(value?: CalculatedFieldsTableEntity, buttonTitle = 'action.add', isDirty = false): Observable { const entityId = this.entityId || value?.entityId; + const entityName = this.entityName || (value as CalculatedFieldInfo)?.entityName; return this.dialog.open(CalculatedFieldDialogComponent, { disableClose: true, panelClass: ['tb-dialog', 'tb-fullscreen-dialog'], @@ -229,8 +232,8 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig { return (calculatedField.type === CalculatedFieldType.SCRIPT || @@ -274,19 +277,20 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig { if (res) { this.updateData(); @@ -350,7 +354,7 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig this.updateData()); } - private getTestScriptDialog(calculatedField: CalculatedField, argumentsObj?: CalculatedFieldEventArguments, openCalculatedFieldEdit = true, expression?: string): Observable { + private getTestScriptDialog(calculatedField: CalculatedFieldsTableEntity, argumentsObj?: CalculatedFieldEventArguments, openCalculatedFieldEdit = true, expression?: string): Observable { if ( calculatedField.type === CalculatedFieldType.SCRIPT || calculatedField.type === CalculatedFieldType.RELATED_ENTITIES_AGGREGATION || diff --git a/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts b/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts index dc89f05fde..05511095cf 100644 --- a/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts +++ b/ui-ngx/src/app/shared/components/entity/entity-subtype-list.component.ts @@ -14,7 +14,7 @@ /// limitations under the License. /// -import { AfterViewInit, Component, ElementRef, forwardRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core'; +import { Component, ElementRef, forwardRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core'; import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; import { Observable, ReplaySubject, Subscription, throwError } from 'rxjs'; import { debounceTime, map, mergeMap, share } from 'rxjs/operators'; @@ -46,7 +46,7 @@ import { CalculatedFieldsService } from "@core/http/calculated-fields.service"; } ] }) -export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit, AfterViewInit, OnDestroy { +export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit, OnDestroy { entitySubtypeListFormGroup: FormGroup; @@ -119,7 +119,7 @@ export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit, private dirty = false; - private propagateChange = (v: any) => { }; + private propagateChange = (_v: any) => { }; private hasPageDataEntitySubTypes = new Set([ EntityType.ALARM, @@ -225,9 +225,6 @@ export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit, ); } - ngAfterViewInit(): void { - } - ngOnDestroy(): void { if (this.broadcastSubscription) { this.broadcastSubscription.unsubscribe(); @@ -335,7 +332,7 @@ export class EntitySubTypeListComponent implements ControlValueAccessor, OnInit, subTypesPagesObservable = this.alarmService.getAlarmTypes(pageLink, {ignoreLoading: true}); break; case EntityType.CALCULATED_FIELD: - subTypesCfPagesObservable = this.calculatedFieldsService.getAlarmRuleNames(pageLink, CalculatedFieldType.ALARM, {ignoreLoading: true}); + subTypesCfPagesObservable = this.calculatedFieldsService.getCalculatedFieldNames(pageLink, CalculatedFieldType.ALARM, {ignoreLoading: true}); } if (subTypesPagesObservable) { this.entitySubtypes = subTypesPagesObservable.pipe( 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 5f07374cf8..825c08a69f 100644 --- a/ui-ngx/src/app/shared/models/calculated-field.models.ts +++ b/ui-ngx/src/app/shared/models/calculated-field.models.ts @@ -79,6 +79,8 @@ export type CalculatedField = | CalculatedFieldRelatedEntityAggregation | CalculatedFieldAlarmRule; +export type CalculatedFieldInfo = CalculatedField & {entityName: string}; + export enum CalculatedFieldType { SIMPLE = 'SIMPLE', SCRIPT = 'SCRIPT',