mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[APPS-2132] migrate components to date-fns (#9001)
* migrate edit process filter to date-fns * refresh unit tests * fix a11y for date-fns * Revert "fix a11y for date-fns" This reverts commit 2e706d4aed1b8a50d1de62fe11d9d528530d628c. * update e2e * start task fixes * cleanup code * remove fdescribe * remove moment, improve unit testing * remove dependency on date util * cleanup search date range component * cleanup code * migrate search date range component * revert e2e changes for now * extra fixes and tests * add missing functionality, extra tests * increase time constraints * improved code, disabled e2e * move e2e to unit tests, extra rework for insights * extra unit test for date range validation * migrate date-range to date-fns
This commit is contained in:
@@ -1,54 +1,50 @@
|
||||
<label for="adf-dateRange" >{{field.nameKey | translate}}</label><br>
|
||||
<label for="adf-dateRange">{{field.nameKey | translate}}</label><br />
|
||||
<div id="adf-dateRange" [formGroup]="dateRange">
|
||||
<small *ngIf="isStartDateGreaterThanEndDate()" class="adf-date-range-analytics-text-danger">
|
||||
{{'DATE-WIDGET.MESSAGES.START-LESS-THAN-END-DATE' | translate}}
|
||||
{{'DATE-WIDGET.MESSAGES.START-LESS-THAN-END-DATE' | translate}}
|
||||
</small>
|
||||
<small *ngIf="isStartDateEmpty()" class="adf-date-range-analytics-text-danger">
|
||||
{{'DATE-WIDGET.MESSAGES.START-DATE-REQUIRED' | translate}}
|
||||
{{'DATE-WIDGET.MESSAGES.START-DATE-REQUIRED' | translate}}
|
||||
</small>
|
||||
|
||||
<mat-grid-list cols="2" rowHeight="80px">
|
||||
<mat-grid-tile>
|
||||
<mat-form-field>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
formControlName="startDate"
|
||||
[matDatepicker]="startDate"
|
||||
[value]="startDatePicker"
|
||||
(keydown)="true"
|
||||
(dateChange)="onGroupValueChanged()"
|
||||
placeholder="{{'DATE-WIDGET.START-DATE' | translate}}"
|
||||
id="startDate_id"
|
||||
required>
|
||||
<mat-datepicker-toggle matSuffix [for]="startDate" ></mat-datepicker-toggle>
|
||||
</mat-form-field>
|
||||
<mat-datepicker
|
||||
#startDate
|
||||
[touchUi]="true">
|
||||
</mat-datepicker>
|
||||
</mat-grid-tile>
|
||||
<mat-grid-tile>
|
||||
<mat-form-field>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
formControlName="endDate"
|
||||
[matDatepicker]="endDate"
|
||||
[value]="endDatePicker"
|
||||
(keydown)="true"
|
||||
(dateChange)="onGroupValueChanged()"
|
||||
placeholder="{{'DATE-WIDGET.END-DATE' | translate}}"
|
||||
id="endDate_id"
|
||||
required>
|
||||
<mat-datepicker-toggle matSuffix [for]="endDate" ></mat-datepicker-toggle>
|
||||
</mat-form-field>
|
||||
<mat-datepicker
|
||||
#endDate
|
||||
[touchUi]="true">
|
||||
</mat-datepicker>
|
||||
</mat-grid-tile>
|
||||
</mat-grid-list>
|
||||
<mat-grid-list cols="2" rowHeight="80px">
|
||||
<mat-grid-tile>
|
||||
<mat-form-field>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
formControlName="startDate"
|
||||
[matDatepicker]="startDate"
|
||||
[value]="startDateValue"
|
||||
(keydown)="true"
|
||||
(dateChange)="onGroupValueChanged()"
|
||||
placeholder="{{'DATE-WIDGET.START-DATE' | translate}}"
|
||||
id="startDate_id"
|
||||
required
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="startDate"></mat-datepicker-toggle>
|
||||
</mat-form-field>
|
||||
<mat-datepicker #startDate [touchUi]="true"></mat-datepicker>
|
||||
</mat-grid-tile>
|
||||
<mat-grid-tile>
|
||||
<mat-form-field>
|
||||
<input
|
||||
matInput
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
formControlName="endDate"
|
||||
[matDatepicker]="endDate"
|
||||
[value]="endDateValue"
|
||||
(keydown)="true"
|
||||
(dateChange)="onGroupValueChanged()"
|
||||
placeholder="{{'DATE-WIDGET.END-DATE' | translate}}"
|
||||
id="endDate_id"
|
||||
required
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="endDate"></mat-datepicker-toggle>
|
||||
</mat-form-field>
|
||||
<mat-datepicker #endDate [touchUi]="true"></mat-datepicker>
|
||||
</mat-grid-tile>
|
||||
</mat-grid-list>
|
||||
</div>
|
||||
|
@@ -0,0 +1,97 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright © 2005-2023 Hyland Software, Inc. and its affiliates. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { DateRangeWidgetComponent } from './date-range.widget';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { InsightsTestingModule } from '../../../../testing/insights.testing.module';
|
||||
import { ReportParameterDetailsModel } from '../../../../diagram/models/report/report-parameter-details.model';
|
||||
import { format } from 'date-fns';
|
||||
|
||||
describe('DateRangeWidgetComponent', () => {
|
||||
let fixture: ComponentFixture<DateRangeWidgetComponent>;
|
||||
let widget: DateRangeWidgetComponent;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
TranslateModule.forRoot(),
|
||||
InsightsTestingModule
|
||||
]
|
||||
});
|
||||
|
||||
fixture = TestBed.createComponent(DateRangeWidgetComponent);
|
||||
widget = fixture.componentInstance;
|
||||
});
|
||||
|
||||
it('should init the start date and end date from the field model', async () => {
|
||||
const field = new ReportParameterDetailsModel({
|
||||
value: {
|
||||
startDate: '2023-03-13',
|
||||
endDate: '2023-04-14'
|
||||
}
|
||||
});
|
||||
|
||||
widget.field = field;
|
||||
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(format(widget.startDateValue, 'yyyy-MM-dd')).toEqual('2023-03-13');
|
||||
expect(format(widget.endDateValue, 'yyyy-MM-dd')).toEqual('2023-04-14');
|
||||
});
|
||||
|
||||
it('should emit dateRangeChanged with empty time/zone', async () => {
|
||||
const field = new ReportParameterDetailsModel({
|
||||
value: {
|
||||
startDate: '2023-03-13',
|
||||
endDate: '2023-04-14'
|
||||
}
|
||||
});
|
||||
|
||||
widget.field = field;
|
||||
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(widget.dateRange.valid).toBeTrue();
|
||||
|
||||
let emitted: { startDate: string; endDate: string };
|
||||
widget.dateRangeChanged.subscribe((value) => emitted = value);
|
||||
|
||||
widget.onGroupValueChanged();
|
||||
|
||||
expect(emitted.startDate).toBe('2023-03-13T00:00:00.000Z');
|
||||
expect(emitted.endDate).toBe('2023-04-14T00:00:00.000Z');
|
||||
});
|
||||
|
||||
it('should validate date range', async () => {
|
||||
const field = new ReportParameterDetailsModel({
|
||||
value: {
|
||||
startDate: '2023-03-13',
|
||||
endDate: '2023-01-14'
|
||||
}
|
||||
});
|
||||
|
||||
widget.field = field;
|
||||
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
expect(widget.dateRange.valid).toBeFalse();
|
||||
});
|
||||
});
|
@@ -17,70 +17,71 @@
|
||||
|
||||
/* eslint-disable @angular-eslint/no-input-rename */
|
||||
|
||||
import { MOMENT_DATE_FORMATS, MomentDateAdapter, UserPreferencesService, UserPreferenceValues } from '@alfresco/adf-core';
|
||||
import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation, OnDestroy } from '@angular/core';
|
||||
import { AbstractControl, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { ADF_DATE_FORMATS, AdfDateFnsAdapter } from '@alfresco/adf-core';
|
||||
import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } from '@angular/core';
|
||||
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
||||
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core';
|
||||
import moment, { Moment } from 'moment';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { ReportParameterDetailsModel } from '../../../../diagram/models/report/report-parameter-details.model';
|
||||
import { isAfter } from 'date-fns';
|
||||
|
||||
const FORMAT_DATE_ACTIVITI = 'YYYY-MM-DD';
|
||||
const SHOW_FORMAT = 'DD/MM/YYYY';
|
||||
const FORMAT_DATE_ACTIVITI = 'yyyy-MM-dd';
|
||||
const DISPLAY_FORMAT = 'dd/MM/yyyy';
|
||||
|
||||
interface DateRangeProps {
|
||||
startDate: FormControl<Date>;
|
||||
endDate: FormControl<Date>;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'adf-date-range-widget',
|
||||
templateUrl: './date-range.widget.html',
|
||||
styleUrls: ['./date-range.widget.scss'],
|
||||
providers: [
|
||||
{ provide: DateAdapter, useClass: MomentDateAdapter },
|
||||
{ provide: MAT_DATE_FORMATS, useValue: MOMENT_DATE_FORMATS }
|
||||
{ provide: DateAdapter, useClass: AdfDateFnsAdapter },
|
||||
{ provide: MAT_DATE_FORMATS, useValue: ADF_DATE_FORMATS }
|
||||
],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class DateRangeWidgetComponent implements OnInit, OnDestroy {
|
||||
export class DateRangeWidgetComponent implements OnInit {
|
||||
@Input('group')
|
||||
dateRange: UntypedFormGroup;
|
||||
dateRange: FormGroup<DateRangeProps>;
|
||||
|
||||
@Input()
|
||||
field: any;
|
||||
field: ReportParameterDetailsModel;
|
||||
|
||||
@Output()
|
||||
dateRangeChanged = new EventEmitter<any>();
|
||||
dateRangeChanged = new EventEmitter<{ startDate: string; endDate: string }>();
|
||||
|
||||
minDate: Moment;
|
||||
maxDate: Moment;
|
||||
startDatePicker: Moment = moment();
|
||||
endDatePicker: Moment = moment();
|
||||
minDate: Date;
|
||||
maxDate: Date;
|
||||
startDateValue = new Date();
|
||||
endDateValue = new Date();
|
||||
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
constructor(private dateAdapter: DateAdapter<Moment>, private userPreferencesService: UserPreferencesService) {}
|
||||
constructor(private dateAdapter: DateAdapter<Date>) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.userPreferencesService
|
||||
.select(UserPreferenceValues.Locale)
|
||||
.pipe(takeUntil(this.onDestroy$))
|
||||
.subscribe((locale) => this.dateAdapter.setLocale(locale));
|
||||
|
||||
const momentDateAdapter = this.dateAdapter as MomentDateAdapter;
|
||||
momentDateAdapter.overrideDisplayFormat = SHOW_FORMAT;
|
||||
const momentDateAdapter = this.dateAdapter as AdfDateFnsAdapter;
|
||||
momentDateAdapter.displayFormat = DISPLAY_FORMAT;
|
||||
|
||||
if (this.field) {
|
||||
if (this.field.value?.startDate) {
|
||||
this.startDatePicker = moment(this.field.value.startDate, FORMAT_DATE_ACTIVITI);
|
||||
this.startDateValue = this.dateAdapter.parse(this.field.value.startDate, FORMAT_DATE_ACTIVITI);
|
||||
}
|
||||
|
||||
if (this.field.value?.endDate) {
|
||||
this.endDatePicker = moment(this.field.value.endDate, FORMAT_DATE_ACTIVITI);
|
||||
this.endDateValue = this.dateAdapter.parse(this.field.value.endDate, FORMAT_DATE_ACTIVITI);
|
||||
}
|
||||
}
|
||||
|
||||
const startDateControl = new UntypedFormControl(this.startDatePicker);
|
||||
if (!this.dateRange) {
|
||||
this.dateRange = new FormGroup({} as any);
|
||||
}
|
||||
|
||||
const startDateControl = new FormControl<Date>(this.startDateValue);
|
||||
startDateControl.setValidators(Validators.required);
|
||||
this.dateRange.addControl('startDate', startDateControl);
|
||||
|
||||
const endDateControl = new UntypedFormControl(this.endDatePicker);
|
||||
const endDateControl = new FormControl<Date>(this.endDateValue);
|
||||
endDateControl.setValidators(Validators.required);
|
||||
this.dateRange.addControl('endDate', endDateControl);
|
||||
|
||||
@@ -88,27 +89,24 @@ export class DateRangeWidgetComponent implements OnInit, OnDestroy {
|
||||
this.dateRange.valueChanges.subscribe(() => this.onGroupValueChanged());
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.onDestroy$.next(true);
|
||||
this.onDestroy$.complete();
|
||||
}
|
||||
|
||||
onGroupValueChanged() {
|
||||
if (this.dateRange.valid) {
|
||||
const dateStart = this.convertToMomentDateWithTime(this.dateRange.controls.startDate.value);
|
||||
const endStart = this.convertToMomentDateWithTime(this.dateRange.controls.endDate.value);
|
||||
const dateStart = this.formatDateTime(this.dateRange.controls.startDate.value);
|
||||
const endStart = this.formatDateTime(this.dateRange.controls.endDate.value);
|
||||
this.dateRangeChanged.emit({ startDate: dateStart, endDate: endStart });
|
||||
}
|
||||
}
|
||||
|
||||
convertToMomentDateWithTime(date: string) {
|
||||
return moment(date, FORMAT_DATE_ACTIVITI, true).format(FORMAT_DATE_ACTIVITI) + 'T00:00:00.000Z';
|
||||
private formatDateTime(date: Date) {
|
||||
const datePart = this.dateAdapter.format(date, FORMAT_DATE_ACTIVITI);
|
||||
return `${datePart}T00:00:00.000Z`;
|
||||
}
|
||||
|
||||
dateCheck(formControl: AbstractControl) {
|
||||
const startDate = moment(formControl.get('startDate').value);
|
||||
const endDate = moment(formControl.get('endDate').value);
|
||||
const isAfterCheck = startDate.isAfter(endDate);
|
||||
dateCheck(formControl: FormGroup<DateRangeProps>) {
|
||||
const startDate = formControl.get('startDate').value;
|
||||
const endDate = formControl.get('endDate').value;
|
||||
const isAfterCheck = isAfter(startDate, endDate);
|
||||
|
||||
return isAfterCheck ? { greaterThan: true } : null;
|
||||
}
|
||||
|
||||
|
@@ -26,7 +26,7 @@ export class ReportParameterDetailsModel {
|
||||
options: ParameterValueModel[];
|
||||
dependsOn: string;
|
||||
|
||||
constructor(obj?: any) {
|
||||
constructor(obj?: Partial<ReportParameterDetailsModel>) {
|
||||
this.id = obj?.id;
|
||||
this.name = obj?.name;
|
||||
this.nameKey = obj?.nameKey;
|
||||
|
Reference in New Issue
Block a user