[ADF-3042] Use the custom date adapter from adf-core on Search Date Range widget (#3394)

-fix localization
-fix tests
-show parse error
This commit is contained in:
Suzana Dirla
2018-05-25 15:45:55 +03:00
committed by Eugenio Romano
parent 85ff224e26
commit 11bac7e796
4 changed files with 46 additions and 52 deletions

View File

@@ -7,13 +7,13 @@
(focusout)="onChangedHandler($event, from)"> (focusout)="onChangedHandler($event, from)">
<mat-datepicker-toggle matSuffix [for]="fromDatepicker"></mat-datepicker-toggle> <mat-datepicker-toggle matSuffix [for]="fromDatepicker"></mat-datepicker-toggle>
<mat-datepicker #fromDatepicker></mat-datepicker> <mat-datepicker #fromDatepicker></mat-datepicker>
<mat-error *ngIf="from.hasError('required') && !from.hasError('matDatepickerParse')"> <mat-error *ngIf="from.hasError('required') && !hasParseError(from)">
{{ 'SEARCH.FILTER.VALIDATION.REQUIRED-VALUE' | translate }} {{ 'SEARCH.FILTER.VALIDATION.REQUIRED-VALUE' | translate }}
</mat-error> </mat-error>
<mat-error *ngIf="from.hasError('matDatepickerMax')"> <mat-error *ngIf="from.hasError('matDatepickerMax')">
{{ 'SEARCH.FILTER.VALIDATION.BEYOND-MAX-DATE' | translate }} {{ 'SEARCH.FILTER.VALIDATION.BEYOND-MAX-DATE' | translate }}
</mat-error> </mat-error>
<mat-error *ngIf="from.hasError('matDatepickerParse')"> <mat-error *ngIf="hasParseError(from)">
{{ 'SEARCH.FILTER.VALIDATION.INVALID-DATE' | translate: { requiredFormat: datePickerDateFormat } }} {{ 'SEARCH.FILTER.VALIDATION.INVALID-DATE' | translate: { requiredFormat: datePickerDateFormat } }}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>
@@ -27,7 +27,7 @@
(focusout)="onChangedHandler($event, to)"> (focusout)="onChangedHandler($event, to)">
<mat-datepicker-toggle matSuffix [for]="toDatepicker"></mat-datepicker-toggle> <mat-datepicker-toggle matSuffix [for]="toDatepicker"></mat-datepicker-toggle>
<mat-datepicker #toDatepicker></mat-datepicker> <mat-datepicker #toDatepicker></mat-datepicker>
<mat-error *ngIf="to.hasError('required') && !to.hasError('matDatepickerParse')"> <mat-error *ngIf="to.hasError('required') && !hasParseError(to)">
{{ 'SEARCH.FILTER.VALIDATION.REQUIRED-VALUE' | translate }} {{ 'SEARCH.FILTER.VALIDATION.REQUIRED-VALUE' | translate }}
</mat-error> </mat-error>
<mat-error *ngIf="to.hasError('matDatepickerMin')"> <mat-error *ngIf="to.hasError('matDatepickerMin')">
@@ -36,7 +36,7 @@
<mat-error *ngIf="to.hasError('matDatepickerMax')"> <mat-error *ngIf="to.hasError('matDatepickerMax')">
{{ 'SEARCH.FILTER.VALIDATION.BEYOND-MAX-DATE' | translate }} {{ 'SEARCH.FILTER.VALIDATION.BEYOND-MAX-DATE' | translate }}
</mat-error> </mat-error>
<mat-error *ngIf="to.hasError('matDatepickerParse')"> <mat-error *ngIf="hasParseError(to)">
{{ 'SEARCH.FILTER.VALIDATION.INVALID-DATE' | translate: { requiredFormat: datePickerDateFormat } }} {{ 'SEARCH.FILTER.VALIDATION.INVALID-DATE' | translate: { requiredFormat: datePickerDateFormat } }}
</mat-error> </mat-error>
</mat-form-field> </mat-form-field>

View File

@@ -15,11 +15,11 @@
* limitations under the License. * limitations under the License.
*/ */
import { CustomMomentDateAdapter, SearchDateRangeComponent } from './search-date-range.component'; import { SearchDateRangeComponent } from './search-date-range.component';
import { Observable } from 'rxjs/Observable'; import { Observable } from 'rxjs/Observable';
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ContentTestingModule } from '../../../testing/content.testing.module'; import { ContentTestingModule } from '../../../testing/content.testing.module';
import { setupTestBed } from '@alfresco/adf-core'; import { setupTestBed, MomentDateAdapter } from '@alfresco/adf-core';
import { By } from '@angular/platform-browser'; import { By } from '@angular/platform-browser';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
@@ -34,9 +34,9 @@ describe('SearchDateRangeComponent', () => {
const localeFixture = 'it'; const localeFixture = 'it';
const dateFormatFixture = 'DD-MMM-YY'; const dateFormatFixture = 'DD-MMM-YY';
const buildAdapter = (): CustomMomentDateAdapter => { const buildAdapter = (): MomentDateAdapter => {
const dateAdapter = new CustomMomentDateAdapter(null); const dateAdapter = new MomentDateAdapter();
dateAdapter.customDateFormat = null; dateAdapter.overrideDisplyaFormat = null;
return dateAdapter; return dateAdapter;
}; };
@@ -72,14 +72,14 @@ describe('SearchDateRangeComponent', () => {
it('should setup the format of the date from configuration', () => { it('should setup the format of the date from configuration', () => {
component.settings = {field: 'cm:created', dateFormat: dateFormatFixture}; component.settings = {field: 'cm:created', dateFormat: dateFormatFixture};
component.ngOnInit(); component.ngOnInit();
expect(theDateAdapter.customDateFormat).toBe(dateFormatFixture); expect(theDateAdapter.overrideDisplyaFormat).toBe(dateFormatFixture);
}); });
it('should setup form control with formatted valid date on change', () => { it('should setup form control with formatted valid date on change', () => {
component.settings = {field: 'cm:created', dateFormat: dateFormatFixture}; component.settings = {field: 'cm:created', dateFormat: dateFormatFixture};
component.ngOnInit(); component.ngOnInit();
const inputString = '20.feb.18'; const inputString = '20-feb-18';
const momentFromInput = moment(inputString, dateFormatFixture); const momentFromInput = moment(inputString, dateFormatFixture);
expect(momentFromInput.isValid()).toBeTruthy(); expect(momentFromInput.isValid()).toBeTruthy();

View File

@@ -18,7 +18,7 @@
import { OnInit, Component, ViewEncapsulation } from '@angular/core'; import { OnInit, Component, ViewEncapsulation } from '@angular/core';
import { FormControl, Validators, FormGroup } from '@angular/forms'; import { FormControl, Validators, FormGroup } from '@angular/forms';
import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material/core'; import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material/core';
import { MomentDateAdapter, MAT_MOMENT_DATE_FORMATS } from '@angular/material-moment-adapter'; import { MomentDateAdapter, MOMENT_DATE_FORMATS } from '@alfresco/adf-core';
import { SearchWidget } from '../../search-widget.interface'; import { SearchWidget } from '../../search-widget.interface';
import { SearchWidgetSettings } from '../../search-widget-settings.interface'; import { SearchWidgetSettings } from '../../search-widget-settings.interface';
@@ -31,29 +31,13 @@ declare let moment: any;
const DEFAULT_FORMAT_DATE: string = 'DD/MM/YYYY'; const DEFAULT_FORMAT_DATE: string = 'DD/MM/YYYY';
export class CustomMomentDateAdapter extends MomentDateAdapter {
customDateFormat: string;
parse(value: any, parseFormat: any): any {
const dateFormat = this.customDateFormat ? this.customDateFormat : DEFAULT_FORMAT_DATE;
return super.parse(value, dateFormat);
}
format(value: Moment, displayFormat: string): string {
const dateFormat = this.customDateFormat ? this.customDateFormat : DEFAULT_FORMAT_DATE;
return super.format(value, dateFormat);
}
}
@Component({ @Component({
selector: 'adf-search-date-range', selector: 'adf-search-date-range',
templateUrl: './search-date-range.component.html', templateUrl: './search-date-range.component.html',
styleUrls: ['./search-date-range.component.scss'], styleUrls: ['./search-date-range.component.scss'],
providers: [ providers: [
{provide: DateAdapter, useClass: CustomMomentDateAdapter, deps: [MAT_DATE_LOCALE]}, {provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE]},
{provide: MAT_DATE_FORMATS, useValue: MAT_MOMENT_DATE_FORMATS} {provide: MAT_DATE_FORMATS, useValue: MOMENT_DATE_FORMATS}
], ],
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
host: { class: 'adf-search-date-range' } host: { class: 'adf-search-date-range' }
@@ -80,8 +64,8 @@ export class SearchDateRangeComponent implements SearchWidget, OnInit {
if (this.settings) { if (this.settings) {
this.datePickerDateFormat = this.settings.dateFormat || DEFAULT_FORMAT_DATE; this.datePickerDateFormat = this.settings.dateFormat || DEFAULT_FORMAT_DATE;
} }
const theCustomDateAdapter = <CustomMomentDateAdapter> <any> this.dateAdapter; const theCustomDateAdapter = <MomentDateAdapter> <any> this.dateAdapter;
theCustomDateAdapter.customDateFormat = this.datePickerDateFormat; theCustomDateAdapter.overrideDisplyaFormat = this.datePickerDateFormat;
this.userPreferencesService.select(UserPreferenceValues.Locale).subscribe((locale) => { this.userPreferencesService.select(UserPreferenceValues.Locale).subscribe((locale) => {
this.setLocale(locale); this.setLocale(locale);
@@ -99,7 +83,7 @@ export class SearchDateRangeComponent implements SearchWidget, OnInit {
to: this.to to: this.to
}); });
this.maxDate = moment().startOf('day'); this.maxDate = this.dateAdapter.today().startOf('day');
} }
apply(model: { from: string, to: string }, isValid: boolean) { apply(model: { from: string, to: string }, isValid: boolean) {
@@ -128,7 +112,7 @@ export class SearchDateRangeComponent implements SearchWidget, OnInit {
if (inputValue) { if (inputValue) {
const formatDate = this.dateAdapter.parse(inputValue, this.datePickerDateFormat); const formatDate = this.dateAdapter.parse(inputValue, this.datePickerDateFormat);
if (formatDate.isValid()) { if (formatDate && formatDate.isValid()) {
formControl.setValue(formatDate); formControl.setValue(formatDate);
} }
} }
@@ -138,4 +122,8 @@ export class SearchDateRangeComponent implements SearchWidget, OnInit {
this.dateAdapter.setLocale(locale); this.dateAdapter.setLocale(locale);
moment.locale(locale); moment.locale(locale);
} }
hasParseError(formControl) {
return formControl.hasError('matDatepickerParse') && formControl.getError('matDatepickerParse').text;
}
} }

View File

@@ -89,7 +89,7 @@ export class MomentDateAdapter extends DateAdapter<Moment> {
} }
clone(date: Moment): Moment { clone(date: Moment): Moment {
return date.clone(); return date.clone().locale(this.locale);
} }
createDate(year: number, month: number, date: number): Moment { createDate(year: number, month: number, date: number): Moment {
@@ -97,13 +97,16 @@ export class MomentDateAdapter extends DateAdapter<Moment> {
} }
today(): Moment { today(): Moment {
return moment(); return moment().locale(this.locale);
} }
parse(value: any, parseFormat: any): Moment { parse(value: any, parseFormat: any): Moment {
let m = moment(value, parseFormat, true);
if (value && typeof value === 'string') {
let m = moment(value, parseFormat, this.locale, true);
if (!m.isValid()) { if (!m.isValid()) {
m = moment(value, this.overrideDisplyaFormat); // use strict parsing because Moment's parser is very forgiving, and this can lead to undesired behavior.
m = moment(value, this.overrideDisplyaFormat, this.locale, true);
} }
if (m.isValid()) { if (m.isValid()) {
// if user omits year, it defaults to 2001, so check for that issue. // if user omits year, it defaults to 2001, so check for that issue.
@@ -116,14 +119,15 @@ export class MomentDateAdapter extends DateAdapter<Moment> {
m.set('year', currentYear - 1); m.set('year', currentYear - 1);
} }
} }
return m;
} else {
return null;
} }
return m;
}
return value ? moment(value).locale(this.locale) : null;
} }
format(date: Moment, displayFormat: any): string { format(date: Moment, displayFormat: any): string {
date = this.clone(date);
displayFormat = this.overrideDisplyaFormat ? this.overrideDisplyaFormat : displayFormat; displayFormat = this.overrideDisplyaFormat ? this.overrideDisplyaFormat : displayFormat;
if (date && date.format) { if (date && date.format) {
@@ -150,6 +154,8 @@ export class MomentDateAdapter extends DateAdapter<Moment> {
} }
setLocale(locale: any): void { setLocale(locale: any): void {
super.setLocale(locale);
this.localeData = moment.localeData(locale); this.localeData = moment.localeData(locale);
} }