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