From 2bcb43911b5c8080615956e3b5bd4c290e9c263d Mon Sep 17 00:00:00 2001 From: Maksym Tsymbarov Date: Fri, 26 Jun 2026 16:43:47 +0200 Subject: [PATCH 1/3] Fixed false "Unsaved changes" popup on the Alarm rule details page --- .../cf-alarm-rule-condition.component.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule-condition.component.ts b/ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule-condition.component.ts index ef539af6f5..f9347d9961 100644 --- a/ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule-condition.component.ts +++ b/ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule-condition.component.ts @@ -143,19 +143,23 @@ export class CfAlarmRuleConditionComponent implements ControlValueAccessor, Vali ngOnChanges(changes: SimpleChanges) { if (changes.arguments && !changes.arguments.firstChange) { - this.recalculateArgumentValidity(); - this.onValidatorChange(); + if (this.recalculateArgumentValidity()) { + this.onValidatorChange(); + } } } - private recalculateArgumentValidity(): void { + private recalculateArgumentValidity(): boolean { + const prevFiltersValid = this.filtersArgumentsValid; + const prevSchedulerValid = this.schedulerArgumentsValid; if (!this.modelValue || !this.arguments) { this.filtersArgumentsValid = true; this.schedulerArgumentsValid = true; - return; + } else { + this.filtersArgumentsValid = this.areFilterAndPredicateArgumentsValid(this.modelValue, this.arguments); + this.schedulerArgumentsValid = this.isScheduleArgumentValid(this.modelValue, Object.keys(this.arguments)); } - this.filtersArgumentsValid = this.areFilterAndPredicateArgumentsValid(this.modelValue, this.arguments); - this.schedulerArgumentsValid = this.isScheduleArgumentValid(this.modelValue, Object.keys(this.arguments)); + return prevFiltersValid !== this.filtersArgumentsValid || prevSchedulerValid !== this.schedulerArgumentsValid; } private isScheduleArgumentValid(obj: any, validArguments: string[]): boolean { From 9038f3c9fd7c17f6034e9902c4a8d43acf048405 Mon Sep 17 00:00:00 2001 From: Maksym Tsymbarov Date: Mon, 29 Jun 2026 17:06:25 +0200 Subject: [PATCH 2/3] Fixed false "Unsaved changes" popup on the Alarm rule details page when a clear condition is present --- .../alarm-rules/cf-alarm-rule.component.ts | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule.component.ts b/ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule.component.ts index d9b7f868ac..ca1e58f774 100644 --- a/ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule.component.ts +++ b/ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule.component.ts @@ -25,7 +25,7 @@ import { Validators } from '@angular/forms'; import { MatDialog } from '@angular/material/dialog'; -import { isDefinedAndNotNull } from '@core/utils'; +import { isDefinedAndNotNull, isEqual } from '@core/utils'; import { DashboardId } from '@shared/models/id/dashboard-id'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { AlarmRule, AlarmRuleCondition } from "@shared/models/alarm-rule.models"; @@ -76,6 +76,7 @@ export class CfAlarmRuleComponent implements ControlValueAccessor, OnInit, Valid testScript: (expression: string) => Observable; private modelValue: AlarmRule; + private propagatedValue: AlarmRule; alarmRuleFormGroup = this.fb.group({ condition: this.fb.control(null, Validators.required), @@ -131,6 +132,7 @@ export class CfAlarmRuleComponent implements ControlValueAccessor, OnInit, Valid dashboardId: this.modelValue.dashboardId?.id } : null; this.alarmRuleFormGroup.patchValue(model, {emitEvent: false}); + this.propagatedValue = this.toModel(this.alarmRuleFormGroup.value); } public openEditDetailsDialog($event: Event) { @@ -161,8 +163,16 @@ export class CfAlarmRuleComponent implements ControlValueAccessor, OnInit, Valid } private updateModel() { - const value = this.alarmRuleFormGroup.value; - this.modelValue = {...value, dashboardId: value.dashboardId ? new DashboardId(value.dashboardId) : null} as AlarmRule; - this.propagateChange(this.modelValue); + const modelValue = this.toModel(this.alarmRuleFormGroup.value); + if (isEqual(modelValue, this.propagatedValue)) { + return; + } + this.modelValue = modelValue; + this.propagatedValue = modelValue; + this.propagateChange(modelValue); + } + + private toModel(value: any): AlarmRule { + return {...value, dashboardId: value.dashboardId ? new DashboardId(value.dashboardId) : null} as AlarmRule; } } From b79d3286e47cb60647d6ff8a240370e268ab8872 Mon Sep 17 00:00:00 2001 From: Maksym Tsymbarov Date: Fri, 3 Jul 2026 13:14:35 +0200 Subject: [PATCH 3/3] Fixed dashboardId being corrupted and dirty-check bypassed in alarm rule form --- .../alarm-rules/cf-alarm-rule.component.ts | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule.component.ts b/ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule.component.ts index ca1e58f774..f1e7367002 100644 --- a/ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule.component.ts +++ b/ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule.component.ts @@ -76,12 +76,11 @@ export class CfAlarmRuleComponent implements ControlValueAccessor, OnInit, Valid testScript: (expression: string) => Observable; private modelValue: AlarmRule; - private propagatedValue: AlarmRule; alarmRuleFormGroup = this.fb.group({ condition: this.fb.control(null, Validators.required), - alarmDetails: [null], - dashboardId: [null] + alarmDetails: this.fb.control(null), + dashboardId: this.fb.control(null) }); private propagateChange = (v: any) => { }; @@ -106,8 +105,8 @@ export class CfAlarmRuleComponent implements ControlValueAccessor, OnInit, Valid ngOnInit() { this.alarmRuleFormGroup.valueChanges.pipe( takeUntilDestroyed(this.destroyRef) - ).subscribe(() => { - this.updateModel(); + ).subscribe((value) => { + this.updateModel(value); }); this.alarmRuleFormGroup.statusChanges.pipe( takeUntilDestroyed(this.destroyRef) @@ -126,13 +125,12 @@ export class CfAlarmRuleComponent implements ControlValueAccessor, OnInit, Valid } writeValue(value: AlarmRule): void { - this.modelValue = value; - const model = this.modelValue ? { - ...this.modelValue, - dashboardId: this.modelValue.dashboardId?.id + const model = value ? { + ...value, + dashboardId: value.dashboardId?.id } : null; this.alarmRuleFormGroup.patchValue(model, {emitEvent: false}); - this.propagatedValue = this.toModel(this.alarmRuleFormGroup.value); + this.modelValue = model ? this.toModel(model) : null; } public openEditDetailsDialog($event: Event) { @@ -162,17 +160,16 @@ export class CfAlarmRuleComponent implements ControlValueAccessor, OnInit, Valid }; } - private updateModel() { - const modelValue = this.toModel(this.alarmRuleFormGroup.value); - if (isEqual(modelValue, this.propagatedValue)) { + private updateModel(value: typeof this.alarmRuleFormGroup.value): void { + const modelValue = this.toModel(value); + if (isEqual(modelValue, this.modelValue)) { return; } this.modelValue = modelValue; - this.propagatedValue = modelValue; this.propagateChange(modelValue); } - private toModel(value: any): AlarmRule { + private toModel(value: typeof this.alarmRuleFormGroup.value): AlarmRule { return {...value, dashboardId: value.dashboardId ? new DashboardId(value.dashboardId) : null} as AlarmRule; } }