diff --git a/ui-ngx/src/app/shared/components/aggregation/aggregation-type-select.component.ts b/ui-ngx/src/app/shared/components/aggregation/aggregation-type-select.component.ts index 7986a28f82..ddc9e544c4 100644 --- a/ui-ngx/src/app/shared/components/aggregation/aggregation-type-select.component.ts +++ b/ui-ngx/src/app/shared/components/aggregation/aggregation-type-select.component.ts @@ -14,12 +14,14 @@ /// limitations under the License. /// -import { Component, forwardRef, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core'; +import { Component, forwardRef, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core'; import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms'; import { TranslateService } from '@ngx-translate/core'; import { coerceBoolean } from '@shared/decorators/coercion'; import { MatFormFieldAppearance, SubscriptSizing } from '@angular/material/form-field'; import { aggregationTranslations, AggregationType } from '@shared/models/time/time.models'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; @Component({ selector: 'tb-aggregation-type-select', @@ -31,7 +33,7 @@ import { aggregationTranslations, AggregationType } from '@shared/models/time/ti multi: true }] }) -export class AggregationTypeSelectComponent implements ControlValueAccessor, OnInit, OnChanges { +export class AggregationTypeSelectComponent implements ControlValueAccessor, OnInit, OnChanges, OnDestroy { aggregationTypeFormGroup: FormGroup; @@ -75,6 +77,8 @@ export class AggregationTypeSelectComponent implements ControlValueAccessor, OnI private propagateChange = (v: any) => { }; + private destroy$ = new Subject(); + constructor(private translate: TranslateService, private fb: FormBuilder) { this.aggregationTypeFormGroup = this.fb.group({ @@ -91,10 +95,12 @@ export class AggregationTypeSelectComponent implements ControlValueAccessor, OnI ngOnInit() { this.aggregationTypes = this.allowedAggregationTypes?.length ? this.allowedAggregationTypes : this.allAggregationTypes; - this.aggregationTypeFormGroup.get('aggregationType').valueChanges.subscribe( + this.aggregationTypeFormGroup.get('aggregationType').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe( (value) => { let modelValue; - if (!value || value === '') { + if (!value) { modelValue = null; } else { modelValue = value; @@ -152,4 +158,9 @@ export class AggregationTypeSelectComponent implements ControlValueAccessor, OnI return ''; } } + + ngOnDestroy() { + this.destroy$.next(); + this.destroy$.complete(); + } } diff --git a/ui-ngx/src/app/shared/components/time/quick-time-interval.component.html b/ui-ngx/src/app/shared/components/time/quick-time-interval.component.html index 8eb18ea34b..b7cb004a75 100644 --- a/ui-ngx/src/app/shared/components/time/quick-time-interval.component.html +++ b/ui-ngx/src/app/shared/components/time/quick-time-interval.component.html @@ -15,10 +15,10 @@ limitations under the License. --> -
+
timewindow.interval - + {{ timeIntervalTranslationMap.get(interval) | translate}} diff --git a/ui-ngx/src/app/shared/components/time/quick-time-interval.component.ts b/ui-ngx/src/app/shared/components/time/quick-time-interval.component.ts index 87b3687d0e..247fd144ff 100644 --- a/ui-ngx/src/app/shared/components/time/quick-time-interval.component.ts +++ b/ui-ngx/src/app/shared/components/time/quick-time-interval.component.ts @@ -14,11 +14,13 @@ /// limitations under the License. /// -import { Component, forwardRef, Input, OnInit } from '@angular/core'; -import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; +import { Component, forwardRef, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core'; +import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms'; import { QuickTimeInterval, QuickTimeIntervalTranslationMap } from '@shared/models/time/time.models'; import { MatFormFieldAppearance, SubscriptSizing } from '@angular/material/form-field'; import { coerceBoolean } from '@shared/decorators/coercion'; +import { Subject } from 'rxjs'; +import { takeUntil } from 'rxjs/operators'; @Component({ selector: 'tb-quick-time-interval', @@ -32,7 +34,7 @@ import { coerceBoolean } from '@shared/decorators/coercion'; } ] }) -export class QuickTimeIntervalComponent implements OnInit, ControlValueAccessor { +export class QuickTimeIntervalComponent implements OnInit, ControlValueAccessor, OnChanges, OnDestroy { private allIntervals = Object.values(QuickTimeInterval); @@ -49,25 +51,60 @@ export class QuickTimeIntervalComponent implements OnInit, ControlValueAccessor @Input() onlyCurrentInterval = false; + @Input() + allowedIntervals: Array + @Input() subscriptSizing: SubscriptSizing = 'fixed'; @Input() appearance: MatFormFieldAppearance = 'fill'; + intervals: Array; + + private allAvailableIntervals: Array; + + quickIntervalFormGroup: FormGroup; + private propagateChange = (_: any) => {}; - constructor() { - } + private destroy$ = new Subject(); - get intervals() { - if (this.onlyCurrentInterval) { - return this.allIntervals.filter(interval => interval.startsWith('CURRENT_')); - } - return this.allIntervals; + constructor(private fb: FormBuilder) { + this.quickIntervalFormGroup = this.fb.group({ + interval: [ null ] + }); + this.quickIntervalFormGroup.get('interval').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((value) => { + let modelValue; + if (!value) { + modelValue = null; + } else { + modelValue = value; + } + this.updateView(modelValue); + }); } ngOnInit(): void { + this.allAvailableIntervals = this.getAllAvailableIntervals(); + this.intervals = this.allowedIntervals?.length ? this.allowedIntervals : this.allAvailableIntervals; + } + + ngOnChanges(changes: SimpleChanges): void { + for (const propName of Object.keys(changes)) { + const change = changes[propName]; + if (!change.firstChange && change.currentValue !== change.previousValue) { + if (propName === 'allowedIntervals') { + this.intervals = this.allowedIntervals?.length ? this.allowedIntervals : this.allAvailableIntervals; + const currentInterval: QuickTimeInterval = this.quickIntervalFormGroup.get('interval').value; + if (currentInterval && !this.intervals.includes(currentInterval)) { + this.quickIntervalFormGroup.get('interval').patchValue(this.intervals[0], {emitEvent: true}); + } + } + } + } } registerOnChange(fn: any): void { @@ -79,13 +116,39 @@ export class QuickTimeIntervalComponent implements OnInit, ControlValueAccessor setDisabledState(isDisabled: boolean): void { this.disabled = isDisabled; + if (this.disabled) { + this.quickIntervalFormGroup.disable({emitEvent: false}); + } else { + this.quickIntervalFormGroup.enable({emitEvent: false}); + } } writeValue(interval: QuickTimeInterval): void { - this.modelValue = interval; + if (interval != null) { + this.modelValue = interval; + this.quickIntervalFormGroup.get('interval').patchValue(interval, {emitEvent: true}); + } else { + this.modelValue = null; + this.quickIntervalFormGroup.get('interval').patchValue(null, {emitEvent: true}); + } } - onIntervalChange() { - this.propagateChange(this.modelValue); + updateView(value: QuickTimeInterval | null) { + if (this.modelValue !== value) { + this.modelValue = value; + this.propagateChange(this.modelValue); + } + } + + ngOnDestroy() { + this.destroy$.next(); + this.destroy$.complete(); + } + + private getAllAvailableIntervals() { + if (this.onlyCurrentInterval) { + return this.allIntervals.filter(interval => interval.startsWith('CURRENT_')); + } + return this.allIntervals; } } diff --git a/ui-ngx/src/app/shared/components/time/timewindow-config-dialog.component.html b/ui-ngx/src/app/shared/components/time/timewindow-config-dialog.component.html index 2b55e12f98..5d214fb435 100644 --- a/ui-ngx/src/app/shared/components/time/timewindow-config-dialog.component.html +++ b/ui-ngx/src/app/shared/components/time/timewindow-config-dialog.component.html @@ -89,6 +89,7 @@ onlyCurrentInterval="true" subscriptSizing="dynamic" appearance="outline" + [allowedIntervals]="timewindowForm.get('realtime.allowedQuickIntervals').value" [required]="timewindowForm.get('selectedTab').value === timewindowTypes.REALTIME && timewindowForm.get('realtime.realtimeType').value === realtimeTypes.INTERVAL">