Commit 7a19dee3eb4a441bf17dfd99e9978351bf5862fa

Authored by Igor Kulikov
1 parent cf6824cf

UI: Dynamic filter value configuration

... ... @@ -27,25 +27,33 @@ public class FilterPredicateValue<T> {
27 27 @Getter
28 28 private final T defaultValue;
29 29 @Getter
  30 + private final T userValue;
  31 + @Getter
30 32 private final DynamicValue<T> dynamicValue;
31 33
32 34 public FilterPredicateValue(T defaultValue) {
33   - this(defaultValue, null);
  35 + this(defaultValue, null, null);
34 36 }
35 37
36 38 @JsonCreator
37 39 public FilterPredicateValue(@JsonProperty("defaultValue") T defaultValue,
  40 + @JsonProperty("userValue") T userValue,
38 41 @JsonProperty("dynamicValue") DynamicValue<T> dynamicValue) {
39 42 this.defaultValue = defaultValue;
  43 + this.userValue = userValue;
40 44 this.dynamicValue = dynamicValue;
41 45 }
42 46
43 47 @JsonIgnore
44 48 public T getValue() {
45   - if (this.dynamicValue != null && this.dynamicValue.getResolvedValue() != null) {
46   - return this.dynamicValue.getResolvedValue();
  49 + if (this.userValue != null) {
  50 + return this.userValue;
47 51 } else {
48   - return defaultValue;
  52 + if (this.dynamicValue != null && this.dynamicValue.getResolvedValue() != null) {
  53 + return this.dynamicValue.getResolvedValue();
  54 + } else {
  55 + return defaultValue;
  56 + }
49 57 }
50 58 }
51 59
... ...
... ... @@ -15,7 +15,7 @@
15 15 limitations under the License.
16 16
17 17 -->
18   -<form [formGroup]="complexFilterFormGroup" (ngSubmit)="save()" style="width: 700px;">
  18 +<form [formGroup]="complexFilterFormGroup" (ngSubmit)="save()" style="width: 900px;">
19 19 <mat-toolbar color="primary">
20 20 <h2 translate>filter.complex-filter</h2>
21 21 <span fxFlex></span>
... ...
... ... @@ -16,7 +16,7 @@
16 16
17 17 -->
18 18 <div fxFlex fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px" [formGroup]="filterPredicateValueFormGroup">
19   - <div fxFlex fxLayout="column">
  19 + <div fxFlex fxLayout="column" [fxShow]="!dynamicMode">
20 20 <div fxFlex fxLayout="column" [ngSwitch]="valueType">
21 21 <ng-template [ngSwitchCase]="valueTypeEnum.STRING">
22 22 <mat-form-field floatLabel="always" hideRequiredMarker fxFlex class="mat-block">
... ... @@ -43,6 +43,40 @@
43 43 </mat-checkbox>
44 44 </ng-template>
45 45 </div>
46   - <div class="tb-hint">Default value</div>
  46 + <div class="tb-hint" translate>filter.default-value</div>
47 47 </div>
  48 + <div fxFlex fxLayout="column" [fxShow]="dynamicMode">
  49 + <div fxFlex formGroupName="dynamicValue" fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
  50 + <div fxFlex fxLayout="column">
  51 + <mat-form-field floatLabel="always" hideRequiredMarker fxFlex class="mat-block">
  52 + <mat-label></mat-label>
  53 + <mat-select formControlName="sourceType" placeholder="{{'filter.dynamic-source-type' | translate}}">
  54 + <mat-option [value]="null">
  55 + {{'filter.no-dynamic-value' | translate}}
  56 + </mat-option>
  57 + <mat-option *ngFor="let sourceType of dynamicValueSourceTypes" [value]="sourceType">
  58 + {{dynamicValueSourceTypeTranslations.get(dynamicValueSourceTypeEnum[sourceType]) | translate}}
  59 + </mat-option>
  60 + </mat-select>
  61 + </mat-form-field>
  62 + <div class="tb-hint" translate>filter.dynamic-source-type</div>
  63 + </div>
  64 + <div fxFlex fxLayout="column">
  65 + <mat-form-field floatLabel="always" hideRequiredMarker fxFlex class="mat-block">
  66 + <mat-label></mat-label>
  67 + <input matInput formControlName="sourceAttribute" placeholder="{{'filter.source-attribute' | translate}}">
  68 + </mat-form-field>
  69 + <div class="tb-hint" translate>filter.source-attribute</div>
  70 + </div>
  71 + </div>
  72 + </div>
  73 + <button mat-icon-button
  74 + class="mat-elevation-z1 tb-mat-32"
  75 + color="primary"
  76 + type="button"
  77 + matTooltip="{{ (dynamicMode ? 'filter.switch-to-default-value' : 'filter.switch-to-dynamic-value') | translate }}"
  78 + matTooltipPosition="above"
  79 + (click)="dynamicMode = !dynamicMode">
  80 + <mat-icon class="tb-mat-20" [svgIcon]="dynamicMode ? 'mdi:numeric' : 'mdi:variable'"></mat-icon>
  81 + </button>
48 82 </div>
... ...
... ... @@ -23,7 +23,12 @@ import {
23 23 ValidatorFn,
24 24 Validators
25 25 } from '@angular/forms';
26   -import { EntityKeyValueType, FilterPredicateValue } from '@shared/models/query/query.models';
  26 +import {
  27 + DynamicValueSourceType,
  28 + dynamicValueSourceTypeTranslationMap,
  29 + EntityKeyValueType,
  30 + FilterPredicateValue
  31 +} from '@shared/models/query/query.models';
27 32
28 33 @Component({
29 34 selector: 'tb-filter-predicate-value',
... ... @@ -46,8 +51,14 @@ export class FilterPredicateValueComponent implements ControlValueAccessor, OnIn
46 51
47 52 valueTypeEnum = EntityKeyValueType;
48 53
  54 + dynamicValueSourceTypes = Object.keys(DynamicValueSourceType);
  55 + dynamicValueSourceTypeEnum = DynamicValueSourceType;
  56 + dynamicValueSourceTypeTranslations = dynamicValueSourceTypeTranslationMap;
  57 +
49 58 filterPredicateValueFormGroup: FormGroup;
50 59
  60 + dynamicMode = false;
  61 +
51 62 private propagateChange = null;
52 63
53 64 constructor(private fb: FormBuilder) {
... ... @@ -83,6 +94,13 @@ export class FilterPredicateValueComponent implements ControlValueAccessor, OnIn
83 94 }
84 95 )
85 96 });
  97 + this.filterPredicateValueFormGroup.get('dynamicValue').get('sourceType').valueChanges.subscribe(
  98 + (sourceType) => {
  99 + if (!sourceType) {
  100 + this.filterPredicateValueFormGroup.get('dynamicValue').get('sourceAttribute').patchValue(null, {emitEvent: false});
  101 + }
  102 + }
  103 + );
86 104 this.filterPredicateValueFormGroup.valueChanges.subscribe(() => {
87 105 this.updateModel();
88 106 });
... ... @@ -106,8 +124,10 @@ export class FilterPredicateValueComponent implements ControlValueAccessor, OnIn
106 124
107 125 writeValue(predicateValue: FilterPredicateValue<string | number | boolean>): void {
108 126 this.filterPredicateValueFormGroup.get('defaultValue').patchValue(predicateValue.defaultValue, {emitEvent: false});
109   - this.filterPredicateValueFormGroup.get('dynamicValue').patchValue(predicateValue.dynamicValue ?
110   - predicateValue.dynamicValue : { sourceType: null, sourceAttribute: null }, {emitEvent: false});
  127 + this.filterPredicateValueFormGroup.get('dynamicValue').get('sourceType').patchValue(predicateValue.dynamicValue ?
  128 + predicateValue.dynamicValue.sourceType : null, {emitEvent: false});
  129 + this.filterPredicateValueFormGroup.get('dynamicValue').get('sourceAttribute').patchValue(predicateValue.dynamicValue ?
  130 + predicateValue.dynamicValue.sourceAttribute : null, {emitEvent: false});
111 131 }
112 132
113 133 private updateModel() {
... ...
... ... @@ -16,7 +16,7 @@
16 16
17 17 -->
18 18 <div fxLayout="column" class="mat-content mat-padding">
19   - <div fxLayout="column" *ngFor="let filter of filtersInfo | keyvalue">
  19 + <div fxLayout="column" *ngFor="let filter of filtersInfo | keyvalue; let last = last">
20 20 <div fxFlex fxLayout="row" fxLayoutAlign="start center">
21 21 <mat-label fxFlex>{{filter.value.filter}}</mat-label>
22 22 <button mat-icon-button color="primary"
... ... @@ -28,6 +28,6 @@
28 28 <mat-icon>edit</mat-icon>
29 29 </button>
30 30 </div>
31   - <mat-divider></mat-divider>
  31 + <mat-divider *ngIf="!last"></mat-divider>
32 32 </div>
33 33 </div>
... ...
... ... @@ -15,7 +15,7 @@
15 15 limitations under the License.
16 16
17 17 -->
18   -<form [formGroup]="keyFilterFormGroup" (ngSubmit)="save()" style="width: 700px;">
  18 +<form [formGroup]="keyFilterFormGroup" (ngSubmit)="save()" style="width: 900px;">
19 19 <mat-toolbar color="primary">
20 20 <h2>{{(data.isAdd ? 'filter.add-key-filter' : 'filter.edit-key-filter') | translate}}</h2>
21 21 <span fxFlex></span>
... ...
... ... @@ -33,10 +33,11 @@ import { DialogComponent } from '@app/shared/components/dialog.component';
33 33 import { TranslateService } from '@ngx-translate/core';
34 34 import {
35 35 EntityKeyValueType,
36   - Filter,
  36 + Filter, FilterPredicateValue,
37 37 filterToUserFilterInfoList,
38 38 UserFilterInputInfo
39 39 } from '@shared/models/query/query.models';
  40 +import { isDefinedAndNotNull } from '@core/utils';
40 41
41 42 export interface UserFilterDialogData {
42 43 filter: Filter;
... ... @@ -81,15 +82,17 @@ export class UserFilterDialogComponent extends DialogComponent<UserFilterDialogC
81 82 }
82 83
83 84 private createUserInputFormControl(userInput: UserFilterInputInfo): AbstractControl {
  85 + const predicateValue: FilterPredicateValue<string | number | boolean> = (userInput.info.keyFilterPredicate as any).value;
  86 + const value = isDefinedAndNotNull(predicateValue.userValue) ? predicateValue.userValue : predicateValue.defaultValue;
84 87 const userInputControl = this.fb.group({
85 88 label: [userInput.label],
86 89 valueType: [userInput.valueType],
87   - value: [(userInput.info.keyFilterPredicate as any).value.defaultValue,
  90 + value: [value,
88 91 userInput.valueType === EntityKeyValueType.NUMERIC ||
89 92 userInput.valueType === EntityKeyValueType.DATE_TIME ? [Validators.required] : []]
90 93 });
91   - userInputControl.get('value').valueChanges.subscribe(value => {
92   - (userInput.info.keyFilterPredicate as any).value.defaultValue = value;
  94 + userInputControl.get('value').valueChanges.subscribe(userValue => {
  95 + (userInput.info.keyFilterPredicate as any).value.userValue = userValue;
93 96 });
94 97 return userInputControl;
95 98 }
... ...
... ... @@ -255,6 +255,7 @@ export interface DynamicValue<T> {
255 255
256 256 export interface FilterPredicateValue<T> {
257 257 defaultValue: T;
  258 + userValue?: T;
258 259 dynamicValue?: DynamicValue<T>;
259 260 }
260 261
... ...
... ... @@ -1230,7 +1230,13 @@
1230 1230 "time": "Time",
1231 1231 "current-tenant": "Current tenant",
1232 1232 "current-customer": "Current customer",
1233   - "current-user": "Current user"
  1233 + "current-user": "Current user",
  1234 + "default-value": "Default value",
  1235 + "dynamic-source-type": "Dynamic source type",
  1236 + "no-dynamic-value": "No dynamic value",
  1237 + "source-attribute": "Source attribute",
  1238 + "switch-to-dynamic-value": "Switch to dynamic value",
  1239 + "switch-to-default-value": "Switch to default value"
1234 1240 },
1235 1241 "fullscreen": {
1236 1242 "expand": "Expand to fullscreen",
... ...