diff --git a/demo-shell/src/app.config.json b/demo-shell/src/app.config.json
index 06e2c6b74f..7390174bf5 100644
--- a/demo-shell/src/app.config.json
+++ b/demo-shell/src/app.config.json
@@ -145,7 +145,8 @@
"component": {
"selector": "date-range",
"settings": {
- "field": "cm:created"
+ "field": "cm:created",
+ "dateFormat": "DD-MMM-YY"
}
}
},
diff --git a/lib/content-services/i18n/en.json b/lib/content-services/i18n/en.json
index 753ff4c3d3..646c62b803 100644
--- a/lib/content-services/i18n/en.json
+++ b/lib/content-services/i18n/en.json
@@ -188,7 +188,8 @@
"VALIDATION": {
"REQUIRED-VALUE": "Required value",
"NO-DAYS": "No days selected.",
- "INVALID-FORMAT": "Invalid Format"
+ "INVALID-FORMAT": "Invalid Format",
+ "BEYOND-MAX-DATE": "Date is too late."
}
},
"ICONS": {
diff --git a/lib/content-services/search/components/search-date-range/search-date-range.component.html b/lib/content-services/search/components/search-date-range/search-date-range.component.html
index 688a263994..b1cb62f0e0 100644
--- a/lib/content-services/search/components/search-date-range/search-date-range.component.html
+++ b/lib/content-services/search/components/search-date-range/search-date-range.component.html
@@ -3,22 +3,30 @@
+ [max]="maxFrom"
+ (focusout)="onChangedHandler($event, from)">
{{ 'SEARCH.FILTER.VALIDATION.REQUIRED-VALUE' | translate }}
+
+ {{ 'SEARCH.FILTER.VALIDATION.BEYOND-MAX-DATE' | translate }}
+
+ [min]="from.value"
+ (focusout)="onChangedHandler($event, to)">
-
+
+ {{ 'SEARCH.FILTER.VALIDATION.REQUIRED-VALUE' | translate }}
+
+
{{ 'SEARCH.FILTER.VALIDATION.NO-DAYS' | translate }}
diff --git a/lib/content-services/search/components/search-date-range/search-date-range.component.spec.ts b/lib/content-services/search/components/search-date-range/search-date-range.component.spec.ts
index 19f6fd0e97..45996a7792 100644
--- a/lib/content-services/search/components/search-date-range/search-date-range.component.spec.ts
+++ b/lib/content-services/search/components/search-date-range/search-date-range.component.spec.ts
@@ -15,26 +15,84 @@
* limitations under the License.
*/
-import { SearchDateRangeComponent } from './search-date-range.component';
-import moment from 'moment-es6';
+import { CustomMomentDateAdapter, SearchDateRangeComponent } from './search-date-range.component';
+import { Observable } from 'rxjs/Observable';
+
+declare let moment: any;
describe('SearchDateRangeComponent', () => {
let component: SearchDateRangeComponent;
let fromDate = '2016-10-16';
let toDate = '2017-10-16';
+ const localeFixture = 'it';
+ const dateFormatFixture = 'DD-MMM-YY';
+
+ const buildAdapter = (): CustomMomentDateAdapter => {
+ const dateAdapter = new CustomMomentDateAdapter(null);
+ dateAdapter.customDateFormat = null;
+ return dateAdapter;
+ };
+
+ const buildUserPreferences = (): any => {
+ const userPreferences = {
+ userPreferenceStatus: { LOCALE: localeFixture },
+ select: (property) => {
+ return Observable.of(userPreferences.userPreferenceStatus[property]);
+ }
+ };
+ return userPreferences;
+ };
+
+ const theDateAdapter = buildAdapter();
beforeEach(() => {
- component = new SearchDateRangeComponent();
+ component = new SearchDateRangeComponent(theDateAdapter, buildUserPreferences());
});
it('should setup form elements on init', () => {
component.ngOnInit();
- expect(component.form).toBeDefined();
+ expect(component.from).toBeDefined();
expect(component.to).toBeDefined();
expect(component.form).toBeDefined();
});
+ it('should setup locale from userPreferencesService', () => {
+ spyOn(component, 'setLocale').and.stub();
+ component.ngOnInit();
+ expect(component.setLocale).toHaveBeenCalledWith(localeFixture);
+ });
+
+ it('should setup the format of the date from configuration', () => {
+ component.settings = { field: 'cm:created', dateFormat: dateFormatFixture };
+ component.ngOnInit();
+ expect(theDateAdapter.customDateFormat).toBe(dateFormatFixture);
+ });
+
+ it('should setup form control with formatted valid date on change', () => {
+ component.settings = { field: 'cm:created', dateFormat: dateFormatFixture };
+ component.ngOnInit();
+
+ const inputString = '20.feb.18';
+ const momentFromInput = moment(inputString, dateFormatFixture);
+ expect(momentFromInput.isValid()).toBeTruthy();
+
+ component.onChangedHandler({ srcElement: { value: inputString }}, component.from);
+ expect(component.from.value).toEqual(momentFromInput);
+ });
+
+ it('should NOT setup form control with invalid date on change', () => {
+ component.settings = { field: 'cm:created', dateFormat: dateFormatFixture };
+ component.ngOnInit();
+
+ const inputString = '20.f.18';
+ const momentFromInput = moment(inputString, dateFormatFixture);
+ expect(momentFromInput.isValid()).toBeFalsy();
+
+ component.onChangedHandler({ srcElement: { value: inputString }}, component.from);
+ expect(component.from.value).not.toEqual(momentFromInput);
+ });
+
it('should reset form', () => {
component.ngOnInit();
component.form.setValue({ from: fromDate, to: toDate });
diff --git a/lib/content-services/search/components/search-date-range/search-date-range.component.ts b/lib/content-services/search/components/search-date-range/search-date-range.component.ts
index 52924b1f8b..13d9ed16b8 100644
--- a/lib/content-services/search/components/search-date-range/search-date-range.component.ts
+++ b/lib/content-services/search/components/search-date-range/search-date-range.component.ts
@@ -17,16 +17,44 @@
import { OnInit, Component, ViewEncapsulation } from '@angular/core';
import { FormControl, Validators, FormGroup } from '@angular/forms';
+import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material/core';
+import { MomentDateAdapter, MAT_MOMENT_DATE_FORMATS } from '@angular/material-moment-adapter';
+
import { SearchWidget } from '../../search-widget.interface';
import { SearchWidgetSettings } from '../../search-widget-settings.interface';
import { SearchQueryBuilderService } from '../../search-query-builder.service';
import { LiveErrorStateMatcher } from '../../forms/live-error-state-matcher';
-import moment from 'moment-es6';
+import { Moment } from 'moment';
+import { UserPreferencesService, UserPreferenceValues } from '@alfresco/adf-core';
+
+declare let moment: any;
+
+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({
selector: 'adf-search-date-range',
templateUrl: './search-date-range.component.html',
styleUrls: ['./search-date-range.component.scss'],
+ providers: [
+ {provide: DateAdapter, useClass: CustomMomentDateAdapter, deps: [MAT_DATE_LOCALE]},
+ {provide: MAT_DATE_FORMATS, useValue: MAT_MOMENT_DATE_FORMATS}
+ ],
encapsulation: ViewEncapsulation.None,
host: { class: 'adf-search-date-range' }
})
@@ -42,8 +70,23 @@ export class SearchDateRangeComponent implements SearchWidget, OnInit {
settings?: SearchWidgetSettings;
context?: SearchQueryBuilderService;
maxFrom: any;
+ datePickerDateFormat = DEFAULT_FORMAT_DATE;
+
+ constructor(private dateAdapter: DateAdapter,
+ private userPreferencesService: UserPreferencesService) {
+ }
ngOnInit() {
+ if (this.settings) {
+ this.datePickerDateFormat = this.settings.dateFormat || DEFAULT_FORMAT_DATE;
+ }
+ const theCustomDateAdapter = this.dateAdapter;
+ theCustomDateAdapter.customDateFormat = this.datePickerDateFormat;
+
+ this.userPreferencesService.select(UserPreferenceValues.Locale).subscribe((locale) => {
+ this.setLocale(locale);
+ });
+
const validators = Validators.compose([
Validators.required
]);
@@ -80,13 +123,20 @@ export class SearchDateRangeComponent implements SearchWidget, OnInit {
}
}
- hasSelectedDays(from: string, to: string): boolean {
- if (from && to) {
- const start = moment(from).startOf('day');
- const end = moment(to).endOf('day');
+ onChangedHandler(event: any, formControl) {
+ const inputValue = event.srcElement.value;
- return start.isBefore(end);
+ if (inputValue) {
+ const formatDate = moment(inputValue, this.datePickerDateFormat);
+
+ if (formatDate.isValid()) {
+ formControl.setValue(formatDate);
+ }
}
- return true;
+ }
+
+ setLocale(locale) {
+ this.dateAdapter.setLocale(locale);
+ moment.locale(locale);
}
}
diff --git a/package-lock.json b/package-lock.json
index bf4e01beb5..0823316939 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -49,6 +49,11 @@
"superagent": "3.8.2"
}
},
+ "moment": {
+ "version": "2.20.1",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.20.1.tgz",
+ "integrity": "sha512-Yh9y73JRljxW5QxN08Fner68eFLxM5ynNOAw2LbIB1YAGeQzZT8QFSUvkAz609Zf+IHhhaUxqZK8dG3W/+HEvg=="
+ },
"pdfjs-dist": {
"version": "1.5.404",
"resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-1.5.404.tgz",
@@ -108,6 +113,11 @@
"superagent": "3.8.2"
}
},
+ "moment": {
+ "version": "2.20.1",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.20.1.tgz",
+ "integrity": "sha512-Yh9y73JRljxW5QxN08Fner68eFLxM5ynNOAw2LbIB1YAGeQzZT8QFSUvkAz609Zf+IHhhaUxqZK8dG3W/+HEvg=="
+ },
"pdfjs-dist": {
"version": "1.5.404",
"resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-1.5.404.tgz",
@@ -168,6 +178,11 @@
"superagent": "3.8.2"
}
},
+ "moment": {
+ "version": "2.20.1",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.20.1.tgz",
+ "integrity": "sha512-Yh9y73JRljxW5QxN08Fner68eFLxM5ynNOAw2LbIB1YAGeQzZT8QFSUvkAz609Zf+IHhhaUxqZK8dG3W/+HEvg=="
+ },
"pdfjs-dist": {
"version": "1.5.404",
"resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-1.5.404.tgz",
@@ -229,6 +244,11 @@
"superagent": "3.8.2"
}
},
+ "moment": {
+ "version": "2.20.1",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.20.1.tgz",
+ "integrity": "sha512-Yh9y73JRljxW5QxN08Fner68eFLxM5ynNOAw2LbIB1YAGeQzZT8QFSUvkAz609Zf+IHhhaUxqZK8dG3W/+HEvg=="
+ },
"pdfjs-dist": {
"version": "1.5.404",
"resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-1.5.404.tgz",
@@ -10552,7 +10572,7 @@
},
"moment": {
"version": "2.20.1",
- "resolved": "http://localhost:4873/moment/-/moment-2.20.1.tgz",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.20.1.tgz",
"integrity": "sha512-Yh9y73JRljxW5QxN08Fner68eFLxM5ynNOAw2LbIB1YAGeQzZT8QFSUvkAz609Zf+IHhhaUxqZK8dG3W/+HEvg=="
},
"moment-es6": {
diff --git a/scripts/test-e2e-bc.sh b/scripts/test-e2e-bc.sh
index 6f38d7917f..2c2b69c21b 100755
--- a/scripts/test-e2e-bc.sh
+++ b/scripts/test-e2e-bc.sh
@@ -8,6 +8,7 @@ ADF_VERSION=$(npm view @alfresco/adf-core version)
ANGULAR_VERSION="5.1.1"
MATERIAL_VERSION="5.0.1"
NGX_TRANSLATE_VERSION="9.1.1"
+MOMENT_VERSION="2.20.1"
npm install
@@ -21,5 +22,6 @@ npm install --save @mat-datetimepicker/core @mat-datetimepicker/moment
npm install --save-exact --save @angular/animations@${ANGULAR_VERSION} @angular/common@${ANGULAR_VERSION} @angular/compiler@${ANGULAR_VERSION} @angular/core@${ANGULAR_VERSION} @angular/platform-browser@${ANGULAR_VERSION} @angular/router@${ANGULAR_VERSION} @angular/flex-layout@2.0.0-beta.12 @angular/forms@${ANGULAR_VERSION} @angular/forms@${ANGULAR_VERSION} @angular/http@${ANGULAR_VERSION} @angular/platform-browser-dynamic@${ANGULAR_VERSION}
npm install --save-exact --save @angular/cdk@${MATERIAL_VERSION} @angular/material@${MATERIAL_VERSION}
npm install --save-exact --save @ngx-translate/core@${NGX_TRANSLATE_VERSION}
+npm install --save-exact --save moment@${MOMENT_VERSION}
npm run e2e