From 44009d4e6cb9058b4489455a752a120ec803a193 Mon Sep 17 00:00:00 2001 From: Ekaterina Chantsova Date: Thu, 6 Feb 2025 19:50:36 +0200 Subject: [PATCH] UI: Date-time period - improve behaviour on changing start/end time --- .../time/datetime-period.component.html | 6 +- .../time/datetime-period.component.ts | 134 +++++++++++------- 2 files changed, 89 insertions(+), 51 deletions(-) diff --git a/ui-ngx/src/app/shared/components/time/datetime-period.component.html b/ui-ngx/src/app/shared/components/time/datetime-period.component.html index 84f6d29d68..03c5a6ac21 100644 --- a/ui-ngx/src/app/shared/components/time/datetime-period.component.html +++ b/ui-ngx/src/app/shared/components/time/datetime-period.component.html @@ -15,17 +15,17 @@ limitations under the License. --> -
+
datetime.from - + datetime.to - +
diff --git a/ui-ngx/src/app/shared/components/time/datetime-period.component.ts b/ui-ngx/src/app/shared/components/time/datetime-period.component.ts index c0fbaea21e..0e212f7630 100644 --- a/ui-ngx/src/app/shared/components/time/datetime-period.component.ts +++ b/ui-ngx/src/app/shared/components/time/datetime-period.component.ts @@ -14,10 +14,17 @@ /// limitations under the License. /// -import { Component, forwardRef, Input, OnInit } from '@angular/core'; -import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; -import { FixedWindow } from '@shared/models/time/time.models'; +import { Component, forwardRef, Input } from '@angular/core'; +import { ControlValueAccessor, FormBuilder, NG_VALUE_ACCESSOR } from '@angular/forms'; +import { DAY, FixedWindow, MINUTE } from '@shared/models/time/time.models'; import { MatFormFieldAppearance, SubscriptSizing } from '@angular/material/form-field'; +import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { distinctUntilChanged } from 'rxjs/operators'; + +interface DateTimePeriod { + startDate: Date; + endDate: Date; +} @Component({ selector: 'tb-datetime-period', @@ -31,7 +38,7 @@ import { MatFormFieldAppearance, SubscriptSizing } from '@angular/material/form- } ] }) -export class DatetimePeriodComponent implements OnInit, ControlValueAccessor { +export class DatetimePeriodComponent implements ControlValueAccessor { @Input() disabled: boolean; @@ -41,25 +48,45 @@ export class DatetimePeriodComponent implements OnInit, ControlValueAccessor { @Input() appearance: MatFormFieldAppearance = 'fill'; - modelValue: FixedWindow; - - startDate: Date; - endDate: Date; - - endTime: any; + private modelValue: FixedWindow; maxStartDate: Date; - minEndDate: Date; maxEndDate: Date; - changePending = false; + private maxStartDateTs: number; + private minEndDateTs: number; + private maxStartTs: number; + private maxEndTs: number; + + private timeShiftMs = MINUTE; + + dateTimePeriodFormGroup = this.fb.group({ + startDate: this.fb.control(null), + endDate: this.fb.control(null) + }); + + private changePending = false; private propagateChange = null; - constructor() { - } + constructor(private fb: FormBuilder) { + this.dateTimePeriodFormGroup.valueChanges.pipe( + distinctUntilChanged((prevDateTimePeriod, dateTimePeriod) => + prevDateTimePeriod.startDate === dateTimePeriod.startDate && prevDateTimePeriod.endDate === dateTimePeriod.endDate), + takeUntilDestroyed() + ).subscribe((dateTimePeriod: DateTimePeriod) => { + this.updateMinMaxDates(dateTimePeriod); + this.updateView(); + }); - ngOnInit(): void { + this.dateTimePeriodFormGroup.get('startDate').valueChanges.pipe( + distinctUntilChanged(), + takeUntilDestroyed() + ).subscribe(startDate => this.onStartDateChange(startDate)); + this.dateTimePeriodFormGroup.get('endDate').valueChanges.pipe( + distinctUntilChanged(), + takeUntilDestroyed() + ).subscribe(endDate => this.onEndDateChange(endDate)); } registerOnChange(fn: any): void { @@ -75,35 +102,38 @@ export class DatetimePeriodComponent implements OnInit, ControlValueAccessor { setDisabledState(isDisabled: boolean): void { this.disabled = isDisabled; + if (this.disabled) { + this.dateTimePeriodFormGroup.disable({emitEvent: false}); + } else { + this.dateTimePeriodFormGroup.enable({emitEvent: false}); + } } writeValue(datePeriod: FixedWindow): void { this.modelValue = datePeriod; if (this.modelValue) { - this.startDate = new Date(this.modelValue.startTimeMs); - this.endDate = new Date(this.modelValue.endTimeMs); + this.dateTimePeriodFormGroup.patchValue({ + startDate: new Date(this.modelValue.startTimeMs), + endDate: new Date(this.modelValue.endTimeMs) + }, {emitEvent: false}); } else { const date = new Date(); - this.startDate = new Date( - date.getFullYear(), - date.getMonth(), - date.getDate() - 1, - date.getHours(), - date.getMinutes(), - date.getSeconds(), - date.getMilliseconds()); - this.endDate = date; + this.dateTimePeriodFormGroup.patchValue({ + startDate: new Date(date.getTime() - DAY), + endDate: date + }, {emitEvent: false}); this.updateView(); } - this.updateMinMaxDates(); + this.updateMinMaxDates(this.dateTimePeriodFormGroup.value); } - updateView() { + private updateView() { let value: FixedWindow = null; - if (this.startDate && this.endDate) { + const dateTimePeriod = this.dateTimePeriodFormGroup.value; + if (dateTimePeriod.startDate && dateTimePeriod.endDate) { value = { - startTimeMs: this.startDate.getTime(), - endTimeMs: this.endDate.getTime() + startTimeMs: dateTimePeriod.startDate.getTime(), + endTimeMs: dateTimePeriod.endDate.getTime() }; } this.modelValue = value; @@ -114,32 +144,40 @@ export class DatetimePeriodComponent implements OnInit, ControlValueAccessor { } } - updateMinMaxDates() { - this.maxStartDate = new Date(this.endDate.getTime() - 1000); - this.minEndDate = new Date(this.startDate.getTime() + 1000); + private updateMinMaxDates(dateTimePeriod: Partial) { this.maxEndDate = new Date(); + this.maxEndTs = this.maxEndDate.getTime(); + this.maxStartTs = this.maxEndTs - this.timeShiftMs; + this.maxStartDate = new Date(this.maxStartTs); + + if (dateTimePeriod.endDate) { + this.maxStartDateTs = dateTimePeriod.endDate.getTime() - this.timeShiftMs; + } + if (dateTimePeriod.startDate) { + this.minEndDateTs = dateTimePeriod.startDate.getTime() + this.timeShiftMs; + } } - onStartDateChange() { - if (this.startDate) { - if (this.startDate.getTime() > this.maxStartDate.getTime()) { - this.startDate = new Date(this.maxStartDate.getTime()); + private onStartDateChange(startDate: Date) { + if (startDate) { + if (startDate.getTime() > this.maxStartTs) { + this.dateTimePeriodFormGroup.get('startDate').patchValue(new Date(this.maxStartTs), { emitEvent: false }); + } + if (startDate.getTime() > this.maxStartDateTs) { + this.dateTimePeriodFormGroup.get('endDate').patchValue(new Date(startDate.getTime() + this.timeShiftMs), { emitEvent: false }); } - this.updateMinMaxDates(); } - this.updateView(); } - onEndDateChange() { - if (this.endDate) { - if (this.endDate.getTime() < this.minEndDate.getTime()) { - this.endDate = new Date(this.minEndDate.getTime()); - } else if (this.endDate.getTime() > this.maxEndDate.getTime()) { - this.endDate = new Date(this.maxEndDate.getTime()); + private onEndDateChange(endDate: Date) { + if (endDate) { + if (endDate.getTime() > this.maxEndTs) { + this.dateTimePeriodFormGroup.get('endDate').patchValue(new Date(this.maxEndTs), { emitEvent: false }); + } + if (endDate.getTime() < this.minEndDateTs) { + this.dateTimePeriodFormGroup.get('startDate').patchValue(new Date(endDate.getTime() - this.timeShiftMs), { emitEvent: false }); } - this.updateMinMaxDates(); } - this.updateView(); } }