diff --git a/application/src/main/data/json/system/widget_types/timeseries_table.json b/application/src/main/data/json/system/widget_types/timeseries_table.json
index 625f7a1e7d..24443cfecf 100644
--- a/application/src/main/data/json/system/widget_types/timeseries_table.json
+++ b/application/src/main/data/json/system/widget_types/timeseries_table.json
@@ -17,7 +17,7 @@
"latestDataKeySettingsDirective": "tb-timeseries-table-latest-key-settings",
"hasBasicMode": true,
"basicModeDirective": "tb-timeseries-table-basic-config",
- "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"entityAliasId\":null,\"filterId\":null,\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temperature °C\",\"color\":\"#2196f3\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n var percent = (value + 60)/120 * 100;\\n var color = tinycolor.mix('blue', 'red', percent);\\n color.setAlpha(.5);\\n return {\\n paddingLeft: '20px',\\n color: '#ffffff',\\n background: color.toRgbString(),\\n fontSize: '18px'\\n };\\n} else {\\n return {};\\n}\",\"useCellContentFunction\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\",\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Humidity, %\",\"color\":\"#ffc107\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n var percent = value;\\n var backgroundColor = tinycolor('blue');\\n backgroundColor.setAlpha(value/100);\\n var color = 'blue';\\n if (value > 50) {\\n color = 'white';\\n }\\n \\n return {\\n paddingLeft: '20px',\\n color: color,\\n background: backgroundColor.toRgbString(),\\n fontSize: '18px'\\n };\\n} else {\\n return {};\\n}\",\"useCellContentFunction\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 5) {\\n\\tvalue = 5;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}],\"latestDataKeys\":[]}],\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"enableSearch\":true,\"enableSelectColumnDisplay\":true,\"enableStickyHeader\":true,\"enableStickyAction\":true,\"showCellActionsMenu\":true,\"reserveSpaceForHiddenAction\":\"true\",\"showTimestamp\":true,\"dateFormat\":{\"format\":\"yyyy-MM-dd HH:mm:ss\"},\"displayPagination\":true,\"useEntityLabel\":false,\"defaultPageSize\":10,\"pageStepCount\":3,\"pageStepIncrement\":10,\"hideEmptyLines\":false,\"disableStickyHeader\":false,\"useRowStyleFunction\":false,\"rowStyleFunction\":\"\",\"tabSortKey\":\"timestamp\"},\"title\":\"Time series table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":true,\"showLegend\":false,\"widgetStyle\":{},\"actions\":{},\"showTitleIcon\":false,\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"configMode\":\"basic\",\"titleFont\":null,\"titleColor\":null,\"titleIcon\":null}"
+ "defaultConfig": "{\"datasources\":[{\"type\":\"function\",\"name\":\"function\",\"entityAliasId\":null,\"filterId\":null,\"dataKeys\":[{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Temperature °C\",\"color\":\"#2196f3\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n var percent = (value + 60)/120 * 100;\\n var color = tinycolor.mix('blue', 'red', percent);\\n color.setAlpha(.5);\\n return {\\n paddingLeft: '20px',\\n color: '#ffffff',\\n background: color.toRgbString(),\\n fontSize: '18px'\\n };\\n} else {\\n return {};\\n}\",\"useCellContentFunction\":false},\"_hash\":0.8587686344902596,\"funcBody\":\"var value = prevValue + Math.random() * 40 - 20;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < -60) {\\n\\tvalue = -60;\\n} else if (value > 60) {\\n\\tvalue = 60;\\n}\\nreturn value;\",\"units\":null,\"decimals\":null,\"usePostProcessing\":null,\"postFuncBody\":null},{\"name\":\"f(x)\",\"type\":\"function\",\"label\":\"Humidity, %\",\"color\":\"#ffc107\",\"settings\":{\"useCellStyleFunction\":true,\"cellStyleFunction\":\"if (value) {\\n var percent = value;\\n var backgroundColor = tinycolor('blue');\\n backgroundColor.setAlpha(value/100);\\n var color = 'blue';\\n if (value > 50) {\\n color = 'white';\\n }\\n \\n return {\\n paddingLeft: '20px',\\n color: color,\\n background: backgroundColor.toRgbString(),\\n fontSize: '18px'\\n };\\n} else {\\n return {};\\n}\",\"useCellContentFunction\":false},\"_hash\":0.12775350966079668,\"funcBody\":\"var value = prevValue + Math.random() * 20 - 10;\\nvar multiplier = Math.pow(10, 1 || 0);\\nvar value = Math.round(value * multiplier) / multiplier;\\nif (value < 5) {\\n\\tvalue = 5;\\n} else if (value > 100) {\\n\\tvalue = 100;\\n}\\nreturn value;\"}],\"latestDataKeys\":[]}],\"showTitle\":true,\"backgroundColor\":\"rgb(255, 255, 255)\",\"color\":\"rgba(0, 0, 0, 0.87)\",\"padding\":\"8px\",\"settings\":{\"enableSearch\":true,\"enableSelectColumnDisplay\":true,\"enableStickyHeader\":true,\"enableStickyAction\":true,\"showCellActionsMenu\":true,\"reserveSpaceForHiddenAction\":\"true\",\"showTimestamp\":true,\"dateFormat\":{\"format\":\"yyyy-MM-dd HH:mm:ss\"},\"displayPagination\":true,\"useEntityLabel\":false,\"defaultPageSize\":10,\"pageStepCount\":3,\"pageStepIncrement\":10,\"hideEmptyLines\":false,\"disableStickyHeader\":false,\"useRowStyleFunction\":false,\"rowStyleFunction\":\"\",\"sortOrder\":{\"property\":\"createdTime\",\"direction\":\"DESC\"}},\"title\":\"Time series table\",\"dropShadow\":true,\"enableFullscreen\":true,\"titleStyle\":{\"fontSize\":\"16px\",\"fontWeight\":400,\"padding\":\"5px 10px 5px 10px\"},\"useDashboardTimewindow\":true,\"showLegend\":false,\"widgetStyle\":{},\"actions\":{},\"showTitleIcon\":false,\"iconColor\":\"rgba(0, 0, 0, 0.87)\",\"iconSize\":\"24px\",\"configMode\":\"basic\",\"titleFont\":null,\"titleColor\":null,\"titleIcon\":null}"
},
"resources": [
{
diff --git a/ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rule-dialog.component.html b/ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rule-dialog.component.html
index d4a93d461f..b734757144 100644
--- a/ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rule-dialog.component.html
+++ b/ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rule-dialog.component.html
@@ -58,6 +58,7 @@
@@ -97,7 +100,7 @@
-
+
diff --git a/ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rule-dialog.component.ts b/ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rule-dialog.component.ts
index b3176414ab..2209cbafba 100644
--- a/ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rule-dialog.component.ts
+++ b/ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rule-dialog.component.ts
@@ -31,8 +31,15 @@ import { EntityId } from '@shared/models/id/entity-id';
import { AdditionalDebugActionConfig } from '@home/components/entity/debug/entity-debug-settings.model';
import { COMMA, ENTER, SEMICOLON } from "@angular/cdk/keycodes";
import { MatChipInputEvent } from "@angular/material/chips";
-import { AlarmRule, AlarmRuleConditionType, AlarmRuleExpressionType } from "@shared/models/alarm-rule.models";
+import {
+ AlarmRule,
+ AlarmRuleConditionType,
+ AlarmRuleExpressionType,
+ AlarmRuleTestScriptFn
+} from "@shared/models/alarm-rule.models";
import { deepTrim } from "@core/utils";
+import { Observable } from "rxjs";
+import { switchMap } from "rxjs/operators";
export interface AlarmRuleDialogData {
value?: CalculatedField;
@@ -43,6 +50,7 @@ export interface AlarmRuleDialogData {
ownerId: EntityId;
additionalDebugActionConfig: AdditionalDebugActionConfig<(calculatedField: CalculatedField) => void>;
isDirty?: boolean;
+ getTestScriptDialogFn: AlarmRuleTestScriptFn,
}
@Component({
@@ -182,4 +190,19 @@ export class AlarmRuleDialogComponent extends DialogComponent {
+ const calculatedFieldId = this.data.value?.id?.id;
+ if (calculatedFieldId) {
+ return this.calculatedFieldsService.getLatestCalculatedFieldDebugEvent(calculatedFieldId, {ignoreLoading: true})
+ .pipe(
+ switchMap(event => {
+ const args = event?.arguments ? JSON.parse(event.arguments) : null;
+ return this.data.getTestScriptDialogFn(this.fromGroupValue, expression, args, false);
+ }),
+ takeUntilDestroyed(this.destroyRef)
+ )
+ }
+ return this.data.getTestScriptDialogFn(this.fromGroupValue, expression, null, false);
+ }
}
diff --git a/ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rule-filter-config.component.ts b/ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rule-filter-config.component.ts
index c961cebe33..a19fc688a8 100644
--- a/ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rule-filter-config.component.ts
+++ b/ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rule-filter-config.component.ts
@@ -90,7 +90,7 @@ export class AlarmRuleFilterConfigComponent implements OnInit, ControlValueAcces
panelMode = false;
- buttonDisplayValue = this.translate.instant('alarm-rule.alarm-rule-filter');
+ buttonDisplayValue = this.translate.instant('alarm-rule.alarm-rule-filter-title');
alarmRuleFilterConfigForm: FormGroup;
@@ -281,6 +281,9 @@ export class AlarmRuleFilterConfigComponent implements OnInit, ControlValueAcces
if (this.alarmRuleFilterConfig?.name?.length) {
filterTextParts.push(this.alarmRuleFilterConfig.name.map((type) => this.customTranslate(type)).join(', '));
}
+ if (this.alarmRuleFilterConfig?.entityType) {
+ filterTextParts.push(this.translate.instant( entityTypeTranslations.get(this.alarmRuleFilterConfig.entityType).type));
+ }
if (!filterTextParts.length) {
this.buttonDisplayValue = this.translate.instant('alarm-rule.alarm-rule-filter-title');
} else {
diff --git a/ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rule-table-header.component.ts b/ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rule-table-header.component.ts
index cf5462d1a2..8f2501d8f1 100644
--- a/ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rule-table-header.component.ts
+++ b/ui-ngx/src/app/modules/home/components/alarm-rules/alarm-rule-table-header.component.ts
@@ -18,7 +18,6 @@ import { Component } from '@angular/core';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { EntityTableHeaderComponent } from '../../components/entity/entity-table-header.component';
-import { AlarmFilterConfig } from '@shared/models/query/query.models';
import { CalculatedFieldAlarmRule, CalculatedFieldsQuery } from "@shared/models/calculated-field.models";
import { AlarmRulesTableConfig } from "@home/components/alarm-rules/alarm-rules-table-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 1dbb7fdc83..6fa6515663 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
@@ -26,7 +26,7 @@ import { TranslateService } from '@ngx-translate/core';
import { Direction } from '@shared/models/page/sort-order';
import { MatDialog } from '@angular/material/dialog';
import { PageLink } from '@shared/models/page/page-link';
-import { Observable, of } from 'rxjs';
+import { EMPTY, Observable, of } from 'rxjs';
import { PageData } from '@shared/models/page/page-data';
import { EntityId } from '@shared/models/id/entity-id';
import { Store } from '@ngrx/store';
@@ -36,13 +36,17 @@ import { DestroyRef, Renderer2 } from '@angular/core';
import { EntityDebugSettings } from '@shared/models/entity.models';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { CalculatedFieldsService } from '@core/http/calculated-fields.service';
-import { catchError, filter, switchMap } from 'rxjs/operators';
+import { catchError, filter, switchMap, tap } from 'rxjs/operators';
import {
ArgumentEntityType,
+ ArgumentType,
CalculatedField,
CalculatedFieldAlarmRule,
+ CalculatedFieldEventArguments,
CalculatedFieldsQuery,
CalculatedFieldType,
+ getCalculatedFieldArgumentsEditorCompleter,
+ getCalculatedFieldArgumentsHighlights,
} from '@shared/models/calculated-field.models';
import { ImportExportService } from '@shared/import-export/import-export.service';
import { EntityDebugSettingsService } from '@home/components/entity/debug/entity-debug-settings.service';
@@ -57,8 +61,13 @@ import {
} 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 } from "@core/utils";
+import { deepClone, getEntityDetailsPageURL, isObject } from "@core/utils";
import { AlarmRuleTableHeaderComponent } from "@home/components/alarm-rules/alarm-rule-table-header.component";
+import { ActionNotificationShow } from "@core/notification/notification.actions";
+import {
+ CalculatedFieldScriptTestDialogComponent,
+ CalculatedFieldTestScriptDialogData
+} from "@home/components/calculated-fields/components/test-dialog/calculated-field-script-test-dialog.component";
export class AlarmRulesTableConfig extends EntityTableConfig {
@@ -223,7 +232,10 @@ export class AlarmRulesTableConfig extends EntityTableConfig {
private copyCalculatedField(calculatedField: CalculatedField, isDirty = false): void {
const copyCalculatedAlarmRule = deepClone(calculatedField);
- copyCalculatedAlarmRule.entityId = null;
+ if (this.pageMode) {
+ copyCalculatedAlarmRule.entityId = null;
+ }
+ delete copyCalculatedAlarmRule.id;
this.getCalculatedAlarmDialog(copyCalculatedAlarmRule, 'action.apply', isDirty)
.subscribe((res) => {
if (res) {
@@ -245,6 +257,7 @@ export class AlarmRulesTableConfig extends EntityTableConfig {
ownerId: this.ownerId ?? {entityType: EntityType.TENANT, id: this.tenantId},
additionalDebugActionConfig: this.additionalDebugActionConfig,
isDirty,
+ getTestScriptDialogFn: this.getTestScriptDialog.bind(this),
},
enterAnimationDuration: isDirty ? 0 : null,
})
@@ -277,6 +290,19 @@ export class AlarmRulesTableConfig extends EntityTableConfig {
this.importExportService.openCalculatedFieldImportDialog()
.pipe(
filter(Boolean),
+ switchMap(calculatedField => {
+ if (calculatedField.type !== CalculatedFieldType.ALARM) {
+ this.store.dispatch(new ActionNotificationShow({
+ message: this.translate.instant('alarm-rule.import-invalid-alarm-rule-type'),
+ type: 'error',
+ verticalPosition: 'top',
+ horizontalPosition: 'left',
+ duration: 5000
+ }));
+ return EMPTY;
+ }
+ return of(calculatedField);
+ }),
switchMap(calculatedField => this.getCalculatedAlarmDialog(this.updateImportedCalculatedField(calculatedField), 'action.add', true)),
filter(Boolean),
switchMap(calculatedField => this.calculatedFieldsService.saveCalculatedField(calculatedField)),
@@ -287,15 +313,7 @@ export class AlarmRulesTableConfig extends EntityTableConfig {
}
private updateImportedCalculatedField(calculatedField: CalculatedField): CalculatedField {
- if (calculatedField.type === CalculatedFieldType.GEOFENCING) {
- calculatedField.configuration.zoneGroups = Object.keys(calculatedField.configuration.zoneGroups).reduce((acc, key) => {
- const arg = calculatedField.configuration.zoneGroups[key];
- acc[key] = arg.refEntityId?.entityType === ArgumentEntityType.Tenant
- ? { ...arg, refEntityId: { id: this.tenantId, entityType: ArgumentEntityType.Tenant } }
- : arg;
- return acc;
- }, {});
- } else {
+ if (calculatedField.type === CalculatedFieldType.ALARM) {
calculatedField.configuration.arguments = Object.keys(calculatedField.configuration.arguments).reduce((acc, key) => {
const arg = calculatedField.configuration.arguments[key];
acc[key] = arg.refEntityId?.entityType === ArgumentEntityType.Tenant
@@ -315,4 +333,41 @@ export class AlarmRulesTableConfig extends EntityTableConfig {
takeUntilDestroyed(this.destroyRef),
).subscribe(() => this.updateData());
}
+
+ private getTestScriptDialog(calculatedField: CalculatedField, 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;
+ 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,
+ {
+ disableClose: true,
+ panelClass: ['tb-dialog', 'tb-fullscreen-dialog', 'tb-fullscreen-dialog-gt-xs'],
+ data: {
+ arguments: resultArguments,
+ expression,
+ argumentsEditorCompleter: getCalculatedFieldArgumentsEditorCompleter(calculatedField.configuration.arguments),
+ argumentsHighlightRules: getCalculatedFieldArgumentsHighlights(calculatedField.configuration.arguments),
+ openCalculatedFieldEdit
+ }
+ }).afterClosed()
+ .pipe(
+ filter(Boolean),
+ tap(expression => {
+ if (openCalculatedFieldEdit) {
+ this.editCalculatedField({
+ entityId: this.entityId, ...calculatedField,
+ configuration: {...calculatedField.configuration, expression} as any
+ }, true)
+ }
+ }),
+ );
+ } else {
+ return of(null);
+ }
+ }
}
diff --git a/ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule-condition-dialog.component.html b/ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule-condition-dialog.component.html
index feafcaa0a4..34f165420a 100644
--- a/ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule-condition-dialog.component.html
+++ b/ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule-condition-dialog.component.html
@@ -67,9 +67,26 @@
[helpPopupStyle]="{ width: '1200px' }"
helpId="alarm-rule/expression_fn">
{{ 'alarm-rule.expression-type.script' | translate }}
+ class="tb-primary-background tbel-script-lang-chip">{{ 'alarm-rule.tbel' | translate }}
+
+ bug_report
+
+
+
+ {{ 'calculated-fields.test-script-function' | translate }}
+
+
}
diff --git a/ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule-condition-dialog.component.ts b/ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule-condition-dialog.component.ts
index 48b290b32c..2b0f25c2fe 100644
--- a/ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule-condition-dialog.component.ts
+++ b/ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule-condition-dialog.component.ts
@@ -28,6 +28,7 @@ import {
AlarmRuleCondition,
AlarmRuleConditionType,
AlarmRuleConditionTypeTranslationMap,
+ alarmRuleDefaultScript,
AlarmRuleExpressionType
} from "@shared/models/alarm-rule.models";
import {
@@ -38,11 +39,13 @@ import {
import { TbEditorCompleter } from "@shared/models/ace/completion.models";
import { AceHighlightRules } from "@shared/models/ace/ace.models";
import { ComplexOperation, complexOperationTranslationMap } from "@shared/models/query/query.models";
+import { Observable } from "rxjs";
export interface CfAlarmRuleConditionDialogData {
readonly: boolean;
condition: AlarmRuleCondition;
arguments?: Record;
+ testScript: (expression: string) => Observable;
}
@Component({
@@ -117,7 +120,7 @@ export class CfAlarmRuleConditionDialogComponent extends DialogComponent {
+ this.conditionFormGroup.get('expression.expression').setValue(expression);
+ this.conditionFormGroup.get('expression.expression').markAsDirty();
+ })
+ }
}
diff --git a/ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule-condition.component.html b/ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule-condition.component.html
index e17d8c8261..0b722b4ec1 100644
--- a/ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule-condition.component.html
+++ b/ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule-condition.component.html
@@ -30,7 +30,7 @@
[nowrap]="true"
[specText]="specText"
required
- addFilterPrompt="{{'alarm-rule.enter-alarm-rule-condition-prompt' | translate}}">
+ addFilterPrompt="{{ (isClearCondition ? 'alarm-rule.enter-alarm-rule-clear-condition-prompt' :'alarm-rule.enter-alarm-rule-condition-prompt') | translate }}">
{{ conditionSet() ? 'edit' : 'add' }}
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 2e8d116ad2..2a0b7a7810 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
@@ -21,8 +21,7 @@ import {
NG_VALIDATORS,
NG_VALUE_ACCESSOR,
UntypedFormControl,
- Validator,
- Validators
+ Validator
} from '@angular/forms';
import { MatDialog } from '@angular/material/dialog';
import { deepClone, isDefinedAndNotNull } from '@core/utils';
@@ -50,6 +49,7 @@ import {
CfAlarmScheduleDialogComponent
} from "@home/components/alarm-rules/cf-alarm-schedule-dialog.component";
import { coerceBoolean } from "@shared/decorators/coercion";
+import { Observable } from "rxjs";
@Component({
selector: 'tb-cf-alarm-rule-condition',
@@ -81,6 +81,13 @@ export class CfAlarmRuleConditionComponent implements ControlValueAccessor, Vali
@Input()
arguments: Record;
+ @Input()
+ @coerceBoolean()
+ isClearCondition = false;
+
+ @Input({required: true})
+ testScript: (expression: string) => Observable;
+
alarmRuleConditionFormGroup = this.fb.group({
type: ['SIMPLE'],
expression: [{type: AlarmRuleExpressionType.SIMPLE}],
@@ -118,10 +125,8 @@ export class CfAlarmRuleConditionComponent implements ControlValueAccessor, Vali
}
writeValue(value: AlarmRuleCondition): void {
- if (value) {
- this.modelValue = value;
- this.updateConditionInfo();
- }
+ this.modelValue = value;
+ this.updateConditionInfo();
}
public conditionSet() {
@@ -147,7 +152,8 @@ export class CfAlarmRuleConditionComponent implements ControlValueAccessor, Vali
data: {
readonly: this.disabled,
condition: this.disabled ? this.modelValue : deepClone(this.modelValue),
- arguments: this.arguments
+ arguments: this.arguments,
+ testScript: this.testScript
}
}).afterClosed().subscribe((result) => {
if (result) {
diff --git a/ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule.component.html b/ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule.component.html
index 14a88b2bf1..38e0bd8023 100644
--- a/ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule.component.html
+++ b/ui-ngx/src/app/modules/home/components/alarm-rules/cf-alarm-rule.component.html
@@ -16,7 +16,7 @@
-->
4"
type="button"
- (click)="addCreateAlarmRule()"
- matTooltip="{{ 'alarm-rule.add-create-alarm-rule' | translate }}"
- matTooltipPosition="above">
+ (click)="addCreateAlarmRule()">
{{ 'alarm-rule.add-create-alarm-rule' | translate }}
diff --git a/ui-ngx/src/app/modules/home/components/alarm-rules/create-cf-alarm-rules.component.ts b/ui-ngx/src/app/modules/home/components/alarm-rules/create-cf-alarm-rules.component.ts
index 94eeb755a9..2197d6d14c 100644
--- a/ui-ngx/src/app/modules/home/components/alarm-rules/create-cf-alarm-rules.component.ts
+++ b/ui-ngx/src/app/modules/home/components/alarm-rules/create-cf-alarm-rules.component.ts
@@ -33,6 +33,7 @@ import { CalculatedFieldArgument } from "@shared/models/calculated-field.models"
import { AlarmSeverityNotificationColors } from "@shared/models/notification.models";
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
import { coerceBoolean } from "@shared/decorators/coercion";
+import { Observable } from "rxjs";
@Component({
selector: 'tb-create-cf-alarm-rules',
@@ -60,6 +61,8 @@ export class CreateCfAlarmRulesComponent implements ControlValueAccessor, Valida
@Input()
arguments: Record;
+ @Input({required: true})
+ testScript: (expression: string) => Observable;
alarmSeverities = Object.keys(AlarmSeverity);
alarmSeverityEnum = AlarmSeverity;
@@ -157,7 +160,7 @@ export class CreateCfAlarmRulesComponent implements ControlValueAccessor, Valida
}
public validate(c: UntypedFormControl) {
- return (this.createAlarmRulesFormArray().length && this.createAlarmRulesFormGroup.valid) ? null : {
+ return this.createAlarmRulesFormArray().length ? null : {
createAlarmRules: {
valid: false,
},
diff --git a/ui-ngx/src/app/modules/home/components/alarm-rules/filter/alarm-rule-filter-dialog.component.html b/ui-ngx/src/app/modules/home/components/alarm-rules/filter/alarm-rule-filter-dialog.component.html
index abc1dd463d..8abb4ea45a 100644
--- a/ui-ngx/src/app/modules/home/components/alarm-rules/filter/alarm-rule-filter-dialog.component.html
+++ b/ui-ngx/src/app/modules/home/components/alarm-rules/filter/alarm-rule-filter-dialog.component.html
@@ -67,7 +67,10 @@