From 399bfb8dbda5439367310d71d320c05501ae599d Mon Sep 17 00:00:00 2001 From: Chantsova Ekaterina Date: Mon, 5 Aug 2024 18:48:52 +0300 Subject: [PATCH] UI: timeinterval component redesign --- .../time/timeinterval.component.html | 54 ++--- .../time/timeinterval.component.scss | 17 +- .../components/time/timeinterval.component.ts | 224 ++++++++++-------- .../time/timewindow-panel.component.html | 2 +- 4 files changed, 153 insertions(+), 144 deletions(-) diff --git a/ui-ngx/src/app/shared/components/time/timeinterval.component.html b/ui-ngx/src/app/shared/components/time/timeinterval.component.html index a67cbdd9be..dc81688418 100644 --- a/ui-ngx/src/app/shared/components/time/timeinterval.component.html +++ b/ui-ngx/src/app/shared/components/time/timeinterval.component.html @@ -15,43 +15,37 @@ limitations under the License. --> -
-
- - -
-
-
- - {{ predefinedName }} - - - {{ interval.name | translate:interval.translateParams }} - - - -
-
- +
+ + {{ predefinedName }} + + + {{ interval.name | translate:interval.translateParams }} + + + +
+
+ timeinterval.days - + - + timeinterval.hours - + - +
+
+ timeinterval.minutes - + - + timeinterval.seconds - + -
-
-
- - +
diff --git a/ui-ngx/src/app/shared/components/time/timeinterval.component.scss b/ui-ngx/src/app/shared/components/time/timeinterval.component.scss index ba1c7b8d5a..c91f37bb2d 100644 --- a/ui-ngx/src/app/shared/components/time/timeinterval.component.scss +++ b/ui-ngx/src/app/shared/components/time/timeinterval.component.scss @@ -18,22 +18,21 @@ :host { min-width: 355px; - .advanced-switch { - margin-bottom: 16px; + .tb-form-panel { + gap: 12px; } - .advanced-label { - margin: 5px 0; - } - - .hide-label { - margin-bottom: 5px; - margin-right: 5px; + .advanced-input { + gap: 8px; } @media #{$mat-xs} { min-width: 0; width: 100%; + + .advanced-input { + gap: 12px; + } } } diff --git a/ui-ngx/src/app/shared/components/time/timeinterval.component.ts b/ui-ngx/src/app/shared/components/time/timeinterval.component.ts index 4ffb18d624..9e533036d7 100644 --- a/ui-ngx/src/app/shared/components/time/timeinterval.component.ts +++ b/ui-ngx/src/app/shared/components/time/timeinterval.component.ts @@ -14,8 +14,8 @@ /// limitations under the License. /// -import { Component, EventEmitter, forwardRef, Input, OnInit, Output } from '@angular/core'; -import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; +import { Component, forwardRef, Input, OnDestroy, OnInit } from '@angular/core'; +import { ControlValueAccessor, FormBuilder, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms'; import { TimeService } from '@core/services/time.service'; import { coerceNumberProperty } from '@angular/cdk/coercion'; import { MatFormFieldAppearance, SubscriptSizing } from '@angular/material/form-field'; @@ -23,6 +23,8 @@ import { coerceBoolean } from '@shared/decorators/coercion'; import { Interval, IntervalMath, TimeInterval } from '@shared/models/time/time.models'; import { isDefined } from '@core/utils'; import { IntervalType } from '@shared/models/telemetry/telemetry.models'; +import { takeUntil } from 'rxjs/operators'; +import { Subject } from 'rxjs'; @Component({ selector: 'tb-timeinterval', @@ -36,7 +38,7 @@ import { IntervalType } from '@shared/models/telemetry/telemetry.models'; } ] }) -export class TimeintervalComponent implements OnInit, ControlValueAccessor { +export class TimeintervalComponent implements OnInit, ControlValueAccessor, OnDestroy { minValue: number; maxValue: number; @@ -67,10 +69,6 @@ export class TimeintervalComponent implements OnInit, ControlValueAccessor { @coerceBoolean() isEdit = false; - @Input() - @coerceBoolean() - hideFlag = false; - @Input() @coerceBoolean() disabledAdvanced = false; @@ -79,8 +77,6 @@ export class TimeintervalComponent implements OnInit, ControlValueAccessor { @coerceBoolean() useCalendarIntervals = false; - @Output() hideFlagChange = new EventEmitter(); - @Input() disabled: boolean; @Input() @@ -89,16 +85,12 @@ export class TimeintervalComponent implements OnInit, ControlValueAccessor { @Input() appearance: MatFormFieldAppearance = 'fill'; - days = 0; - hours = 0; - mins = 1; - secs = 0; - - interval: Interval = 0; intervals: Array; advanced = false; + timeintervalFormGroup: FormGroup; + customTimeInterval: TimeInterval = { name: 'timeinterval.custom', translateParams: {}, @@ -113,7 +105,43 @@ export class TimeintervalComponent implements OnInit, ControlValueAccessor { this.propagateChangeValue = value; }; - constructor(private timeService: TimeService) { + private destroy$ = new Subject(); + + constructor(private timeService: TimeService, + private fb: FormBuilder) { + this.timeintervalFormGroup = this.fb.group({ + interval: [ 1 ], + customInterval: this.fb.group({ + days: [ 0 ], + hours: [ 0 ], + mins: [ 1 ], + secs: [ 0 ] + }) + }); + + this.timeintervalFormGroup.get('interval').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe(() => this.onIntervalChange()); + + this.timeintervalFormGroup.get('customInterval').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe(() => this.updateView()); + + this.timeintervalFormGroup.get('customInterval.secs').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((secs) => this.onSecsChange(secs)); + + this.timeintervalFormGroup.get('customInterval.mins').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((mins) => this.onMinsChange(mins)); + + this.timeintervalFormGroup.get('customInterval.hours').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((hours) => this.onHoursChange(hours)); + + this.timeintervalFormGroup.get('customInterval.days').valueChanges.pipe( + takeUntil(this.destroy$) + ).subscribe((days) => this.onDaysChange(days)); } ngOnInit(): void { @@ -132,6 +160,11 @@ export class TimeintervalComponent implements OnInit, ControlValueAccessor { setDisabledState(isDisabled: boolean): void { this.disabled = isDisabled; + if (this.disabled) { + this.timeintervalFormGroup.disable({emitEvent: false}); + } else { + this.timeintervalFormGroup.enable({emitEvent: false}); + } } writeValue(interval: Interval): void { @@ -156,20 +189,31 @@ export class TimeintervalComponent implements OnInit, ControlValueAccessor { } private setInterval(interval: Interval) { - // if (!this.advanced) { - this.interval = interval; - // } + if (!this.advanced) { + this.timeintervalFormGroup.get('interval').patchValue(interval); + } else { + this.timeintervalFormGroup.get('interval').patchValue(IntervalType.CUSTOM); + this.setCustomInterval(interval); + } + } + + private setCustomInterval(interval: Interval) { const intervalSeconds = Math.floor(IntervalMath.numberValue(interval) / 1000); - this.days = Math.floor(intervalSeconds / 86400); - this.hours = Math.floor((intervalSeconds % 86400) / 3600); - this.mins = Math.floor(((intervalSeconds % 86400) % 3600) / 60); - this.secs = intervalSeconds % 60; + this.timeintervalFormGroup.get('customInterval').patchValue({ + days: Math.floor(intervalSeconds / 86400), + hours: Math.floor((intervalSeconds % 86400) / 3600), + mins: Math.floor(((intervalSeconds % 86400) % 3600) / 60), + secs: intervalSeconds % 60 + }); } private boundInterval(updateToPreferred = false) { const min = this.timeService.boundMinInterval(this.minValue); const max = this.timeService.boundMaxInterval(this.maxValue); this.intervals = this.timeService.getIntervals(this.minValue, this.maxValue, this.useCalendarIntervals); + if (!this.disabledAdvanced) { + this.intervals.push(this.customTimeInterval); + } if (this.rendered) { let newInterval = this.modelValue; const newIntervalMs = IntervalMath.numberValue(newInterval); @@ -195,7 +239,7 @@ export class TimeintervalComponent implements OnInit, ControlValueAccessor { let value: Interval = null; let interval: Interval; if (!this.advanced) { - interval = this.interval; + interval = this.timeintervalFormGroup.get('interval').value; if (!interval || typeof interval === 'number' && isNaN(interval)) { interval = this.calculateIntervalMs(); } @@ -211,118 +255,90 @@ export class TimeintervalComponent implements OnInit, ControlValueAccessor { } private calculateIntervalMs(): number { - return (this.days * 86400 + - this.hours * 3600 + - this.mins * 60 + - this.secs) * 1000; + const customInterval = this.timeintervalFormGroup.get('customInterval').value; + return (customInterval.days * 86400 + + customInterval.hours * 3600 + + customInterval.mins * 60 + + customInterval.secs) * 1000; } onIntervalChange() { - this.updateView(); - } - - onAdvancedChange() { - if (!this.advanced) { - this.interval = this.calculateIntervalMs(); - } else { - let interval = this.interval; - if (!interval || typeof interval === 'number' && isNaN(interval)) { - interval = this.calculateIntervalMs(); + const customIntervalSelected = this.timeintervalFormGroup.get('interval').value === IntervalType.CUSTOM; + if (customIntervalSelected !== this.advanced) { + this.advanced = customIntervalSelected; + if (this.advanced) { + this.setCustomInterval(this.modelValue); } - this.setInterval(interval); } this.updateView(); } - onHideFlagChange() { - this.hideFlagChange.emit(this.hideFlag); - } - - onTimeInputChange(type: string) { - switch (type) { - case 'secs': - setTimeout(() => this.onSecsChange(), 0); - break; - case 'mins': - setTimeout(() => this.onMinsChange(), 0); - break; - case 'hours': - setTimeout(() => this.onHoursChange(), 0); - break; - case 'days': - setTimeout(() => this.onDaysChange(), 0); - break; - } - } - - private onSecsChange() { - if (typeof this.secs === 'undefined') { + private onSecsChange(secs: number) { + const customInterval = this.timeintervalFormGroup.get('customInterval').value; + if (typeof secs === 'undefined') { return; } - if (this.secs < 0) { - if ((this.days + this.hours + this.mins) > 0) { - this.secs = this.secs + 60; - this.mins--; - this.onMinsChange(); + if (secs < 0) { + if ((customInterval.days + customInterval.hours + customInterval.mins) > 0) { + this.timeintervalFormGroup.get('customInterval.secs').patchValue(secs + 60, {emitEvent: false}); + this.timeintervalFormGroup.get('customInterval.mins').patchValue(customInterval.mins - 1, {emitEvent: true}); } else { - this.secs = 0; + this.timeintervalFormGroup.get('customInterval.secs').patchValue(0, {emitEvent: false}); } - } else if (this.secs >= 60) { - this.secs = this.secs - 60; - this.mins++; - this.onMinsChange(); + } else if (secs >= 60) { + this.timeintervalFormGroup.get('customInterval.secs').patchValue(secs - 60, {emitEvent: false}); + this.timeintervalFormGroup.get('customInterval.mins').patchValue(customInterval.mins + 1, {emitEvent: true}); } - this.updateView(); } - private onMinsChange() { - if (typeof this.mins === 'undefined') { + private onMinsChange(mins: number) { + const customInterval = this.timeintervalFormGroup.get('customInterval').value; + if (typeof mins === 'undefined') { return; } - if (this.mins < 0) { - if ((this.days + this.hours) > 0) { - this.mins = this.mins + 60; - this.hours--; - this.onHoursChange(); + if (mins < 0) { + if ((customInterval.days + customInterval.hours) > 0) { + this.timeintervalFormGroup.get('customInterval.mins').patchValue(mins + 60, {emitEvent: false}); + this.timeintervalFormGroup.get('customInterval.hours').patchValue(customInterval.hours - 1, {emitEvent: true}); } else { - this.mins = 0; + this.timeintervalFormGroup.get('customInterval.mins').patchValue(0, {emitEvent: false}); } - } else if (this.mins >= 60) { - this.mins = this.mins - 60; - this.hours++; - this.onHoursChange(); + } else if (mins >= 60) { + this.timeintervalFormGroup.get('customInterval.mins').patchValue(mins - 60, {emitEvent: false}); + this.timeintervalFormGroup.get('customInterval.hours').patchValue(customInterval.hours + 1, {emitEvent: true}); } - this.updateView(); } - private onHoursChange() { - if (typeof this.hours === 'undefined') { + private onHoursChange(hours: number) { + const customInterval = this.timeintervalFormGroup.get('customInterval').value; + if (typeof hours === 'undefined') { return; } - if (this.hours < 0) { - if (this.days > 0) { - this.hours = this.hours + 24; - this.days--; - this.onDaysChange(); + if (hours < 0) { + if (customInterval.days > 0) { + this.timeintervalFormGroup.get('customInterval.hours').patchValue(hours + 24, {emitEvent: false}); + this.timeintervalFormGroup.get('customInterval.days').patchValue(customInterval.days - 1, {emitEvent: true}); } else { - this.hours = 0; + this.timeintervalFormGroup.get('customInterval.hours').patchValue(0, {emitEvent: false}); } - } else if (this.hours >= 24) { - this.hours = this.hours - 24; - this.days++; - this.onDaysChange(); + } else if (hours >= 24) { + this.timeintervalFormGroup.get('customInterval.hours').patchValue(hours - 24, {emitEvent: false}); + this.timeintervalFormGroup.get('customInterval.days').patchValue(customInterval.days + 1, {emitEvent: true}); } - this.updateView(); } - private onDaysChange() { - if (typeof this.days === 'undefined') { + private onDaysChange(days: number) { + if (typeof days === 'undefined') { return; } - if (this.days < 0) { - this.days = 0; + if (days < 0) { + this.timeintervalFormGroup.get('customInterval.days').patchValue(0, {emitEvent: false}); } - this.updateView(); + } + + ngOnDestroy() { + this.destroy$.next(); + this.destroy$.complete(); } } diff --git a/ui-ngx/src/app/shared/components/time/timewindow-panel.component.html b/ui-ngx/src/app/shared/components/time/timewindow-panel.component.html index 03be25a760..dbb36b84a6 100644 --- a/ui-ngx/src/app/shared/components/time/timewindow-panel.component.html +++ b/ui-ngx/src/app/shared/components/time/timewindow-panel.component.html @@ -159,7 +159,7 @@
-
{{ 'aggregation.group-interval' | translate }}