Merge pull request #4327 from vvlladd28/bug/validator/alarm-rule

UI: Fixed alarm rules validation in change keyType or valueType
This commit is contained in:
Igor Kulikov 2021-04-14 15:14:39 +03:00 committed by GitHub
commit 59b5f7352e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 199 additions and 56 deletions

View File

@ -15,11 +15,21 @@
/// ///
import { Component, forwardRef, Input, OnInit } from '@angular/core'; import { Component, forwardRef, Input, OnInit } from '@angular/core';
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; import {
ControlValueAccessor,
FormBuilder,
FormGroup,
NG_VALIDATORS,
NG_VALUE_ACCESSOR,
ValidationErrors,
Validator,
Validators
} from '@angular/forms';
import { import {
BooleanFilterPredicate, BooleanFilterPredicate,
BooleanOperation, BooleanOperation,
booleanOperationTranslationMap, EntityKeyValueType, booleanOperationTranslationMap,
EntityKeyValueType,
FilterPredicateType FilterPredicateType
} from '@shared/models/query/query.models'; } from '@shared/models/query/query.models';
@ -32,10 +42,15 @@ import {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => BooleanFilterPredicateComponent), useExisting: forwardRef(() => BooleanFilterPredicateComponent),
multi: true multi: true
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => BooleanFilterPredicateComponent),
multi: true
} }
] ]
}) })
export class BooleanFilterPredicateComponent implements ControlValueAccessor, OnInit { export class BooleanFilterPredicateComponent implements ControlValueAccessor, Validator, OnInit {
@Input() disabled: boolean; @Input() disabled: boolean;
@ -73,7 +88,7 @@ export class BooleanFilterPredicateComponent implements ControlValueAccessor, On
registerOnTouched(fn: any): void { registerOnTouched(fn: any): void {
} }
setDisabledState?(isDisabled: boolean): void { setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled; this.disabled = isDisabled;
if (this.disabled) { if (this.disabled) {
this.booleanFilterPredicateFormGroup.disable({emitEvent: false}); this.booleanFilterPredicateFormGroup.disable({emitEvent: false});
@ -82,17 +97,20 @@ export class BooleanFilterPredicateComponent implements ControlValueAccessor, On
} }
} }
validate(): ValidationErrors | null {
return this.booleanFilterPredicateFormGroup ? null : {
booleanFilterPredicate: {valid: false}
};
}
writeValue(predicate: BooleanFilterPredicate): void { writeValue(predicate: BooleanFilterPredicate): void {
this.booleanFilterPredicateFormGroup.get('operation').patchValue(predicate.operation, {emitEvent: false}); this.booleanFilterPredicateFormGroup.get('operation').patchValue(predicate.operation, {emitEvent: false});
this.booleanFilterPredicateFormGroup.get('value').patchValue(predicate.value, {emitEvent: false}); this.booleanFilterPredicateFormGroup.get('value').patchValue(predicate.value, {emitEvent: false});
} }
private updateModel() { private updateModel() {
let predicate: BooleanFilterPredicate = null; const predicate: BooleanFilterPredicate = this.booleanFilterPredicateFormGroup.getRawValue();
if (this.booleanFilterPredicateFormGroup.valid) {
predicate = this.booleanFilterPredicateFormGroup.getRawValue();
predicate.type = FilterPredicateType.BOOLEAN; predicate.type = FilterPredicateType.BOOLEAN;
}
this.propagateChange(predicate); this.propagateChange(predicate);
} }

View File

@ -16,11 +16,7 @@
import { Component, forwardRef, Input, OnInit } from '@angular/core'; import { Component, forwardRef, Input, OnInit } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { import { ComplexFilterPredicateInfo, EntityKeyValueType } from '@shared/models/query/query.models';
ComplexFilterPredicate,
ComplexFilterPredicateInfo,
EntityKeyValueType
} from '@shared/models/query/query.models';
import { MatDialog } from '@angular/material/dialog'; import { MatDialog } from '@angular/material/dialog';
import { import {
ComplexFilterPredicateDialogComponent, ComplexFilterPredicateDialogComponent,
@ -71,7 +67,7 @@ export class ComplexFilterPredicateComponent implements ControlValueAccessor, On
registerOnTouched(fn: any): void { registerOnTouched(fn: any): void {
} }
setDisabledState?(isDisabled: boolean): void { setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled; this.disabled = isDisabled;
} }

View File

@ -21,7 +21,10 @@ import {
FormArray, FormArray,
FormBuilder, FormBuilder,
FormGroup, FormGroup,
NG_VALIDATORS,
NG_VALUE_ACCESSOR, NG_VALUE_ACCESSOR,
ValidationErrors,
Validator,
Validators Validators
} from '@angular/forms'; } from '@angular/forms';
import { Observable, of, Subscription } from 'rxjs'; import { Observable, of, Subscription } from 'rxjs';
@ -49,10 +52,15 @@ import { map } from 'rxjs/operators';
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => FilterPredicateListComponent), useExisting: forwardRef(() => FilterPredicateListComponent),
multi: true multi: true
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => FilterPredicateListComponent),
multi: true
} }
] ]
}) })
export class FilterPredicateListComponent implements ControlValueAccessor, OnInit { export class FilterPredicateListComponent implements ControlValueAccessor, Validator, OnInit {
@Input() disabled: boolean; @Input() disabled: boolean;
@ -108,6 +116,12 @@ export class FilterPredicateListComponent implements ControlValueAccessor, OnIni
} }
} }
validate(control: AbstractControl): ValidationErrors | null {
return this.filterListFormGroup.valid ? null : {
filterList: {valid: false}
};
}
writeValue(predicates: Array<KeyFilterPredicateInfo>): void { writeValue(predicates: Array<KeyFilterPredicateInfo>): void {
if (this.valueChangeSubscription) { if (this.valueChangeSubscription) {
this.valueChangeSubscription.unsubscribe(); this.valueChangeSubscription.unsubscribe();
@ -178,7 +192,7 @@ export class FilterPredicateListComponent implements ControlValueAccessor, OnIni
private updateModel() { private updateModel() {
const predicates: Array<KeyFilterPredicateInfo> = this.filterListFormGroup.getRawValue().predicates; const predicates: Array<KeyFilterPredicateInfo> = this.filterListFormGroup.getRawValue().predicates;
if (this.filterListFormGroup.valid && predicates.length) { if (predicates.length) {
this.propagateChange(predicates); this.propagateChange(predicates);
} else { } else {
this.propagateChange(null); this.propagateChange(null);

View File

@ -19,7 +19,10 @@ import {
ControlValueAccessor, ControlValueAccessor,
FormBuilder, FormBuilder,
FormGroup, FormGroup,
NG_VALIDATORS,
NG_VALUE_ACCESSOR, NG_VALUE_ACCESSOR,
ValidationErrors,
Validator,
ValidatorFn, ValidatorFn,
Validators Validators
} from '@angular/forms'; } from '@angular/forms';
@ -39,10 +42,15 @@ import {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => FilterPredicateValueComponent), useExisting: forwardRef(() => FilterPredicateValueComponent),
multi: true multi: true
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => FilterPredicateValueComponent),
multi: true
} }
] ]
}) })
export class FilterPredicateValueComponent implements ControlValueAccessor, OnInit { export class FilterPredicateValueComponent implements ControlValueAccessor, Validator, OnInit {
private readonly inheritModeForSources: DynamicValueSourceType[] = [ private readonly inheritModeForSources: DynamicValueSourceType[] = [
DynamicValueSourceType.CURRENT_CUSTOMER, DynamicValueSourceType.CURRENT_CUSTOMER,
@ -62,7 +70,22 @@ export class FilterPredicateValueComponent implements ControlValueAccessor, OnIn
} }
} }
@Input() onlyUserDynamicSource = false; private onlyUserDynamicSourceValue = false;
@Input()
set onlyUserDynamicSource(dynamicMode: boolean) {
this.onlyUserDynamicSourceValue = dynamicMode;
if (this.filterPredicateValueFormGroup) {
this.updateValidationDynamicMode();
setTimeout(() => {
this.updateModel();
}, 0);
}
}
get onlyUserDynamicSource(): boolean {
return this.onlyUserDynamicSourceValue;
}
@Input() @Input()
valueType: EntityKeyValueType; valueType: EntityKeyValueType;
@ -83,6 +106,7 @@ export class FilterPredicateValueComponent implements ControlValueAccessor, OnIn
allow = true; allow = true;
private propagateChange = null; private propagateChange = null;
private propagateChangePending = false;
constructor(private fb: FormBuilder) { constructor(private fb: FormBuilder) {
} }
@ -126,6 +150,7 @@ export class FilterPredicateValueComponent implements ControlValueAccessor, OnIn
this.updateShowInheritMode(sourceType); this.updateShowInheritMode(sourceType);
} }
); );
this.updateValidationDynamicMode();
this.filterPredicateValueFormGroup.valueChanges.subscribe(() => { this.filterPredicateValueFormGroup.valueChanges.subscribe(() => {
this.updateModel(); this.updateModel();
}); });
@ -133,12 +158,18 @@ export class FilterPredicateValueComponent implements ControlValueAccessor, OnIn
registerOnChange(fn: any): void { registerOnChange(fn: any): void {
this.propagateChange = fn; this.propagateChange = fn;
if (this.propagateChangePending) {
this.propagateChangePending = false;
setTimeout(() => {
this.updateModel();
}, 0);
}
} }
registerOnTouched(fn: any): void { registerOnTouched(fn: any): void {
} }
setDisabledState?(isDisabled: boolean): void { setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled; this.disabled = isDisabled;
if (this.disabled) { if (this.disabled) {
this.filterPredicateValueFormGroup.disable({emitEvent: false}); this.filterPredicateValueFormGroup.disable({emitEvent: false});
@ -147,28 +178,35 @@ export class FilterPredicateValueComponent implements ControlValueAccessor, OnIn
} }
} }
validate(): ValidationErrors | null {
return this.filterPredicateValueFormGroup.valid ? null : {
filterPredicateValue: {valid: false}
};
}
writeValue(predicateValue: FilterPredicateValue<string | number | boolean>): void { writeValue(predicateValue: FilterPredicateValue<string | number | boolean>): void {
this.propagateChangePending = false;
this.filterPredicateValueFormGroup.get('defaultValue').patchValue(predicateValue.defaultValue, {emitEvent: false}); this.filterPredicateValueFormGroup.get('defaultValue').patchValue(predicateValue.defaultValue, {emitEvent: false});
this.filterPredicateValueFormGroup.get('dynamicValue.sourceType').patchValue(predicateValue.dynamicValue ? this.filterPredicateValueFormGroup.get('dynamicValue').patchValue({
predicateValue.dynamicValue.sourceType : null, {emitEvent: false}); sourceType: predicateValue.dynamicValue ? predicateValue.dynamicValue.sourceType : null,
this.filterPredicateValueFormGroup.get('dynamicValue.sourceAttribute').patchValue(predicateValue.dynamicValue ? sourceAttribute: predicateValue.dynamicValue ? predicateValue.dynamicValue.sourceAttribute : null,
predicateValue.dynamicValue.sourceAttribute : null, {emitEvent: false}); inherit: predicateValue.dynamicValue ? predicateValue.dynamicValue.inherit : false
this.filterPredicateValueFormGroup.get('dynamicValue.inherit').patchValue(predicateValue.dynamicValue ? }, {emitEvent: this.onlyUserDynamicSource});
predicateValue.dynamicValue.inherit : false, {emitEvent: false});
this.updateShowInheritMode(predicateValue?.dynamicValue?.sourceType); this.updateShowInheritMode(predicateValue?.dynamicValue?.sourceType);
} }
private updateModel() { private updateModel() {
let predicateValue: FilterPredicateValue<string | number | boolean> = null; const predicateValue: FilterPredicateValue<string | number | boolean> = this.filterPredicateValueFormGroup.getRawValue();
if (this.filterPredicateValueFormGroup.valid) {
predicateValue = this.filterPredicateValueFormGroup.getRawValue();
if (predicateValue.dynamicValue) { if (predicateValue.dynamicValue) {
if (!predicateValue.dynamicValue.sourceType || !predicateValue.dynamicValue.sourceAttribute) { if (!predicateValue.dynamicValue.sourceType || !predicateValue.dynamicValue.sourceAttribute) {
predicateValue.dynamicValue = null; predicateValue.dynamicValue = null;
} }
} }
} if (this.propagateChange) {
this.propagateChange(predicateValue); this.propagateChange(predicateValue);
} else {
this.propagateChangePending = true;
}
} }
private updateShowInheritMode(sourceType: DynamicValueSourceType) { private updateShowInheritMode(sourceType: DynamicValueSourceType) {
@ -179,4 +217,16 @@ export class FilterPredicateValueComponent implements ControlValueAccessor, OnIn
this.inheritMode = false; this.inheritMode = false;
} }
} }
private updateValidationDynamicMode() {
if (this.onlyUserDynamicSource) {
this.filterPredicateValueFormGroup.get('dynamicValue.sourceType').setValidators(Validators.required);
this.filterPredicateValueFormGroup.get('dynamicValue.sourceAttribute').setValidators(Validators.required);
} else {
this.filterPredicateValueFormGroup.get('dynamicValue.sourceType').clearValidators();
this.filterPredicateValueFormGroup.get('dynamicValue.sourceAttribute').clearValidators();
}
this.filterPredicateValueFormGroup.get('dynamicValue.sourceType').updateValueAndValidity({emitEvent: false});
this.filterPredicateValueFormGroup.get('dynamicValue.sourceAttribute').updateValueAndValidity({emitEvent: false});
}
} }

View File

@ -15,11 +15,17 @@
/// ///
import { Component, forwardRef, Input, OnInit } from '@angular/core'; import { Component, forwardRef, Input, OnInit } from '@angular/core';
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms';
import { import {
EntityKeyValueType, ControlValueAccessor,
FilterPredicateType, KeyFilterPredicate, KeyFilterPredicateInfo FormBuilder,
} from '@shared/models/query/query.models'; FormGroup,
NG_VALIDATORS,
NG_VALUE_ACCESSOR,
ValidationErrors,
Validator,
Validators
} from '@angular/forms';
import { EntityKeyValueType, FilterPredicateType, KeyFilterPredicateInfo } from '@shared/models/query/query.models';
@Component({ @Component({
selector: 'tb-filter-predicate', selector: 'tb-filter-predicate',
@ -30,10 +36,15 @@ import {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => FilterPredicateComponent), useExisting: forwardRef(() => FilterPredicateComponent),
multi: true multi: true
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => FilterPredicateComponent),
multi: true
} }
] ]
}) })
export class FilterPredicateComponent implements ControlValueAccessor, OnInit { export class FilterPredicateComponent implements ControlValueAccessor, Validator, OnInit {
@Input() disabled: boolean; @Input() disabled: boolean;
@ -75,7 +86,7 @@ export class FilterPredicateComponent implements ControlValueAccessor, OnInit {
registerOnTouched(fn: any): void { registerOnTouched(fn: any): void {
} }
setDisabledState?(isDisabled: boolean): void { setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled; this.disabled = isDisabled;
if (this.disabled) { if (this.disabled) {
this.filterPredicateFormGroup.disable({emitEvent: false}); this.filterPredicateFormGroup.disable({emitEvent: false});
@ -84,6 +95,12 @@ export class FilterPredicateComponent implements ControlValueAccessor, OnInit {
} }
} }
validate(): ValidationErrors | null {
return this.filterPredicateFormGroup.valid ? null : {
filterPredicate: {valid: false}
};
}
writeValue(predicate: KeyFilterPredicateInfo): void { writeValue(predicate: KeyFilterPredicateInfo): void {
this.type = predicate.keyFilterPredicate.type; this.type = predicate.keyFilterPredicate.type;
this.filterPredicateFormGroup.get('predicate').patchValue(predicate.keyFilterPredicate, {emitEvent: false}); this.filterPredicateFormGroup.get('predicate').patchValue(predicate.keyFilterPredicate, {emitEvent: false});

View File

@ -22,7 +22,10 @@ import {
FormBuilder, FormBuilder,
FormControl, FormControl,
FormGroup, FormGroup,
NG_VALIDATORS,
NG_VALUE_ACCESSOR, NG_VALUE_ACCESSOR,
ValidationErrors,
Validator,
Validators Validators
} from '@angular/forms'; } from '@angular/forms';
import { Observable, Subscription } from 'rxjs'; import { Observable, Subscription } from 'rxjs';
@ -46,10 +49,15 @@ import { EntityId } from '@shared/models/id/entity-id';
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => KeyFilterListComponent), useExisting: forwardRef(() => KeyFilterListComponent),
multi: true multi: true
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => KeyFilterListComponent),
multi: true
} }
] ]
}) })
export class KeyFilterListComponent implements ControlValueAccessor, OnInit { export class KeyFilterListComponent implements ControlValueAccessor, Validator, OnInit {
@Input() disabled: boolean; @Input() disabled: boolean;
@ -104,6 +112,12 @@ export class KeyFilterListComponent implements ControlValueAccessor, OnInit {
} }
} }
validate(): ValidationErrors | null {
return this.keyFilterListFormGroup.valid && this.keyFiltersControl.valid ? null : {
keyFilterList: {valid: false}
};
}
writeValue(keyFilters: Array<KeyFilterInfo>): void { writeValue(keyFilters: Array<KeyFilterInfo>): void {
if (this.valueChangeSubscription) { if (this.valueChangeSubscription) {
this.valueChangeSubscription.unsubscribe(); this.valueChangeSubscription.unsubscribe();

View File

@ -15,7 +15,16 @@
/// ///
import { Component, forwardRef, Input, OnInit } from '@angular/core'; import { Component, forwardRef, Input, OnInit } from '@angular/core';
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; import {
ControlValueAccessor,
FormBuilder,
FormGroup,
NG_VALIDATORS,
NG_VALUE_ACCESSOR,
ValidationErrors,
Validator,
Validators
} from '@angular/forms';
import { import {
EntityKeyValueType, EntityKeyValueType,
FilterPredicateType, FilterPredicateType,
@ -33,10 +42,15 @@ import {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => NumericFilterPredicateComponent), useExisting: forwardRef(() => NumericFilterPredicateComponent),
multi: true multi: true
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => NumericFilterPredicateComponent),
multi: true
} }
] ]
}) })
export class NumericFilterPredicateComponent implements ControlValueAccessor, OnInit { export class NumericFilterPredicateComponent implements ControlValueAccessor, Validator, OnInit {
@Input() disabled: boolean; @Input() disabled: boolean;
@ -76,7 +90,7 @@ export class NumericFilterPredicateComponent implements ControlValueAccessor, On
registerOnTouched(fn: any): void { registerOnTouched(fn: any): void {
} }
setDisabledState?(isDisabled: boolean): void { setDisabledState(isDisabled: boolean): void {
this.disabled = isDisabled; this.disabled = isDisabled;
if (this.disabled) { if (this.disabled) {
this.numericFilterPredicateFormGroup.disable({emitEvent: false}); this.numericFilterPredicateFormGroup.disable({emitEvent: false});
@ -85,17 +99,20 @@ export class NumericFilterPredicateComponent implements ControlValueAccessor, On
} }
} }
validate(): ValidationErrors | null {
return this.numericFilterPredicateFormGroup.valid ? null : {
numericFilterPredicate: {valid: false}
};
}
writeValue(predicate: NumericFilterPredicate): void { writeValue(predicate: NumericFilterPredicate): void {
this.numericFilterPredicateFormGroup.get('operation').patchValue(predicate.operation, {emitEvent: false}); this.numericFilterPredicateFormGroup.get('operation').patchValue(predicate.operation, {emitEvent: false});
this.numericFilterPredicateFormGroup.get('value').patchValue(predicate.value, {emitEvent: false}); this.numericFilterPredicateFormGroup.get('value').patchValue(predicate.value, {emitEvent: false});
} }
private updateModel() { private updateModel() {
let predicate: NumericFilterPredicate = null; const predicate: NumericFilterPredicate = this.numericFilterPredicateFormGroup.getRawValue();
if (this.numericFilterPredicateFormGroup.valid) {
predicate = this.numericFilterPredicateFormGroup.getRawValue();
predicate.type = FilterPredicateType.NUMERIC; predicate.type = FilterPredicateType.NUMERIC;
}
this.propagateChange(predicate); this.propagateChange(predicate);
} }

View File

@ -15,7 +15,16 @@
/// ///
import { Component, forwardRef, Input, OnInit } from '@angular/core'; import { Component, forwardRef, Input, OnInit } from '@angular/core';
import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR, Validators } from '@angular/forms'; import {
ControlValueAccessor,
FormBuilder,
FormGroup,
NG_VALIDATORS,
NG_VALUE_ACCESSOR,
ValidationErrors,
Validator,
Validators
} from '@angular/forms';
import { import {
EntityKeyValueType, EntityKeyValueType,
FilterPredicateType, FilterPredicateType,
@ -33,10 +42,15 @@ import {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => StringFilterPredicateComponent), useExisting: forwardRef(() => StringFilterPredicateComponent),
multi: true multi: true
},
{
provide: NG_VALIDATORS,
useExisting: forwardRef(() => StringFilterPredicateComponent),
multi: true
} }
] ]
}) })
export class StringFilterPredicateComponent implements ControlValueAccessor, OnInit { export class StringFilterPredicateComponent implements ControlValueAccessor, Validator, OnInit {
@Input() disabled: boolean; @Input() disabled: boolean;
@ -90,12 +104,15 @@ export class StringFilterPredicateComponent implements ControlValueAccessor, OnI
this.stringFilterPredicateFormGroup.get('ignoreCase').patchValue(predicate.ignoreCase, {emitEvent: false}); this.stringFilterPredicateFormGroup.get('ignoreCase').patchValue(predicate.ignoreCase, {emitEvent: false});
} }
private updateModel() { validate(c): ValidationErrors {
let predicate: StringFilterPredicate = null; return this.stringFilterPredicateFormGroup.valid ? null : {
if (this.stringFilterPredicateFormGroup.valid) { stringFilterPredicate: {valid: false}
predicate = this.stringFilterPredicateFormGroup.getRawValue(); };
predicate.type = FilterPredicateType.STRING;
} }
private updateModel() {
const predicate: StringFilterPredicate = this.stringFilterPredicateFormGroup.getRawValue();
predicate.type = FilterPredicateType.STRING;
this.propagateChange(predicate); this.propagateChange(predicate);
} }