From cf6824cf22b60a0e8d6464820a7dc71066414109 Mon Sep 17 00:00:00 2001 From: Igor Kulikov Date: Thu, 2 Jul 2020 20:05:34 +0300 Subject: [PATCH] Filter predicate dynamic value --- .../BaseEntityQueryControllerTest.java | 3 +- .../controller/ControllerSqlTestSuite.java | 4 +- .../data/query/BooleanFilterPredicate.java | 2 +- .../common/data/query/DynamicValue.java | 33 +++++ .../data/query/DynamicValueSourceType.java | 22 +++ .../data/query/FilterPredicateValue.java | 63 +++++++++ .../data/query/NumericFilterPredicate.java | 2 +- .../data/query/StringFilterPredicate.java | 2 +- .../dao/sql/query/EntityKeyMapping.java | 6 +- .../dao/service/BaseEntityServiceTest.java | 9 +- ui-ngx/src/app/core/http/entity.service.ts | 4 +- .../boolean-filter-predicate.component.html | 9 +- .../boolean-filter-predicate.component.ts | 13 +- .../filter-predicate-list.component.html | 2 +- .../filter-predicate-value.component.html | 48 +++++++ .../filter-predicate-value.component.ts | 126 ++++++++++++++++++ .../components/filter/filter-predicate.scss | 7 + .../numeric-filter-predicate.component.html | 21 +-- .../numeric-filter-predicate.component.ts | 13 +- .../string-filter-predicate.component.html | 10 +- .../string-filter-predicate.component.ts | 10 +- .../filter/user-filter-dialog.component.ts | 4 +- .../home/components/home-components.module.ts | 4 +- .../app/shared/models/query/query.models.ts | 42 +++++- .../assets/locale/locale.constant-en_US.json | 5 +- 25 files changed, 395 insertions(+), 69 deletions(-) create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/query/DynamicValue.java create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/query/DynamicValueSourceType.java create mode 100644 common/data/src/main/java/org/thingsboard/server/common/data/query/FilterPredicateValue.java create mode 100644 ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.html create mode 100644 ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.ts diff --git a/application/src/test/java/org/thingsboard/server/controller/BaseEntityQueryControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/BaseEntityQueryControllerTest.java index 75de7293f0..4c589da4db 100644 --- a/application/src/test/java/org/thingsboard/server/controller/BaseEntityQueryControllerTest.java +++ b/application/src/test/java/org/thingsboard/server/controller/BaseEntityQueryControllerTest.java @@ -44,6 +44,7 @@ import org.thingsboard.server.common.data.query.EntityDataSortOrder; import org.thingsboard.server.common.data.query.EntityKey; import org.thingsboard.server.common.data.query.EntityKeyType; import org.thingsboard.server.common.data.query.EntityListFilter; +import org.thingsboard.server.common.data.query.FilterPredicateValue; import org.thingsboard.server.common.data.query.KeyFilter; import org.thingsboard.server.common.data.query.NumericFilterPredicate; import org.thingsboard.server.common.data.security.Authority; @@ -259,7 +260,7 @@ public abstract class BaseEntityQueryControllerTest extends AbstractControllerTe KeyFilter highTemperatureFilter = new KeyFilter(); highTemperatureFilter.setKey(new EntityKey(EntityKeyType.ATTRIBUTE, "temperature")); NumericFilterPredicate predicate = new NumericFilterPredicate(); - predicate.setValue(45); + predicate.setValue(FilterPredicateValue.fromDouble(45)); predicate.setOperation(NumericFilterPredicate.NumericOperation.GREATER); highTemperatureFilter.setPredicate(predicate); List keyFilters = Collections.singletonList(highTemperatureFilter); diff --git a/application/src/test/java/org/thingsboard/server/controller/ControllerSqlTestSuite.java b/application/src/test/java/org/thingsboard/server/controller/ControllerSqlTestSuite.java index 0a5dae47b7..15da972cf5 100644 --- a/application/src/test/java/org/thingsboard/server/controller/ControllerSqlTestSuite.java +++ b/application/src/test/java/org/thingsboard/server/controller/ControllerSqlTestSuite.java @@ -26,9 +26,9 @@ import java.util.Arrays; @RunWith(ClasspathSuite.class) @ClasspathSuite.ClassnameFilters({ - "org.thingsboard.server.controller.sql.WebsocketApiSqlTest", +// "org.thingsboard.server.controller.sql.WebsocketApiSqlTest", // "org.thingsboard.server.controller.sql.EntityQueryControllerSqlTest", -// "org.thingsboard.server.controller.sql.*Test", + "org.thingsboard.server.controller.sql.*Test", }) public class ControllerSqlTestSuite { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/query/BooleanFilterPredicate.java b/common/data/src/main/java/org/thingsboard/server/common/data/query/BooleanFilterPredicate.java index d0c0413d9c..63d7cb2d9a 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/query/BooleanFilterPredicate.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/query/BooleanFilterPredicate.java @@ -21,7 +21,7 @@ import lombok.Data; public class BooleanFilterPredicate implements KeyFilterPredicate { private BooleanOperation operation; - private boolean value; + private FilterPredicateValue value; @Override public FilterPredicateType getType() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/query/DynamicValue.java b/common/data/src/main/java/org/thingsboard/server/common/data/query/DynamicValue.java new file mode 100644 index 0000000000..d80a679d30 --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/query/DynamicValue.java @@ -0,0 +1,33 @@ +/** + * 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. + */ +package org.thingsboard.server.common.data.query; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; +import lombok.Getter; + +@Data +public class DynamicValue { + + @JsonIgnore + private T resolvedValue; + + @Getter + private final DynamicValueSourceType sourceType; + @Getter + private final String sourceAttribute; + +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/query/DynamicValueSourceType.java b/common/data/src/main/java/org/thingsboard/server/common/data/query/DynamicValueSourceType.java new file mode 100644 index 0000000000..96734fde92 --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/query/DynamicValueSourceType.java @@ -0,0 +1,22 @@ +/** + * 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. + */ +package org.thingsboard.server.common.data.query; + +public enum DynamicValueSourceType { + CURRENT_TENANT, + CURRENT_CUSTOMER, + CURRENT_USER +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/query/FilterPredicateValue.java b/common/data/src/main/java/org/thingsboard/server/common/data/query/FilterPredicateValue.java new file mode 100644 index 0000000000..b2611f7216 --- /dev/null +++ b/common/data/src/main/java/org/thingsboard/server/common/data/query/FilterPredicateValue.java @@ -0,0 +1,63 @@ +/** + * 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. + */ +package org.thingsboard.server.common.data.query; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.Getter; + +@Data +public class FilterPredicateValue { + + @Getter + private final T defaultValue; + @Getter + private final DynamicValue dynamicValue; + + public FilterPredicateValue(T defaultValue) { + this(defaultValue, null); + } + + @JsonCreator + public FilterPredicateValue(@JsonProperty("defaultValue") T defaultValue, + @JsonProperty("dynamicValue") DynamicValue dynamicValue) { + this.defaultValue = defaultValue; + this.dynamicValue = dynamicValue; + } + + @JsonIgnore + public T getValue() { + if (this.dynamicValue != null && this.dynamicValue.getResolvedValue() != null) { + return this.dynamicValue.getResolvedValue(); + } else { + return defaultValue; + } + } + + public static FilterPredicateValue fromDouble(double value) { + return new FilterPredicateValue<>(value); + } + + public static FilterPredicateValue fromString(String value) { + return new FilterPredicateValue<>(value); + } + + public static FilterPredicateValue fromBoolean(boolean value) { + return new FilterPredicateValue<>(value); + } +} diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/query/NumericFilterPredicate.java b/common/data/src/main/java/org/thingsboard/server/common/data/query/NumericFilterPredicate.java index b00d7b9dee..3d0789e80e 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/query/NumericFilterPredicate.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/query/NumericFilterPredicate.java @@ -21,7 +21,7 @@ import lombok.Data; public class NumericFilterPredicate implements KeyFilterPredicate { private NumericOperation operation; - private double value; + private FilterPredicateValue value; @Override public FilterPredicateType getType() { diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/query/StringFilterPredicate.java b/common/data/src/main/java/org/thingsboard/server/common/data/query/StringFilterPredicate.java index 6c19565724..36a47b0675 100644 --- a/common/data/src/main/java/org/thingsboard/server/common/data/query/StringFilterPredicate.java +++ b/common/data/src/main/java/org/thingsboard/server/common/data/query/StringFilterPredicate.java @@ -21,7 +21,7 @@ import lombok.Data; public class StringFilterPredicate implements KeyFilterPredicate { private StringOperation operation; - private String value; + private FilterPredicateValue value; private boolean ignoreCase; @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java index 75be3610db..d1d037e90e 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/query/EntityKeyMapping.java @@ -440,7 +440,7 @@ public class EntityKeyMapping { private String buildStringPredicateQuery(QueryContext ctx, String field, StringFilterPredicate stringFilterPredicate) { String operationField = field; String paramName = getNextParameterName(field); - String value = stringFilterPredicate.getValue(); + String value = stringFilterPredicate.getValue().getValue(); String stringOperationQuery = ""; if (stringFilterPredicate.isIgnoreCase()) { value = value.toLowerCase(); @@ -476,7 +476,7 @@ public class EntityKeyMapping { private String buildNumericPredicateQuery(QueryContext ctx, String field, NumericFilterPredicate numericFilterPredicate) { String paramName = getNextParameterName(field); - ctx.addDoubleParameter(paramName, numericFilterPredicate.getValue()); + ctx.addDoubleParameter(paramName, numericFilterPredicate.getValue().getValue()); String numericOperationQuery = ""; switch (numericFilterPredicate.getOperation()) { case EQUAL: @@ -504,7 +504,7 @@ public class EntityKeyMapping { private String buildBooleanPredicateQuery(QueryContext ctx, String field, BooleanFilterPredicate booleanFilterPredicate) { String paramName = getNextParameterName(field); - ctx.addBooleanParameter(paramName, booleanFilterPredicate.isValue()); + ctx.addBooleanParameter(paramName, booleanFilterPredicate.getValue().getValue()); String booleanOperationQuery = ""; switch (booleanFilterPredicate.getOperation()) { case EQUAL: diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceTest.java index 2521a359af..8ec35b0b14 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseEntityServiceTest.java @@ -49,6 +49,7 @@ import org.thingsboard.server.common.data.query.EntityDataSortOrder; import org.thingsboard.server.common.data.query.EntityKey; import org.thingsboard.server.common.data.query.EntityKeyType; import org.thingsboard.server.common.data.query.EntityListFilter; +import org.thingsboard.server.common.data.query.FilterPredicateValue; import org.thingsboard.server.common.data.query.KeyFilter; import org.thingsboard.server.common.data.query.NumericFilterPredicate; import org.thingsboard.server.common.data.query.RelationsQueryFilter; @@ -239,7 +240,7 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { KeyFilter highTemperatureFilter = new KeyFilter(); highTemperatureFilter.setKey(new EntityKey(EntityKeyType.ATTRIBUTE, "temperature")); NumericFilterPredicate predicate = new NumericFilterPredicate(); - predicate.setValue(45); + predicate.setValue(FilterPredicateValue.fromDouble(45)); predicate.setOperation(NumericFilterPredicate.NumericOperation.GREATER); highTemperatureFilter.setPredicate(predicate); List keyFilters = Collections.singletonList(highTemperatureFilter); @@ -311,7 +312,7 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { KeyFilter highTemperatureFilter = new KeyFilter(); highTemperatureFilter.setKey(new EntityKey(EntityKeyType.ATTRIBUTE, "temperature")); NumericFilterPredicate predicate = new NumericFilterPredicate(); - predicate.setValue(45); + predicate.setValue(FilterPredicateValue.fromDouble(45)); predicate.setOperation(NumericFilterPredicate.NumericOperation.GREATER); highTemperatureFilter.setPredicate(predicate); List keyFilters = Collections.singletonList(highTemperatureFilter); @@ -382,7 +383,7 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { KeyFilter highTemperatureFilter = new KeyFilter(); highTemperatureFilter.setKey(new EntityKey(EntityKeyType.ATTRIBUTE, "consumption")); NumericFilterPredicate predicate = new NumericFilterPredicate(); - predicate.setValue(50); + predicate.setValue(FilterPredicateValue.fromDouble(50)); predicate.setOperation(NumericFilterPredicate.NumericOperation.GREATER); highTemperatureFilter.setPredicate(predicate); List keyFilters = Collections.singletonList(highTemperatureFilter); @@ -584,7 +585,7 @@ public abstract class BaseEntityServiceTest extends AbstractServiceTest { KeyFilter highTemperatureFilter = new KeyFilter(); highTemperatureFilter.setKey(new EntityKey(EntityKeyType.ATTRIBUTE, "temperature")); NumericFilterPredicate predicate = new NumericFilterPredicate(); - predicate.setValue(45); + predicate.setValue(FilterPredicateValue.fromDouble(45)); predicate.setOperation(NumericFilterPredicate.NumericOperation.GREATER); highTemperatureFilter.setPredicate(predicate); List keyFilters = Collections.singletonList(highTemperatureFilter); diff --git a/ui-ngx/src/app/core/http/entity.service.ts b/ui-ngx/src/app/core/http/entity.service.ts index 3040738c9a..7e3c160344 100644 --- a/ui-ngx/src/app/core/http/entity.service.ts +++ b/ui-ngx/src/app/core/http/entity.service.ts @@ -396,7 +396,9 @@ export class EntityService { type: FilterPredicateType.STRING, operation: StringOperation.STARTS_WITH, ignoreCase: true, - value: searchText + value: { + defaultValue: searchText + } } } ] : null diff --git a/ui-ngx/src/app/modules/home/components/filter/boolean-filter-predicate.component.html b/ui-ngx/src/app/modules/home/components/filter/boolean-filter-predicate.component.html index 22dafcec14..5e4c597447 100644 --- a/ui-ngx/src/app/modules/home/components/filter/boolean-filter-predicate.component.html +++ b/ui-ngx/src/app/modules/home/components/filter/boolean-filter-predicate.component.html @@ -15,7 +15,7 @@ limitations under the License. --> -
+
@@ -24,7 +24,8 @@ - - {{ (booleanFilterPredicateFormGroup.get('value').value ? 'value.true' : 'value.false') | translate }} - + +
diff --git a/ui-ngx/src/app/modules/home/components/filter/boolean-filter-predicate.component.ts b/ui-ngx/src/app/modules/home/components/filter/boolean-filter-predicate.component.ts index 237154814b..e7e1dd5c81 100644 --- a/ui-ngx/src/app/modules/home/components/filter/boolean-filter-predicate.component.ts +++ b/ui-ngx/src/app/modules/home/components/filter/boolean-filter-predicate.component.ts @@ -18,10 +18,10 @@ import { Component, forwardRef, Input, OnInit } from '@angular/core'; import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; import { BooleanFilterPredicate, - BooleanOperation, booleanOperationTranslationMap, + BooleanOperation, + booleanOperationTranslationMap, EntityKeyValueType, FilterPredicateType } from '@shared/models/query/query.models'; -import { isDefined } from '@core/utils'; @Component({ selector: 'tb-boolean-filter-predicate', @@ -39,6 +39,8 @@ export class BooleanFilterPredicateComponent implements ControlValueAccessor, On @Input() disabled: boolean; + valueTypeEnum = EntityKeyValueType; + booleanFilterPredicateFormGroup: FormGroup; booleanOperations = Object.keys(BooleanOperation); @@ -53,7 +55,7 @@ export class BooleanFilterPredicateComponent implements ControlValueAccessor, On ngOnInit(): void { this.booleanFilterPredicateFormGroup = this.fb.group({ operation: [BooleanOperation.EQUAL, [Validators.required]], - value: [false] + value: [null, [Validators.required]] }); this.booleanFilterPredicateFormGroup.valueChanges.subscribe(() => { this.updateModel(); @@ -78,16 +80,13 @@ export class BooleanFilterPredicateComponent implements ControlValueAccessor, On writeValue(predicate: BooleanFilterPredicate): void { this.booleanFilterPredicateFormGroup.get('operation').patchValue(predicate.operation, {emitEvent: false}); - this.booleanFilterPredicateFormGroup.get('value').patchValue(isDefined(predicate.value) ? predicate.value : false, {emitEvent: false}); + this.booleanFilterPredicateFormGroup.get('value').patchValue(predicate.value, {emitEvent: false}); } private updateModel() { let predicate: BooleanFilterPredicate = null; if (this.booleanFilterPredicateFormGroup.valid) { predicate = this.booleanFilterPredicateFormGroup.getRawValue(); - if (!isDefined(predicate.value)) { - predicate.value = false; - } predicate.type = FilterPredicateType.BOOLEAN; } this.propagateChange(predicate); diff --git a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html index 85a78b749c..dd42106dd3 100644 --- a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html +++ b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-list.component.html @@ -39,7 +39,7 @@
-
diff --git a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.html b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.html new file mode 100644 index 0000000000..c97ee2a100 --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.html @@ -0,0 +1,48 @@ + +
+
+
+ + + + + + + + + + + + + + + + + + {{ (filterPredicateValueFormGroup.get('defaultValue').value ? 'value.true' : 'value.false') | translate }} + + +
+
Default value
+
+
diff --git a/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.ts b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.ts new file mode 100644 index 0000000000..4997d270db --- /dev/null +++ b/ui-ngx/src/app/modules/home/components/filter/filter-predicate-value.component.ts @@ -0,0 +1,126 @@ +/// +/// 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, + FormGroup, + NG_VALUE_ACCESSOR, + ValidatorFn, + Validators +} from '@angular/forms'; +import { EntityKeyValueType, FilterPredicateValue } from '@shared/models/query/query.models'; + +@Component({ + selector: 'tb-filter-predicate-value', + templateUrl: './filter-predicate-value.component.html', + styleUrls: ['./filter-predicate.scss'], + providers: [ + { + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => FilterPredicateValueComponent), + multi: true + } + ] +}) +export class FilterPredicateValueComponent implements ControlValueAccessor, OnInit { + + @Input() disabled: boolean; + + @Input() + valueType: EntityKeyValueType; + + valueTypeEnum = EntityKeyValueType; + + filterPredicateValueFormGroup: FormGroup; + + private propagateChange = null; + + constructor(private fb: FormBuilder) { + } + + ngOnInit(): void { + let defaultValue: string | number | boolean; + let defaultValueValidators: ValidatorFn[]; + switch (this.valueType) { + case EntityKeyValueType.STRING: + defaultValue = ''; + defaultValueValidators = []; + break; + case EntityKeyValueType.NUMERIC: + defaultValue = 0; + defaultValueValidators = [Validators.required]; + break; + case EntityKeyValueType.BOOLEAN: + defaultValue = false; + defaultValueValidators = []; + break; + case EntityKeyValueType.DATE_TIME: + defaultValue = Date.now(); + defaultValueValidators = [Validators.required]; + break; + } + this.filterPredicateValueFormGroup = this.fb.group({ + defaultValue: [defaultValue, defaultValueValidators], + dynamicValue: this.fb.group( + { + sourceType: [null], + sourceAttribute: [null] + } + ) + }); + this.filterPredicateValueFormGroup.valueChanges.subscribe(() => { + this.updateModel(); + }); + } + + registerOnChange(fn: any): void { + this.propagateChange = fn; + } + + registerOnTouched(fn: any): void { + } + + setDisabledState?(isDisabled: boolean): void { + this.disabled = isDisabled; + if (this.disabled) { + this.filterPredicateValueFormGroup.disable({emitEvent: false}); + } else { + this.filterPredicateValueFormGroup.enable({emitEvent: false}); + } + } + + writeValue(predicateValue: FilterPredicateValue): void { + this.filterPredicateValueFormGroup.get('defaultValue').patchValue(predicateValue.defaultValue, {emitEvent: false}); + this.filterPredicateValueFormGroup.get('dynamicValue').patchValue(predicateValue.dynamicValue ? + predicateValue.dynamicValue : { sourceType: null, sourceAttribute: null }, {emitEvent: false}); + } + + private updateModel() { + let predicateValue: FilterPredicateValue = null; + if (this.filterPredicateValueFormGroup.valid) { + predicateValue = this.filterPredicateValueFormGroup.getRawValue(); + if (predicateValue.dynamicValue) { + if (!predicateValue.dynamicValue.sourceType || !predicateValue.dynamicValue.sourceAttribute) { + predicateValue.dynamicValue = null; + } + } + } + this.propagateChange(predicateValue); + } + +} diff --git a/ui-ngx/src/app/modules/home/components/filter/filter-predicate.scss b/ui-ngx/src/app/modules/home/components/filter/filter-predicate.scss index 3f86c48084..4b1b99f933 100644 --- a/ui-ngx/src/app/modules/home/components/filter/filter-predicate.scss +++ b/ui-ngx/src/app/modules/home/components/filter/filter-predicate.scss @@ -13,6 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +:host { + .tb-hint { + padding-bottom: 0; + } +} + :host ::ng-deep { mat-form-field { .mat-form-field-wrapper { diff --git a/ui-ngx/src/app/modules/home/components/filter/numeric-filter-predicate.component.html b/ui-ngx/src/app/modules/home/components/filter/numeric-filter-predicate.component.html index cd7055edc3..7a4a9c552b 100644 --- a/ui-ngx/src/app/modules/home/components/filter/numeric-filter-predicate.component.html +++ b/ui-ngx/src/app/modules/home/components/filter/numeric-filter-predicate.component.html @@ -15,7 +15,7 @@ limitations under the License. --> -
+
@@ -24,19 +24,8 @@ -
- - - - - - - - - -
+ +
diff --git a/ui-ngx/src/app/modules/home/components/filter/numeric-filter-predicate.component.ts b/ui-ngx/src/app/modules/home/components/filter/numeric-filter-predicate.component.ts index bc6db423c1..e9e4f89c3b 100644 --- a/ui-ngx/src/app/modules/home/components/filter/numeric-filter-predicate.component.ts +++ b/ui-ngx/src/app/modules/home/components/filter/numeric-filter-predicate.component.ts @@ -18,9 +18,11 @@ import { Component, forwardRef, Input, OnInit } from '@angular/core'; import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; import { EntityKeyValueType, - FilterPredicateType, NumericFilterPredicate, NumericOperation, numericOperationTranslationMap, + FilterPredicateType, + NumericFilterPredicate, + NumericOperation, + numericOperationTranslationMap, } from '@shared/models/query/query.models'; -import { isDefined } from '@core/utils'; @Component({ selector: 'tb-numeric-filter-predicate', @@ -56,7 +58,7 @@ export class NumericFilterPredicateComponent implements ControlValueAccessor, On ngOnInit(): void { this.numericFilterPredicateFormGroup = this.fb.group({ operation: [NumericOperation.EQUAL, [Validators.required]], - value: [0, [Validators.required]] + value: [null, [Validators.required]] }); this.numericFilterPredicateFormGroup.valueChanges.subscribe(() => { this.updateModel(); @@ -81,16 +83,13 @@ export class NumericFilterPredicateComponent implements ControlValueAccessor, On writeValue(predicate: NumericFilterPredicate): void { this.numericFilterPredicateFormGroup.get('operation').patchValue(predicate.operation, {emitEvent: false}); - this.numericFilterPredicateFormGroup.get('value').patchValue(isDefined(predicate.value) ? predicate.value : 0, {emitEvent: false}); + this.numericFilterPredicateFormGroup.get('value').patchValue(predicate.value, {emitEvent: false}); } private updateModel() { let predicate: NumericFilterPredicate = null; if (this.numericFilterPredicateFormGroup.valid) { predicate = this.numericFilterPredicateFormGroup.getRawValue(); - if (!predicate.value) { - predicate.value = 0; - } predicate.type = FilterPredicateType.NUMERIC; } this.propagateChange(predicate); diff --git a/ui-ngx/src/app/modules/home/components/filter/string-filter-predicate.component.html b/ui-ngx/src/app/modules/home/components/filter/string-filter-predicate.component.html index f05e0719b8..ef9f2c01e7 100644 --- a/ui-ngx/src/app/modules/home/components/filter/string-filter-predicate.component.html +++ b/ui-ngx/src/app/modules/home/components/filter/string-filter-predicate.component.html @@ -15,7 +15,7 @@ limitations under the License. --> -
+
@@ -28,8 +28,8 @@
- - - - + +
diff --git a/ui-ngx/src/app/modules/home/components/filter/string-filter-predicate.component.ts b/ui-ngx/src/app/modules/home/components/filter/string-filter-predicate.component.ts index a9dbbdff74..f115748e48 100644 --- a/ui-ngx/src/app/modules/home/components/filter/string-filter-predicate.component.ts +++ b/ui-ngx/src/app/modules/home/components/filter/string-filter-predicate.component.ts @@ -17,6 +17,7 @@ import { Component, forwardRef, Input, OnInit } from '@angular/core'; import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; import { + EntityKeyValueType, FilterPredicateType, StringFilterPredicate, StringOperation, @@ -39,6 +40,8 @@ export class StringFilterPredicateComponent implements ControlValueAccessor, OnI @Input() disabled: boolean; + valueTypeEnum = EntityKeyValueType; + stringFilterPredicateFormGroup: FormGroup; stringOperations = Object.keys(StringOperation); @@ -53,7 +56,7 @@ export class StringFilterPredicateComponent implements ControlValueAccessor, OnI ngOnInit(): void { this.stringFilterPredicateFormGroup = this.fb.group({ operation: [StringOperation.STARTS_WITH, [Validators.required]], - value: [''], + value: [null, [Validators.required]], ignoreCase: [false] }); this.stringFilterPredicateFormGroup.valueChanges.subscribe(() => { @@ -79,7 +82,7 @@ export class StringFilterPredicateComponent implements ControlValueAccessor, OnI writeValue(predicate: StringFilterPredicate): void { this.stringFilterPredicateFormGroup.get('operation').patchValue(predicate.operation, {emitEvent: false}); - this.stringFilterPredicateFormGroup.get('value').patchValue(predicate.value ? predicate.value : '', {emitEvent: false}); + this.stringFilterPredicateFormGroup.get('value').patchValue(predicate.value, {emitEvent: false}); this.stringFilterPredicateFormGroup.get('ignoreCase').patchValue(predicate.ignoreCase, {emitEvent: false}); } @@ -87,9 +90,6 @@ export class StringFilterPredicateComponent implements ControlValueAccessor, OnI let predicate: StringFilterPredicate = null; if (this.stringFilterPredicateFormGroup.valid) { predicate = this.stringFilterPredicateFormGroup.getRawValue(); - if (!predicate.value) { - predicate.value = ''; - } predicate.type = FilterPredicateType.STRING; } this.propagateChange(predicate); diff --git a/ui-ngx/src/app/modules/home/components/filter/user-filter-dialog.component.ts b/ui-ngx/src/app/modules/home/components/filter/user-filter-dialog.component.ts index 8d1a6e95a9..58634d7424 100644 --- a/ui-ngx/src/app/modules/home/components/filter/user-filter-dialog.component.ts +++ b/ui-ngx/src/app/modules/home/components/filter/user-filter-dialog.component.ts @@ -84,12 +84,12 @@ export class UserFilterDialogComponent extends DialogComponent { - (userInput.info.keyFilterPredicate as any).value = value; + (userInput.info.keyFilterPredicate as any).value.defaultValue = value; }); return userInputControl; } diff --git a/ui-ngx/src/app/modules/home/components/home-components.module.ts b/ui-ngx/src/app/modules/home/components/home-components.module.ts index af508dbb6c..f2b8e1f2d6 100644 --- a/ui-ngx/src/app/modules/home/components/home-components.module.ts +++ b/ui-ngx/src/app/modules/home/components/home-components.module.ts @@ -83,6 +83,7 @@ import { FiltersEditPanelComponent } from '@home/components/filter/filters-edit- import { UserFilterDialogComponent } from '@home/components/filter/user-filter-dialog.component'; import { FilterUserInfoComponent } from './filter/filter-user-info.component'; import { FilterUserInfoDialogComponent } from './filter/filter-user-info-dialog.component'; +import { FilterPredicateValueComponent } from './filter/filter-predicate-value.component'; @NgModule({ declarations: @@ -148,7 +149,8 @@ import { FilterUserInfoDialogComponent } from './filter/filter-user-info-dialog. FiltersEditPanelComponent, UserFilterDialogComponent, FilterUserInfoComponent, - FilterUserInfoDialogComponent + FilterUserInfoDialogComponent, + FilterPredicateValueComponent ], imports: [ CommonModule, diff --git a/ui-ngx/src/app/shared/models/query/query.models.ts b/ui-ngx/src/app/shared/models/query/query.models.ts index 80b2b86b33..d9bd0ca15f 100644 --- a/ui-ngx/src/app/shared/models/query/query.models.ts +++ b/ui-ngx/src/app/shared/models/query/query.models.ts @@ -138,16 +138,22 @@ export function createDefaultFilterPredicate(valueType: EntityKeyValueType, comp switch (predicate.type) { case FilterPredicateType.STRING: predicate.operation = StringOperation.STARTS_WITH; - predicate.value = ''; + predicate.value = { + defaultValue: '' + }; predicate.ignoreCase = false; break; case FilterPredicateType.NUMERIC: predicate.operation = NumericOperation.EQUAL; - predicate.value = valueType === EntityKeyValueType.DATE_TIME ? Date.now() : 0; + predicate.value = { + defaultValue: valueType === EntityKeyValueType.DATE_TIME ? Date.now() : 0 + }; break; case FilterPredicateType.BOOLEAN: predicate.operation = BooleanOperation.EQUAL; - predicate.value = false; + predicate.value = { + defaultValue: false + }; break; case FilterPredicateType.COMPLEX: predicate.operation = ComplexOperation.AND; @@ -228,23 +234,47 @@ export const complexOperationTranslationMap = new Map( ] ); +export enum DynamicValueSourceType { + CURRENT_TENANT = 'CURRENT_TENANT', + CURRENT_CUSTOMER = 'CURRENT_CUSTOMER', + CURRENT_USER = 'CURRENT_USER' +} + +export const dynamicValueSourceTypeTranslationMap = new Map( + [ + [DynamicValueSourceType.CURRENT_TENANT, 'filter.current-tenant'], + [DynamicValueSourceType.CURRENT_CUSTOMER, 'filter.current-customer'], + [DynamicValueSourceType.CURRENT_USER, 'filter.current-user'] + ] +); + +export interface DynamicValue { + sourceType: DynamicValueSourceType; + sourceAttribute: string; +} + +export interface FilterPredicateValue { + defaultValue: T; + dynamicValue?: DynamicValue; +} + export interface StringFilterPredicate { type: FilterPredicateType.STRING, operation: StringOperation; - value: string; + value: FilterPredicateValue; ignoreCase: boolean; } export interface NumericFilterPredicate { type: FilterPredicateType.NUMERIC, operation: NumericOperation; - value: number; + value: FilterPredicateValue; } export interface BooleanFilterPredicate { type: FilterPredicateType.BOOLEAN, operation: BooleanOperation; - value: boolean; + value: FilterPredicateValue; } export interface BaseComplexFilterPredicate { 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 08b2c4faa4..0a97e56e96 100644 --- a/ui-ngx/src/assets/locale/locale.constant-en_US.json +++ b/ui-ngx/src/assets/locale/locale.constant-en_US.json @@ -1227,7 +1227,10 @@ "remove-key-filter": "Remove key filter", "edit-key-filter": "Edit key filter", "date": "Date", - "time": "Time" + "time": "Time", + "current-tenant": "Current tenant", + "current-customer": "Current customer", + "current-user": "Current user" }, "fullscreen": { "expand": "Expand to fullscreen",