UI: Date-time period - improve behaviour on changing start/end time
This commit is contained in:
		
							parent
							
								
									d55f36d803
								
							
						
					
					
						commit
						44009d4e6c
					
				@ -15,17 +15,17 @@
 | 
			
		||||
    limitations under the License.
 | 
			
		||||
 | 
			
		||||
-->
 | 
			
		||||
<section class="tb-form-row column-xs no-border no-padding tb-standard-fields">
 | 
			
		||||
<section class="tb-form-row column-xs no-border no-padding tb-standard-fields" [formGroup]="dateTimePeriodFormGroup">
 | 
			
		||||
    <mat-form-field class="flex" [subscriptSizing]="subscriptSizing" [appearance]="appearance">
 | 
			
		||||
      <mat-label translate>datetime.from</mat-label>
 | 
			
		||||
      <mat-datetimepicker-toggle [for]="startDatePicker" matSuffix></mat-datetimepicker-toggle>
 | 
			
		||||
      <mat-datetimepicker #startDatePicker type="datetime" openOnFocus="true"></mat-datetimepicker>
 | 
			
		||||
      <input matInput [disabled]="disabled" [(ngModel)]="startDate" [matDatetimepicker]="startDatePicker" (ngModelChange)="onStartDateChange()">
 | 
			
		||||
      <input matInput formControlName="startDate" [matDatetimepicker]="startDatePicker" [max]="maxStartDate">
 | 
			
		||||
    </mat-form-field>
 | 
			
		||||
    <mat-form-field class="flex" [subscriptSizing]="subscriptSizing" [appearance]="appearance">
 | 
			
		||||
      <mat-label translate>datetime.to</mat-label>
 | 
			
		||||
      <mat-datetimepicker-toggle [for]="endDatePicker" matSuffix></mat-datetimepicker-toggle>
 | 
			
		||||
      <mat-datetimepicker #endDatePicker type="datetime" openOnFocus="true"></mat-datetimepicker>
 | 
			
		||||
      <input matInput [disabled]="disabled" [(ngModel)]="endDate" [matDatetimepicker]="endDatePicker" (ngModelChange)="onEndDateChange()">
 | 
			
		||||
      <input matInput formControlName="endDate" [matDatetimepicker]="endDatePicker" [max]="maxEndDate">
 | 
			
		||||
    </mat-form-field>
 | 
			
		||||
</section>
 | 
			
		||||
 | 
			
		||||
@ -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<Date>(null),
 | 
			
		||||
    endDate: this.fb.control<Date>(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<DateTimePeriod>) {
 | 
			
		||||
    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();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user