Merge pull request #12630 from ChantsovaEkaterina/improvement/datetime-period-validation
Timewindow date-time period - improve behavior on changing start/end time
This commit is contained in:
commit
1ca7e1de3e
@ -15,17 +15,17 @@
|
|||||||
limitations under the License.
|
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-form-field class="flex" [subscriptSizing]="subscriptSizing" [appearance]="appearance">
|
||||||
<mat-label translate>datetime.from</mat-label>
|
<mat-label translate>datetime.from</mat-label>
|
||||||
<mat-datetimepicker-toggle [for]="startDatePicker" matSuffix></mat-datetimepicker-toggle>
|
<mat-datetimepicker-toggle [for]="startDatePicker" matSuffix></mat-datetimepicker-toggle>
|
||||||
<mat-datetimepicker #startDatePicker type="datetime" openOnFocus="true"></mat-datetimepicker>
|
<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>
|
||||||
<mat-form-field class="flex" [subscriptSizing]="subscriptSizing" [appearance]="appearance">
|
<mat-form-field class="flex" [subscriptSizing]="subscriptSizing" [appearance]="appearance">
|
||||||
<mat-label translate>datetime.to</mat-label>
|
<mat-label translate>datetime.to</mat-label>
|
||||||
<mat-datetimepicker-toggle [for]="endDatePicker" matSuffix></mat-datetimepicker-toggle>
|
<mat-datetimepicker-toggle [for]="endDatePicker" matSuffix></mat-datetimepicker-toggle>
|
||||||
<mat-datetimepicker #endDatePicker type="datetime" openOnFocus="true"></mat-datetimepicker>
|
<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>
|
</mat-form-field>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@ -14,10 +14,17 @@
|
|||||||
/// limitations under the License.
|
/// limitations under the License.
|
||||||
///
|
///
|
||||||
|
|
||||||
import { Component, forwardRef, Input, OnInit } from '@angular/core';
|
import { Component, forwardRef, Input } from '@angular/core';
|
||||||
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
import { ControlValueAccessor, FormBuilder, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||||
import { FixedWindow } from '@shared/models/time/time.models';
|
import { DAY, FixedWindow, MINUTE } from '@shared/models/time/time.models';
|
||||||
import { MatFormFieldAppearance, SubscriptSizing } from '@angular/material/form-field';
|
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({
|
@Component({
|
||||||
selector: 'tb-datetime-period',
|
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;
|
@Input() disabled: boolean;
|
||||||
|
|
||||||
@ -41,25 +48,45 @@ export class DatetimePeriodComponent implements OnInit, ControlValueAccessor {
|
|||||||
@Input()
|
@Input()
|
||||||
appearance: MatFormFieldAppearance = 'fill';
|
appearance: MatFormFieldAppearance = 'fill';
|
||||||
|
|
||||||
modelValue: FixedWindow;
|
private modelValue: FixedWindow;
|
||||||
|
|
||||||
startDate: Date;
|
|
||||||
endDate: Date;
|
|
||||||
|
|
||||||
endTime: any;
|
|
||||||
|
|
||||||
maxStartDate: Date;
|
maxStartDate: Date;
|
||||||
minEndDate: Date;
|
|
||||||
maxEndDate: 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;
|
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 {
|
registerOnChange(fn: any): void {
|
||||||
@ -75,35 +102,38 @@ export class DatetimePeriodComponent implements OnInit, ControlValueAccessor {
|
|||||||
|
|
||||||
setDisabledState(isDisabled: boolean): void {
|
setDisabledState(isDisabled: boolean): void {
|
||||||
this.disabled = isDisabled;
|
this.disabled = isDisabled;
|
||||||
|
if (this.disabled) {
|
||||||
|
this.dateTimePeriodFormGroup.disable({emitEvent: false});
|
||||||
|
} else {
|
||||||
|
this.dateTimePeriodFormGroup.enable({emitEvent: false});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
writeValue(datePeriod: FixedWindow): void {
|
writeValue(datePeriod: FixedWindow): void {
|
||||||
this.modelValue = datePeriod;
|
this.modelValue = datePeriod;
|
||||||
if (this.modelValue) {
|
if (this.modelValue) {
|
||||||
this.startDate = new Date(this.modelValue.startTimeMs);
|
this.dateTimePeriodFormGroup.patchValue({
|
||||||
this.endDate = new Date(this.modelValue.endTimeMs);
|
startDate: new Date(this.modelValue.startTimeMs),
|
||||||
|
endDate: new Date(this.modelValue.endTimeMs)
|
||||||
|
}, {emitEvent: false});
|
||||||
} else {
|
} else {
|
||||||
const date = new Date();
|
const date = new Date();
|
||||||
this.startDate = new Date(
|
this.dateTimePeriodFormGroup.patchValue({
|
||||||
date.getFullYear(),
|
startDate: new Date(date.getTime() - DAY),
|
||||||
date.getMonth(),
|
endDate: date
|
||||||
date.getDate() - 1,
|
}, {emitEvent: false});
|
||||||
date.getHours(),
|
|
||||||
date.getMinutes(),
|
|
||||||
date.getSeconds(),
|
|
||||||
date.getMilliseconds());
|
|
||||||
this.endDate = date;
|
|
||||||
this.updateView();
|
this.updateView();
|
||||||
}
|
}
|
||||||
this.updateMinMaxDates();
|
this.updateMinMaxDates(this.dateTimePeriodFormGroup.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateView() {
|
private updateView() {
|
||||||
let value: FixedWindow = null;
|
let value: FixedWindow = null;
|
||||||
if (this.startDate && this.endDate) {
|
const dateTimePeriod = this.dateTimePeriodFormGroup.value;
|
||||||
|
if (dateTimePeriod.startDate && dateTimePeriod.endDate) {
|
||||||
value = {
|
value = {
|
||||||
startTimeMs: this.startDate.getTime(),
|
startTimeMs: dateTimePeriod.startDate.getTime(),
|
||||||
endTimeMs: this.endDate.getTime()
|
endTimeMs: dateTimePeriod.endDate.getTime()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
this.modelValue = value;
|
this.modelValue = value;
|
||||||
@ -114,32 +144,40 @@ export class DatetimePeriodComponent implements OnInit, ControlValueAccessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateMinMaxDates() {
|
private updateMinMaxDates(dateTimePeriod: Partial<DateTimePeriod>) {
|
||||||
this.maxStartDate = new Date(this.endDate.getTime() - 1000);
|
|
||||||
this.minEndDate = new Date(this.startDate.getTime() + 1000);
|
|
||||||
this.maxEndDate = new Date();
|
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() {
|
private onStartDateChange(startDate: Date) {
|
||||||
if (this.startDate) {
|
if (startDate) {
|
||||||
if (this.startDate.getTime() > this.maxStartDate.getTime()) {
|
if (startDate.getTime() > this.maxStartTs) {
|
||||||
this.startDate = new Date(this.maxStartDate.getTime());
|
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() {
|
private onEndDateChange(endDate: Date) {
|
||||||
if (this.endDate) {
|
if (endDate) {
|
||||||
if (this.endDate.getTime() < this.minEndDate.getTime()) {
|
if (endDate.getTime() > this.maxEndTs) {
|
||||||
this.endDate = new Date(this.minEndDate.getTime());
|
this.dateTimePeriodFormGroup.get('endDate').patchValue(new Date(this.maxEndTs), { emitEvent: false });
|
||||||
} else if (this.endDate.getTime() > this.maxEndDate.getTime()) {
|
}
|
||||||
this.endDate = new Date(this.maxEndDate.getTime());
|
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