UI: Dynamic filter value configuration

This commit is contained in:
Igor Kulikov 2020-07-03 12:15:11 +03:00
parent cf6824cf22
commit 7a19dee3eb
9 changed files with 90 additions and 18 deletions

View File

@ -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;
}
}
}

View File

@ -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>

View File

@ -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>

View File

@ -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() {

View File

@ -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>

View File

@ -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>

View File

@ -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;
}

View File

@ -255,6 +255,7 @@ export interface DynamicValue<T> {
export interface FilterPredicateValue<T> {
defaultValue: T;
userValue?: T;
dynamicValue?: DynamicValue<T>;
}

View File

@ -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",