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 7a2ad22fdd..0fcb6d0135 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
@@ -137,23 +137,27 @@ export class CfAlarmRuleConditionComponent implements ControlValueAccessor, Vali
writeValue(value: AlarmRuleCondition): void {
this.modelValue = value;
this.updateConditionInfo();
- if (value && !this.disabled) {
- if (this.validate(this.alarmRuleConditionFormGroup)) {
- this.onValidatorChange();
- }
- }
+ this.recalculateArgumentValidity();
}
ngOnChanges(changes: SimpleChanges) {
if (changes.arguments) {
- if (changes.arguments && !changes.arguments.firstChange && this.modelValue && !this.disabled) {
- if (this.validate(this.alarmRuleConditionFormGroup)) {
- this.onValidatorChange();
- }
+ if (changes.arguments && !changes.arguments.firstChange) {
+ this.recalculateArgumentValidity();
}
}
}
+ private recalculateArgumentValidity(): void {
+ if (!this.modelValue || !this.arguments) {
+ this.filtersArgumentsValid = true;
+ this.schedulerArgumentsValid = true;
+ return;
+ }
+ this.filtersArgumentsValid = this.areFilterAndPredicateArgumentsValid(this.modelValue, this.arguments);
+ this.schedulerArgumentsValid = this.isScheduleArgumentValid(this.modelValue, Object.keys(this.arguments));
+ }
+
private isScheduleArgumentValid(obj: any, validArguments: string[]): boolean {
const arg = obj?.schedule?.dynamicValueArgument;
return !arg || validArguments.includes(arg);
@@ -177,21 +181,14 @@ export class CfAlarmRuleConditionComponent implements ControlValueAccessor, Vali
return true;
}
- public conditionSet() {
- return this.modelValue && (this.modelValue.expression?.expression || this.modelValue.expression?.filters);
+ public conditionSet(): boolean {
+ return !!this.modelValue && !!(this.modelValue.expression?.expression || this.modelValue.expression?.filters);
}
public validate(control: AbstractControl): ValidationErrors | null {
- this.filtersArgumentsValid = this.areFilterAndPredicateArgumentsValid(this.modelValue, this.arguments);
- this.schedulerArgumentsValid = this.isScheduleArgumentValid(this.modelValue, Object.keys(this.arguments));
- this.onValidatorChange = () => {
- control.updateValueAndValidity({ emitEvent: !this.disabled });
- };
- return this.conditionSet() && this.filtersArgumentsValid && this.schedulerArgumentsValid ? null : {
- alarmRuleCondition: {
- valid: false,
- }
- };
+ const hasCondition = this.conditionSet();
+ const argsValid = this.filtersArgumentsValid && this.schedulerArgumentsValid;
+ return (hasCondition && argsValid) ? null : { alarmRuleCondition: { valid: false } };
}
public openFilterDialog($event: Event) {
@@ -212,7 +209,6 @@ export class CfAlarmRuleConditionComponent implements ControlValueAccessor, Vali
if (result) {
this.modelValue = {...this.modelValue, ...result};
this.updateModel();
- this.cd.detectChanges();
}
});
}
@@ -278,10 +274,10 @@ export class CfAlarmRuleConditionComponent implements ControlValueAccessor, Vali
private updateModel() {
this.updateConditionInfo();
+ this.recalculateArgumentValidity();
this.propagateChange(this.modelValue);
- if (this.modelValue) {
- this.onValidatorChange();
- }
+ this.onValidatorChange();
+ this.cd.detectChanges();
}
public openScheduleDialog($event: Event) {
@@ -301,7 +297,6 @@ export class CfAlarmRuleConditionComponent implements ControlValueAccessor, Vali
if (result) {
this.modelValue.schedule = result;
this.updateModel();
- this.cd.detectChanges();
}
});
}
diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/calculated-field.component.ts b/ui-ngx/src/app/modules/home/components/calculated-fields/calculated-field.component.ts
index 65595fe9b8..fcf20b5421 100644
--- a/ui-ngx/src/app/modules/home/components/calculated-fields/calculated-field.component.ts
+++ b/ui-ngx/src/app/modules/home/components/calculated-fields/calculated-field.component.ts
@@ -39,6 +39,10 @@ import {
} from '@home/components/calculated-fields/calculated-fields-table-config';
import { TenantId } from '@shared/models/id/tenant-id';
import { CalculatedFieldFormService } from '@core/services/calculated-field-form.service';
+import { AssetInfo } from '@shared/models/asset.models';
+import { DeviceInfo } from '@shared/models/device.models';
+import { NULL_UUID } from '@shared/models/id/has-uuid';
+import { EntityService } from '@core/http/entity.service';
@Component({
selector: 'tb-calculated-field',
@@ -55,7 +59,7 @@ export class CalculatedFieldComponent extends EntityComponent {
+ if (this.isAssignedToCustomer(entity)) {
+ this.ownerId = entity.customerId;
+ }
+ }
+ );
+ }
+ }
+
+ private isAssignedToCustomer(entity: AssetInfo | DeviceInfo): boolean {
+ return entity && entity.customerId && entity.customerId.id !== NULL_UUID;
+ }
}
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 e09949d2c6..49cc6b75ca 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
@@ -333,7 +333,7 @@ export class CalculatedFieldsTableConfig extends EntityTableConfig {
- if (calculatedField.type === CalculatedFieldType.ALARM) {
+ if (calculatedField.type === CalculatedFieldType.ALARM || !CalculatedFieldType[calculatedField.type]) {
this.store.dispatch(new ActionNotificationShow({
message: this.translate.instant('calculated-fields.hint.import-invalid-calculated-field-type'),
type: 'error',
diff --git a/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.html b/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.html
index 1c4a2995b5..4aba05c99e 100644
--- a/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.html
+++ b/ui-ngx/src/app/modules/home/components/calculated-fields/components/dialog/calculated-field-dialog.component.html
@@ -94,7 +94,7 @@
[class.tb-form-panel-disabled]="disabledConfiguration"
[entityId]="entityId"
[entityName]="entityName"
- [ownerId]="data.ownerId"
+ [ownerId]="ownerId"
[tenantId]="data.tenantId"
>
}
@@ -104,7 +104,7 @@
[entityId]="entityId"
[entityName]="entityName"
[tenantId]="data.tenantId"
- [ownerId]="data.ownerId"
+ [ownerId]="ownerId"
[testScript]="onTestScript.bind(this)"
>
}
@@ -130,7 +130,7 @@
[class.tb-form-panel-disabled]="disabledConfiguration"
[entityId]="entityId"
[entityName]="entityName"
- [ownerId]="data.ownerId"
+ [ownerId]="ownerId"
[tenantId]="data.tenantId"
[isScript]="fieldFormGroup.get('type').value === CalculatedFieldType.SCRIPT"
[testScript]="onTestScript.bind(this)"
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 ee38fb2a2d..7f1c9e376a 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
@@ -39,6 +39,9 @@ import { deepTrim } from '@core/utils';
import { BaseData } from '@shared/models/base-data';
import { CalculatedFieldFormService } from '@core/services/calculated-field-form.service';
import { FormGroup } from '@angular/forms';
+import { AssetInfo } from '@shared/models/asset.models';
+import { DeviceInfo } from '@shared/models/device.models';
+import { NULL_UUID } from '@shared/models/id/has-uuid';
export interface CalculatedFieldDialogData {
value?: CalculatedField;
@@ -69,6 +72,7 @@ export class CalculatedFieldDialogComponent extends DialogComponent): void {
this.entityName = entity.name;
+ if (this.isAssignedToCustomer(entity as AssetInfo | DeviceInfo)) {
+ this.ownerId = (entity as AssetInfo | DeviceInfo).customerId;
+ }
}
get entityId(): EntityId {
@@ -163,4 +171,8 @@ export class CalculatedFieldDialogComponent extends DialogComponent
): void {
this.entityChanged.emit(entity);
}
+
+ entityAutocompleteMarkAsTouched() {
+ this.entityAutocompleteComponent.markAsTouched();
+ }
}
diff --git a/ui-ngx/src/app/shared/components/string-items-list.component.html b/ui-ngx/src/app/shared/components/string-items-list.component.html
index 0469be2589..bcd0076269 100644
--- a/ui-ngx/src/app/shared/components/string-items-list.component.html
+++ b/ui-ngx/src/app/shared/components/string-items-list.component.html
@@ -52,7 +52,9 @@
@for (value of filteredValues | async; track value.value) {
} @empty {
- {{ 'common.not-found' | translate }}
+ @if (!allowUserValue) {
+ {{ 'common.not-found' | translate }}
+ }
}
diff --git a/ui-ngx/src/app/shared/components/string-items-list.component.ts b/ui-ngx/src/app/shared/components/string-items-list.component.ts
index 1c210fdf1f..ab9f1f5831 100644
--- a/ui-ngx/src/app/shared/components/string-items-list.component.ts
+++ b/ui-ngx/src/app/shared/components/string-items-list.component.ts
@@ -210,8 +210,8 @@ export class StringItemsListComponent implements ControlValueAccessor, OnInit {
addOnBlur(event: FocusEvent) {
const target: HTMLElement = event.relatedTarget as HTMLElement;
- if (target && target.tagName !== 'MAT-OPTION') {
- this.addItem(this.stringItemInput.nativeElement.value ?? '')
+ if ((target && target.tagName !== 'MAT-OPTION') || this.allowUserValue) {
+ this.addItem(this.stringItemInput.nativeElement.value ?? '');
}
this.onTouched();
}
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 b0c2c1a899..db3da4235e 100644
--- a/ui-ngx/src/app/shared/models/calculated-field.models.ts
+++ b/ui-ngx/src/app/shared/models/calculated-field.models.ts
@@ -525,7 +525,7 @@ export const ArgumentEntityTypeParamsMap =new Map {
- switch (entityId.entityType) {
+ switch (entityId?.entityType) {
case EntityType.ASSET_PROFILE:
return {
assetTypes: [entityName],
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 e6ce6ccdc0..eaad687821 100644
--- a/ui-ngx/src/assets/locale/locale.constant-en_US.json
+++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json
@@ -1434,7 +1434,7 @@
"condition-during": "During {{during}}",
"condition-during-dynamic": "During \"{{ attribute }}\"",
"condition-repeat-times": "Repeats { count, plural, =1 {1 time} other {# times} }",
- "condition-repeat-times-dynamic": "Repeats \"{{ attribute }}\"",
+ "condition-repeat-times-dynamic": "Repeats \"{{ attribute }}\" times",
"filter-preview": "Filter preview",
"condition-settings": "Condition settings",
"static": "Static",