UI: Dynamic filter value configuration
This commit is contained in:
		
							parent
							
								
									cf6824cf22
								
							
						
					
					
						commit
						7a19dee3eb
					
				@ -27,25 +27,33 @@ public class FilterPredicateValue<T> {
 | 
			
		||||
    @Getter
 | 
			
		||||
    private final T defaultValue;
 | 
			
		||||
    @Getter
 | 
			
		||||
    private final T userValue;
 | 
			
		||||
    @Getter
 | 
			
		||||
    private final DynamicValue<T> dynamicValue;
 | 
			
		||||
 | 
			
		||||
    public FilterPredicateValue(T defaultValue) {
 | 
			
		||||
        this(defaultValue, null);
 | 
			
		||||
        this(defaultValue, null, null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @JsonCreator
 | 
			
		||||
    public FilterPredicateValue(@JsonProperty("defaultValue") T defaultValue,
 | 
			
		||||
                                @JsonProperty("userValue") T userValue,
 | 
			
		||||
                                @JsonProperty("dynamicValue") DynamicValue<T> dynamicValue) {
 | 
			
		||||
        this.defaultValue = defaultValue;
 | 
			
		||||
        this.userValue = userValue;
 | 
			
		||||
        this.dynamicValue = dynamicValue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @JsonIgnore
 | 
			
		||||
    public T getValue() {
 | 
			
		||||
        if (this.dynamicValue != null && this.dynamicValue.getResolvedValue() != null) {
 | 
			
		||||
            return this.dynamicValue.getResolvedValue();
 | 
			
		||||
        if (this.userValue != null) {
 | 
			
		||||
            return this.userValue;
 | 
			
		||||
        } else {
 | 
			
		||||
            return defaultValue;
 | 
			
		||||
            if (this.dynamicValue != null && this.dynamicValue.getResolvedValue() != null) {
 | 
			
		||||
                return this.dynamicValue.getResolvedValue();
 | 
			
		||||
            } else {
 | 
			
		||||
                return defaultValue;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -15,7 +15,7 @@
 | 
			
		||||
    limitations under the License.
 | 
			
		||||
 | 
			
		||||
-->
 | 
			
		||||
<form [formGroup]="complexFilterFormGroup" (ngSubmit)="save()" style="width: 700px;">
 | 
			
		||||
<form [formGroup]="complexFilterFormGroup" (ngSubmit)="save()" style="width: 900px;">
 | 
			
		||||
  <mat-toolbar color="primary">
 | 
			
		||||
    <h2 translate>filter.complex-filter</h2>
 | 
			
		||||
    <span fxFlex></span>
 | 
			
		||||
 | 
			
		||||
@ -16,7 +16,7 @@
 | 
			
		||||
 | 
			
		||||
-->
 | 
			
		||||
<div fxFlex fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px" [formGroup]="filterPredicateValueFormGroup">
 | 
			
		||||
  <div fxFlex fxLayout="column">
 | 
			
		||||
  <div fxFlex fxLayout="column" [fxShow]="!dynamicMode">
 | 
			
		||||
    <div fxFlex fxLayout="column" [ngSwitch]="valueType">
 | 
			
		||||
      <ng-template [ngSwitchCase]="valueTypeEnum.STRING">
 | 
			
		||||
        <mat-form-field floatLabel="always" hideRequiredMarker fxFlex class="mat-block">
 | 
			
		||||
@ -43,6 +43,40 @@
 | 
			
		||||
        </mat-checkbox>
 | 
			
		||||
      </ng-template>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="tb-hint">Default value</div>
 | 
			
		||||
    <div class="tb-hint" translate>filter.default-value</div>
 | 
			
		||||
  </div>
 | 
			
		||||
  <div fxFlex fxLayout="column" [fxShow]="dynamicMode">
 | 
			
		||||
    <div fxFlex formGroupName="dynamicValue" fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="8px">
 | 
			
		||||
      <div fxFlex fxLayout="column">
 | 
			
		||||
        <mat-form-field floatLabel="always" hideRequiredMarker fxFlex class="mat-block">
 | 
			
		||||
          <mat-label></mat-label>
 | 
			
		||||
          <mat-select formControlName="sourceType" placeholder="{{'filter.dynamic-source-type' | translate}}">
 | 
			
		||||
            <mat-option [value]="null">
 | 
			
		||||
              {{'filter.no-dynamic-value' | translate}}
 | 
			
		||||
            </mat-option>
 | 
			
		||||
            <mat-option *ngFor="let sourceType of dynamicValueSourceTypes" [value]="sourceType">
 | 
			
		||||
              {{dynamicValueSourceTypeTranslations.get(dynamicValueSourceTypeEnum[sourceType]) | translate}}
 | 
			
		||||
            </mat-option>
 | 
			
		||||
          </mat-select>
 | 
			
		||||
        </mat-form-field>
 | 
			
		||||
        <div class="tb-hint" translate>filter.dynamic-source-type</div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div fxFlex fxLayout="column">
 | 
			
		||||
        <mat-form-field floatLabel="always" hideRequiredMarker fxFlex class="mat-block">
 | 
			
		||||
          <mat-label></mat-label>
 | 
			
		||||
          <input matInput formControlName="sourceAttribute" placeholder="{{'filter.source-attribute' | translate}}">
 | 
			
		||||
        </mat-form-field>
 | 
			
		||||
        <div class="tb-hint" translate>filter.source-attribute</div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
  <button mat-icon-button
 | 
			
		||||
          class="mat-elevation-z1 tb-mat-32"
 | 
			
		||||
          color="primary"
 | 
			
		||||
          type="button"
 | 
			
		||||
          matTooltip="{{ (dynamicMode ? 'filter.switch-to-default-value' : 'filter.switch-to-dynamic-value') | translate }}"
 | 
			
		||||
          matTooltipPosition="above"
 | 
			
		||||
          (click)="dynamicMode = !dynamicMode">
 | 
			
		||||
    <mat-icon class="tb-mat-20" [svgIcon]="dynamicMode ? 'mdi:numeric' : 'mdi:variable'"></mat-icon>
 | 
			
		||||
  </button>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
@ -23,7 +23,12 @@ import {
 | 
			
		||||
  ValidatorFn,
 | 
			
		||||
  Validators
 | 
			
		||||
} from '@angular/forms';
 | 
			
		||||
import { EntityKeyValueType, FilterPredicateValue } from '@shared/models/query/query.models';
 | 
			
		||||
import {
 | 
			
		||||
  DynamicValueSourceType,
 | 
			
		||||
  dynamicValueSourceTypeTranslationMap,
 | 
			
		||||
  EntityKeyValueType,
 | 
			
		||||
  FilterPredicateValue
 | 
			
		||||
} from '@shared/models/query/query.models';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'tb-filter-predicate-value',
 | 
			
		||||
@ -46,8 +51,14 @@ export class FilterPredicateValueComponent implements ControlValueAccessor, OnIn
 | 
			
		||||
 | 
			
		||||
  valueTypeEnum = EntityKeyValueType;
 | 
			
		||||
 | 
			
		||||
  dynamicValueSourceTypes = Object.keys(DynamicValueSourceType);
 | 
			
		||||
  dynamicValueSourceTypeEnum = DynamicValueSourceType;
 | 
			
		||||
  dynamicValueSourceTypeTranslations = dynamicValueSourceTypeTranslationMap;
 | 
			
		||||
 | 
			
		||||
  filterPredicateValueFormGroup: FormGroup;
 | 
			
		||||
 | 
			
		||||
  dynamicMode = false;
 | 
			
		||||
 | 
			
		||||
  private propagateChange = null;
 | 
			
		||||
 | 
			
		||||
  constructor(private fb: FormBuilder) {
 | 
			
		||||
@ -83,6 +94,13 @@ export class FilterPredicateValueComponent implements ControlValueAccessor, OnIn
 | 
			
		||||
        }
 | 
			
		||||
      )
 | 
			
		||||
    });
 | 
			
		||||
    this.filterPredicateValueFormGroup.get('dynamicValue').get('sourceType').valueChanges.subscribe(
 | 
			
		||||
      (sourceType) => {
 | 
			
		||||
        if (!sourceType) {
 | 
			
		||||
          this.filterPredicateValueFormGroup.get('dynamicValue').get('sourceAttribute').patchValue(null, {emitEvent: false});
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
    this.filterPredicateValueFormGroup.valueChanges.subscribe(() => {
 | 
			
		||||
      this.updateModel();
 | 
			
		||||
    });
 | 
			
		||||
@ -106,8 +124,10 @@ export class FilterPredicateValueComponent implements ControlValueAccessor, OnIn
 | 
			
		||||
 | 
			
		||||
  writeValue(predicateValue: FilterPredicateValue<string | number | boolean>): 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});
 | 
			
		||||
    this.filterPredicateValueFormGroup.get('dynamicValue').get('sourceType').patchValue(predicateValue.dynamicValue ?
 | 
			
		||||
      predicateValue.dynamicValue.sourceType : null, {emitEvent: false});
 | 
			
		||||
    this.filterPredicateValueFormGroup.get('dynamicValue').get('sourceAttribute').patchValue(predicateValue.dynamicValue ?
 | 
			
		||||
      predicateValue.dynamicValue.sourceAttribute : null, {emitEvent: false});
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private updateModel() {
 | 
			
		||||
 | 
			
		||||
@ -16,7 +16,7 @@
 | 
			
		||||
 | 
			
		||||
-->
 | 
			
		||||
<div fxLayout="column" class="mat-content mat-padding">
 | 
			
		||||
  <div fxLayout="column" *ngFor="let filter of filtersInfo | keyvalue">
 | 
			
		||||
  <div fxLayout="column" *ngFor="let filter of filtersInfo | keyvalue; let last = last">
 | 
			
		||||
    <div fxFlex fxLayout="row" fxLayoutAlign="start center">
 | 
			
		||||
      <mat-label fxFlex>{{filter.value.filter}}</mat-label>
 | 
			
		||||
      <button mat-icon-button color="primary"
 | 
			
		||||
@ -28,6 +28,6 @@
 | 
			
		||||
        <mat-icon>edit</mat-icon>
 | 
			
		||||
      </button>
 | 
			
		||||
    </div>
 | 
			
		||||
    <mat-divider></mat-divider>
 | 
			
		||||
    <mat-divider *ngIf="!last"></mat-divider>
 | 
			
		||||
  </div>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
@ -15,7 +15,7 @@
 | 
			
		||||
    limitations under the License.
 | 
			
		||||
 | 
			
		||||
-->
 | 
			
		||||
<form [formGroup]="keyFilterFormGroup" (ngSubmit)="save()" style="width: 700px;">
 | 
			
		||||
<form [formGroup]="keyFilterFormGroup" (ngSubmit)="save()" style="width: 900px;">
 | 
			
		||||
  <mat-toolbar color="primary">
 | 
			
		||||
    <h2>{{(data.isAdd ? 'filter.add-key-filter' : 'filter.edit-key-filter') | translate}}</h2>
 | 
			
		||||
    <span fxFlex></span>
 | 
			
		||||
 | 
			
		||||
@ -33,10 +33,11 @@ import { DialogComponent } from '@app/shared/components/dialog.component';
 | 
			
		||||
import { TranslateService } from '@ngx-translate/core';
 | 
			
		||||
import {
 | 
			
		||||
  EntityKeyValueType,
 | 
			
		||||
  Filter,
 | 
			
		||||
  Filter, FilterPredicateValue,
 | 
			
		||||
  filterToUserFilterInfoList,
 | 
			
		||||
  UserFilterInputInfo
 | 
			
		||||
} from '@shared/models/query/query.models';
 | 
			
		||||
import { isDefinedAndNotNull } from '@core/utils';
 | 
			
		||||
 | 
			
		||||
export interface UserFilterDialogData {
 | 
			
		||||
  filter: Filter;
 | 
			
		||||
@ -81,15 +82,17 @@ export class UserFilterDialogComponent extends DialogComponent<UserFilterDialogC
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private createUserInputFormControl(userInput: UserFilterInputInfo): AbstractControl {
 | 
			
		||||
    const predicateValue: FilterPredicateValue<string | number | boolean> = (userInput.info.keyFilterPredicate as any).value;
 | 
			
		||||
    const value = isDefinedAndNotNull(predicateValue.userValue) ? predicateValue.userValue : predicateValue.defaultValue;
 | 
			
		||||
    const userInputControl = this.fb.group({
 | 
			
		||||
      label: [userInput.label],
 | 
			
		||||
      valueType: [userInput.valueType],
 | 
			
		||||
      value: [(userInput.info.keyFilterPredicate as any).value.defaultValue,
 | 
			
		||||
      value: [value,
 | 
			
		||||
        userInput.valueType === EntityKeyValueType.NUMERIC ||
 | 
			
		||||
        userInput.valueType === EntityKeyValueType.DATE_TIME  ? [Validators.required] : []]
 | 
			
		||||
    });
 | 
			
		||||
    userInputControl.get('value').valueChanges.subscribe(value => {
 | 
			
		||||
      (userInput.info.keyFilterPredicate as any).value.defaultValue = value;
 | 
			
		||||
    userInputControl.get('value').valueChanges.subscribe(userValue => {
 | 
			
		||||
      (userInput.info.keyFilterPredicate as any).value.userValue = userValue;
 | 
			
		||||
    });
 | 
			
		||||
    return userInputControl;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -255,6 +255,7 @@ export interface DynamicValue<T> {
 | 
			
		||||
 | 
			
		||||
export interface FilterPredicateValue<T> {
 | 
			
		||||
  defaultValue: T;
 | 
			
		||||
  userValue?: T;
 | 
			
		||||
  dynamicValue?: DynamicValue<T>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1230,7 +1230,13 @@
 | 
			
		||||
         "time": "Time",
 | 
			
		||||
         "current-tenant": "Current tenant",
 | 
			
		||||
         "current-customer": "Current customer",
 | 
			
		||||
         "current-user": "Current user"
 | 
			
		||||
         "current-user": "Current user",
 | 
			
		||||
         "default-value": "Default value",
 | 
			
		||||
         "dynamic-source-type": "Dynamic source type",
 | 
			
		||||
         "no-dynamic-value": "No dynamic value",
 | 
			
		||||
         "source-attribute": "Source attribute",
 | 
			
		||||
         "switch-to-dynamic-value": "Switch to dynamic value",
 | 
			
		||||
         "switch-to-default-value": "Switch to default value"
 | 
			
		||||
    },
 | 
			
		||||
    "fullscreen": {
 | 
			
		||||
        "expand": "Expand to fullscreen",
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user