Browse Source

UI: Device profile alarm rules

pull/3477/head
Igor Kulikov 6 years ago
parent
commit
3a830eeb9a
  1. 19
      ui-ngx/src/app/modules/home/components/filter/filter-text.component.html
  2. 79
      ui-ngx/src/app/modules/home/components/filter/filter-text.component.scss
  3. 101
      ui-ngx/src/app/modules/home/components/filter/filter-text.component.ts
  4. 3
      ui-ngx/src/app/modules/home/components/home-components.module.ts
  5. 32
      ui-ngx/src/app/modules/home/components/profile/alarm/alarm-rule-condition.component.html
  6. 17
      ui-ngx/src/app/modules/home/components/profile/alarm/alarm-rule-condition.component.scss
  7. 23
      ui-ngx/src/app/modules/home/components/profile/alarm/alarm-rule-condition.component.ts
  8. 88
      ui-ngx/src/app/modules/home/components/profile/alarm/alarm-rule.component.html
  9. 5
      ui-ngx/src/app/modules/home/components/profile/alarm/alarm-rule.component.scss
  10. 6
      ui-ngx/src/app/modules/home/components/profile/alarm/create-alarm-rules.component.html
  11. 2
      ui-ngx/src/app/modules/home/components/profile/alarm/create-alarm-rules.component.ts
  12. 4
      ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.html
  13. 3
      ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarms.component.html
  14. 2
      ui-ngx/src/app/modules/home/components/profile/device-profile-data.component.html
  15. 94
      ui-ngx/src/app/shared/models/query/query.models.ts
  16. 12
      ui-ngx/src/assets/locale/locale.constant-en_US.json

19
ui-ngx/src/app/modules/home/components/filter/filter-text.component.html

@ -0,0 +1,19 @@
<!--
Copyright © 2016-2020 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.
-->
<div class="tb-filter-text" [ngClass]="{disabled: disabled, required: requiredClass}"
[innerHTML]="filterText"></div>

79
ui-ngx/src/app/modules/home/components/filter/filter-text.component.scss

@ -0,0 +1,79 @@
/**
* Copyright © 2016-2020 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 {
.tb-filter-text {
overflow-y: auto;
&.disabled {
opacity: 0.7;
}
&.required {
color: #f44336;
}
}
}
:host ::ng-deep {
.tb-filter-text {
line-height: 1.8em;
span {
display: inline-block;
vertical-align: middle;
line-height: 1.4em;
}
.tb-filter-predicate {
padding-right: 4px;
padding-left: 4px;
}
.tb-filter-entity-key, .tb-filter-value, .tb-filter-dynamic-source {
font-weight: bold;
border: 1px groove rgba(0, 0, 0, .25);
border-radius: 4px;
padding-left: 4px;
padding-right: 4px;
}
.tb-filter-entity-key, .tb-filter-value {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 150px;
}
.tb-filter-dynamic-source {
}
.tb-filter-entity-key {
color: #305680;
}
.tb-filter-value {
color: #ff5722;
}
.tb-filter-simple-operation {
font-size: 0.9em;
}
.tb-filter-complex-operation {
text-transform: uppercase;
font-weight: bold;
}
.tb-filter-dynamic-value {
.tb-filter-dynamic-source, .tb-filter-value {
color: #0c959c;
}
}
.tb-filter-bracket {
.tb-left-bracket, .tb-right-bracket {
font-size: 1.2em;
}
}
}
}

101
ui-ngx/src/app/modules/home/components/filter/filter-text.component.ts

@ -0,0 +1,101 @@
///
/// Copyright © 2016-2020 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 { Component, forwardRef, Input, OnInit } from '@angular/core';
import { ControlValueAccessor, FormBuilder, NG_VALUE_ACCESSOR } from '@angular/forms';
import { MatDialog } from '@angular/material/dialog';
import { KeyFilter, keyFiltersToText } from '@shared/models/query/query.models';
import { TranslateService } from '@ngx-translate/core';
import { DatePipe } from '@angular/common';
import { coerceBooleanProperty } from '@angular/cdk/coercion';
@Component({
selector: 'tb-filter-text',
templateUrl: './filter-text.component.html',
styleUrls: ['./filter-text.component.scss'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => FilterTextComponent),
multi: true
}
]
})
export class FilterTextComponent implements ControlValueAccessor, OnInit {
private requiredValue: boolean;
get required(): boolean {
return this.requiredValue;
}
@Input()
set required(value: boolean) {
this.requiredValue = coerceBooleanProperty(value);
}
@Input()
disabled: boolean;
@Input()
noFilterText = this.translate.instant('filter.no-filter-text');
@Input()
addFilterPrompt = this.translate.instant('filter.add-filter-prompt');
requiredClass = false;
private filterText: string;
private propagateChange = (v: any) => { };
constructor(private dialog: MatDialog,
private fb: FormBuilder,
private translate: TranslateService,
private datePipe: DatePipe) {
}
registerOnChange(fn: any): void {
this.propagateChange = fn;
}
registerOnTouched(fn: any): void {
}
ngOnInit() {
}
setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled;
}
writeValue(value: Array<KeyFilter>): void {
this.updateFilterText(value);
}
private updateFilterText(value: Array<KeyFilter>) {
this.requiredClass = false;
if (value && value.length) {
this.filterText = keyFiltersToText(this.translate, this.datePipe, value);
} else {
if (this.required && !this.disabled) {
this.filterText = this.addFilterPrompt;
this.requiredClass = true;
} else {
this.filterText = this.noFilterText;
}
}
}
}

3
ui-ngx/src/app/modules/home/components/home-components.module.ts

@ -104,6 +104,7 @@ import { CreateAlarmRulesComponent } from './profile/alarm/create-alarm-rules.co
import { AlarmRuleComponent } from './profile/alarm/alarm-rule.component';
import { AlarmRuleConditionComponent } from './profile/alarm/alarm-rule-condition.component';
import { AlarmRuleKeyFiltersDialogComponent } from './profile/alarm/alarm-rule-key-filters-dialog.component';
import { FilterTextComponent } from './filter/filter-text.component';
@NgModule({
declarations:
@ -165,6 +166,7 @@ import { AlarmRuleKeyFiltersDialogComponent } from './profile/alarm/alarm-rule-k
FilterDialogComponent,
FiltersDialogComponent,
FilterSelectComponent,
FilterTextComponent,
FiltersEditComponent,
FiltersEditPanelComponent,
UserFilterDialogComponent,
@ -245,6 +247,7 @@ import { AlarmRuleKeyFiltersDialogComponent } from './profile/alarm/alarm-rule-k
FilterDialogComponent,
FiltersDialogComponent,
FilterSelectComponent,
FilterTextComponent,
FiltersEditComponent,
UserFilterDialogComponent,
TenantProfileAutocompleteComponent,

32
ui-ngx/src/app/modules/home/components/profile/alarm/alarm-rule-condition.component.html

@ -15,16 +15,22 @@
limitations under the License.
-->
<mat-form-field class="mat-block" (click)="openFilterDialog($event)" floatLabel="always" hideRequiredMarker>
<mat-label></mat-label>
<input readonly
required matInput [formControl]="alarmRuleConditionControl"
placeholder="{{'device-profile.enter-alarm-rule-condition-prompt' | translate}}">
<a matSuffix mat-icon-button color="primary"
type="button"
(click)="openFilterDialog($event)"
matTooltip="{{ (disabled ? 'action.view' : 'action.edit') | translate }}"
matTooltipPosition="above">
<mat-icon>{{ disabled ? 'more_vert' : 'edit' }}</mat-icon>
</a>
</mat-form-field>
<div fxLayout="column" fxFlex>
<div fxLayout="row" fxLayoutAlign="start center" style="min-height: 40px;">
<div class="tb-small" translate>device-profile.alarm-rule-condition</div>
<span fxFlex></span>
<a mat-button color="primary"
type="button"
(click)="openFilterDialog($event)"
matTooltip="{{ (disabled ? 'action.view' : 'action.edit') | translate }}"
matTooltipPosition="above">
{{ (disabled ? 'action.view' : (conditionSet() ? 'action.edit' : 'action.add')) | translate }}
</a>
</div>
<div class="tb-alarm-rule-condition" fxFlex fxLayout="column" fxLayoutAlign="center" (click)="openFilterDialog($event)">
<tb-filter-text [formControl]="alarmRuleConditionControl"
required
addFilterPrompt="{{'device-profile.enter-alarm-rule-condition-prompt' | translate}}">
</tb-filter-text>
</div>
</div>

17
ui-ngx/src/app/modules/home/components/profile/alarm/alarm-rule-condition.component.scss

@ -14,9 +14,24 @@
* limitations under the License.
*/
:host {
a.mat-icon-button {
display: flex;
a.mat-button {
&:hover, &:focus {
border-bottom: none;
}
}
.tb-alarm-rule-condition {
padding: 8px;
border: 1px groove rgba(0, 0, 0, .25);
border-radius: 4px;
cursor: pointer;
}
}
:host ::ng-deep {
.tb-alarm-rule-condition {
.tb-filter-text {
max-height: 200px;
}
}
}

23
ui-ngx/src/app/modules/home/components/profile/alarm/alarm-rule-condition.component.ts

@ -30,6 +30,8 @@ import {
AlarmRuleKeyFiltersDialogComponent,
AlarmRuleKeyFiltersDialogData
} from './alarm-rule-key-filters-dialog.component';
import { TranslateService } from '@ngx-translate/core';
import { DatePipe } from '@angular/common';
@Component({
selector: 'tb-alarm-rule-condition',
@ -60,7 +62,9 @@ export class AlarmRuleConditionComponent implements ControlValueAccessor, OnInit
private propagateChange = (v: any) => { };
constructor(private dialog: MatDialog,
private fb: FormBuilder) {
private fb: FormBuilder,
private translate: TranslateService,
private datePipe: DatePipe) {
}
registerOnChange(fn: any): void {
@ -76,6 +80,11 @@ export class AlarmRuleConditionComponent implements ControlValueAccessor, OnInit
setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled;
if (this.disabled) {
this.alarmRuleConditionControl.disable({emitEvent: false});
} else {
this.alarmRuleConditionControl.enable({emitEvent: false});
}
}
writeValue(value: Array<KeyFilter>): void {
@ -83,8 +92,12 @@ export class AlarmRuleConditionComponent implements ControlValueAccessor, OnInit
this.updateConditionInfo();
}
public conditionSet() {
return this.modelValue && this.modelValue.length;
}
public validate(c: FormControl) {
return (this.modelValue && this.modelValue.length) ? null : {
return this.conditionSet() ? null : {
alarmRuleCondition: {
valid: false,
},
@ -112,11 +125,7 @@ export class AlarmRuleConditionComponent implements ControlValueAccessor, OnInit
}
private updateConditionInfo() {
if (this.modelValue && this.modelValue.length) {
this.alarmRuleConditionControl.patchValue('Condition set');
} else {
this.alarmRuleConditionControl.patchValue(null);
}
this.alarmRuleConditionControl.patchValue(this.modelValue);
}
private updateModel() {

88
ui-ngx/src/app/modules/home/components/profile/alarm/alarm-rule.component.html

@ -16,56 +16,56 @@
-->
<div fxLayout="column" [formGroup]="alarmRuleFormGroup">
<div formGroupName="condition" fxLayout="row" fxLayoutAlign="start" fxLayoutGap="8px" fxFlex>
<div fxLayout="column" fxFlex>
<div formGroupName="condition" fxLayout="row" fxLayoutGap="8px" fxFlex>
<tb-alarm-rule-condition fxFlex
formControlName="condition">
</tb-alarm-rule-condition>
<div fxLayout="column">
<div fxLayout="row" fxLayoutAlign="start center" style="min-height: 40px;">
<label class="tb-small" translate>device-profile.alarm-rule-condition</label>
</div>
<tb-alarm-rule-condition fxFlex
formControlName="condition">
</tb-alarm-rule-condition>
</div>
<div fxLayout="column" style="min-width: 250px;">
<div fxLayout="row" fxLayoutAlign="start center" style="min-height: 40px;">
<label fxFlex class="tb-small" translate>device-profile.condition-duration</label>
<div class="tb-small" translate>device-profile.condition-duration</div>
<span fxFlex></span>
<mat-slide-toggle [disabled]="disabled"
color="primary"
[ngModelOptions]="{standalone: true}"
(ngModelChange)="enableDurationChanged($event)"
[ngModel]="enableDuration">
</mat-slide-toggle>
</div>
<div fxLayout="row" fxLayoutGap="8px" [fxShow]="enableDuration">
<mat-form-field class="mat-block duration-value-field" hideRequiredMarker floatLabel="always">
<mat-label></mat-label>
<input type="number"
[required]="enableDuration"
step="1"
min="1" max="2147483647" matInput
placeholder="{{ 'device-profile.condition-duration-value' | translate }}"
formControlName="durationValue">
<mat-error *ngIf="alarmRuleFormGroup.get('condition').get('durationValue').hasError('required')">
{{ 'device-profile.condition-duration-value-required' | translate }}
</mat-error>
<mat-error *ngIf="alarmRuleFormGroup.get('condition').get('durationValue').hasError('min')">
{{ 'device-profile.condition-duration-value-range' | translate }}
</mat-error>
<mat-error *ngIf="alarmRuleFormGroup.get('condition').get('durationValue').hasError('max')">
{{ 'device-profile.condition-duration-value-range' | translate }}
</mat-error>
</mat-form-field>
<mat-form-field class="mat-block duration-unit-field" hideRequiredMarker floatLabel="always">
<mat-label></mat-label>
<mat-select formControlName="durationUnit"
[required]="enableDuration"
placeholder="{{ 'device-profile.condition-duration-time-unit' | translate }}">
<mat-option *ngFor="let timeUnit of timeUnits" [value]="timeUnit">
{{ timeUnitTranslations.get(timeUnit) | translate }}
</mat-option>
</mat-select>
<mat-error *ngIf="alarmRuleFormGroup.get('condition').get('durationUnit').hasError('required')">
{{ 'device-profile.condition-duration-time-unit-required' | translate }}
</mat-error>
</mat-form-field>
<div class="tb-condition-duration" fxFlex fxLayout="row" fxLayoutGap="8px">
<span style="min-width: 250px;" [fxShow]="!enableDuration"></span>
<div style="min-width: 250px;" fxLayout="row" fxLayoutGap="8px" [fxShow]="enableDuration">
<mat-form-field class="mat-block duration-value-field" hideRequiredMarker floatLabel="always">
<mat-label></mat-label>
<input type="number"
[required]="enableDuration"
step="1"
min="1" max="2147483647" matInput
placeholder="{{ 'device-profile.condition-duration-value' | translate }}"
formControlName="durationValue">
<mat-error *ngIf="alarmRuleFormGroup.get('condition').get('durationValue').hasError('required')">
{{ 'device-profile.condition-duration-value-required' | translate }}
</mat-error>
<mat-error *ngIf="alarmRuleFormGroup.get('condition').get('durationValue').hasError('min')">
{{ 'device-profile.condition-duration-value-range' | translate }}
</mat-error>
<mat-error *ngIf="alarmRuleFormGroup.get('condition').get('durationValue').hasError('max')">
{{ 'device-profile.condition-duration-value-range' | translate }}
</mat-error>
</mat-form-field>
<mat-form-field class="mat-block duration-unit-field" hideRequiredMarker floatLabel="always">
<mat-label></mat-label>
<mat-select formControlName="durationUnit"
[required]="enableDuration"
placeholder="{{ 'device-profile.condition-duration-time-unit' | translate }}">
<mat-option *ngFor="let timeUnit of timeUnits" [value]="timeUnit">
{{ timeUnitTranslations.get(timeUnit) | translate }}
</mat-option>
</mat-select>
<mat-error *ngIf="alarmRuleFormGroup.get('condition').get('durationUnit').hasError('required')">
{{ 'device-profile.condition-duration-time-unit-required' | translate }}
</mat-error>
</mat-form-field>
</div>
</div>
</div>
</div>
@ -73,7 +73,7 @@
<mat-expansion-panel-header>
<mat-panel-title>
<div fxFlex fxLayout="row" fxLayoutAlign="end center">
<div class="tb-small" translate>device-profile.advanced-settings</div>
<div class="tb-small" translate>device-profile.alarm-rule-details</div>
</div>
</mat-panel-title>
</mat-expansion-panel-header>

5
ui-ngx/src/app/modules/home/components/profile/alarm/alarm-rule.component.scss

@ -14,6 +14,11 @@
* limitations under the License.
*/
:host {
.tb-condition-duration {
padding: 8px;
border: 1px groove rgba(0, 0, 0, .25);
border-radius: 4px;
}
.mat-expansion-panel.advanced-settings {
box-shadow: none;
border: none;

6
ui-ngx/src/app/modules/home/components/profile/alarm/create-alarm-rules.component.html

@ -36,7 +36,7 @@
<tb-alarm-rule formControlName="alarmRule" required fxFlex>
</tb-alarm-rule>
</div>
<button *ngIf="!disabled && createAlarmRulesFormArray().controls.length > 1"
<button *ngIf="!disabled"
mat-icon-button color="primary" style="min-width: 40px;"
type="button"
(click)="removeCreateAlarmRule($index)"
@ -45,6 +45,10 @@
<mat-icon>remove_circle_outline</mat-icon>
</button>
</div>
<div *ngIf="disabled && !createAlarmRulesFormArray().controls.length">
<span translate fxLayoutAlign="center center"
class="tb-prompt">device-profile.no-create-alarm-rules</span>
</div>
<div fxLayout="row" *ngIf="!disabled">
<button mat-stroked-button color="primary"
type="button"

2
ui-ngx/src/app/modules/home/components/profile/alarm/create-alarm-rules.component.ts

@ -142,7 +142,7 @@ export class CreateAlarmRulesComponent implements ControlValueAccessor, OnInit,
}
public validate(c: FormControl) {
return (this.createAlarmRulesFormGroup.valid && this.createAlarmRulesFormGroup.get('createAlarmRules').value.length) ? null : {
return (this.createAlarmRulesFormGroup.valid) ? null : {
createAlarmRules: {
valid: false,
},

4
ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarm.component.html

@ -66,6 +66,10 @@
<mat-icon>remove_circle_outline</mat-icon>
</button>
</div>
<div *ngIf="disabled && !alarmFormGroup.get('clearRule').value">
<span translate fxLayoutAlign="center center"
class="tb-prompt">device-profile.no-clear-alarm-rule</span>
</div>
<div fxLayout="row" *ngIf="!disabled"
[fxShow]="!alarmFormGroup.get('clearRule').value">
<button mat-stroked-button color="primary"

3
ui-ngx/src/app/modules/home/components/profile/alarm/device-profile-alarms.component.html

@ -32,8 +32,7 @@
(click)="addAlarm()"
matTooltip="{{ 'device-profile.add-alarm-rule' | translate }}"
matTooltipPosition="above">
<mat-icon>add</mat-icon>
<span translate>action.add</span>
<span translate>device-profile.add-alarm-rule</span>
</button>
</div>
</div>

2
ui-ngx/src/app/modules/home/components/profile/device-profile-data.component.html

@ -39,7 +39,7 @@
required>
</tb-device-profile-transport-configuration>
</mat-expansion-panel>
<mat-expansion-panel [expanded]="false">
<mat-expansion-panel [expanded]="true">
<mat-expansion-panel-header>
<mat-panel-title>
<div>{{'device-profile.alarm-rules' | translate:

94
ui-ngx/src/app/shared/models/query/query.models.ts

@ -25,6 +25,8 @@ import { PageData } from '@shared/models/page/page-data';
import { isDefined, isEqual } from '@core/utils';
import { TranslateService } from '@ngx-translate/core';
import { AlarmInfo, AlarmSearchStatus, AlarmSeverity } from '../alarm.models';
import { Filter } from '@material-ui/icons';
import { DatePipe } from '@angular/common';
export enum EntityKeyType {
ATTRIBUTE = 'ATTRIBUTE',
@ -358,6 +360,98 @@ export interface FiltersInfo {
datasourceFilters: {[datasourceIndex: number]: FilterInfo};
}
export function keyFiltersToText(translate: TranslateService, datePipe: DatePipe, keyFilters: Array<KeyFilter>): string {
const filtersText = keyFilters.map(keyFilter =>
keyFilterToText(translate, datePipe, keyFilter,
keyFilters.length > 1 ? ComplexOperation.AND : undefined));
let result: string;
if (filtersText.length > 1) {
const andText = translate.instant('filter.operation.and');
result = filtersText.join(' <span class="tb-filter-complex-operation">' + andText + '</span> ');
} else {
result = filtersText[0];
}
return result;
}
export function keyFilterToText(translate: TranslateService, datePipe: DatePipe, keyFilter: KeyFilter,
parentComplexOperation?: ComplexOperation): string {
const keyFilterPredicate = keyFilter.predicate;
return keyFilterPredicateToText(translate, datePipe, keyFilter, keyFilterPredicate, parentComplexOperation);
}
export function keyFilterPredicateToText(translate: TranslateService,
datePipe: DatePipe,
keyFilter: KeyFilter,
keyFilterPredicate: KeyFilterPredicate,
parentComplexOperation?: ComplexOperation): string {
if (keyFilterPredicate.type === FilterPredicateType.COMPLEX) {
const complexPredicate = keyFilterPredicate as ComplexFilterPredicate;
const complexOperation = complexPredicate.operation;
const complexPredicatesText =
complexPredicate.predicates.map(predicate => keyFilterPredicateToText(translate, datePipe, keyFilter, predicate, complexOperation));
if (complexPredicatesText.length > 1) {
const operationText = translate.instant(complexOperationTranslationMap.get(complexOperation));
let result = complexPredicatesText.join(' <span class="tb-filter-complex-operation">' + operationText + '</span> ');
if (complexOperation === ComplexOperation.OR && parentComplexOperation && ComplexOperation.OR !== parentComplexOperation) {
result = `<span class="tb-filter-bracket"><span class="tb-left-bracket">(</span>${result}<span class="tb-right-bracket">)</span></span>`;
}
return result;
} else {
return complexPredicatesText[0];
}
} else {
return simpleKeyFilterPredicateToText(translate, datePipe, keyFilter, keyFilterPredicate);
}
}
function simpleKeyFilterPredicateToText(translate: TranslateService,
datePipe: DatePipe,
keyFilter: KeyFilter,
keyFilterPredicate: StringFilterPredicate |
NumericFilterPredicate |
BooleanFilterPredicate): string {
const key = keyFilter.key.key;
let operation: string;
let value: string;
const val = keyFilterPredicate.value;
const dynamicValue = !!val.dynamicValue && !!val.dynamicValue.sourceType;
if (dynamicValue) {
value = '<span class="tb-filter-dynamic-value"><span class="tb-filter-dynamic-source">' +
translate.instant(dynamicValueSourceTypeTranslationMap.get(val.dynamicValue.sourceType)) + '</span>';
value += '.<span class="tb-filter-value">' + val.dynamicValue.sourceAttribute + '</span></span>';
}
switch (keyFilterPredicate.type) {
case FilterPredicateType.STRING:
operation = translate.instant(stringOperationTranslationMap.get(keyFilterPredicate.operation));
if (keyFilterPredicate.ignoreCase) {
operation += ' ' + translate.instant('filter.ignore-case');
}
if (!dynamicValue) {
value = `'${keyFilterPredicate.value.defaultValue}'`;
}
break;
case FilterPredicateType.NUMERIC:
operation = translate.instant(numericOperationTranslationMap.get(keyFilterPredicate.operation));
if (!dynamicValue) {
if (keyFilter.valueType === EntityKeyValueType.DATE_TIME) {
value = datePipe.transform(keyFilterPredicate.value.defaultValue, 'yyyy-MM-dd HH:mm');
} else {
value = keyFilterPredicate.value.defaultValue + '';
}
}
break;
case FilterPredicateType.BOOLEAN:
operation = translate.instant(booleanOperationTranslationMap.get(keyFilterPredicate.operation));
value = translate.instant(keyFilterPredicate.value.defaultValue ? 'value.true' : 'value.false');
break;
}
if (!dynamicValue) {
value = `<span class="tb-filter-value">${value}</span>`;
}
return `<span class="tb-filter-predicate"><span class="tb-filter-entity-key">${key}</span> <span class="tb-filter-simple-operation">${operation}</span> ${value}</span>`;
}
export function keyFilterInfosToKeyFilters(keyFilterInfos: Array<KeyFilterInfo>): Array<KeyFilter> {
const keyFilters: Array<KeyFilter> = [];
for (const keyFilterInfo of keyFilterInfos) {

12
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -813,15 +813,16 @@
"alarm-rules": "Alarm rules ({{count}})",
"add-alarm-rule": "Add alarm rule",
"edit-alarm-rule": "Edit alarm rule",
"alarm-rule-details": "Alarm rule details",
"alarm-type": "Alarm type",
"alarm-type-required": "Alarm type is required.",
"alarm-type-pattern-hint": "Alarm type pattern, use <code>${metaKeyName}</code> to substitute variables from metadata",
"create-alarm-pattern": "Create <b>{{alarmType}}</b> alarm",
"create-alarm-rules": "Create alarm rules",
"no-create-alarm-rules": "No create conditions configured",
"clear-alarm-rule": "Clear alarm rule",
"add-create-alarm-rule": "Add create alarm rule",
"add-clear-alarm-rule": "Add clear alarm rule",
"no-clear-alarm-rule": "No clear condition configured",
"add-create-alarm-rule": "Add create condition",
"add-clear-alarm-rule": "Add clear condition",
"select-alarm-severity": "Select alarm severity",
"alarm-severity-required": "Alarm severity is required.",
"condition-duration": "Condition duration",
@ -831,6 +832,7 @@
"condition-duration-value-required": "Duration value is required.",
"condition-duration-time-unit-required": "Time unit is required.",
"advanced-settings": "Advanced settings",
"alarm-rule-details": "Details",
"propagate-alarm": "Propagate alarm",
"alarm-details": "Alarm details",
"alarm-rule-condition": "Alarm rule condition",
@ -1277,6 +1279,8 @@
"filter": "Filter",
"editable": "Editable",
"no-filters-found": "No filters found.",
"no-filter-text": "No filter specified",
"add-filter-prompt": "Please add filter",
"no-filter-matching": "'{{filter}}' not found.",
"create-new-filter": "Create a new one!",
"filter-required": "Filter is required.",
@ -1295,7 +1299,7 @@
"and": "and",
"or": "or"
},
"ignore-case": "Ignore case",
"ignore-case": "ignore case",
"value": "Value",
"remove-filter": "Remove filter",
"no-filters": "No filters configured",

Loading…
Cancel
Save