From b388cb55e5e1245249127d43db03a8540acffd1e Mon Sep 17 00:00:00 2001 From: SheenaMalhotra182 Date: Fri, 22 Sep 2023 20:46:32 +0530 Subject: [PATCH 01/19] [ACS-5857] migrated adfMomentDate Pipe to date-fns equivalent --- .../widgets/core/form-field-validator.ts | 111 ++++++++++++------ .../widgets/core/form-field.model.spec.ts | 13 +- .../widgets/core/form-field.model.ts | 43 +++++-- .../widgets/date/date.widget.spec.ts | 12 +- .../components/widgets/date/date.widget.ts | 16 +-- lib/core/src/lib/form/public-api.ts | 1 + .../date-format-translation.service.spec.ts | 72 ++++++++++++ .../date-format-translation.service.ts | 60 ++++++++++ lib/core/src/lib/pipes/date.pipe.spec.ts | 74 ++++++++++++ lib/core/src/lib/pipes/date.pipe.ts | 30 +++++ lib/core/src/lib/pipes/pipe.module.ts | 4 + lib/core/src/lib/pipes/public-api.ts | 1 + .../widgets/date/date-cloud.widget.html | 8 +- .../widgets/date/date-cloud.widget.spec.ts | 37 +++--- .../widgets/date/date-cloud.widget.ts | 54 ++++----- .../src/lib/models/date-format-cloud.model.ts | 2 +- 16 files changed, 427 insertions(+), 111 deletions(-) create mode 100644 lib/core/src/lib/form/services/date-format-translation.service.spec.ts create mode 100644 lib/core/src/lib/form/services/date-format-translation.service.ts create mode 100644 lib/core/src/lib/pipes/date.pipe.spec.ts create mode 100644 lib/core/src/lib/pipes/date.pipe.ts diff --git a/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts b/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts index cf63d348a0c..7a696d019a4 100644 --- a/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts +++ b/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts @@ -21,6 +21,7 @@ import moment from 'moment'; import { FormFieldTypes } from './form-field-types'; import { isNumberValue } from './form-field-utils'; import { FormFieldModel } from './form-field.model'; +import { format, isAfter, isBefore, isValid, parse } from 'date-fns'; export interface FormFieldValidator { @@ -145,10 +146,10 @@ export class DateFieldValidator implements FormFieldValidator { ]; // Validates that the input string is a valid date formatted as (default D-M-YYYY) - static isValidDate(inputDate: string, dateFormat: string = 'D-M-YYYY'): boolean { + static isValidDate(inputDate: string, dateFormat: string = 'd-M-yyyy'): boolean { if (inputDate) { - const d = moment(inputDate, dateFormat, true); - return d.isValid(); + const d = parseUpdate(inputDate, dateFormat); + return isValid(d); } return false; @@ -204,26 +205,26 @@ export class DateTimeFieldValidator implements FormFieldValidator { export abstract class BoundaryDateFieldValidator implements FormFieldValidator { - DATE_FORMAT_CLOUD = 'YYYY-MM-DD'; - DATE_FORMAT = 'DD-MM-YYYY'; + DATE_FORMAT_CLOUD = 'yyyy-MM-dd'; + DATE_FORMAT = 'dd-MM-yyyy'; supportedTypes = [ FormFieldTypes.DATE ]; validate(field: FormFieldModel): boolean { - let isValid = true; + let isFieldValid = true; if (this.isSupported(field) && field.value && field.isVisible) { const dateFormat = field.dateDisplayFormat; if (!DateFieldValidator.isValidDate(field.value, dateFormat)) { field.validationSummary.message = 'FORM.FIELD.VALIDATOR.INVALID_DATE'; - isValid = false; + isFieldValid = false; } else { - isValid = this.checkDate(field, dateFormat); + isFieldValid = this.checkDate(field, dateFormat); } } - return isValid; + return isFieldValid; } extractDateFormat(date: string): string { @@ -240,24 +241,24 @@ export class MinDateFieldValidator extends BoundaryDateFieldValidator { checkDate(field: FormFieldModel, dateFormat: string): boolean { - let isValid = true; + let isFieldValid = true; // remove time and timezone info let fieldValueData; if (typeof field.value === 'string') { - fieldValueData = moment(field.value.split('T')[0], dateFormat); + fieldValueData = parseUpdate(field.value.split('T')[0], dateFormat); } else { fieldValueData = field.value; } const minValueDateFormat = this.extractDateFormat(field.minValue); - const min = moment(field.minValue, minValueDateFormat); + const min = parseUpdate(field.minValue, minValueDateFormat); - if (fieldValueData.isBefore(min)) { + if (isBefore(fieldValueData, min)) { field.validationSummary.message = `FORM.FIELD.VALIDATOR.NOT_LESS_THAN`; - field.validationSummary.attributes.set('minValue', min.format(field.dateDisplayFormat).toLocaleUpperCase()); - isValid = false; + field.validationSummary.attributes.set('minValue', formatUpdate(min, field.dateDisplayFormat).toLocaleUpperCase()); + isFieldValid = false; } - return isValid; + return isFieldValid; } isSupported(field: FormFieldModel): boolean { @@ -270,24 +271,24 @@ export class MaxDateFieldValidator extends BoundaryDateFieldValidator { checkDate(field: FormFieldModel, dateFormat: string): boolean { - let isValid = true; + let isFieldValid = true; // remove time and timezone info let fieldValueData; if (typeof field.value === 'string') { - fieldValueData = moment(field.value.split('T')[0], dateFormat); + fieldValueData = parseUpdate(field.value.split('T')[0], dateFormat); } else { fieldValueData = field.value; } const maxValueDateFormat = this.extractDateFormat(field.maxValue); - const max = moment(field.maxValue, maxValueDateFormat); + const max = parseUpdate(field.maxValue, maxValueDateFormat); - if (fieldValueData.isAfter(max)) { + if (isAfter(fieldValueData, max)) { field.validationSummary.message = `FORM.FIELD.VALIDATOR.NOT_GREATER_THAN`; - field.validationSummary.attributes.set('maxValue', max.format(field.dateDisplayFormat).toLocaleUpperCase()); - isValid = false; + field.validationSummary.attributes.set('maxValue', formatUpdate(max, field.dateDisplayFormat).toLocaleUpperCase()); + isFieldValid = false; } - return isValid; + return isFieldValid; } isSupported(field: FormFieldModel): boolean { @@ -309,22 +310,22 @@ export class MinDateTimeFieldValidator implements FormFieldValidator { } validate(field: FormFieldModel): boolean { - let isValid = true; + let isFieldValid = true; if (this.isSupported(field) && field.value && field.isVisible) { const dateFormat = field.dateDisplayFormat; if (!DateFieldValidator.isValidDate(field.value, dateFormat)) { field.validationSummary.message = 'FORM.FIELD.VALIDATOR.INVALID_DATE'; - isValid = false; + isFieldValid = false; } else { - isValid = this.checkDateTime(field, dateFormat); + isFieldValid = this.checkDateTime(field, dateFormat); } } - return isValid; + return isFieldValid; } private checkDateTime(field: FormFieldModel, dateFormat: string): boolean { - let isValid = true; + let isFieldValid = true; let fieldValueDate; if (typeof field.value === 'string') { fieldValueDate = moment(field.value, dateFormat); @@ -336,9 +337,9 @@ export class MinDateTimeFieldValidator implements FormFieldValidator { if (fieldValueDate.isBefore(min)) { field.validationSummary.message = `FORM.FIELD.VALIDATOR.NOT_LESS_THAN`; field.validationSummary.attributes.set('minValue', min.format(field.dateDisplayFormat).replace(':', '-')); - isValid = false; + isFieldValid = false; } - return isValid; + return isFieldValid; } } @@ -355,22 +356,22 @@ export class MaxDateTimeFieldValidator implements FormFieldValidator { } validate(field: FormFieldModel): boolean { - let isValid = true; + let isFieldValid = true; if (this.isSupported(field) && field.value && field.isVisible) { const dateFormat = field.dateDisplayFormat; if (!DateFieldValidator.isValidDate(field.value, dateFormat)) { field.validationSummary.message = 'FORM.FIELD.VALIDATOR.INVALID_DATE'; - isValid = false; + isFieldValid = false; } else { - isValid = this.checkDateTime(field, dateFormat); + isFieldValid = this.checkDateTime(field, dateFormat); } } - return isValid; + return isFieldValid; } private checkDateTime(field: FormFieldModel, dateFormat: string): boolean { - let isValid = true; + let isFieldValid = true; let fieldValueDate; if (typeof field.value === 'string') { @@ -383,9 +384,9 @@ export class MaxDateTimeFieldValidator implements FormFieldValidator { if (fieldValueDate.isAfter(max)) { field.validationSummary.message = `FORM.FIELD.VALIDATOR.NOT_GREATER_THAN`; field.validationSummary.attributes.set('maxValue', max.format(field.dateDisplayFormat).replace(':', '-')); - isValid = false; + isFieldValid = false; } - return isValid; + return isFieldValid; } } @@ -583,3 +584,39 @@ export const FORM_FIELD_VALIDATORS = [ new MinDateTimeFieldValidator(), new MaxDateTimeFieldValidator() ]; + +export const momentToDateFnsMap = { + M: 'M', + D: 'd', + Y: 'y', + A: 'a' +}; + +export const dateFnsToMomentMap = { + M: 'M', + d: 'D', + y: 'Y', + a: 'A' +}; + +export function convertMomentToDateFnsFormat(dateDisplayFormat: string): string { + for (const [search, replace] of Object.entries(momentToDateFnsMap)) { + dateDisplayFormat = dateDisplayFormat.replace(new RegExp(search, 'g'), replace); + } + return dateDisplayFormat; +} + +export function convertDateFnsToMomentFormat(dateDisplayFormat: string): string { + for (const [search, replace] of Object.entries(dateFnsToMomentMap)) { + dateDisplayFormat = dateDisplayFormat.replace(new RegExp(search, 'g'), replace); + } + return dateDisplayFormat; +} + +export function formatUpdate(date: number|Date, dateFormat: string): string { + return format(date, convertMomentToDateFnsFormat(dateFormat)); +} + +export function parseUpdate(value: string, dateFormat: string, date = new Date()): Date { + return parse(value, convertMomentToDateFnsFormat(dateFormat), date); +} diff --git a/lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts b/lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts index 99efcbd8b9c..0537d098a85 100644 --- a/lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts +++ b/lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts @@ -19,9 +19,16 @@ import moment from 'moment'; import { FormFieldTypes } from './form-field-types'; import { FormFieldModel } from './form-field.model'; import { FormModel } from './form.model'; +import { DateFormatTranslationService } from '../../../public-api'; describe('FormFieldModel', () => { + let dateFormatTranslationService: DateFormatTranslationService; + + beforeEach(() => { + dateFormatTranslationService = new DateFormatTranslationService(); + }); + it('should store the form reference', () => { const form = new FormModel(); const model = new FormFieldModel(form); @@ -273,9 +280,9 @@ describe('FormFieldModel', () => { dateDisplayFormat: 'DD-MM-YYYY' }); - const currentDate = moment(new Date()); - const expectedDate = moment(currentDate).format('DD-MM-YYYY'); - const expectedDateFormat = `${currentDate.format('YYYY-MM-DD')}T00:00:00.000Z`; + const currentDate = new Date(); + const expectedDate = dateFormatTranslationService.format(currentDate, 'DD-MM-YYYY'); + const expectedDateFormat = `${dateFormatTranslationService.format(currentDate, 'YYYY-MM-DD')}T00:00:00.000Z`; expect(field.value).toBe(expectedDate); expect(form.values['ddmmyyy']).toEqual(expectedDateFormat); diff --git a/lib/core/src/lib/form/components/widgets/core/form-field.model.ts b/lib/core/src/lib/form/components/widgets/core/form-field.model.ts index dd2c0b2f95a..a85fb69e8a7 100644 --- a/lib/core/src/lib/form/components/widgets/core/form-field.model.ts +++ b/lib/core/src/lib/form/components/widgets/core/form-field.model.ts @@ -29,15 +29,20 @@ import { ProcessFormModel } from './process-form-model.interface'; import { isNumberValue } from './form-field-utils'; import { VariableConfig } from './form-field-variable-options'; import { DataColumn } from '../../../../datatable/data/data-column.model'; +import { isValid } from 'date-fns'; +import { DateFormatTranslationService } from '../../../services/date-format-translation.service'; // Maps to FormFieldRepresentation + +export const dateFormatTranslationService = new DateFormatTranslationService(); + export class FormFieldModel extends FormWidgetModel { private _value: string; private _readOnly: boolean = false; private _isValid: boolean = true; private _required: boolean = false; - readonly defaultDateFormat: string = 'D-M-YYYY'; + readonly defaultDateFormat: string = 'd-M-yyyy'; readonly defaultDateTimeFormat: string = 'D-M-YYYY hh:mm A'; // model members @@ -239,6 +244,15 @@ export class FormFieldModel extends FormWidgetModel { } private getDefaultDateFormat(jsonField: any): string { + if(jsonField.fields) { + Object.keys(jsonField.fields).forEach((el) => { + if(jsonField.fields[el]) { + jsonField.fields[el].forEach((element) => { + element.dateDisplayFormat = element.dateDisplayFormat? dateFormatTranslationService.convertMomentToDateFnsFormat(element.dateDisplayFormat): element.dateDisplayFormat; + }); + } + }); + } let originalType = jsonField.type; if (FormFieldTypes.isReadOnlyType(jsonField.type) && jsonField.params && jsonField.params.field) { originalType = jsonField.params.field.type; @@ -335,13 +349,13 @@ export class FormFieldModel extends FormWidgetModel { This is needed due to Activiti displaying/editing dates in d-M-YYYY format but storing on server in ISO8601 format (i.e. 2013-02-04T22:44:30.652Z) */ - if (this.isDateField(json) || this.isDateTimeField(json)) { + if (this.isDateTimeField(json)) { if (value) { let dateValue; if (isNumberValue(value)) { dateValue = moment(value); } else { - dateValue = this.isDateTimeField(json) ? moment.utc(value, 'YYYY-MM-DD hh:mm A') : moment.utc(value.split('T')[0], 'YYYY-M-D'); + dateValue = moment.utc(value, 'YYYY-MM-DD hh:mm A'); } if (dateValue?.isValid()) { value = dateValue.utc().format(this.dateDisplayFormat); @@ -349,6 +363,20 @@ export class FormFieldModel extends FormWidgetModel { } } + if (this.isDateField(json)) { + if (value) { + let dateValue; + if (isNumberValue(value)) { + dateValue = new Date(value); + } else { + dateValue = dateFormatTranslationService.parse(value.split('T')[0], 'YYYY-M-D'); + } + if (isValid(dateValue)) { + value = dateFormatTranslationService.format(dateValue, this.dateDisplayFormat); + } + } + } + if (this.isCheckboxField(json)) { value = json.value === 'true' || json.value === true; } @@ -417,12 +445,13 @@ export class FormFieldModel extends FormWidgetModel { } case FormFieldTypes.DATE: { if (typeof this.value === 'string' && this.value === 'today') { - this.value = moment(new Date()).format(this.dateDisplayFormat); + this.value = dateFormatTranslationService.format(new Date(), this.dateDisplayFormat); } - const dateValue = moment(this.value, this.dateDisplayFormat, true); - if (dateValue?.isValid()) { - this.form.values[this.id] = `${dateValue.format('YYYY-MM-DD')}T00:00:00.000Z`; + const dateValue = dateFormatTranslationService.parse(this.value, this.dateDisplayFormat); + + if (isValid(dateValue)) { + this.form.values[this.id] = `${dateFormatTranslationService.format(dateValue, 'YYYY-MM-DD')}T00:00:00.000Z`; } else { this.form.values[this.id] = null; this._value = this.value; diff --git a/lib/core/src/lib/form/components/widgets/date/date.widget.spec.ts b/lib/core/src/lib/form/components/widgets/date/date.widget.spec.ts index 7c364f8885d..5b6c979595d 100644 --- a/lib/core/src/lib/form/components/widgets/date/date.widget.spec.ts +++ b/lib/core/src/lib/form/components/widgets/date/date.widget.spec.ts @@ -16,13 +16,13 @@ */ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import moment from 'moment'; import { FormFieldModel } from '../core/form-field.model'; import { FormModel } from '../core/form.model'; import { DateWidgetComponent } from './date.widget'; import { CoreTestingModule } from '../../../../testing/core.testing.module'; import { TranslateModule } from '@ngx-translate/core'; import { FormFieldTypes } from '../core/form-field-types'; +import { format, isSameDay, parse } from 'date-fns'; describe('DateWidgetComponent', () => { let widget: DateWidgetComponent; @@ -62,8 +62,9 @@ describe('DateWidgetComponent', () => { widget.ngOnInit(); - const expected = moment(minValue, widget.field.dateDisplayFormat); - expect(widget.minDate.isSame(expected)).toBeTruthy(); + const expected = parse(minValue, widget.field.dateDisplayFormat, new Date()); + const widgetDate = parse(widget.minDate, widget.field.dateDisplayFormat, new Date()); + expect(isSameDay(widgetDate, expected)).toBeTruthy(); }); it('should date field be present', () => { @@ -85,8 +86,9 @@ describe('DateWidgetComponent', () => { }); widget.ngOnInit(); - const expected = moment(maxValue, widget.field.dateDisplayFormat); - expect(widget.maxDate.isSame(expected)).toBeTruthy(); + const expected = parse(maxValue, widget.field.dateDisplayFormat, new Date()); + const widgetDate = parse(widget.maxDate, widget.field.dateDisplayFormat, new Date()); + expect(isSameDay(widgetDate, expected)).toBeTruthy(); }); it('should eval visibility on date changed', () => { diff --git a/lib/core/src/lib/form/components/widgets/date/date.widget.ts b/lib/core/src/lib/form/components/widgets/date/date.widget.ts index 74c916bf4be..985f97e3b3b 100644 --- a/lib/core/src/lib/form/components/widgets/date/date.widget.ts +++ b/lib/core/src/lib/form/components/widgets/date/date.widget.ts @@ -32,8 +32,9 @@ import { MatDatepickerInputEvent } from '@angular/material/datepicker'; @Component({ selector: 'date-widget', providers: [ - { provide: DateAdapter, useClass: MomentDateAdapter }, - { provide: MAT_DATE_FORMATS, useValue: MOMENT_DATE_FORMATS }], + { provide: DateAdapter, useClass: DateFnsAdapter }, + { provide: MAT_DATE_FORMATS, useValue: MAT_DATE_FNS_FORMATS } + ], templateUrl: './date.widget.html', host: { '(click)': 'event($event)', @@ -62,8 +63,10 @@ export class DateWidgetComponent extends WidgetComponent implements OnInit, OnDe private onDestroy$ = new Subject(); constructor(public formService: FormService, - private dateAdapter: DateAdapter, - private userPreferencesService: UserPreferencesService) { + private dateAdapter: DateAdapter, + private userPreferencesService: UserPreferencesService, + @Inject(MAT_DATE_FORMATS) private dateFormatConfig: MatDateFormats, + protected dateFormatTranslationService: DateFormatTranslationService) { super(formService); } @@ -71,10 +74,9 @@ export class DateWidgetComponent extends WidgetComponent implements OnInit, OnDe this.userPreferencesService .select(UserPreferenceValues.Locale) .pipe(takeUntil(this.onDestroy$)) - .subscribe(locale => this.dateAdapter.setLocale(locale)); + .subscribe(locale => this.dateAdapter.setLocale(DateFnsUtils.getLocaleFromString(locale))); - const momentDateAdapter = this.dateAdapter as MomentDateAdapter; - momentDateAdapter.overrideDisplayFormat = this.field.dateDisplayFormat; + this.dateFormatConfig.display.dateInput = this.field.dateDisplayFormat; if (this.field) { if (this.field.minValue) { diff --git a/lib/core/src/lib/form/public-api.ts b/lib/core/src/lib/form/public-api.ts index fa80753e8b4..15f0303eca2 100644 --- a/lib/core/src/lib/form/public-api.ts +++ b/lib/core/src/lib/form/public-api.ts @@ -26,6 +26,7 @@ export * from './services/form-rendering.service'; export * from './services/form.service'; export * from './services/form-validation-service.interface'; export * from './services/widget-visibility.service'; +export * from './services/date-format-translation.service'; export * from './events'; diff --git a/lib/core/src/lib/form/services/date-format-translation.service.spec.ts b/lib/core/src/lib/form/services/date-format-translation.service.spec.ts new file mode 100644 index 00000000000..171aa4e0448 --- /dev/null +++ b/lib/core/src/lib/form/services/date-format-translation.service.spec.ts @@ -0,0 +1,72 @@ +/*! + * @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 { TestBed } from '@angular/core/testing'; +import { DateFormatTranslationService } from './date-format-translation.service'; +import { TranslateModule } from '@ngx-translate/core'; +import { CoreTestingModule } from '../../testing/core.testing.module'; + +describe('DateFormatTranslationService', () => { + let service: DateFormatTranslationService; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot(), CoreTestingModule], + providers: [DateFormatTranslationService] + }); + + service = TestBed.inject(DateFormatTranslationService); + }); + + it('should convert moment to date-fns format correctly', () => { + const momentFormat = 'YYYY-MM-DD'; + const expectedDateFnsFormat = 'yyyy-MM-dd'; + + const result = service.convertMomentToDateFnsFormat(momentFormat); + + expect(result).toBe(expectedDateFnsFormat); + }); + + it('should convert date-fns to moment format correctly', () => { + const dateFnsFormat = 'yyyy-MM-dd'; + const expectedMomentFormat = 'YYYY-MM-DD'; + + const result = service.convertDateFnsToMomentFormat(dateFnsFormat); + + expect(result).toBe(expectedMomentFormat); + }); + + it('should format a date correctly', () => { + const date = new Date('2023-09-22T12:00:00Z'); + const dateFormat = 'yyyy-MM-dd'; + const expectedFormattedDate = '2023-09-22'; + + const result = service.format(date, dateFormat); + + expect(result).toBe(expectedFormattedDate); + }); + + it('should parse a date correctly', () => { + const dateString = '2023-09-22'; + const dateFormat = 'yyyy-MM-dd'; + const expectedParsedDate = new Date('2023-09-22T00:00:00Z'); + + const result = service.parse(dateString, dateFormat); + + expect(result).toEqual(expectedParsedDate); + }); +}); diff --git a/lib/core/src/lib/form/services/date-format-translation.service.ts b/lib/core/src/lib/form/services/date-format-translation.service.ts new file mode 100644 index 00000000000..4016f96bdad --- /dev/null +++ b/lib/core/src/lib/form/services/date-format-translation.service.ts @@ -0,0 +1,60 @@ +/*! + * @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 { Injectable } from '@angular/core'; +import { format, parse } from 'date-fns'; + +@Injectable({ + providedIn: 'root' +}) +export class DateFormatTranslationService { + private momentToDateFnsMap = { + M: 'M', + D: 'd', + Y: 'y', + A: 'a' + }; + + private dateFnsToMomentMap = { + M: 'M', + d: 'D', + y: 'Y', + a: 'A' + }; + + convertMomentToDateFnsFormat(dateDisplayFormat: string): string { + for (const [search, replace] of Object.entries(this.momentToDateFnsMap)) { + dateDisplayFormat = dateDisplayFormat.replace(new RegExp(search, 'g'), replace); + } + return dateDisplayFormat; + } + + convertDateFnsToMomentFormat(dateDisplayFormat: string): string { + for (const [search, replace] of Object.entries(this.dateFnsToMomentMap)) { + dateDisplayFormat = dateDisplayFormat.replace(new RegExp(search, 'g'), replace); + } + return dateDisplayFormat; + } + + format(date: number|Date, dateFormat: string): string { + return format(date, this.convertMomentToDateFnsFormat(dateFormat)); + } + + parse(value: string, dateFormat: string, date = new Date()): Date { + return parse(value, this.convertMomentToDateFnsFormat(dateFormat), date); + } +} diff --git a/lib/core/src/lib/pipes/date.pipe.spec.ts b/lib/core/src/lib/pipes/date.pipe.spec.ts new file mode 100644 index 00000000000..a2ccc3ed653 --- /dev/null +++ b/lib/core/src/lib/pipes/date.pipe.spec.ts @@ -0,0 +1,74 @@ +/*! + * @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 { TestBed } from '@angular/core/testing'; +import { CoreTestingModule } from '../testing/core.testing.module'; +import { TranslateModule } from '@ngx-translate/core'; +import { DatePipe } from './date.pipe'; +import { DateFormatTranslationService } from '../form/public-api'; + +describe('DatePipe', () => { + let datePipe: DatePipe; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [TranslateModule.forRoot(), CoreTestingModule], + providers: [DatePipe, DateFormatTranslationService] + }); + datePipe = TestBed.inject(DatePipe); + }); + + it('should return the formatted date string when given a valid date object', () => { + const inputDate = new Date('2023-08-14'); + const dateFormat = 'DD-MM-YYYY'; + const expectedOutput = '14-08-2023'; + + const result = datePipe.transform(inputDate, dateFormat); + + expect(result).toBe(expectedOutput); + }); + + it('should return the input value when given an invalid date object', () => { + const inputDate = new Date('invalid'); + const dateFormat = 'DD-MM-YYYY'; + const expectedOutput = inputDate.toString(); + + const result = datePipe.transform(inputDate, dateFormat); + + expect(result).toBe(expectedOutput); + }); + + it('should return the formatted date string when given a valid date string', () => { + const inputDate = '2023-08-14'; + const dateFormat = 'DD-MM-YYYY'; + const expectedOutput = '14-08-2023'; + + const result = datePipe.transform(inputDate, dateFormat); + + expect(result).toBe(expectedOutput); + }); + + it('should return the input value when given an invalid date string', () => { + const inputDate = 'not_a_valid_date'; + const dateFormat = 'DD-MM-YYYY'; + const expectedOutput = inputDate; + + const result = datePipe.transform(inputDate, dateFormat); + + expect(result).toBe(expectedOutput); + }); +}); diff --git a/lib/core/src/lib/pipes/date.pipe.ts b/lib/core/src/lib/pipes/date.pipe.ts new file mode 100644 index 00000000000..6bb180984da --- /dev/null +++ b/lib/core/src/lib/pipes/date.pipe.ts @@ -0,0 +1,30 @@ +/*! + * @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 { Pipe, PipeTransform } from '@angular/core'; +import { isValid } from 'date-fns'; +import { DateFormatTranslationService } from '../form/services/date-format-translation.service'; + +@Pipe({ name: 'adfDate' }) +export class DatePipe implements PipeTransform { + constructor(private dateFormatTranslationService: DateFormatTranslationService) {} + + transform(value: Date | string, dateFormat: string): string { + const date = value instanceof Date ? value : new Date(value); + return isValid(date) ? this.dateFormatTranslationService.format(date, dateFormat) : value.toString(); + } +} diff --git a/lib/core/src/lib/pipes/pipe.module.ts b/lib/core/src/lib/pipes/pipe.module.ts index 29bbf9a156f..792920117da 100644 --- a/lib/core/src/lib/pipes/pipe.module.ts +++ b/lib/core/src/lib/pipes/pipe.module.ts @@ -36,6 +36,7 @@ import { MomentDateTimePipe } from './moment-datetime.pipe'; import { FilterStringPipe } from './filter-string.pipe'; import { FilterOutArrayObjectsByPropPipe } from './filter-out-every-object-by-prop.pipe'; import { DateTimePipe } from './date-time.pipe'; +import { DatePipe } from './date.pipe'; @NgModule({ imports: [ @@ -56,6 +57,7 @@ import { DateTimePipe } from './date-time.pipe'; DecimalNumberPipe, LocalizedRolePipe, MomentDatePipe, + DatePipe, MomentDateTimePipe, DateTimePipe, FilterStringPipe, @@ -74,6 +76,7 @@ import { DateTimePipe } from './date-time.pipe'; DecimalNumberPipe, LocalizedRolePipe, MomentDatePipe, + DatePipe, MomentDateTimePipe, DateTimePipe, FilterStringPipe, @@ -93,6 +96,7 @@ import { DateTimePipe } from './date-time.pipe'; DecimalNumberPipe, LocalizedRolePipe, MomentDatePipe, + DatePipe, MomentDateTimePipe, DateTimePipe, FilterStringPipe, diff --git a/lib/core/src/lib/pipes/public-api.ts b/lib/core/src/lib/pipes/public-api.ts index 8424f55653b..d85dc947aa2 100644 --- a/lib/core/src/lib/pipes/public-api.ts +++ b/lib/core/src/lib/pipes/public-api.ts @@ -29,6 +29,7 @@ export * from './user-initial.pipe'; export * from './localized-role.pipe'; export * from './pipe.module'; export * from './moment-date.pipe'; +export * from './date.pipe'; export * from './moment-datetime.pipe'; export * from './date-time.pipe'; export * from './filter-string.pipe'; diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.html b/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.html index f65fb13fa0c..e8fe51b4998 100644 --- a/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.html +++ b/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.html @@ -1,11 +1,11 @@
-
- - + { @@ -52,8 +52,8 @@ describe('DateWidgetComponent', () => { widget.ngOnInit(); - const expected = moment(minValue, DATE_FORMAT_CLOUD); - expect(widget.minDate.isSame(expected)).toBeTruthy(); + const expected = format(new Date(minValue), DATE_FORMAT_CLOUD); + expect(widget.minDate).toEqual(expected); }); it('should date field be present', () => { @@ -75,8 +75,8 @@ describe('DateWidgetComponent', () => { }); widget.ngOnInit(); - const expected = moment(maxValue, DATE_FORMAT_CLOUD); - expect(widget.maxDate.isSame(expected)).toBeTruthy(); + const expected = format(new Date(maxValue), DATE_FORMAT_CLOUD); + expect(widget.maxDate).toEqual(expected); }); it('should eval visibility on date changed', () => { @@ -91,8 +91,8 @@ describe('DateWidgetComponent', () => { }); widget.field = field; - const todayDate = moment().format(DATE_FORMAT_CLOUD); - widget.onDateChanged({ value: todayDate }); + const todayDate = new Date(); + widget.onDateChanged({ value: format(todayDate, DATE_FORMAT_CLOUD) }); expect(widget.onFieldChanged).toHaveBeenCalledWith(field); }); @@ -293,8 +293,8 @@ describe('DateWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const todayDate = moment().format(DATE_FORMAT_CLOUD); - const expected = moment(todayDate).subtract(widget.field.minDateRangeValue, 'days'); + const todayDate = new Date(); + const expected = format(subDays(todayDate, widget.field.minDateRangeValue), DATE_FORMAT_CLOUD); expect(widget.minDate).toEqual(expected); }); @@ -343,8 +343,8 @@ describe('DateWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const todayDate = moment().format(DATE_FORMAT_CLOUD); - const expected = moment(todayDate).add(widget.field.maxDateRangeValue, 'days'); + const todayDate = new Date(); + const expected = format(addDays(todayDate, widget.field.maxDateRangeValue), DATE_FORMAT_CLOUD); expect(widget.maxDate).toEqual(expected); }); @@ -392,7 +392,6 @@ describe('DateWidgetComponent', () => { describe('check date validation by dynamic date ranges', () => { it('should minValue be equal to today date minus minDateRangeValue', async () => { - spyOn(widget, 'getTodaysFormattedDate').and.returnValue('2022-07-22'); widget.field = new FormFieldModel(null, { dynamicDateRangeSelection: true, maxDateRangeValue: null, @@ -404,7 +403,8 @@ describe('DateWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const expectedMinValueString = '2022-07-21'; + const currentDate = new Date(); + const expectedMinValueString = format(subDays(currentDate, 1), DATE_FORMAT_CLOUD); expect(widget.field.minValue).toEqual(expectedMinValueString); expect(widget.maxDate).toBeUndefined(); @@ -412,7 +412,6 @@ describe('DateWidgetComponent', () => { }); it('should maxValue be equal to today date plus maxDateRangeValue', async () => { - spyOn(widget, 'getTodaysFormattedDate').and.returnValue('2022-07-22'); widget.field = new FormFieldModel(null, { dynamicDateRangeSelection: true, maxDateRangeValue: 8, @@ -424,7 +423,8 @@ describe('DateWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const expectedMaxValueString = '2022-07-30'; + const currentDate = new Date(); + const expectedMaxValueString = format(addDays(currentDate, 8), DATE_FORMAT_CLOUD); expect(widget.field.maxValue).toEqual(expectedMaxValueString); expect(widget.minDate).toBeUndefined(); @@ -432,7 +432,6 @@ describe('DateWidgetComponent', () => { }); it('should maxValue and minValue be null if maxDateRangeValue and minDateRangeValue are null', async () => { - spyOn(widget, 'getTodaysFormattedDate').and.returnValue('2022-07-22'); widget.field = new FormFieldModel(null, { dynamicDateRangeSelection: true, maxDateRangeValue: null, @@ -451,7 +450,6 @@ describe('DateWidgetComponent', () => { }); it('should maxValue and minValue not be null if maxDateRangeVale and minDateRangeValue are not null', async () => { - spyOn(widget, 'getTodaysFormattedDate').and.returnValue('2022-07-22'); widget.field = new FormFieldModel(null, { dynamicDateRangeSelection: true, maxDateRangeValue: 8, @@ -463,8 +461,9 @@ describe('DateWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const expectedMaxValueString = '2022-07-30'; - const expectedMinValueString = '2022-07-12'; + const currentDate = new Date(); + const expectedMaxValueString = format(addDays(currentDate, 8), DATE_FORMAT_CLOUD); + const expectedMinValueString = format(subDays(currentDate, 10), DATE_FORMAT_CLOUD); expect(widget.field.maxValue).toEqual(expectedMaxValueString); expect(widget.field.minValue).toEqual(expectedMinValueString); diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.ts b/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.ts index 8d621442499..a8a9d292bdc 100644 --- a/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.ts +++ b/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.ts @@ -17,22 +17,23 @@ /* eslint-disable @angular-eslint/component-selector */ -import { Component, OnInit, ViewEncapsulation, OnDestroy } from '@angular/core'; -import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core'; -import moment, { Moment } from 'moment'; +import { Component, OnInit, ViewEncapsulation, OnDestroy, Inject } from '@angular/core'; +import { DateAdapter, MAT_DATE_FORMATS, MatDateFormats } from '@angular/material/core'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { - MOMENT_DATE_FORMATS, MomentDateAdapter, WidgetComponent, - UserPreferencesService, UserPreferenceValues, FormService + WidgetComponent, + UserPreferencesService, UserPreferenceValues, FormService, DateFormatTranslationService, DateFnsUtils } from '@alfresco/adf-core'; import { DATE_FORMAT_CLOUD } from '../../../../models/date-format-cloud.model'; +import { DateFnsAdapter, MAT_DATE_FNS_FORMATS } from '@angular/material-date-fns-adapter'; +import { addDays, isValid, subDays } from 'date-fns'; @Component({ selector: 'date-widget', providers: [ - { provide: DateAdapter, useClass: MomentDateAdapter }, - { provide: MAT_DATE_FORMATS, useValue: MOMENT_DATE_FORMATS }], + { provide: DateAdapter, useClass: DateFnsAdapter }, + { provide: MAT_DATE_FORMATS, useValue: MAT_DATE_FNS_FORMATS }], templateUrl: './date-cloud.widget.html', styleUrls: ['./date-cloud.widget.scss'], host: { @@ -51,14 +52,16 @@ import { DATE_FORMAT_CLOUD } from '../../../../models/date-format-cloud.model'; export class DateCloudWidgetComponent extends WidgetComponent implements OnInit, OnDestroy { typeId = 'DateCloudWidgetComponent'; - minDate: Moment; - maxDate: Moment; + minDate: string; + maxDate: string; private onDestroy$ = new Subject(); constructor(public formService: FormService, - private dateAdapter: DateAdapter, - private userPreferencesService: UserPreferencesService) { + private dateAdapter: DateAdapter, + private userPreferencesService: UserPreferencesService, + @Inject(MAT_DATE_FORMATS) private dateFormatConfig: MatDateFormats, + protected dateFormatTranslationService: DateFormatTranslationService) { super(formService); } @@ -66,47 +69,42 @@ export class DateCloudWidgetComponent extends WidgetComponent implements OnInit, this.userPreferencesService .select(UserPreferenceValues.Locale) .pipe(takeUntil(this.onDestroy$)) - .subscribe(locale => this.dateAdapter.setLocale(locale)); + .subscribe(locale => this.dateAdapter.setLocale(DateFnsUtils.getLocaleFromString(locale))); - const momentDateAdapter = this.dateAdapter as MomentDateAdapter; - momentDateAdapter.overrideDisplayFormat = this.field.dateDisplayFormat; + this.dateFormatConfig.display.dateInput = this.field.dateDisplayFormat; if (this.field) { if (this.field.dynamicDateRangeSelection) { - const today = this.getTodaysFormattedDate(); + const today = new Date(); if (Number.isInteger(this.field.minDateRangeValue)) { - this.minDate = moment(today).subtract(this.field.minDateRangeValue, 'days'); - this.field.minValue = this.minDate.format(DATE_FORMAT_CLOUD); + this.minDate = this.dateFormatTranslationService.format(subDays(today, this.field.minDateRangeValue), DATE_FORMAT_CLOUD); + this.field.minValue = this.minDate; } if (Number.isInteger(this.field.maxDateRangeValue)) { - this.maxDate = moment(today).add(this.field.maxDateRangeValue, 'days'); - this.field.maxValue = this.maxDate.format(DATE_FORMAT_CLOUD); + this.maxDate = this.dateFormatTranslationService.format(addDays(today, this.field.maxDateRangeValue), DATE_FORMAT_CLOUD); + this.field.maxValue = this.maxDate; } } else { if (this.field.minValue) { - this.minDate = moment(this.field.minValue, DATE_FORMAT_CLOUD); + this.minDate = this.dateFormatTranslationService.format(new Date(this.field.minValue), DATE_FORMAT_CLOUD); } if (this.field.maxValue) { - this.maxDate = moment(this.field.maxValue, DATE_FORMAT_CLOUD); + this.maxDate = this.dateFormatTranslationService.format(new Date(this.field.maxValue), DATE_FORMAT_CLOUD); } } } } - getTodaysFormattedDate() { - return moment().format(DATE_FORMAT_CLOUD); - } - ngOnDestroy() { this.onDestroy$.next(true); this.onDestroy$.complete(); } onDateChanged(newDateValue) { - const date = moment(newDateValue, this.field.dateDisplayFormat, true); - if (date.isValid()) { - this.field.value = date.format(this.field.dateDisplayFormat); + const date = new Date(newDateValue); + if (isValid(date)) { + this.field.value = this.dateFormatTranslationService.format(date, this.field.dateDisplayFormat); } else { this.field.value = newDateValue; } diff --git a/lib/process-services-cloud/src/lib/models/date-format-cloud.model.ts b/lib/process-services-cloud/src/lib/models/date-format-cloud.model.ts index 786c8c316be..79f48c0033e 100644 --- a/lib/process-services-cloud/src/lib/models/date-format-cloud.model.ts +++ b/lib/process-services-cloud/src/lib/models/date-format-cloud.model.ts @@ -15,4 +15,4 @@ * limitations under the License. */ -export const DATE_FORMAT_CLOUD = 'YYYY-MM-DD'; +export const DATE_FORMAT_CLOUD = 'yyyy-MM-dd'; From 9fc4c970f61b78a8d95b03ca0910493e3b2c7bb4 Mon Sep 17 00:00:00 2001 From: SheenaMalhotra182 Date: Fri, 22 Sep 2023 22:08:56 +0530 Subject: [PATCH 02/19] [ACS-5857] fixed date parsing and linting --- .../src/lib/form/components/widgets/date/date-cloud.widget.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.ts b/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.ts index a8a9d292bdc..10fd714b6b7 100644 --- a/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.ts +++ b/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.ts @@ -102,7 +102,7 @@ export class DateCloudWidgetComponent extends WidgetComponent implements OnInit, } onDateChanged(newDateValue) { - const date = new Date(newDateValue); + const date = this.dateFormatTranslationService.parse(newDateValue, this.field.dateDisplayFormat, new Date()); if (isValid(date)) { this.field.value = this.dateFormatTranslationService.format(date, this.field.dateDisplayFormat); } else { From b94591eadda91d0e9f6c1b3b3c7eaaa05f9ce5db Mon Sep 17 00:00:00 2001 From: SheenaMalhotra182 Date: Fri, 29 Sep 2023 19:13:42 +0530 Subject: [PATCH 03/19] migrated adfMomentDate Pipe to date-fns equivalent and used custom date-fns methods --- .../lib/common/utils/date-fns-utils.spec.ts | 9 ++ .../src/lib/common/utils/date-fns-utils.ts | 30 ++++++- .../widgets/core/form-field-validator.spec.ts | 12 +-- .../widgets/core/form-field-validator.ts | 83 ++++++------------- .../widgets/core/form-field.model.spec.ts | 22 ++--- .../widgets/core/form-field.model.ts | 36 ++++---- .../widgets/date-time/date-time.widget.html | 6 +- .../date-time/date-time.widget.spec.ts | 20 +++-- .../widgets/date-time/date-time.widget.ts | 62 ++++++++------ .../components/widgets/date/date.widget.ts | 2 +- lib/core/src/lib/pipes/date.pipe.spec.ts | 76 +++++++++++++---- lib/core/src/lib/pipes/date.pipe.ts | 8 +- lib/core/src/lib/pipes/pipe.module.ts | 8 +- .../widgets/date/date-cloud.widget.html | 4 +- .../widgets/date/date-cloud.widget.ts | 23 +++-- 15 files changed, 231 insertions(+), 170 deletions(-) diff --git a/lib/core/src/lib/common/utils/date-fns-utils.spec.ts b/lib/core/src/lib/common/utils/date-fns-utils.spec.ts index 59f21e2c377..3c545ae6c9e 100644 --- a/lib/core/src/lib/common/utils/date-fns-utils.spec.ts +++ b/lib/core/src/lib/common/utils/date-fns-utils.spec.ts @@ -55,4 +55,13 @@ describe('Date Format Translations', () => { expect(result).toEqual(expectedParsedDate); }); + + it('should add seconds to a date time value', () => { + const inputDateTime = '2023-09-02T10:00:00Z'; + const expectedUpdatedValue = '2023-09-02T10:00:00.00Z'; + + const result = DateFnsUtils.addSeconds(inputDateTime); + + expect(result).toEqual(expectedUpdatedValue); + }); }); diff --git a/lib/core/src/lib/common/utils/date-fns-utils.ts b/lib/core/src/lib/common/utils/date-fns-utils.ts index 15937cdae62..fba78b85e09 100644 --- a/lib/core/src/lib/common/utils/date-fns-utils.ts +++ b/lib/core/src/lib/common/utils/date-fns-utils.ts @@ -87,7 +87,9 @@ export class DateFnsUtils { D: 'd', Y: 'y', A: 'a', - ll: 'PP' + ll: 'PP', + Z: 'XXX', + T: `'T'` }; /** @@ -97,7 +99,8 @@ export class DateFnsUtils { d: 'D', y: 'Y', a: 'A', - PP: 'll' + PP: 'll', + xxx: 'Z' }; /** @@ -107,6 +110,14 @@ export class DateFnsUtils { * @returns The equivalent date-fns format string. */ static convertMomentToDateFnsFormat(dateDisplayFormat: string): string { + // Check if 'A' is present in the format string + const containsA = dateDisplayFormat.includes('A'); + + // Replace 'HH' with 'hh' if 'A' is also present + if (containsA) { + dateDisplayFormat = dateDisplayFormat.replace(/HH/g, 'hh'); + } + if (dateDisplayFormat && dateDisplayFormat.trim() !== '') { for (const [search, replace] of Object.entries(this.momentToDateFnsMap)) { dateDisplayFormat = dateDisplayFormat.replace(new RegExp(search, 'g'), replace); @@ -156,4 +167,19 @@ export class DateFnsUtils { static parseDate(value: string, dateFormat: string): Date { return parse(value, this.convertMomentToDateFnsFormat(dateFormat), new Date()); } + + /** + * Adds seconds to a date time value represented as a string in the format 'YYYY-MM-DDTHH:mm:ssZ'. + * + * @param value - The input time value to which seconds will be added. + * @returns - A string representing the input date time value with seconds added. + */ + static addSeconds(value: string): string { + const colonIndex: number = value.lastIndexOf(':'); + const updatedValue = value.slice(0, colonIndex) + ':' + value.slice(colonIndex + 1); + const dateParts: string[] = updatedValue.split(':'); + dateParts[2] = '00.' + dateParts[2]; + value = dateParts.join(':'); + return value; + } } diff --git a/lib/core/src/lib/form/components/widgets/core/form-field-validator.spec.ts b/lib/core/src/lib/form/components/widgets/core/form-field-validator.spec.ts index 4e990d9a5b3..275348bb755 100644 --- a/lib/core/src/lib/form/components/widgets/core/form-field-validator.spec.ts +++ b/lib/core/src/lib/form/components/widgets/core/form-field-validator.spec.ts @@ -15,6 +15,7 @@ * limitations under the License. */ +import { DateFnsUtils } from '../../../../common'; import { ErrorMessageModel } from './error-message.model'; import { FormFieldOption } from './form-field-option'; import { FormFieldTypes } from './form-field-types'; @@ -35,7 +36,6 @@ import { } from './form-field-validator'; import { FormFieldModel } from './form-field.model'; import { FormModel } from './form.model'; -declare let moment: any; describe('FormFieldValidator', () => { describe('RequiredFieldValidator', () => { @@ -708,7 +708,7 @@ describe('FormFieldValidator', () => { it('should take into account that max value is in UTC and NOT fail validating value checking the time', () => { const maxValueFromActivitiInput = '31-3-2018 12:00 AM'; - const maxValueSavedInForm = moment(maxValueFromActivitiInput, 'DD-M-YYYY hh:mm A').utc().format(); + const maxValueSavedInForm = DateFnsUtils.formatDate(DateFnsUtils.parseDate(maxValueFromActivitiInput, 'DD-M-YYYY hh:mm A'), `YYYY-MM-DDTHH:mm:ssZ`); const localValidValue = '2018-3-30 11:59 PM'; @@ -723,7 +723,7 @@ describe('FormFieldValidator', () => { it('should take into account that max value is in UTC and fail validating value checking the time', () => { const maxValueFromActivitiInput = '31-3-2018 12:00 AM'; - const maxValueSavedInForm = moment(maxValueFromActivitiInput, 'DD-M-YYYY hh:mm A').utc().format(); + const maxValueSavedInForm = DateFnsUtils.formatDate(DateFnsUtils.parseDate(maxValueFromActivitiInput, 'DD-M-YYYY hh:mm A'), `YYYY-MM-DDTHH:mm:ssZ`); const localInvalidValue = '2018-3-31 12:01 AM'; @@ -833,7 +833,7 @@ describe('FormFieldValidator', () => { it('should take into account that min value is in UTC and NOT fail validating value checking the time', () => { const minValueFromActivitiInput = '02-3-2018 06:00 AM'; - const minValueSavedInForm = moment(minValueFromActivitiInput, 'DD-M-YYYY hh:mm A').utc().format(); + const minValueSavedInForm = DateFnsUtils.formatDate(DateFnsUtils.parseDate(minValueFromActivitiInput, 'DD-M-YYYY hh:mm A'), `YYYY-MM-DDTHH:mm:ssZ`); const localValidValue = '2018-3-02 06:01 AM'; @@ -848,7 +848,7 @@ describe('FormFieldValidator', () => { it('should take into account that min value is in UTC and fail validating value checking the time', () => { const minValueFromActivitiInput = '02-3-2018 06:00 AM'; - const minValueSavedInForm = moment(minValueFromActivitiInput, 'DD-M-YYYY hh:mm A').utc().format(); + const minValueSavedInForm = DateFnsUtils.formatDate(DateFnsUtils.parseDate(minValueFromActivitiInput, 'DD-M-YYYY hh:mm A'), `YYYY-MM-DDTHH:mm:ssZ`); const localInvalidValue = '2018-3-02 05:59 AM'; @@ -1113,7 +1113,7 @@ describe('FormFieldValidator', () => { it('should validate dateTime format with default format', () => { const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATETIME, - value: '2021-06-09 14:10' + value: '2021-06-09 02:10 AM' }); expect(validator.validate(field)).toBeTruthy(); }); diff --git a/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts b/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts index 7a696d019a4..921aa6453c3 100644 --- a/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts +++ b/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts @@ -17,11 +17,11 @@ /* eslint-disable @angular-eslint/component-selector */ -import moment from 'moment'; import { FormFieldTypes } from './form-field-types'; import { isNumberValue } from './form-field-utils'; import { FormFieldModel } from './form-field.model'; -import { format, isAfter, isBefore, isValid, parse } from 'date-fns'; +import { isAfter, isBefore, isValid } from 'date-fns'; +import { DateFnsUtils } from '../../../../common/utils/date-fns-utils'; export interface FormFieldValidator { @@ -146,9 +146,9 @@ export class DateFieldValidator implements FormFieldValidator { ]; // Validates that the input string is a valid date formatted as (default D-M-YYYY) - static isValidDate(inputDate: string, dateFormat: string = 'd-M-yyyy'): boolean { + static isValidDate(inputDate: string, dateFormat: string = 'D-M-YYYY'): boolean { if (inputDate) { - const d = parseUpdate(inputDate, dateFormat); + const d = DateFnsUtils.parseDate(inputDate, dateFormat); return isValid(d); } @@ -180,8 +180,8 @@ export class DateTimeFieldValidator implements FormFieldValidator { // Validates that the input string is a valid date formatted as (default D-M-YYYY) static isValidDate(inputDate: string, dateFormat: string = 'YYYY-MM-DD HH:mm'): boolean { if (inputDate) { - const d = moment(inputDate, dateFormat, true); - return d.isValid(); + const d = DateFnsUtils.parseDate(inputDate, dateFormat); + return isValid(d); } return false; @@ -193,7 +193,7 @@ export class DateTimeFieldValidator implements FormFieldValidator { validate(field: FormFieldModel): boolean { if (this.isSupported(field) && field.value && field.isVisible) { - if (DateFieldValidator.isValidDate(field.value, field.dateDisplayFormat)) { + if (DateTimeFieldValidator.isValidDate(field.value, DateFnsUtils.convertMomentToDateFnsFormat(field.dateDisplayFormat))) { return true; } field.validationSummary.message = field.dateDisplayFormat; @@ -245,17 +245,17 @@ export class MinDateFieldValidator extends BoundaryDateFieldValidator { // remove time and timezone info let fieldValueData; if (typeof field.value === 'string') { - fieldValueData = parseUpdate(field.value.split('T')[0], dateFormat); + fieldValueData = DateFnsUtils.parseDate(field.value.split('T')[0], dateFormat); } else { fieldValueData = field.value; } const minValueDateFormat = this.extractDateFormat(field.minValue); - const min = parseUpdate(field.minValue, minValueDateFormat); + const min = DateFnsUtils.parseDate(field.minValue, minValueDateFormat); if (isBefore(fieldValueData, min)) { field.validationSummary.message = `FORM.FIELD.VALIDATOR.NOT_LESS_THAN`; - field.validationSummary.attributes.set('minValue', formatUpdate(min, field.dateDisplayFormat).toLocaleUpperCase()); + field.validationSummary.attributes.set('minValue', DateFnsUtils.formatDate(min, field.dateDisplayFormat).toLocaleUpperCase()); isFieldValid = false; } return isFieldValid; @@ -275,17 +275,17 @@ export class MaxDateFieldValidator extends BoundaryDateFieldValidator { // remove time and timezone info let fieldValueData; if (typeof field.value === 'string') { - fieldValueData = parseUpdate(field.value.split('T')[0], dateFormat); + fieldValueData = DateFnsUtils.parseDate(field.value.split('T')[0], dateFormat); } else { fieldValueData = field.value; } const maxValueDateFormat = this.extractDateFormat(field.maxValue); - const max = parseUpdate(field.maxValue, maxValueDateFormat); + const max = DateFnsUtils.parseDate(field.maxValue, maxValueDateFormat); if (isAfter(fieldValueData, max)) { field.validationSummary.message = `FORM.FIELD.VALIDATOR.NOT_GREATER_THAN`; - field.validationSummary.attributes.set('maxValue', formatUpdate(max, field.dateDisplayFormat).toLocaleUpperCase()); + field.validationSummary.attributes.set('maxValue', DateFnsUtils.formatDate(max, field.dateDisplayFormat).toLocaleUpperCase()); isFieldValid = false; } return isFieldValid; @@ -302,7 +302,7 @@ export class MinDateTimeFieldValidator implements FormFieldValidator { private supportedTypes = [ FormFieldTypes.DATETIME ]; - MIN_DATETIME_FORMAT = 'YYYY-MM-DD hh:mm AZ'; + MIN_DATETIME_FORMAT = 'YYYY-MM-DD hh:mm A'; isSupported(field: FormFieldModel): boolean { return field && @@ -328,15 +328,15 @@ export class MinDateTimeFieldValidator implements FormFieldValidator { let isFieldValid = true; let fieldValueDate; if (typeof field.value === 'string') { - fieldValueDate = moment(field.value, dateFormat); + fieldValueDate = DateFnsUtils.parseDate(field.value, dateFormat); } else { fieldValueDate = field.value; } - const min = moment(field.minValue, this.MIN_DATETIME_FORMAT); + const min = DateFnsUtils.formatDate(new Date(field.minValue), this.MIN_DATETIME_FORMAT); - if (fieldValueDate.isBefore(min)) { + if (isBefore(fieldValueDate, new Date(min))) { field.validationSummary.message = `FORM.FIELD.VALIDATOR.NOT_LESS_THAN`; - field.validationSummary.attributes.set('minValue', min.format(field.dateDisplayFormat).replace(':', '-')); + field.validationSummary.attributes.set('minValue', DateFnsUtils.formatDate(new Date(min), field.dateDisplayFormat).replace(':', '-')); isFieldValid = false; } return isFieldValid; @@ -348,7 +348,7 @@ export class MaxDateTimeFieldValidator implements FormFieldValidator { private supportedTypes = [ FormFieldTypes.DATETIME ]; - MAX_DATETIME_FORMAT = 'YYYY-MM-DD hh:mm AZ'; + MAX_DATETIME_FORMAT = 'YYYY-MM-DD hh:mm A'; isSupported(field: FormFieldModel): boolean { return field && @@ -375,15 +375,16 @@ export class MaxDateTimeFieldValidator implements FormFieldValidator { let fieldValueDate; if (typeof field.value === 'string') { - fieldValueDate = moment(field.value, dateFormat); + fieldValueDate = DateFnsUtils.parseDate(field.value, dateFormat); } else { fieldValueDate = field.value; } - const max = moment(field.maxValue, this.MAX_DATETIME_FORMAT); + const max = DateFnsUtils.formatDate(new Date(field.maxValue), this.MAX_DATETIME_FORMAT); + - if (fieldValueDate.isAfter(max)) { + if (isAfter(fieldValueDate, new Date(max))) { field.validationSummary.message = `FORM.FIELD.VALIDATOR.NOT_GREATER_THAN`; - field.validationSummary.attributes.set('maxValue', max.format(field.dateDisplayFormat).replace(':', '-')); + field.validationSummary.attributes.set('maxValue', DateFnsUtils.formatDate(new Date(max), field.dateDisplayFormat).replace(':', '-')); isFieldValid = false; } return isFieldValid; @@ -584,39 +585,3 @@ export const FORM_FIELD_VALIDATORS = [ new MinDateTimeFieldValidator(), new MaxDateTimeFieldValidator() ]; - -export const momentToDateFnsMap = { - M: 'M', - D: 'd', - Y: 'y', - A: 'a' -}; - -export const dateFnsToMomentMap = { - M: 'M', - d: 'D', - y: 'Y', - a: 'A' -}; - -export function convertMomentToDateFnsFormat(dateDisplayFormat: string): string { - for (const [search, replace] of Object.entries(momentToDateFnsMap)) { - dateDisplayFormat = dateDisplayFormat.replace(new RegExp(search, 'g'), replace); - } - return dateDisplayFormat; -} - -export function convertDateFnsToMomentFormat(dateDisplayFormat: string): string { - for (const [search, replace] of Object.entries(dateFnsToMomentMap)) { - dateDisplayFormat = dateDisplayFormat.replace(new RegExp(search, 'g'), replace); - } - return dateDisplayFormat; -} - -export function formatUpdate(date: number|Date, dateFormat: string): string { - return format(date, convertMomentToDateFnsFormat(dateFormat)); -} - -export function parseUpdate(value: string, dateFormat: string, date = new Date()): Date { - return parse(value, convertMomentToDateFnsFormat(dateFormat), date); -} diff --git a/lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts b/lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts index 0537d098a85..a6899f8eb50 100644 --- a/lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts +++ b/lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts @@ -15,20 +15,13 @@ * limitations under the License. */ -import moment from 'moment'; import { FormFieldTypes } from './form-field-types'; import { FormFieldModel } from './form-field.model'; import { FormModel } from './form.model'; -import { DateFormatTranslationService } from '../../../public-api'; +import { DateFnsUtils } from '../../../../common/utils/date-fns-utils'; describe('FormFieldModel', () => { - let dateFormatTranslationService: DateFormatTranslationService; - - beforeEach(() => { - dateFormatTranslationService = new DateFormatTranslationService(); - }); - it('should store the form reference', () => { const form = new FormModel(); const model = new FormFieldModel(form); @@ -281,8 +274,8 @@ describe('FormFieldModel', () => { }); const currentDate = new Date(); - const expectedDate = dateFormatTranslationService.format(currentDate, 'DD-MM-YYYY'); - const expectedDateFormat = `${dateFormatTranslationService.format(currentDate, 'YYYY-MM-DD')}T00:00:00.000Z`; + const expectedDate = DateFnsUtils.formatDate(currentDate, 'DD-MM-YYYY'); + const expectedDateFormat = `${DateFnsUtils.formatDate(currentDate, 'YYYY-MM-DD')}T00:00:00.000Z`; expect(field.value).toBe(expectedDate); expect(form.values['ddmmyyy']).toEqual(expectedDateFormat); @@ -311,9 +304,12 @@ describe('FormFieldModel', () => { dateDisplayFormat: 'YYYY-MM-DD HH:mm' }); - const currentDateTime = moment(new Date()); - const expectedDateTime = moment.utc(currentDateTime).format('YYYY-MM-DD HH:mm'); - const expectedDateTimeFormat = `${currentDateTime.utc().format('YYYY-MM-DDTHH:mm:00')}.000Z`; + const currentDateTime = new Date(); + const formattedDate = DateFnsUtils.formatDate(currentDateTime, 'YYYY-MM-DD'); + const formattedTime = DateFnsUtils.formatDate(currentDateTime, 'HH:mm'); + + const expectedDateTime = DateFnsUtils.formatDate(currentDateTime, 'YYYY-MM-DD HH:mm'); + const expectedDateTimeFormat = formattedDate + `T${formattedTime}:00.000Z`; expect(field.value).toBe(expectedDateTime); expect(form.values['datetime']).toEqual(expectedDateTimeFormat); diff --git a/lib/core/src/lib/form/components/widgets/core/form-field.model.ts b/lib/core/src/lib/form/components/widgets/core/form-field.model.ts index a85fb69e8a7..5a2607e925c 100644 --- a/lib/core/src/lib/form/components/widgets/core/form-field.model.ts +++ b/lib/core/src/lib/form/components/widgets/core/form-field.model.ts @@ -16,7 +16,6 @@ */ /* eslint-disable @angular-eslint/component-selector */ -import moment from 'moment'; import { WidgetVisibilityModel } from '../../../models/widget-visibility.model'; import { ContainerColumnModel } from './container-column.model'; import { ErrorMessageModel } from './error-message.model'; @@ -30,12 +29,10 @@ import { isNumberValue } from './form-field-utils'; import { VariableConfig } from './form-field-variable-options'; import { DataColumn } from '../../../../datatable/data/data-column.model'; import { isValid } from 'date-fns'; -import { DateFormatTranslationService } from '../../../services/date-format-translation.service'; +import { DateFnsUtils } from '../../../../common/utils/date-fns-utils'; // Maps to FormFieldRepresentation -export const dateFormatTranslationService = new DateFormatTranslationService(); - export class FormFieldModel extends FormWidgetModel { private _value: string; private _readOnly: boolean = false; @@ -43,7 +40,7 @@ export class FormFieldModel extends FormWidgetModel { private _required: boolean = false; readonly defaultDateFormat: string = 'd-M-yyyy'; - readonly defaultDateTimeFormat: string = 'D-M-YYYY hh:mm A'; + readonly defaultDateTimeFormat: string = 'd-M-yyyy hh:mm a'; // model members fieldType: string; @@ -248,7 +245,7 @@ export class FormFieldModel extends FormWidgetModel { Object.keys(jsonField.fields).forEach((el) => { if(jsonField.fields[el]) { jsonField.fields[el].forEach((element) => { - element.dateDisplayFormat = element.dateDisplayFormat? dateFormatTranslationService.convertMomentToDateFnsFormat(element.dateDisplayFormat): element.dateDisplayFormat; + element.dateDisplayFormat = element.dateDisplayFormat? DateFnsUtils.convertMomentToDateFnsFormat(element.dateDisplayFormat): element.dateDisplayFormat; }); } }); @@ -353,12 +350,12 @@ export class FormFieldModel extends FormWidgetModel { if (value) { let dateValue; if (isNumberValue(value)) { - dateValue = moment(value); + dateValue = new Date(value); } else { - dateValue = moment.utc(value, 'YYYY-MM-DD hh:mm A'); + dateValue = DateFnsUtils.parseDate(value, 'YYYY-MM-DD hh:mm A'); } - if (dateValue?.isValid()) { - value = dateValue.utc().format(this.dateDisplayFormat); + if (isValid(dateValue)) { + value = DateFnsUtils.formatDate(dateValue, this.dateDisplayFormat); } } } @@ -369,10 +366,10 @@ export class FormFieldModel extends FormWidgetModel { if (isNumberValue(value)) { dateValue = new Date(value); } else { - dateValue = dateFormatTranslationService.parse(value.split('T')[0], 'YYYY-M-D'); + dateValue = DateFnsUtils.parseDate(value.split('T')[0], 'YYYY-M-D'); } if (isValid(dateValue)) { - value = dateFormatTranslationService.format(dateValue, this.dateDisplayFormat); + value = DateFnsUtils.formatDate(dateValue, this.dateDisplayFormat); } } } @@ -445,13 +442,13 @@ export class FormFieldModel extends FormWidgetModel { } case FormFieldTypes.DATE: { if (typeof this.value === 'string' && this.value === 'today') { - this.value = dateFormatTranslationService.format(new Date(), this.dateDisplayFormat); + this.value = DateFnsUtils.formatDate(new Date(), this.dateDisplayFormat); } - const dateValue = dateFormatTranslationService.parse(this.value, this.dateDisplayFormat); + const dateValue = DateFnsUtils.parseDate(this.value, this.dateDisplayFormat); if (isValid(dateValue)) { - this.form.values[this.id] = `${dateFormatTranslationService.format(dateValue, 'YYYY-MM-DD')}T00:00:00.000Z`; + this.form.values[this.id] = `${DateFnsUtils.formatDate(dateValue, 'YYYY-MM-DD')}T00:00:00.000Z`; } else { this.form.values[this.id] = null; this._value = this.value; @@ -460,13 +457,14 @@ export class FormFieldModel extends FormWidgetModel { } case FormFieldTypes.DATETIME: { if (typeof this.value === 'string' && this.value === 'now') { - this.value = moment(new Date()).utc().format(this.dateDisplayFormat); + this.value = DateFnsUtils.formatDate(new Date(), this.dateDisplayFormat); } - const dateTimeValue = moment.utc(this.value, this.dateDisplayFormat, true); - if (dateTimeValue?.isValid()) { + const dateTimeValue = DateFnsUtils.parseDate(this.value, this.dateDisplayFormat); + + if (isValid(dateTimeValue)) { /* cspell:disable-next-line */ - this.form.values[this.id] = `${dateTimeValue.utc().format('YYYY-MM-DDTHH:mm:ss')}.000Z`; + this.form.values[this.id] = `${DateFnsUtils.formatDate(dateTimeValue, 'YYYY-MM-DDTHH:mm:ss')}.000Z`; } else { this.form.values[this.id] = null; this._value = this.value; diff --git a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.html b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.html index f2081c71ad7..d3487f71e91 100644 --- a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.html +++ b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.html @@ -1,10 +1,10 @@
- +
- + { @@ -52,7 +52,7 @@ describe('DateTimeWidgetComponent', () => { }); it('should setup min value for date picker', () => { - const minValue = '1982-03-13T10:00:000Z'; + let minValue = '1982-03-13T10:00:000Z'; widget.field = new FormFieldModel(null, { id: 'date-id', name: 'date-name', @@ -62,8 +62,10 @@ describe('DateTimeWidgetComponent', () => { fixture.detectChanges(); - const expected = moment(minValue, 'YYYY-MM-DDTHH:mm:ssZ'); - expect(widget.minDate.isSame(expected)).toBeTruthy(); + minValue = DateFnsUtils.addSeconds(minValue); + + const expected = DateFnsUtils.formatDate(new Date(minValue), 'YYYY-MM-DDTHH:mm:ssZ'); + expect(widget.minDate).toBe(expected); }); it('should date field be present', () => { @@ -79,14 +81,16 @@ describe('DateTimeWidgetComponent', () => { }); it('should setup max value for date picker', () => { - const maxValue = '1982-03-13T10:00:000Z'; + let maxValue = '1982-03-13T10:00:000Z'; widget.field = new FormFieldModel(null, { maxValue }); fixture.detectChanges(); - const expected = moment(maxValue, 'YYYY-MM-DDTHH:mm:ssZ'); - expect(widget.maxDate.isSame(expected)).toBeTruthy(); + maxValue = DateFnsUtils.addSeconds(maxValue); + + const expected = DateFnsUtils.formatDate(new Date(maxValue), 'YYYY-MM-DDTHH:mm:ssZ'); + expect(widget.maxDate).toBe(expected); }); it('should eval visibility on date changed', () => { @@ -101,7 +105,7 @@ describe('DateTimeWidgetComponent', () => { }); widget.field = field; - const mockDate = moment('1982-03-13T10:00:000Z', 'YYYY-MM-DDTHH:mm:ssZ'); + const mockDate = DateFnsUtils.formatDate(new Date('1982-03-13 10:00 AM'), 'YYYY-MM-DDTHH:mm:ssZ'); widget.onDateChanged(mockDate); expect(widget.onFieldChanged).toHaveBeenCalledWith(field); diff --git a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts index cd8a60f8b7f..e72b95d6d13 100644 --- a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts +++ b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts @@ -17,25 +17,22 @@ /* eslint-disable @angular-eslint/component-selector */ -import { Component, OnInit, ViewEncapsulation, OnDestroy } from '@angular/core'; -import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core'; -import { DatetimeAdapter, MAT_DATETIME_FORMATS } from '@mat-datetimepicker/core'; -import { MomentDatetimeAdapter, MAT_MOMENT_DATETIME_FORMATS } from '@mat-datetimepicker/moment'; -import moment, { Moment } from 'moment'; +import { Component, OnInit, ViewEncapsulation, OnDestroy, Inject } from '@angular/core'; +import { DateAdapter, MAT_DATE_FORMATS, MatDateFormats } from '@angular/material/core'; import { UserPreferencesService, UserPreferenceValues } from '../../../../common/services/user-preferences.service'; -import { MomentDateAdapter } from '../../../../common/utils/moment-date-adapter'; -import { MOMENT_DATE_FORMATS } from '../../../../common/utils/moment-date-formats.model'; import { FormService } from '../../../services/form.service'; import { WidgetComponent } from '../widget.component'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; +import { DateFnsUtils } from '../../../../common/utils/date-fns-utils'; +import { TranslationService } from '../../../../../../../core/src/lib/translation/translation.service'; +import { FormFieldModel } from '../core'; +import { isValid } from 'date-fns'; +import { DateFnsAdapter } from '@angular/material-date-fns-adapter'; @Component({ providers: [ - { provide: DateAdapter, useClass: MomentDateAdapter }, - { provide: MAT_DATE_FORMATS, useValue: MOMENT_DATE_FORMATS }, - { provide: DatetimeAdapter, useClass: MomentDatetimeAdapter }, - { provide: MAT_DATETIME_FORMATS, useValue: MAT_MOMENT_DATETIME_FORMATS } + { provide: DateAdapter, useClass: DateFnsAdapter } ], selector: 'date-time-widget', templateUrl: './date-time.widget.html', @@ -43,15 +40,16 @@ import { takeUntil } from 'rxjs/operators'; encapsulation: ViewEncapsulation.None }) export class DateTimeWidgetComponent extends WidgetComponent implements OnInit, OnDestroy { - - minDate: Moment; - maxDate: Moment; + minDate: string; + maxDate: string; private onDestroy$ = new Subject(); constructor(public formService: FormService, - private dateAdapter: DateAdapter, - private userPreferencesService: UserPreferencesService) { + private dateAdapter: DateAdapter, + private userPreferencesService: UserPreferencesService, + @Inject(MAT_DATE_FORMATS) private dateFormatConfig: MatDateFormats, + private translationService: TranslationService) { super(formService); } @@ -59,18 +57,27 @@ export class DateTimeWidgetComponent extends WidgetComponent implements OnInit, this.userPreferencesService .select(UserPreferenceValues.Locale) .pipe(takeUntil(this.onDestroy$)) - .subscribe(locale => this.dateAdapter.setLocale(locale)); + .subscribe((locale) => this.dateAdapter.setLocale(DateFnsUtils.getLocaleFromString(locale))); - const momentDateAdapter = this.dateAdapter as MomentDateAdapter; - momentDateAdapter.overrideDisplayFormat = this.field.dateDisplayFormat; + this.dateFormatConfig.display.dateInput = this.field.dateDisplayFormat; if (this.field) { if (this.field.minValue) { - this.minDate = moment.utc(this.field.minValue, 'YYYY-MM-DDTHH:mm:ssZ'); + this.field.minValue = DateFnsUtils.addSeconds(this.field.minValue); + + const minDate = new Date(this.field.minValue); + if (isValid(minDate)) { + this.minDate = DateFnsUtils.formatDate(minDate, 'YYYY-MM-DDTHH:mm:ssZ'); + } } if (this.field.maxValue) { - this.maxDate = moment.utc(this.field.maxValue, 'YYYY-MM-DDTHH:mm:ssZ'); + this.field.maxValue = DateFnsUtils.addSeconds(this.field.maxValue); + + const maxDate = new Date(this.field.maxValue); + if (isValid(maxDate)) { + this.maxDate = DateFnsUtils.formatDate(maxDate, 'YYYY-MM-DDTHH:mm:ssZ'); + } } } } @@ -80,10 +87,17 @@ export class DateTimeWidgetComponent extends WidgetComponent implements OnInit, this.onDestroy$.complete(); } + formatLabel(field: FormFieldModel): string { + const displayName = this.translationService.instant(field.name); + const displayFormat = DateFnsUtils.convertDateFnsToMomentFormat(field.dateDisplayFormat); + + return `${displayName} (${displayFormat})`; + } + onDateChanged(newDateValue) { - const date = moment(newDateValue, this.field.dateDisplayFormat, true); - if (date.isValid()) { - this.field.value = moment(date).utc().local().format(this.field.dateDisplayFormat); + const date = new Date(newDateValue); + if (isValid(date)) { + this.field.value = DateFnsUtils.formatDate(date, this.field.dateDisplayFormat); } else { this.field.value = newDateValue; } diff --git a/lib/core/src/lib/form/components/widgets/date/date.widget.ts b/lib/core/src/lib/form/components/widgets/date/date.widget.ts index 985f97e3b3b..4f6b8d232a2 100644 --- a/lib/core/src/lib/form/components/widgets/date/date.widget.ts +++ b/lib/core/src/lib/form/components/widgets/date/date.widget.ts @@ -66,7 +66,7 @@ export class DateWidgetComponent extends WidgetComponent implements OnInit, OnDe private dateAdapter: DateAdapter, private userPreferencesService: UserPreferencesService, @Inject(MAT_DATE_FORMATS) private dateFormatConfig: MatDateFormats, - protected dateFormatTranslationService: DateFormatTranslationService) { + private translationService: TranslationService) { super(formService); } diff --git a/lib/core/src/lib/pipes/date.pipe.spec.ts b/lib/core/src/lib/pipes/date.pipe.spec.ts index a2ccc3ed653..ae4d29fd17b 100644 --- a/lib/core/src/lib/pipes/date.pipe.spec.ts +++ b/lib/core/src/lib/pipes/date.pipe.spec.ts @@ -16,36 +16,56 @@ */ import { TestBed } from '@angular/core/testing'; -import { CoreTestingModule } from '../testing/core.testing.module'; -import { TranslateModule } from '@ngx-translate/core'; -import { DatePipe } from './date.pipe'; -import { DateFormatTranslationService } from '../form/public-api'; +import { ADFDatePipe } from './date.pipe'; -describe('DatePipe', () => { - let datePipe: DatePipe; +describe('ADFDatePipe', () => { + let datePipe: ADFDatePipe; beforeEach(() => { TestBed.configureTestingModule({ - imports: [TranslateModule.forRoot(), CoreTestingModule], - providers: [DatePipe, DateFormatTranslationService] + providers: [ADFDatePipe] }); - datePipe = TestBed.inject(DatePipe); + datePipe = TestBed.inject(ADFDatePipe); }); it('should return the formatted date string when given a valid date object', () => { const inputDate = new Date('2023-08-14'); - const dateFormat = 'DD-MM-YYYY'; - const expectedOutput = '14-08-2023'; - const result = datePipe.transform(inputDate, dateFormat); + let dateFormat = 'DD-MM-YYYY'; + let expectedOutput = '14-08-2023'; + let result = datePipe.transform(inputDate, dateFormat); + expect(result).toBe(expectedOutput); + + dateFormat = 'MM-DD-YYYY'; + expectedOutput = '08-14-2023'; + result = datePipe.transform(inputDate, dateFormat); + expect(result).toBe(expectedOutput); + + dateFormat = 'YYYY-MM-DD'; + expectedOutput = '2023-08-14'; + result = datePipe.transform(inputDate, dateFormat); + expect(result).toBe(expectedOutput); + + dateFormat = 'YYYY-DD-MM'; + expectedOutput = '2023-14-08'; + result = datePipe.transform(inputDate, dateFormat); + expect(result).toBe(expectedOutput); + + dateFormat = 'MM-DD-YY'; + expectedOutput = '08-14-23'; + result = datePipe.transform(inputDate, dateFormat); + expect(result).toBe(expectedOutput); + dateFormat = 'DD-MM-YY'; + expectedOutput = '14-08-23'; + result = datePipe.transform(inputDate, dateFormat); expect(result).toBe(expectedOutput); }); it('should return the input value when given an invalid date object', () => { const inputDate = new Date('invalid'); const dateFormat = 'DD-MM-YYYY'; - const expectedOutput = inputDate.toString(); + const expectedOutput = 'Invalid Date'; const result = datePipe.transform(inputDate, dateFormat); @@ -54,11 +74,35 @@ describe('DatePipe', () => { it('should return the formatted date string when given a valid date string', () => { const inputDate = '2023-08-14'; - const dateFormat = 'DD-MM-YYYY'; - const expectedOutput = '14-08-2023'; - const result = datePipe.transform(inputDate, dateFormat); + let dateFormat = 'DD-MM-YYYY'; + let expectedOutput = '14-08-2023'; + let result = datePipe.transform(inputDate, dateFormat); + expect(result).toBe(expectedOutput); + + dateFormat = 'MM-DD-YYYY'; + expectedOutput = '08-14-2023'; + result = datePipe.transform(inputDate, dateFormat); + expect(result).toBe(expectedOutput); + + dateFormat = 'YYYY-MM-DD'; + expectedOutput = '2023-08-14'; + result = datePipe.transform(inputDate, dateFormat); + expect(result).toBe(expectedOutput); + + dateFormat = 'YYYY-DD-MM'; + expectedOutput = '2023-14-08'; + result = datePipe.transform(inputDate, dateFormat); + expect(result).toBe(expectedOutput); + + dateFormat = 'MM-DD-YY'; + expectedOutput = '08-14-23'; + result = datePipe.transform(inputDate, dateFormat); + expect(result).toBe(expectedOutput); + dateFormat = 'DD-MM-YY'; + expectedOutput = '14-08-23'; + result = datePipe.transform(inputDate, dateFormat); expect(result).toBe(expectedOutput); }); diff --git a/lib/core/src/lib/pipes/date.pipe.ts b/lib/core/src/lib/pipes/date.pipe.ts index 6bb180984da..a04f85703fd 100644 --- a/lib/core/src/lib/pipes/date.pipe.ts +++ b/lib/core/src/lib/pipes/date.pipe.ts @@ -17,14 +17,12 @@ import { Pipe, PipeTransform } from '@angular/core'; import { isValid } from 'date-fns'; -import { DateFormatTranslationService } from '../form/services/date-format-translation.service'; +import { DateFnsUtils } from '../common/utils/date-fns-utils'; @Pipe({ name: 'adfDate' }) -export class DatePipe implements PipeTransform { - constructor(private dateFormatTranslationService: DateFormatTranslationService) {} - +export class ADFDatePipe implements PipeTransform { transform(value: Date | string, dateFormat: string): string { const date = value instanceof Date ? value : new Date(value); - return isValid(date) ? this.dateFormatTranslationService.format(date, dateFormat) : value.toString(); + return isValid(date) ? DateFnsUtils.formatDate(date, dateFormat) : value.toString(); } } diff --git a/lib/core/src/lib/pipes/pipe.module.ts b/lib/core/src/lib/pipes/pipe.module.ts index 792920117da..83b0a3a1291 100644 --- a/lib/core/src/lib/pipes/pipe.module.ts +++ b/lib/core/src/lib/pipes/pipe.module.ts @@ -36,7 +36,7 @@ import { MomentDateTimePipe } from './moment-datetime.pipe'; import { FilterStringPipe } from './filter-string.pipe'; import { FilterOutArrayObjectsByPropPipe } from './filter-out-every-object-by-prop.pipe'; import { DateTimePipe } from './date-time.pipe'; -import { DatePipe } from './date.pipe'; +import { ADFDatePipe } from './date.pipe'; @NgModule({ imports: [ @@ -57,7 +57,7 @@ import { DatePipe } from './date.pipe'; DecimalNumberPipe, LocalizedRolePipe, MomentDatePipe, - DatePipe, + ADFDatePipe, MomentDateTimePipe, DateTimePipe, FilterStringPipe, @@ -76,7 +76,7 @@ import { DatePipe } from './date.pipe'; DecimalNumberPipe, LocalizedRolePipe, MomentDatePipe, - DatePipe, + ADFDatePipe, MomentDateTimePipe, DateTimePipe, FilterStringPipe, @@ -96,7 +96,7 @@ import { DatePipe } from './date.pipe'; DecimalNumberPipe, LocalizedRolePipe, MomentDatePipe, - DatePipe, + ADFDatePipe, MomentDateTimePipe, DateTimePipe, FilterStringPipe, diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.html b/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.html index e8fe51b4998..03789caed50 100644 --- a/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.html +++ b/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.html @@ -1,11 +1,11 @@
-
- , private userPreferencesService: UserPreferencesService, @Inject(MAT_DATE_FORMATS) private dateFormatConfig: MatDateFormats, - protected dateFormatTranslationService: DateFormatTranslationService) { + private translationService: TranslationService) { super(formService); } @@ -77,20 +77,20 @@ export class DateCloudWidgetComponent extends WidgetComponent implements OnInit, if (this.field.dynamicDateRangeSelection) { const today = new Date(); if (Number.isInteger(this.field.minDateRangeValue)) { - this.minDate = this.dateFormatTranslationService.format(subDays(today, this.field.minDateRangeValue), DATE_FORMAT_CLOUD); + this.minDate = DateFnsUtils.formatDate(subDays(today, this.field.minDateRangeValue), DATE_FORMAT_CLOUD); this.field.minValue = this.minDate; } if (Number.isInteger(this.field.maxDateRangeValue)) { - this.maxDate = this.dateFormatTranslationService.format(addDays(today, this.field.maxDateRangeValue), DATE_FORMAT_CLOUD); + this.maxDate = DateFnsUtils.formatDate(addDays(today, this.field.maxDateRangeValue), DATE_FORMAT_CLOUD); this.field.maxValue = this.maxDate; } } else { if (this.field.minValue) { - this.minDate = this.dateFormatTranslationService.format(new Date(this.field.minValue), DATE_FORMAT_CLOUD); + this.minDate = DateFnsUtils.formatDate(new Date(this.field.minValue), DATE_FORMAT_CLOUD); } if (this.field.maxValue) { - this.maxDate = this.dateFormatTranslationService.format(new Date(this.field.maxValue), DATE_FORMAT_CLOUD); + this.maxDate = DateFnsUtils.formatDate(new Date(this.field.maxValue), DATE_FORMAT_CLOUD); } } } @@ -101,10 +101,17 @@ export class DateCloudWidgetComponent extends WidgetComponent implements OnInit, this.onDestroy$.complete(); } + formatLabel(field: FormFieldModel): string { + const displayName = this.translationService.instant(field.name); + const displayFormat = DateFnsUtils.convertDateFnsToMomentFormat(field.dateDisplayFormat); + + return `${displayName} (${displayFormat})`; + } + onDateChanged(newDateValue) { - const date = this.dateFormatTranslationService.parse(newDateValue, this.field.dateDisplayFormat, new Date()); + const date = DateFnsUtils.parseDate(newDateValue, this.field.dateDisplayFormat); if (isValid(date)) { - this.field.value = this.dateFormatTranslationService.format(date, this.field.dateDisplayFormat); + this.field.value = DateFnsUtils.formatDate(date, this.field.dateDisplayFormat); } else { this.field.value = newDateValue; } From 8c1e5c94486dbbe346da4f39e3be9db9911feb92 Mon Sep 17 00:00:00 2001 From: SheenaMalhotra182 Date: Fri, 29 Sep 2023 19:59:51 +0530 Subject: [PATCH 04/19] [ACS-5857] fixed unit test for adding seconds --- lib/core/src/lib/common/utils/date-fns-utils.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/core/src/lib/common/utils/date-fns-utils.spec.ts b/lib/core/src/lib/common/utils/date-fns-utils.spec.ts index 3c545ae6c9e..9280e6862bc 100644 --- a/lib/core/src/lib/common/utils/date-fns-utils.spec.ts +++ b/lib/core/src/lib/common/utils/date-fns-utils.spec.ts @@ -57,8 +57,8 @@ describe('Date Format Translations', () => { }); it('should add seconds to a date time value', () => { - const inputDateTime = '2023-09-02T10:00:00Z'; - const expectedUpdatedValue = '2023-09-02T10:00:00.00Z'; + const inputDateTime = '2023-09-02T10:00:000Z'; + const expectedUpdatedValue = '2023-09-02T10:00:00.000Z'; const result = DateFnsUtils.addSeconds(inputDateTime); From ec2d09a1187c1da2fc3316cf19cddb7ff83f600b Mon Sep 17 00:00:00 2001 From: SheenaMalhotra182 Date: Fri, 29 Sep 2023 20:17:35 +0530 Subject: [PATCH 05/19] [ACS-5857] fixed imports --- .../widgets/core/form-field-validator.ts | 2 +- .../widgets/core/form-field.model.spec.ts | 2 +- .../widgets/core/form-field.model.ts | 2 +- .../widgets/date-time/date-time.widget.ts | 2 +- .../widgets/date/date-cloud.widget.spec.ts | 22 +++++++++---------- .../src/lib/models/date-format-cloud.model.ts | 2 +- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts b/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts index 921aa6453c3..bc2b7edd496 100644 --- a/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts +++ b/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts @@ -21,7 +21,7 @@ import { FormFieldTypes } from './form-field-types'; import { isNumberValue } from './form-field-utils'; import { FormFieldModel } from './form-field.model'; import { isAfter, isBefore, isValid } from 'date-fns'; -import { DateFnsUtils } from '../../../../common/utils/date-fns-utils'; +import { DateFnsUtils } from '../../../../common'; export interface FormFieldValidator { diff --git a/lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts b/lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts index a6899f8eb50..c28971fc681 100644 --- a/lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts +++ b/lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts @@ -18,7 +18,7 @@ import { FormFieldTypes } from './form-field-types'; import { FormFieldModel } from './form-field.model'; import { FormModel } from './form.model'; -import { DateFnsUtils } from '../../../../common/utils/date-fns-utils'; +import { DateFnsUtils } from '../../../../common'; describe('FormFieldModel', () => { diff --git a/lib/core/src/lib/form/components/widgets/core/form-field.model.ts b/lib/core/src/lib/form/components/widgets/core/form-field.model.ts index 5a2607e925c..7b66221a5ad 100644 --- a/lib/core/src/lib/form/components/widgets/core/form-field.model.ts +++ b/lib/core/src/lib/form/components/widgets/core/form-field.model.ts @@ -29,7 +29,7 @@ import { isNumberValue } from './form-field-utils'; import { VariableConfig } from './form-field-variable-options'; import { DataColumn } from '../../../../datatable/data/data-column.model'; import { isValid } from 'date-fns'; -import { DateFnsUtils } from '../../../../common/utils/date-fns-utils'; +import { DateFnsUtils } from '../../../../common'; // Maps to FormFieldRepresentation diff --git a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts index e72b95d6d13..89c7ad894ae 100644 --- a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts +++ b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts @@ -24,7 +24,7 @@ import { FormService } from '../../../services/form.service'; import { WidgetComponent } from '../widget.component'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; -import { DateFnsUtils } from '../../../../common/utils/date-fns-utils'; +import { DateFnsUtils } from '../../../../common'; import { TranslationService } from '../../../../../../../core/src/lib/translation/translation.service'; import { FormFieldModel } from '../core'; import { isValid } from 'date-fns'; diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.spec.ts b/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.spec.ts index 1ef016bffed..4f1688e8a8c 100644 --- a/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.spec.ts +++ b/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.spec.ts @@ -17,12 +17,12 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { DateCloudWidgetComponent } from './date-cloud.widget'; -import { FormFieldModel, FormModel, FormFieldTypes } from '@alfresco/adf-core'; +import { FormFieldModel, FormModel, FormFieldTypes, DateFnsUtils } from '@alfresco/adf-core'; import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module'; import { TranslateModule } from '@ngx-translate/core'; import { DATE_FORMAT_CLOUD } from '../../../../models/date-format-cloud.model'; import { By } from '@angular/platform-browser'; -import { addDays, format, subDays } from 'date-fns'; +import { addDays, subDays } from 'date-fns'; describe('DateWidgetComponent', () => { @@ -52,7 +52,7 @@ describe('DateWidgetComponent', () => { widget.ngOnInit(); - const expected = format(new Date(minValue), DATE_FORMAT_CLOUD); + const expected = DateFnsUtils.formatDate(new Date(minValue), DATE_FORMAT_CLOUD); expect(widget.minDate).toEqual(expected); }); @@ -75,7 +75,7 @@ describe('DateWidgetComponent', () => { }); widget.ngOnInit(); - const expected = format(new Date(maxValue), DATE_FORMAT_CLOUD); + const expected = DateFnsUtils.formatDate(new Date(maxValue), DATE_FORMAT_CLOUD); expect(widget.maxDate).toEqual(expected); }); @@ -92,7 +92,7 @@ describe('DateWidgetComponent', () => { widget.field = field; const todayDate = new Date(); - widget.onDateChanged({ value: format(todayDate, DATE_FORMAT_CLOUD) }); + widget.onDateChanged({ value: DateFnsUtils.formatDate(todayDate, DATE_FORMAT_CLOUD) }); expect(widget.onFieldChanged).toHaveBeenCalledWith(field); }); @@ -294,7 +294,7 @@ describe('DateWidgetComponent', () => { await fixture.whenStable(); const todayDate = new Date(); - const expected = format(subDays(todayDate, widget.field.minDateRangeValue), DATE_FORMAT_CLOUD); + const expected = DateFnsUtils.formatDate(subDays(todayDate, widget.field.minDateRangeValue), DATE_FORMAT_CLOUD); expect(widget.minDate).toEqual(expected); }); @@ -344,7 +344,7 @@ describe('DateWidgetComponent', () => { await fixture.whenStable(); const todayDate = new Date(); - const expected = format(addDays(todayDate, widget.field.maxDateRangeValue), DATE_FORMAT_CLOUD); + const expected = DateFnsUtils.formatDate(addDays(todayDate, widget.field.maxDateRangeValue), DATE_FORMAT_CLOUD); expect(widget.maxDate).toEqual(expected); }); @@ -404,7 +404,7 @@ describe('DateWidgetComponent', () => { await fixture.whenStable(); const currentDate = new Date(); - const expectedMinValueString = format(subDays(currentDate, 1), DATE_FORMAT_CLOUD); + const expectedMinValueString = DateFnsUtils.formatDate(subDays(currentDate, 1), DATE_FORMAT_CLOUD); expect(widget.field.minValue).toEqual(expectedMinValueString); expect(widget.maxDate).toBeUndefined(); @@ -424,7 +424,7 @@ describe('DateWidgetComponent', () => { await fixture.whenStable(); const currentDate = new Date(); - const expectedMaxValueString = format(addDays(currentDate, 8), DATE_FORMAT_CLOUD); + const expectedMaxValueString = DateFnsUtils.formatDate(addDays(currentDate, 8), DATE_FORMAT_CLOUD); expect(widget.field.maxValue).toEqual(expectedMaxValueString); expect(widget.minDate).toBeUndefined(); @@ -462,8 +462,8 @@ describe('DateWidgetComponent', () => { await fixture.whenStable(); const currentDate = new Date(); - const expectedMaxValueString = format(addDays(currentDate, 8), DATE_FORMAT_CLOUD); - const expectedMinValueString = format(subDays(currentDate, 10), DATE_FORMAT_CLOUD); + const expectedMaxValueString = DateFnsUtils.formatDate(addDays(currentDate, 8), DATE_FORMAT_CLOUD); + const expectedMinValueString = DateFnsUtils.formatDate(subDays(currentDate, 10), DATE_FORMAT_CLOUD); expect(widget.field.maxValue).toEqual(expectedMaxValueString); expect(widget.field.minValue).toEqual(expectedMinValueString); diff --git a/lib/process-services-cloud/src/lib/models/date-format-cloud.model.ts b/lib/process-services-cloud/src/lib/models/date-format-cloud.model.ts index 79f48c0033e..786c8c316be 100644 --- a/lib/process-services-cloud/src/lib/models/date-format-cloud.model.ts +++ b/lib/process-services-cloud/src/lib/models/date-format-cloud.model.ts @@ -15,4 +15,4 @@ * limitations under the License. */ -export const DATE_FORMAT_CLOUD = 'yyyy-MM-dd'; +export const DATE_FORMAT_CLOUD = 'YYYY-MM-DD'; From 621b05e82324cd2770802823a3e508224ecdafa4 Mon Sep 17 00:00:00 2001 From: SheenaMalhotra182 Date: Fri, 29 Sep 2023 20:31:31 +0530 Subject: [PATCH 06/19] [ACS-5857] linting fixes --- .../form/components/widgets/core/form-field.model.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/core/src/lib/form/components/widgets/core/form-field.model.ts b/lib/core/src/lib/form/components/widgets/core/form-field.model.ts index 7b66221a5ad..4e1a3b38d16 100644 --- a/lib/core/src/lib/form/components/widgets/core/form-field.model.ts +++ b/lib/core/src/lib/form/components/widgets/core/form-field.model.ts @@ -241,11 +241,13 @@ export class FormFieldModel extends FormWidgetModel { } private getDefaultDateFormat(jsonField: any): string { - if(jsonField.fields) { + if (jsonField.fields) { Object.keys(jsonField.fields).forEach((el) => { - if(jsonField.fields[el]) { + if (jsonField.fields[el]) { jsonField.fields[el].forEach((element) => { - element.dateDisplayFormat = element.dateDisplayFormat? DateFnsUtils.convertMomentToDateFnsFormat(element.dateDisplayFormat): element.dateDisplayFormat; + element.dateDisplayFormat = element.dateDisplayFormat + ? DateFnsUtils.convertMomentToDateFnsFormat(element.dateDisplayFormat) + : element.dateDisplayFormat; }); } }); @@ -346,7 +348,7 @@ export class FormFieldModel extends FormWidgetModel { This is needed due to Activiti displaying/editing dates in d-M-YYYY format but storing on server in ISO8601 format (i.e. 2013-02-04T22:44:30.652Z) */ - if (this.isDateTimeField(json)) { + if (this.isDateTimeField(json)) { if (value) { let dateValue; if (isNumberValue(value)) { From 5a25ea8a70e575be890878fcaa10a52ceda4d39b Mon Sep 17 00:00:00 2001 From: SheenaMalhotra182 Date: Fri, 29 Sep 2023 21:31:28 +0530 Subject: [PATCH 07/19] [ACS-5857] added unit tests for formatLabel --- .../widgets/date-time/date-time.widget.spec.ts | 16 ++++++++++++++++ .../widgets/date-time/date-time.widget.ts | 2 +- .../components/widgets/date/date.widget.spec.ts | 16 ++++++++++++++++ .../widgets/date/date-cloud.widget.spec.ts | 16 ++++++++++++++++ 4 files changed, 49 insertions(+), 1 deletion(-) diff --git a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.spec.ts b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.spec.ts index 57bab55a1d1..856cab47e3d 100644 --- a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.spec.ts +++ b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.spec.ts @@ -331,4 +331,20 @@ describe('DateTimeWidgetComponent', () => { expect(adfLeftLabel).toBeNull(); }); }); + + describe('format label', () => { + beforeEach(() => { + widget.field = new FormFieldModel(new FormModel({ taskId: '' }), { + name: 'Date Time', + dateDisplayFormat: 'd-M-yyyy hh:mm a' + }); + fixture.detectChanges(); + }); + + it('should format label correctly', () => { + const result = widget.formatLabel(widget.field); + + expect(result).toBe('Date Time (D-M-YYYY hh:mm A)'); + }); + }); }); diff --git a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts index 89c7ad894ae..27d0ffa9ba9 100644 --- a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts +++ b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts @@ -25,7 +25,7 @@ import { WidgetComponent } from '../widget.component'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { DateFnsUtils } from '../../../../common'; -import { TranslationService } from '../../../../../../../core/src/lib/translation/translation.service'; +import { TranslationService } from '../../../../../../../core/src/lib/translation'; import { FormFieldModel } from '../core'; import { isValid } from 'date-fns'; import { DateFnsAdapter } from '@angular/material-date-fns-adapter'; diff --git a/lib/core/src/lib/form/components/widgets/date/date.widget.spec.ts b/lib/core/src/lib/form/components/widgets/date/date.widget.spec.ts index 5b6c979595d..cd88396ce9d 100644 --- a/lib/core/src/lib/form/components/widgets/date/date.widget.spec.ts +++ b/lib/core/src/lib/form/components/widgets/date/date.widget.spec.ts @@ -251,4 +251,20 @@ describe('DateWidgetComponent', () => { expect(dateElement?.value).toContain('03-02-2020'); }); + + describe('format label', () => { + beforeEach(() => { + widget.field = new FormFieldModel(new FormModel({ taskId: '' }), { + name: 'Date', + dateDisplayFormat: 'd-M-yyyy' + }); + fixture.detectChanges(); + }); + + it('should format label correctly', () => { + const result = widget.formatLabel(widget.field); + + expect(result).toBe('Date (D-M-YYYY)'); + }); + }); }); diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.spec.ts b/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.spec.ts index 4f1688e8a8c..2a88f094c1a 100644 --- a/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.spec.ts +++ b/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.spec.ts @@ -541,4 +541,20 @@ describe('DateWidgetComponent', () => { expect(element.querySelector('.adf-invalid')).toBeTruthy(); }); }); + + describe('format label', () => { + beforeEach(() => { + widget.field = new FormFieldModel(new FormModel({ taskId: '' }), { + name: 'Date Field', + dateDisplayFormat: 'd-M-yyyy' + }); + fixture.detectChanges(); + }); + + it('should format label correctly', () => { + const result = widget.formatLabel(widget.field); + + expect(result).toBe('Date Field (D-M-YYYY)'); + }); + }); }); From 55baa9426d68e9c6ac325efc834286c927b76d26 Mon Sep 17 00:00:00 2001 From: SheenaMalhotra182 Date: Wed, 4 Oct 2023 01:10:31 +0530 Subject: [PATCH 08/19] [ACS-5857] fixed paths and minDate maxDate logic in date-time-widget --- .../date-time/date-time.widget.spec.ts | 14 ++++++++---- .../widgets/date-time/date-time.widget.ts | 22 +++++++++++++------ 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.spec.ts b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.spec.ts index 856cab47e3d..12853232576 100644 --- a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.spec.ts +++ b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.spec.ts @@ -62,9 +62,12 @@ describe('DateTimeWidgetComponent', () => { fixture.detectChanges(); - minValue = DateFnsUtils.addSeconds(minValue); + if (!minValue.includes('00.')) { + minValue = DateFnsUtils.addSeconds(minValue); + } - const expected = DateFnsUtils.formatDate(new Date(minValue), 'YYYY-MM-DDTHH:mm:ssZ'); + const [year, month, day, hours, minutes, seconds] = minValue.split(/[-T:.Z]/).map(Number); + const expected = new Date(Date.UTC(year, month - 1, day, hours, minutes, seconds)).toISOString(); expect(widget.minDate).toBe(expected); }); @@ -87,9 +90,12 @@ describe('DateTimeWidgetComponent', () => { }); fixture.detectChanges(); - maxValue = DateFnsUtils.addSeconds(maxValue); + if (!maxValue.includes('00.')) { + maxValue = DateFnsUtils.addSeconds(maxValue); + } - const expected = DateFnsUtils.formatDate(new Date(maxValue), 'YYYY-MM-DDTHH:mm:ssZ'); + const [year, month, day, hours, minutes, seconds] = maxValue.split(/[-T:.Z]/).map(Number); + const expected = new Date(Date.UTC(year, month - 1, day, hours, minutes, seconds)).toISOString(); expect(widget.maxDate).toBe(expected); }); diff --git a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts index 27d0ffa9ba9..c2b77d48c79 100644 --- a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts +++ b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts @@ -25,7 +25,7 @@ import { WidgetComponent } from '../widget.component'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { DateFnsUtils } from '../../../../common'; -import { TranslationService } from '../../../../../../../core/src/lib/translation'; +import { TranslationService } from '../../../../../lib/translation/translation.service'; import { FormFieldModel } from '../core'; import { isValid } from 'date-fns'; import { DateFnsAdapter } from '@angular/material-date-fns-adapter'; @@ -63,20 +63,28 @@ export class DateTimeWidgetComponent extends WidgetComponent implements OnInit, if (this.field) { if (this.field.minValue) { - this.field.minValue = DateFnsUtils.addSeconds(this.field.minValue); + if (!this.field.minValue.includes('00.')) { + this.field.minValue = DateFnsUtils.addSeconds(this.field.minValue); + } + + const [year, month, day, hours, minutes, seconds] = this.field.minValue.split(/[-T:.Z]/).map(Number); + const minDate = new Date(Date.UTC(year, month - 1, day, hours, minutes, seconds)); - const minDate = new Date(this.field.minValue); if (isValid(minDate)) { - this.minDate = DateFnsUtils.formatDate(minDate, 'YYYY-MM-DDTHH:mm:ssZ'); + this.minDate = minDate.toISOString(); } } if (this.field.maxValue) { - this.field.maxValue = DateFnsUtils.addSeconds(this.field.maxValue); + if (!this.field.maxValue.includes('00.')) { + this.field.maxValue = DateFnsUtils.addSeconds(this.field.maxValue); + } + + const [year, month, day, hours, minutes, seconds] = this.field.maxValue.split(/[-T:.Z]/).map(Number); + const maxDate = new Date(Date.UTC(year, month - 1, day, hours, minutes, seconds)); - const maxDate = new Date(this.field.maxValue); if (isValid(maxDate)) { - this.maxDate = DateFnsUtils.formatDate(maxDate, 'YYYY-MM-DDTHH:mm:ssZ'); + this.maxDate = maxDate.toISOString(); } } } From d1766918497eb99b5be647ca2bf9d9d9d88c5732 Mon Sep 17 00:00:00 2001 From: SheenaMalhotra182 Date: Wed, 4 Oct 2023 10:36:01 +0530 Subject: [PATCH 09/19] [ACS-5857] linting fixes --- .../components/widgets/date-time/date-time.widget.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.spec.ts b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.spec.ts index 12853232576..1c02d0b2fa4 100644 --- a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.spec.ts +++ b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.spec.ts @@ -66,7 +66,7 @@ describe('DateTimeWidgetComponent', () => { minValue = DateFnsUtils.addSeconds(minValue); } - const [year, month, day, hours, minutes, seconds] = minValue.split(/[-T:.Z]/).map(Number); + const [year, month, day, hours, minutes, seconds] = minValue.split(/[-T:.Z]/).map(Number); const expected = new Date(Date.UTC(year, month - 1, day, hours, minutes, seconds)).toISOString(); expect(widget.minDate).toBe(expected); }); @@ -94,7 +94,7 @@ describe('DateTimeWidgetComponent', () => { maxValue = DateFnsUtils.addSeconds(maxValue); } - const [year, month, day, hours, minutes, seconds] = maxValue.split(/[-T:.Z]/).map(Number); + const [year, month, day, hours, minutes, seconds] = maxValue.split(/[-T:.Z]/).map(Number); const expected = new Date(Date.UTC(year, month - 1, day, hours, minutes, seconds)).toISOString(); expect(widget.maxDate).toBe(expected); }); From 2dd0e0d761b98523c0aa76b3604e13a63b616752 Mon Sep 17 00:00:00 2001 From: SheenaMalhotra182 Date: Wed, 4 Oct 2023 11:58:01 +0530 Subject: [PATCH 10/19] [ACS-5857] e2e fixes - converted dateFormat back to moment while validating --- .../lib/form/components/widgets/core/form-field-validator.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts b/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts index bc2b7edd496..b4cd7c1b1cb 100644 --- a/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts +++ b/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts @@ -164,7 +164,7 @@ export class DateFieldValidator implements FormFieldValidator { if (DateFieldValidator.isValidDate(field.value, field.dateDisplayFormat)) { return true; } - field.validationSummary.message = field.dateDisplayFormat; + field.validationSummary.message = DateFnsUtils.convertDateFnsToMomentFormat(field.dateDisplayFormat); return false; } return true; @@ -196,7 +196,7 @@ export class DateTimeFieldValidator implements FormFieldValidator { if (DateTimeFieldValidator.isValidDate(field.value, DateFnsUtils.convertMomentToDateFnsFormat(field.dateDisplayFormat))) { return true; } - field.validationSummary.message = field.dateDisplayFormat; + field.validationSummary.message = DateFnsUtils.convertDateFnsToMomentFormat(field.dateDisplayFormat); return false; } return true; From 6877adb5fb93f7887aabacd9c3769e1bd7a0fb05 Mon Sep 17 00:00:00 2001 From: SheenaMalhotra182 Date: Wed, 4 Oct 2023 13:37:52 +0530 Subject: [PATCH 11/19] [ACS-5857] cleanup --- lib/core/src/lib/form/public-api.ts | 1 - .../date-format-translation.service.spec.ts | 72 ------------------- .../date-format-translation.service.ts | 60 ---------------- 3 files changed, 133 deletions(-) delete mode 100644 lib/core/src/lib/form/services/date-format-translation.service.spec.ts delete mode 100644 lib/core/src/lib/form/services/date-format-translation.service.ts diff --git a/lib/core/src/lib/form/public-api.ts b/lib/core/src/lib/form/public-api.ts index 15f0303eca2..fa80753e8b4 100644 --- a/lib/core/src/lib/form/public-api.ts +++ b/lib/core/src/lib/form/public-api.ts @@ -26,7 +26,6 @@ export * from './services/form-rendering.service'; export * from './services/form.service'; export * from './services/form-validation-service.interface'; export * from './services/widget-visibility.service'; -export * from './services/date-format-translation.service'; export * from './events'; diff --git a/lib/core/src/lib/form/services/date-format-translation.service.spec.ts b/lib/core/src/lib/form/services/date-format-translation.service.spec.ts deleted file mode 100644 index 171aa4e0448..00000000000 --- a/lib/core/src/lib/form/services/date-format-translation.service.spec.ts +++ /dev/null @@ -1,72 +0,0 @@ -/*! - * @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 { TestBed } from '@angular/core/testing'; -import { DateFormatTranslationService } from './date-format-translation.service'; -import { TranslateModule } from '@ngx-translate/core'; -import { CoreTestingModule } from '../../testing/core.testing.module'; - -describe('DateFormatTranslationService', () => { - let service: DateFormatTranslationService; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [TranslateModule.forRoot(), CoreTestingModule], - providers: [DateFormatTranslationService] - }); - - service = TestBed.inject(DateFormatTranslationService); - }); - - it('should convert moment to date-fns format correctly', () => { - const momentFormat = 'YYYY-MM-DD'; - const expectedDateFnsFormat = 'yyyy-MM-dd'; - - const result = service.convertMomentToDateFnsFormat(momentFormat); - - expect(result).toBe(expectedDateFnsFormat); - }); - - it('should convert date-fns to moment format correctly', () => { - const dateFnsFormat = 'yyyy-MM-dd'; - const expectedMomentFormat = 'YYYY-MM-DD'; - - const result = service.convertDateFnsToMomentFormat(dateFnsFormat); - - expect(result).toBe(expectedMomentFormat); - }); - - it('should format a date correctly', () => { - const date = new Date('2023-09-22T12:00:00Z'); - const dateFormat = 'yyyy-MM-dd'; - const expectedFormattedDate = '2023-09-22'; - - const result = service.format(date, dateFormat); - - expect(result).toBe(expectedFormattedDate); - }); - - it('should parse a date correctly', () => { - const dateString = '2023-09-22'; - const dateFormat = 'yyyy-MM-dd'; - const expectedParsedDate = new Date('2023-09-22T00:00:00Z'); - - const result = service.parse(dateString, dateFormat); - - expect(result).toEqual(expectedParsedDate); - }); -}); diff --git a/lib/core/src/lib/form/services/date-format-translation.service.ts b/lib/core/src/lib/form/services/date-format-translation.service.ts deleted file mode 100644 index 4016f96bdad..00000000000 --- a/lib/core/src/lib/form/services/date-format-translation.service.ts +++ /dev/null @@ -1,60 +0,0 @@ -/*! - * @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 { Injectable } from '@angular/core'; -import { format, parse } from 'date-fns'; - -@Injectable({ - providedIn: 'root' -}) -export class DateFormatTranslationService { - private momentToDateFnsMap = { - M: 'M', - D: 'd', - Y: 'y', - A: 'a' - }; - - private dateFnsToMomentMap = { - M: 'M', - d: 'D', - y: 'Y', - a: 'A' - }; - - convertMomentToDateFnsFormat(dateDisplayFormat: string): string { - for (const [search, replace] of Object.entries(this.momentToDateFnsMap)) { - dateDisplayFormat = dateDisplayFormat.replace(new RegExp(search, 'g'), replace); - } - return dateDisplayFormat; - } - - convertDateFnsToMomentFormat(dateDisplayFormat: string): string { - for (const [search, replace] of Object.entries(this.dateFnsToMomentMap)) { - dateDisplayFormat = dateDisplayFormat.replace(new RegExp(search, 'g'), replace); - } - return dateDisplayFormat; - } - - format(date: number|Date, dateFormat: string): string { - return format(date, this.convertMomentToDateFnsFormat(dateFormat)); - } - - parse(value: string, dateFormat: string, date = new Date()): Date { - return parse(value, this.convertMomentToDateFnsFormat(dateFormat), date); - } -} From 61f8e12e8e849606ed36e67434b2940e1df43566 Mon Sep 17 00:00:00 2001 From: SheenaMalhotra182 Date: Wed, 4 Oct 2023 15:33:16 +0530 Subject: [PATCH 12/19] [ACS-5857] modified code to reduce duplication --- .../widgets/core/form-field-validator.ts | 8 +++---- .../widgets/date-time/date-time.widget.html | 4 ++-- .../date-time/date-time.widget.spec.ts | 2 +- .../widgets/date-time/date-time.widget.ts | 14 +++++------ .../widgets/date/date.widget.spec.ts | 10 ++++---- lib/core/src/lib/pipes/date.pipe.spec.ts | 24 +++++++++---------- 6 files changed, 31 insertions(+), 31 deletions(-) diff --git a/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts b/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts index b4cd7c1b1cb..fadc227fe7d 100644 --- a/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts +++ b/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts @@ -148,8 +148,8 @@ export class DateFieldValidator implements FormFieldValidator { // Validates that the input string is a valid date formatted as (default D-M-YYYY) static isValidDate(inputDate: string, dateFormat: string = 'D-M-YYYY'): boolean { if (inputDate) { - const d = DateFnsUtils.parseDate(inputDate, dateFormat); - return isValid(d); + const date = DateFnsUtils.parseDate(inputDate, dateFormat); + return isValid(date); } return false; @@ -180,8 +180,8 @@ export class DateTimeFieldValidator implements FormFieldValidator { // Validates that the input string is a valid date formatted as (default D-M-YYYY) static isValidDate(inputDate: string, dateFormat: string = 'YYYY-MM-DD HH:mm'): boolean { if (inputDate) { - const d = DateFnsUtils.parseDate(inputDate, dateFormat); - return isValid(d); + const dateTime = DateFnsUtils.parseDate(inputDate, dateFormat); + return isValid(dateTime); } return false; diff --git a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.html b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.html index d3487f71e91..7173016014f 100644 --- a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.html +++ b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.html @@ -1,10 +1,10 @@
- +
- + { }); it('should format label correctly', () => { - const result = widget.formatLabel(widget.field); + const result = widget.formatDateTimeLabel(widget.field); expect(result).toBe('Date Time (D-M-YYYY hh:mm A)'); }); diff --git a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts index c2b77d48c79..249abe28f0d 100644 --- a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts +++ b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts @@ -95,17 +95,17 @@ export class DateTimeWidgetComponent extends WidgetComponent implements OnInit, this.onDestroy$.complete(); } - formatLabel(field: FormFieldModel): string { - const displayName = this.translationService.instant(field.name); - const displayFormat = DateFnsUtils.convertDateFnsToMomentFormat(field.dateDisplayFormat); + formatDateTimeLabel(field: FormFieldModel): string { + const dateTimeDisplayName = this.translationService.instant(field.name); + const dateTimeDisplayFormat = DateFnsUtils.convertDateFnsToMomentFormat(field.dateDisplayFormat); - return `${displayName} (${displayFormat})`; + return `${dateTimeDisplayName} (${dateTimeDisplayFormat})`; } onDateChanged(newDateValue) { - const date = new Date(newDateValue); - if (isValid(date)) { - this.field.value = DateFnsUtils.formatDate(date, this.field.dateDisplayFormat); + const dateTimeValue = new Date(newDateValue); + if (isValid(dateTimeValue)) { + this.field.value = DateFnsUtils.formatDate(dateTimeValue, this.field.dateDisplayFormat); } else { this.field.value = newDateValue; } diff --git a/lib/core/src/lib/form/components/widgets/date/date.widget.spec.ts b/lib/core/src/lib/form/components/widgets/date/date.widget.spec.ts index cd88396ce9d..10944967eda 100644 --- a/lib/core/src/lib/form/components/widgets/date/date.widget.spec.ts +++ b/lib/core/src/lib/form/components/widgets/date/date.widget.spec.ts @@ -62,9 +62,9 @@ describe('DateWidgetComponent', () => { widget.ngOnInit(); - const expected = parse(minValue, widget.field.dateDisplayFormat, new Date()); + const expectedMinDate = parse(minValue, widget.field.dateDisplayFormat, new Date()); const widgetDate = parse(widget.minDate, widget.field.dateDisplayFormat, new Date()); - expect(isSameDay(widgetDate, expected)).toBeTruthy(); + expect(isSameDay(widgetDate, expectedMinDate)).toBeTruthy(); }); it('should date field be present', () => { @@ -86,9 +86,9 @@ describe('DateWidgetComponent', () => { }); widget.ngOnInit(); - const expected = parse(maxValue, widget.field.dateDisplayFormat, new Date()); + const expectedMaxDate = parse(maxValue, widget.field.dateDisplayFormat, new Date()); const widgetDate = parse(widget.maxDate, widget.field.dateDisplayFormat, new Date()); - expect(isSameDay(widgetDate, expected)).toBeTruthy(); + expect(isSameDay(widgetDate, expectedMaxDate)).toBeTruthy(); }); it('should eval visibility on date changed', () => { @@ -262,7 +262,7 @@ describe('DateWidgetComponent', () => { }); it('should format label correctly', () => { - const result = widget.formatLabel(widget.field); + const result = widget.formatDateLabel(widget.field); expect(result).toBe('Date (D-M-YYYY)'); }); diff --git a/lib/core/src/lib/pipes/date.pipe.spec.ts b/lib/core/src/lib/pipes/date.pipe.spec.ts index ae4d29fd17b..5f4ef651c7a 100644 --- a/lib/core/src/lib/pipes/date.pipe.spec.ts +++ b/lib/core/src/lib/pipes/date.pipe.spec.ts @@ -75,33 +75,33 @@ describe('ADFDatePipe', () => { it('should return the formatted date string when given a valid date string', () => { const inputDate = '2023-08-14'; - let dateFormat = 'DD-MM-YYYY'; - let expectedOutput = '14-08-2023'; + let dateFormat = 'DD-MM-YY'; + let expectedOutput = '14-08-23'; let result = datePipe.transform(inputDate, dateFormat); expect(result).toBe(expectedOutput); - dateFormat = 'MM-DD-YYYY'; - expectedOutput = '08-14-2023'; + dateFormat = 'MM-DD-YY'; + expectedOutput = '08-14-23'; result = datePipe.transform(inputDate, dateFormat); expect(result).toBe(expectedOutput); - dateFormat = 'YYYY-MM-DD'; - expectedOutput = '2023-08-14'; + dateFormat = 'YYYY-DD-MM'; + expectedOutput = '2023-14-08'; result = datePipe.transform(inputDate, dateFormat); expect(result).toBe(expectedOutput); - dateFormat = 'YYYY-DD-MM'; - expectedOutput = '2023-14-08'; + dateFormat = 'YYYY-MM-DD'; + expectedOutput = '2023-08-14'; result = datePipe.transform(inputDate, dateFormat); expect(result).toBe(expectedOutput); - dateFormat = 'MM-DD-YY'; - expectedOutput = '08-14-23'; + dateFormat = 'MM-DD-YYYY'; + expectedOutput = '08-14-2023'; result = datePipe.transform(inputDate, dateFormat); expect(result).toBe(expectedOutput); - dateFormat = 'DD-MM-YY'; - expectedOutput = '14-08-23'; + dateFormat = 'DD-MM-YYYY'; + expectedOutput = '14-08-2023'; result = datePipe.transform(inputDate, dateFormat); expect(result).toBe(expectedOutput); }); From b0b0ffb9f3881af1a7f92284e19903c82b617f90 Mon Sep 17 00:00:00 2001 From: SheenaMalhotra182 Date: Wed, 4 Oct 2023 16:03:01 +0530 Subject: [PATCH 13/19] [ACS-5857] fixed code smell by creating a method --- .../date-time/date-time.widget.spec.ts | 8 ++--- .../widgets/date-time/date-time.widget.ts | 35 ++++++++----------- 2 files changed, 17 insertions(+), 26 deletions(-) diff --git a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.spec.ts b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.spec.ts index db7a7059a0e..c99f8af20b7 100644 --- a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.spec.ts +++ b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.spec.ts @@ -62,9 +62,7 @@ describe('DateTimeWidgetComponent', () => { fixture.detectChanges(); - if (!minValue.includes('00.')) { - minValue = DateFnsUtils.addSeconds(minValue); - } + widget.parseDateAndSetMinMaxValue(minValue, 'minDate'); const [year, month, day, hours, minutes, seconds] = minValue.split(/[-T:.Z]/).map(Number); const expected = new Date(Date.UTC(year, month - 1, day, hours, minutes, seconds)).toISOString(); @@ -90,9 +88,7 @@ describe('DateTimeWidgetComponent', () => { }); fixture.detectChanges(); - if (!maxValue.includes('00.')) { - maxValue = DateFnsUtils.addSeconds(maxValue); - } + widget.parseDateAndSetMinMaxValue(maxValue, 'minDate'); const [year, month, day, hours, minutes, seconds] = maxValue.split(/[-T:.Z]/).map(Number); const expected = new Date(Date.UTC(year, month - 1, day, hours, minutes, seconds)).toISOString(); diff --git a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts index 249abe28f0d..dfbed80ec26 100644 --- a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts +++ b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts @@ -63,33 +63,28 @@ export class DateTimeWidgetComponent extends WidgetComponent implements OnInit, if (this.field) { if (this.field.minValue) { - if (!this.field.minValue.includes('00.')) { - this.field.minValue = DateFnsUtils.addSeconds(this.field.minValue); - } - - const [year, month, day, hours, minutes, seconds] = this.field.minValue.split(/[-T:.Z]/).map(Number); - const minDate = new Date(Date.UTC(year, month - 1, day, hours, minutes, seconds)); - - if (isValid(minDate)) { - this.minDate = minDate.toISOString(); - } + this.parseDateAndSetMinMaxValue(this.field.minValue, 'minDate'); } if (this.field.maxValue) { - if (!this.field.maxValue.includes('00.')) { - this.field.maxValue = DateFnsUtils.addSeconds(this.field.maxValue); - } - - const [year, month, day, hours, minutes, seconds] = this.field.maxValue.split(/[-T:.Z]/).map(Number); - const maxDate = new Date(Date.UTC(year, month - 1, day, hours, minutes, seconds)); - - if (isValid(maxDate)) { - this.maxDate = maxDate.toISOString(); - } + this.parseDateAndSetMinMaxValue(this.field.maxValue, 'maxDate'); } } } + parseDateAndSetMinMaxValue = (dateString, targetProperty) => { + if (dateString && !dateString.includes('00.')) { + this.field[targetProperty] = DateFnsUtils.addSeconds(dateString); + } + + const [year, month, day, hours, minutes, seconds] = dateString.split(/[-T:.Z]/).map(Number); + const parsedDate = new Date(Date.UTC(year, month - 1, day, hours, minutes, seconds)); + + if (isValid(parsedDate)) { + this[targetProperty] = parsedDate.toISOString(); + } + } + ngOnDestroy() { this.onDestroy$.next(true); this.onDestroy$.complete(); From 0dffbe4f23d2fed598e1357bb6578deef5255b65 Mon Sep 17 00:00:00 2001 From: SheenaMalhotra182 Date: Wed, 4 Oct 2023 16:18:39 +0530 Subject: [PATCH 14/19] [ACS-5857] fixed linting --- .../form/components/widgets/date-time/date-time.widget.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts index dfbed80ec26..5cc1b15ef19 100644 --- a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts +++ b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts @@ -76,14 +76,14 @@ export class DateTimeWidgetComponent extends WidgetComponent implements OnInit, if (dateString && !dateString.includes('00.')) { this.field[targetProperty] = DateFnsUtils.addSeconds(dateString); } - + const [year, month, day, hours, minutes, seconds] = dateString.split(/[-T:.Z]/).map(Number); const parsedDate = new Date(Date.UTC(year, month - 1, day, hours, minutes, seconds)); - + if (isValid(parsedDate)) { this[targetProperty] = parsedDate.toISOString(); } - } + }; ngOnDestroy() { this.onDestroy$.next(true); From 64044817893507541d74a0bf156968288723a255 Mon Sep 17 00:00:00 2001 From: SheenaMalhotra182 Date: Thu, 5 Oct 2023 19:41:53 +0530 Subject: [PATCH 15/19] [ACS-5857] addressed review comments --- .../src/lib/common/utils/date-fns-utils.ts | 2 +- .../widgets/core/form-field-validator.spec.ts | 20 +-- .../widgets/core/form-field-validator.ts | 16 ++- .../widgets/core/form-field.model.spec.ts | 2 +- .../widgets/core/form-field.model.ts | 8 +- .../date-time/date-time.widget.spec.ts | 8 +- .../widgets/date-time/date-time.widget.ts | 6 +- .../widgets/date/date.widget.spec.ts | 19 ++- lib/core/src/lib/pipes/date.pipe.spec.ts | 123 ++++++------------ lib/core/src/lib/pipes/date.pipe.ts | 13 +- .../widgets/date/date-cloud.widget.spec.ts | 22 ++-- .../widgets/date/date-cloud.widget.ts | 16 +-- 12 files changed, 115 insertions(+), 140 deletions(-) diff --git a/lib/core/src/lib/common/utils/date-fns-utils.ts b/lib/core/src/lib/common/utils/date-fns-utils.ts index fba78b85e09..c42648bcbd6 100644 --- a/lib/core/src/lib/common/utils/date-fns-utils.ts +++ b/lib/core/src/lib/common/utils/date-fns-utils.ts @@ -88,7 +88,7 @@ export class DateFnsUtils { Y: 'y', A: 'a', ll: 'PP', - Z: 'XXX', + Z: ` zzzz`, T: `'T'` }; diff --git a/lib/core/src/lib/form/components/widgets/core/form-field-validator.spec.ts b/lib/core/src/lib/form/components/widgets/core/form-field-validator.spec.ts index 275348bb755..f1ec318d0e9 100644 --- a/lib/core/src/lib/form/components/widgets/core/form-field-validator.spec.ts +++ b/lib/core/src/lib/form/components/widgets/core/form-field-validator.spec.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { DateFnsUtils } from '../../../../common'; +import { DateFnsUtils } from '../../../../common/utils/date-fns-utils'; import { ErrorMessageModel } from './error-message.model'; import { FormFieldOption } from './form-field-option'; import { FormFieldTypes } from './form-field-types'; @@ -708,9 +708,9 @@ describe('FormFieldValidator', () => { it('should take into account that max value is in UTC and NOT fail validating value checking the time', () => { const maxValueFromActivitiInput = '31-3-2018 12:00 AM'; - const maxValueSavedInForm = DateFnsUtils.formatDate(DateFnsUtils.parseDate(maxValueFromActivitiInput, 'DD-M-YYYY hh:mm A'), `YYYY-MM-DDTHH:mm:ssZ`); + const maxValueSavedInForm = DateFnsUtils.parseDate(maxValueFromActivitiInput, 'DD-M-YYYY hh:mm A').toISOString(); - const localValidValue = '2018-3-30 11:59 PM'; + const localValidValue = new Date('2018-3-30 11:59 PM').toISOString(); const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATETIME, @@ -723,9 +723,9 @@ describe('FormFieldValidator', () => { it('should take into account that max value is in UTC and fail validating value checking the time', () => { const maxValueFromActivitiInput = '31-3-2018 12:00 AM'; - const maxValueSavedInForm = DateFnsUtils.formatDate(DateFnsUtils.parseDate(maxValueFromActivitiInput, 'DD-M-YYYY hh:mm A'), `YYYY-MM-DDTHH:mm:ssZ`); + const maxValueSavedInForm = DateFnsUtils.parseDate(maxValueFromActivitiInput, 'DD-M-YYYY hh:mm A').toISOString(); - const localInvalidValue = '2018-3-31 12:01 AM'; + const localInvalidValue = new Date('2018-3-31 12:01 AM').toISOString(); const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATETIME, @@ -833,9 +833,9 @@ describe('FormFieldValidator', () => { it('should take into account that min value is in UTC and NOT fail validating value checking the time', () => { const minValueFromActivitiInput = '02-3-2018 06:00 AM'; - const minValueSavedInForm = DateFnsUtils.formatDate(DateFnsUtils.parseDate(minValueFromActivitiInput, 'DD-M-YYYY hh:mm A'), `YYYY-MM-DDTHH:mm:ssZ`); + const minValueSavedInForm = DateFnsUtils.parseDate(minValueFromActivitiInput, 'DD-M-YYYY hh:mm A').toISOString(); - const localValidValue = '2018-3-02 06:01 AM'; + const localValidValue = new Date('2018-3-02 06:01 AM').toISOString(); const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATETIME, @@ -848,9 +848,9 @@ describe('FormFieldValidator', () => { it('should take into account that min value is in UTC and fail validating value checking the time', () => { const minValueFromActivitiInput = '02-3-2018 06:00 AM'; - const minValueSavedInForm = DateFnsUtils.formatDate(DateFnsUtils.parseDate(minValueFromActivitiInput, 'DD-M-YYYY hh:mm A'), `YYYY-MM-DDTHH:mm:ssZ`); + const minValueSavedInForm = DateFnsUtils.parseDate(minValueFromActivitiInput, 'DD-M-YYYY hh:mm A').toISOString(); - const localInvalidValue = '2018-3-02 05:59 AM'; + const localInvalidValue = new Date('2018-3-02 05:59 AM').toISOString(); const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATETIME, @@ -1113,7 +1113,7 @@ describe('FormFieldValidator', () => { it('should validate dateTime format with default format', () => { const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATETIME, - value: '2021-06-09 02:10 AM' + value: '2021-06-09 14:10' }); expect(validator.validate(field)).toBeTruthy(); }); diff --git a/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts b/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts index fadc227fe7d..c90e689210a 100644 --- a/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts +++ b/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts @@ -21,7 +21,7 @@ import { FormFieldTypes } from './form-field-types'; import { isNumberValue } from './form-field-utils'; import { FormFieldModel } from './form-field.model'; import { isAfter, isBefore, isValid } from 'date-fns'; -import { DateFnsUtils } from '../../../../common'; +import { DateFnsUtils } from '../../../../common/utils/date-fns-utils'; export interface FormFieldValidator { @@ -180,7 +180,13 @@ export class DateTimeFieldValidator implements FormFieldValidator { // Validates that the input string is a valid date formatted as (default D-M-YYYY) static isValidDate(inputDate: string, dateFormat: string = 'YYYY-MM-DD HH:mm'): boolean { if (inputDate) { - const dateTime = DateFnsUtils.parseDate(inputDate, dateFormat); + let dateTime = DateFnsUtils.parseDate(inputDate, dateFormat); + + if (!isValid(dateTime) && dateFormat !== 'YYYY-MM-DD HH:mm') { + dateFormat = 'YYYY-MM-DD HH:mm'; + dateTime = DateFnsUtils.parseDate(inputDate, dateFormat); + } + return isValid(dateTime); } @@ -193,7 +199,7 @@ export class DateTimeFieldValidator implements FormFieldValidator { validate(field: FormFieldModel): boolean { if (this.isSupported(field) && field.value && field.isVisible) { - if (DateTimeFieldValidator.isValidDate(field.value, DateFnsUtils.convertMomentToDateFnsFormat(field.dateDisplayFormat))) { + if (DateTimeFieldValidator.isValidDate(field.value, field.dateDisplayFormat)) { return true; } field.validationSummary.message = DateFnsUtils.convertDateFnsToMomentFormat(field.dateDisplayFormat); @@ -302,7 +308,7 @@ export class MinDateTimeFieldValidator implements FormFieldValidator { private supportedTypes = [ FormFieldTypes.DATETIME ]; - MIN_DATETIME_FORMAT = 'YYYY-MM-DD hh:mm A'; + MIN_DATETIME_FORMAT = 'YYYY-MM-DD hh:mm AZ'; isSupported(field: FormFieldModel): boolean { return field && @@ -348,7 +354,7 @@ export class MaxDateTimeFieldValidator implements FormFieldValidator { private supportedTypes = [ FormFieldTypes.DATETIME ]; - MAX_DATETIME_FORMAT = 'YYYY-MM-DD hh:mm A'; + MAX_DATETIME_FORMAT = 'YYYY-MM-DD hh:mm AZ'; isSupported(field: FormFieldModel): boolean { return field && diff --git a/lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts b/lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts index c28971fc681..a6899f8eb50 100644 --- a/lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts +++ b/lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts @@ -18,7 +18,7 @@ import { FormFieldTypes } from './form-field-types'; import { FormFieldModel } from './form-field.model'; import { FormModel } from './form.model'; -import { DateFnsUtils } from '../../../../common'; +import { DateFnsUtils } from '../../../../common/utils/date-fns-utils'; describe('FormFieldModel', () => { diff --git a/lib/core/src/lib/form/components/widgets/core/form-field.model.ts b/lib/core/src/lib/form/components/widgets/core/form-field.model.ts index 4e1a3b38d16..6b7af660296 100644 --- a/lib/core/src/lib/form/components/widgets/core/form-field.model.ts +++ b/lib/core/src/lib/form/components/widgets/core/form-field.model.ts @@ -28,8 +28,8 @@ import { ProcessFormModel } from './process-form-model.interface'; import { isNumberValue } from './form-field-utils'; import { VariableConfig } from './form-field-variable-options'; import { DataColumn } from '../../../../datatable/data/data-column.model'; -import { isValid } from 'date-fns'; -import { DateFnsUtils } from '../../../../common'; +import { isValid, parseISO } from 'date-fns'; +import { DateFnsUtils } from '../../../../common/utils/date-fns-utils'; // Maps to FormFieldRepresentation @@ -354,7 +354,7 @@ export class FormFieldModel extends FormWidgetModel { if (isNumberValue(value)) { dateValue = new Date(value); } else { - dateValue = DateFnsUtils.parseDate(value, 'YYYY-MM-DD hh:mm A'); + dateValue = parseISO(value); } if (isValid(dateValue)) { value = DateFnsUtils.formatDate(dateValue, this.dateDisplayFormat); @@ -368,7 +368,7 @@ export class FormFieldModel extends FormWidgetModel { if (isNumberValue(value)) { dateValue = new Date(value); } else { - dateValue = DateFnsUtils.parseDate(value.split('T')[0], 'YYYY-M-D'); + dateValue = parseISO(value); } if (isValid(dateValue)) { value = DateFnsUtils.formatDate(dateValue, this.dateDisplayFormat); diff --git a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.spec.ts b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.spec.ts index c99f8af20b7..2f37cb45938 100644 --- a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.spec.ts +++ b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.spec.ts @@ -24,7 +24,7 @@ import { TranslateModule } from '@ngx-translate/core'; import { MatTooltipModule } from '@angular/material/tooltip'; import { FormFieldTypes } from '../core/form-field-types'; import { By } from '@angular/platform-browser'; -import { DateFnsUtils } from '../../../../common'; +import { DateFnsUtils } from '../../../../common/utils/date-fns-utils'; describe('DateTimeWidgetComponent', () => { @@ -52,7 +52,7 @@ describe('DateTimeWidgetComponent', () => { }); it('should setup min value for date picker', () => { - let minValue = '1982-03-13T10:00:000Z'; + const minValue = '1982-03-13T10:00:000Z'; widget.field = new FormFieldModel(null, { id: 'date-id', name: 'date-name', @@ -82,7 +82,7 @@ describe('DateTimeWidgetComponent', () => { }); it('should setup max value for date picker', () => { - let maxValue = '1982-03-13T10:00:000Z'; + const maxValue = '1982-03-13T10:00:000Z'; widget.field = new FormFieldModel(null, { maxValue }); @@ -107,7 +107,7 @@ describe('DateTimeWidgetComponent', () => { }); widget.field = field; - const mockDate = DateFnsUtils.formatDate(new Date('1982-03-13 10:00 AM'), 'YYYY-MM-DDTHH:mm:ssZ'); + const mockDate = DateFnsUtils.formatDate(new Date(DateFnsUtils.addSeconds('1982-03-13T10:00:000Z')), 'YYYY-MM-DDTHH:mm:ssZ'); widget.onDateChanged(mockDate); expect(widget.onFieldChanged).toHaveBeenCalledWith(field); diff --git a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts index 5cc1b15ef19..e45cfb4280d 100644 --- a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts +++ b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts @@ -24,7 +24,7 @@ import { FormService } from '../../../services/form.service'; import { WidgetComponent } from '../widget.component'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; -import { DateFnsUtils } from '../../../../common'; +import { DateFnsUtils } from '../../../../common/utils/date-fns-utils'; import { TranslationService } from '../../../../../lib/translation/translation.service'; import { FormFieldModel } from '../core'; import { isValid } from 'date-fns'; @@ -40,8 +40,8 @@ import { DateFnsAdapter } from '@angular/material-date-fns-adapter'; encapsulation: ViewEncapsulation.None }) export class DateTimeWidgetComponent extends WidgetComponent implements OnInit, OnDestroy { - minDate: string; - maxDate: string; + minDate: Date; + maxDate: Date; private onDestroy$ = new Subject(); diff --git a/lib/core/src/lib/form/components/widgets/date/date.widget.spec.ts b/lib/core/src/lib/form/components/widgets/date/date.widget.spec.ts index 10944967eda..c1410d85db4 100644 --- a/lib/core/src/lib/form/components/widgets/date/date.widget.spec.ts +++ b/lib/core/src/lib/form/components/widgets/date/date.widget.spec.ts @@ -22,7 +22,8 @@ import { DateWidgetComponent } from './date.widget'; import { CoreTestingModule } from '../../../../testing/core.testing.module'; import { TranslateModule } from '@ngx-translate/core'; import { FormFieldTypes } from '../core/form-field-types'; -import { format, isSameDay, parse } from 'date-fns'; +import { isSameDay } from 'date-fns'; +import { DateFnsUtils } from '../../../../common'; describe('DateWidgetComponent', () => { let widget: DateWidgetComponent; @@ -62,9 +63,8 @@ describe('DateWidgetComponent', () => { widget.ngOnInit(); - const expectedMinDate = parse(minValue, widget.field.dateDisplayFormat, new Date()); - const widgetDate = parse(widget.minDate, widget.field.dateDisplayFormat, new Date()); - expect(isSameDay(widgetDate, expectedMinDate)).toBeTruthy(); + const expectedMinDate = DateFnsUtils.parseDate(minValue, widget.field.dateDisplayFormat); + expect(isSameDay(widget.minDate, expectedMinDate)).toBeTruthy(); }); it('should date field be present', () => { @@ -86,9 +86,8 @@ describe('DateWidgetComponent', () => { }); widget.ngOnInit(); - const expectedMaxDate = parse(maxValue, widget.field.dateDisplayFormat, new Date()); - const widgetDate = parse(widget.maxDate, widget.field.dateDisplayFormat, new Date()); - expect(isSameDay(widgetDate, expectedMaxDate)).toBeTruthy(); + const expectedMaxDate = DateFnsUtils.parseDate(maxValue, widget.field.dateDisplayFormat); + expect(isSameDay(widget.maxDate, expectedMaxDate)).toBeTruthy(); }); it('should eval visibility on date changed', () => { @@ -166,7 +165,7 @@ describe('DateWidgetComponent', () => { readOnly: 'false' }); widget.field.isVisible = true; - widget.field.dateDisplayFormat = 'MM-DD-YYYY'; + widget.field.dateDisplayFormat = DateFnsUtils.convertMomentToDateFnsFormat('MM-DD-YYYY'); fixture.detectChanges(); await fixture.whenStable(); @@ -175,7 +174,7 @@ describe('DateWidgetComponent', () => { expect(dateElement?.value).toContain('12-30-9999'); widget.field.value = '05.06.2019'; - widget.field.dateDisplayFormat = 'DD.MM.YYYY'; + widget.field.dateDisplayFormat = DateFnsUtils.convertMomentToDateFnsFormat('DD.MM.YYYY'); fixture.componentInstance.ngOnInit(); fixture.detectChanges(); @@ -234,7 +233,7 @@ describe('DateWidgetComponent', () => { }); field.isVisible = true; - field.dateDisplayFormat = 'MM-DD-YYYY'; + field.dateDisplayFormat = DateFnsUtils.convertMomentToDateFnsFormat('MM-DD-YYYY'); widget.field = field; fixture.detectChanges(); diff --git a/lib/core/src/lib/pipes/date.pipe.spec.ts b/lib/core/src/lib/pipes/date.pipe.spec.ts index 5f4ef651c7a..2b70cb90ecf 100644 --- a/lib/core/src/lib/pipes/date.pipe.spec.ts +++ b/lib/core/src/lib/pipes/date.pipe.spec.ts @@ -28,91 +28,54 @@ describe('ADFDatePipe', () => { datePipe = TestBed.inject(ADFDatePipe); }); - it('should return the formatted date string when given a valid date object', () => { - const inputDate = new Date('2023-08-14'); - - let dateFormat = 'DD-MM-YYYY'; - let expectedOutput = '14-08-2023'; - let result = datePipe.transform(inputDate, dateFormat); - expect(result).toBe(expectedOutput); - - dateFormat = 'MM-DD-YYYY'; - expectedOutput = '08-14-2023'; - result = datePipe.transform(inputDate, dateFormat); - expect(result).toBe(expectedOutput); - - dateFormat = 'YYYY-MM-DD'; - expectedOutput = '2023-08-14'; - result = datePipe.transform(inputDate, dateFormat); - expect(result).toBe(expectedOutput); - - dateFormat = 'YYYY-DD-MM'; - expectedOutput = '2023-14-08'; - result = datePipe.transform(inputDate, dateFormat); - expect(result).toBe(expectedOutput); - - dateFormat = 'MM-DD-YY'; - expectedOutput = '08-14-23'; - result = datePipe.transform(inputDate, dateFormat); - expect(result).toBe(expectedOutput); - - dateFormat = 'DD-MM-YY'; - expectedOutput = '14-08-23'; - result = datePipe.transform(inputDate, dateFormat); - expect(result).toBe(expectedOutput); - }); - - it('should return the input value when given an invalid date object', () => { - const inputDate = new Date('invalid'); - const dateFormat = 'DD-MM-YYYY'; - const expectedOutput = 'Invalid Date'; - - const result = datePipe.transform(inputDate, dateFormat); - - expect(result).toBe(expectedOutput); + it('should transform a valid date string into a Date object', () => { + const testDates = [ + { dateString: '2023-10-05', dateFormat: 'yyyy-MM-dd' }, + { dateString: '2023-10-5', dateFormat: 'yyyy-M-d' }, + { dateString: '05-10-2023', dateFormat: 'dd-MM-yyyy' }, + { dateString: '5-10-2023', dateFormat: 'd-M-yyyy' }, + { dateString: '10-5-2023', dateFormat: 'M-d-yyyy' }, + { dateString: '10-05-2023', dateFormat: 'MM-d-yyyy' } + ]; + testDates.forEach(({ dateString, dateFormat }) => { + const transformedDate = datePipe.transform(dateString, dateFormat); + + expect(transformedDate instanceof Date).toBe(true); + expect(transformedDate.getFullYear()).toBe(2023); + expect(transformedDate.getMonth()).toBe(9); // October is 9 (0-based) + expect(transformedDate.getDate()).toBe(5); + }); }); - it('should return the formatted date string when given a valid date string', () => { - const inputDate = '2023-08-14'; - - let dateFormat = 'DD-MM-YY'; - let expectedOutput = '14-08-23'; - let result = datePipe.transform(inputDate, dateFormat); - expect(result).toBe(expectedOutput); - - dateFormat = 'MM-DD-YY'; - expectedOutput = '08-14-23'; - result = datePipe.transform(inputDate, dateFormat); - expect(result).toBe(expectedOutput); - - dateFormat = 'YYYY-DD-MM'; - expectedOutput = '2023-14-08'; - result = datePipe.transform(inputDate, dateFormat); - expect(result).toBe(expectedOutput); - - dateFormat = 'YYYY-MM-DD'; - expectedOutput = '2023-08-14'; - result = datePipe.transform(inputDate, dateFormat); - expect(result).toBe(expectedOutput); - - dateFormat = 'MM-DD-YYYY'; - expectedOutput = '08-14-2023'; - result = datePipe.transform(inputDate, dateFormat); - expect(result).toBe(expectedOutput); - - dateFormat = 'DD-MM-YYYY'; - expectedOutput = '14-08-2023'; - result = datePipe.transform(inputDate, dateFormat); - expect(result).toBe(expectedOutput); + it('should transform a valid date object into a Date object', () => { + const testDates = [ + { dateString: new Date(), dateFormat: 'yyyy-MM-dd' }, + { dateString: new Date(), dateFormat: 'yyyy-M-d' }, + { dateString: new Date(), dateFormat: 'dd-MM-yyyy' }, + { dateString: new Date(), dateFormat: 'd-M-yyyy' }, + { dateString: new Date(), dateFormat: 'M-d-yyyy' }, + { dateString: new Date(), dateFormat: 'MM-d-yyyy' } + ]; + + testDates.forEach(({ dateString, dateFormat }) => { + const transformedDate = datePipe.transform(dateString, dateFormat); + const today = new Date(); + + expect(transformedDate instanceof Date).toBe(true); + expect(transformedDate.getFullYear()).toBe(today.getFullYear()); + expect(transformedDate.getMonth()).toBe(today.getMonth()); // October is 9 (0-based) + expect(transformedDate.getDate()).toBe(today.getDate()); + }); }); - it('should return the input value when given an invalid date string', () => { - const inputDate = 'not_a_valid_date'; - const dateFormat = 'DD-MM-YYYY'; - const expectedOutput = inputDate; + it('should handle undefined input by returning the current date', () => { + const undefinedInput = undefined; + const dateFormat = 'dd-MM-yyyy'; - const result = datePipe.transform(inputDate, dateFormat); + const transformedDate = datePipe.transform(undefinedInput, dateFormat); + const today = new Date(); - expect(result).toBe(expectedOutput); + expect(transformedDate instanceof Date).toBe(true); + expect(transformedDate).toEqual(today); }); }); diff --git a/lib/core/src/lib/pipes/date.pipe.ts b/lib/core/src/lib/pipes/date.pipe.ts index a04f85703fd..1b05a434764 100644 --- a/lib/core/src/lib/pipes/date.pipe.ts +++ b/lib/core/src/lib/pipes/date.pipe.ts @@ -16,13 +16,18 @@ */ import { Pipe, PipeTransform } from '@angular/core'; -import { isValid } from 'date-fns'; import { DateFnsUtils } from '../common/utils/date-fns-utils'; +import { isDate } from 'date-fns'; @Pipe({ name: 'adfDate' }) export class ADFDatePipe implements PipeTransform { - transform(value: Date | string, dateFormat: string): string { - const date = value instanceof Date ? value : new Date(value); - return isValid(date) ? DateFnsUtils.formatDate(date, dateFormat) : value.toString(); + transform(value: Date | string, dateFormat: string): Date { + if (value) { + const date = typeof value === 'string' ? DateFnsUtils.parseDate(value, dateFormat) : value; + if (isDate(date)) { + return date; + } + } + return new Date(); } } diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.spec.ts b/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.spec.ts index 2a88f094c1a..f6fa6dec70f 100644 --- a/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.spec.ts +++ b/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.spec.ts @@ -22,7 +22,7 @@ import { ProcessServiceCloudTestingModule } from '../../../../testing/process-se import { TranslateModule } from '@ngx-translate/core'; import { DATE_FORMAT_CLOUD } from '../../../../models/date-format-cloud.model'; import { By } from '@angular/platform-browser'; -import { addDays, subDays } from 'date-fns'; +import { addDays, isSameDay, subDays } from 'date-fns'; describe('DateWidgetComponent', () => { @@ -52,8 +52,8 @@ describe('DateWidgetComponent', () => { widget.ngOnInit(); - const expected = DateFnsUtils.formatDate(new Date(minValue), DATE_FORMAT_CLOUD); - expect(widget.minDate).toEqual(expected); + const expected = DateFnsUtils.parseDate(minValue, DATE_FORMAT_CLOUD); + expect(isSameDay(widget.minDate, expected)).toBeTruthy(); }); it('should date field be present', () => { @@ -75,8 +75,8 @@ describe('DateWidgetComponent', () => { }); widget.ngOnInit(); - const expected = DateFnsUtils.formatDate(new Date(maxValue), DATE_FORMAT_CLOUD); - expect(widget.maxDate).toEqual(expected); + const expected = DateFnsUtils.parseDate(maxValue, DATE_FORMAT_CLOUD); + expect(isSameDay(widget.maxDate, expected)).toBeTruthy(); }); it('should eval visibility on date changed', () => { @@ -119,7 +119,7 @@ describe('DateWidgetComponent', () => { expect(element.querySelector('#date-field-id')).toBeDefined(); expect(element.querySelector('#date-field-id')).not.toBeNull(); const dateElement = element.querySelector('#date-field-id'); - expect(dateElement.value).toContain('9-9-9999'); + expect(dateElement.value).toContain('9999-9-9'); }); it('should show the correct format type', async () => { @@ -131,7 +131,7 @@ describe('DateWidgetComponent', () => { readOnly: 'false' }); widget.field.isVisible = true; - widget.field.dateDisplayFormat = 'YYYY-DD-MM'; + widget.field.dateDisplayFormat = DateFnsUtils.convertMomentToDateFnsFormat('YYYY-DD-MM'); widget.ngOnInit(); fixture.detectChanges(); await fixture.whenStable(); @@ -192,7 +192,7 @@ describe('DateWidgetComponent', () => { readOnly: 'false' }); field.isVisible = true; - field.dateDisplayFormat = 'MM-DD-YYYY'; + field.dateDisplayFormat = DateFnsUtils.convertMomentToDateFnsFormat('MM-DD-YYYY'); widget.field = field; widget.ngOnInit(); fixture.detectChanges(); @@ -295,7 +295,8 @@ describe('DateWidgetComponent', () => { const todayDate = new Date(); const expected = DateFnsUtils.formatDate(subDays(todayDate, widget.field.minDateRangeValue), DATE_FORMAT_CLOUD); - expect(widget.minDate).toEqual(expected); + const minDateFormatted = DateFnsUtils.formatDate(widget.minDate, DATE_FORMAT_CLOUD); + expect(minDateFormatted).toEqual(expected); }); it('should min date and max date be undefined if dynamic min and max date are not set', async () => { @@ -345,7 +346,8 @@ describe('DateWidgetComponent', () => { const todayDate = new Date(); const expected = DateFnsUtils.formatDate(addDays(todayDate, widget.field.maxDateRangeValue), DATE_FORMAT_CLOUD); - expect(widget.maxDate).toEqual(expected); + const maxDateFormatted = DateFnsUtils.formatDate(widget.maxDate, DATE_FORMAT_CLOUD); + expect(maxDateFormatted).toEqual(expected); }); it('should maxDate and minDate be undefined if minDateRangeValue and maxDateRangeValue are null', async () => { diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.ts b/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.ts index 6ee92004c52..6946a173606 100644 --- a/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.ts +++ b/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.ts @@ -52,8 +52,8 @@ import { addDays, isValid, subDays } from 'date-fns'; export class DateCloudWidgetComponent extends WidgetComponent implements OnInit, OnDestroy { typeId = 'DateCloudWidgetComponent'; - minDate: string; - maxDate: string; + minDate: Date; + maxDate: Date; private onDestroy$ = new Subject(); @@ -77,20 +77,20 @@ export class DateCloudWidgetComponent extends WidgetComponent implements OnInit, if (this.field.dynamicDateRangeSelection) { const today = new Date(); if (Number.isInteger(this.field.minDateRangeValue)) { - this.minDate = DateFnsUtils.formatDate(subDays(today, this.field.minDateRangeValue), DATE_FORMAT_CLOUD); - this.field.minValue = this.minDate; + this.minDate = subDays(today, this.field.minDateRangeValue); + this.field.minValue = DateFnsUtils.formatDate(this.minDate, DATE_FORMAT_CLOUD); } if (Number.isInteger(this.field.maxDateRangeValue)) { - this.maxDate = DateFnsUtils.formatDate(addDays(today, this.field.maxDateRangeValue), DATE_FORMAT_CLOUD); - this.field.maxValue = this.maxDate; + this.maxDate = addDays(today, this.field.maxDateRangeValue); + this.field.maxValue = DateFnsUtils.formatDate(this.maxDate, DATE_FORMAT_CLOUD); } } else { if (this.field.minValue) { - this.minDate = DateFnsUtils.formatDate(new Date(this.field.minValue), DATE_FORMAT_CLOUD); + this.minDate = DateFnsUtils.parseDate(this.field.minValue, DATE_FORMAT_CLOUD); } if (this.field.maxValue) { - this.maxDate = DateFnsUtils.formatDate(new Date(this.field.maxValue), DATE_FORMAT_CLOUD); + this.maxDate = DateFnsUtils.parseDate(this.field.maxValue, DATE_FORMAT_CLOUD); } } } From 2cc6f6c96c423c15dfbb3024b9092c9186adcb8d Mon Sep 17 00:00:00 2001 From: SheenaMalhotra182 Date: Mon, 9 Oct 2023 19:17:43 +0530 Subject: [PATCH 16/19] [ACS-5857] addressed review comments --- .../src/lib/common/utils/date-fns-utils.ts | 12 +++-- .../widgets/core/form-field-validator.spec.ts | 8 +-- .../widgets/core/form-field.model.ts | 8 +-- .../widgets/date/date.widget.spec.ts | 6 +-- lib/core/src/lib/pipes/date.pipe.spec.ts | 54 ++++++------------- lib/core/src/lib/pipes/date.pipe.ts | 11 ++-- .../widgets/date/date-cloud.widget.spec.ts | 6 +-- 7 files changed, 42 insertions(+), 63 deletions(-) diff --git a/lib/core/src/lib/common/utils/date-fns-utils.ts b/lib/core/src/lib/common/utils/date-fns-utils.ts index c42648bcbd6..ca7840f4abd 100644 --- a/lib/core/src/lib/common/utils/date-fns-utils.ts +++ b/lib/core/src/lib/common/utils/date-fns-utils.ts @@ -111,7 +111,10 @@ export class DateFnsUtils { */ static convertMomentToDateFnsFormat(dateDisplayFormat: string): string { // Check if 'A' is present in the format string - const containsA = dateDisplayFormat.includes('A'); + let containsA; + if (dateDisplayFormat) { + containsA = dateDisplayFormat.includes('A'); + } // Replace 'HH' with 'hh' if 'A' is also present if (containsA) { @@ -164,8 +167,11 @@ export class DateFnsUtils { * @param dateFormat - The date format string to use for parsing. * @returns The parsed Date object. */ - static parseDate(value: string, dateFormat: string): Date { - return parse(value, this.convertMomentToDateFnsFormat(dateFormat), new Date()); + static parseDate(date: Date | string, dateFormat: string): Date { + if (date instanceof Date) { + date = date.toISOString(); + } + return parse(date, this.convertMomentToDateFnsFormat(dateFormat), new Date()); } /** diff --git a/lib/core/src/lib/form/components/widgets/core/form-field-validator.spec.ts b/lib/core/src/lib/form/components/widgets/core/form-field-validator.spec.ts index f1ec318d0e9..996e8cc2edf 100644 --- a/lib/core/src/lib/form/components/widgets/core/form-field-validator.spec.ts +++ b/lib/core/src/lib/form/components/widgets/core/form-field-validator.spec.ts @@ -710,7 +710,7 @@ describe('FormFieldValidator', () => { const maxValueFromActivitiInput = '31-3-2018 12:00 AM'; const maxValueSavedInForm = DateFnsUtils.parseDate(maxValueFromActivitiInput, 'DD-M-YYYY hh:mm A').toISOString(); - const localValidValue = new Date('2018-3-30 11:59 PM').toISOString(); + const localValidValue = '2018-3-30 11:59 PM'; const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATETIME, @@ -725,7 +725,7 @@ describe('FormFieldValidator', () => { const maxValueFromActivitiInput = '31-3-2018 12:00 AM'; const maxValueSavedInForm = DateFnsUtils.parseDate(maxValueFromActivitiInput, 'DD-M-YYYY hh:mm A').toISOString(); - const localInvalidValue = new Date('2018-3-31 12:01 AM').toISOString(); + const localInvalidValue = '2018-3-31 12:01 AM'; const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATETIME, @@ -835,7 +835,7 @@ describe('FormFieldValidator', () => { const minValueFromActivitiInput = '02-3-2018 06:00 AM'; const minValueSavedInForm = DateFnsUtils.parseDate(minValueFromActivitiInput, 'DD-M-YYYY hh:mm A').toISOString(); - const localValidValue = new Date('2018-3-02 06:01 AM').toISOString(); + const localValidValue = '2018-3-02 06:01 AM'; const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATETIME, @@ -850,7 +850,7 @@ describe('FormFieldValidator', () => { const minValueFromActivitiInput = '02-3-2018 06:00 AM'; const minValueSavedInForm = DateFnsUtils.parseDate(minValueFromActivitiInput, 'DD-M-YYYY hh:mm A').toISOString(); - const localInvalidValue = new Date('2018-3-02 05:59 AM').toISOString(); + const localInvalidValue = '2018-3-02 05:59 AM'; const field = new FormFieldModel(new FormModel(), { type: FormFieldTypes.DATETIME, diff --git a/lib/core/src/lib/form/components/widgets/core/form-field.model.ts b/lib/core/src/lib/form/components/widgets/core/form-field.model.ts index 6b7af660296..0c97a14eca4 100644 --- a/lib/core/src/lib/form/components/widgets/core/form-field.model.ts +++ b/lib/core/src/lib/form/components/widgets/core/form-field.model.ts @@ -28,7 +28,7 @@ import { ProcessFormModel } from './process-form-model.interface'; import { isNumberValue } from './form-field-utils'; import { VariableConfig } from './form-field-variable-options'; import { DataColumn } from '../../../../datatable/data/data-column.model'; -import { isValid, parseISO } from 'date-fns'; +import { isValid } from 'date-fns'; import { DateFnsUtils } from '../../../../common/utils/date-fns-utils'; // Maps to FormFieldRepresentation @@ -190,7 +190,7 @@ export class FormFieldModel extends FormWidgetModel { this.visibilityCondition = json.visibilityCondition ? new WidgetVisibilityModel(json.visibilityCondition) : undefined; this.enableFractions = json.enableFractions; this.currency = json.currency; - this.dateDisplayFormat = json.dateDisplayFormat || this.getDefaultDateFormat(json); + this.dateDisplayFormat = DateFnsUtils.convertMomentToDateFnsFormat(json.dateDisplayFormat) || this.getDefaultDateFormat(json); this._value = this.parseValue(json); this.validationSummary = new ErrorMessageModel(); this.tooltip = json.tooltip; @@ -354,7 +354,7 @@ export class FormFieldModel extends FormWidgetModel { if (isNumberValue(value)) { dateValue = new Date(value); } else { - dateValue = parseISO(value); + dateValue = DateFnsUtils.parseDate(value, 'YYYY-MM-DD hh:mm A'); } if (isValid(dateValue)) { value = DateFnsUtils.formatDate(dateValue, this.dateDisplayFormat); @@ -368,7 +368,7 @@ export class FormFieldModel extends FormWidgetModel { if (isNumberValue(value)) { dateValue = new Date(value); } else { - dateValue = parseISO(value); + dateValue = DateFnsUtils.parseDate(value.split('T')[0], 'YYYY-M-D'); } if (isValid(dateValue)) { value = DateFnsUtils.formatDate(dateValue, this.dateDisplayFormat); diff --git a/lib/core/src/lib/form/components/widgets/date/date.widget.spec.ts b/lib/core/src/lib/form/components/widgets/date/date.widget.spec.ts index c1410d85db4..e13d2837756 100644 --- a/lib/core/src/lib/form/components/widgets/date/date.widget.spec.ts +++ b/lib/core/src/lib/form/components/widgets/date/date.widget.spec.ts @@ -165,7 +165,7 @@ describe('DateWidgetComponent', () => { readOnly: 'false' }); widget.field.isVisible = true; - widget.field.dateDisplayFormat = DateFnsUtils.convertMomentToDateFnsFormat('MM-DD-YYYY'); + widget.field.dateDisplayFormat = 'MM-DD-YYYY'; fixture.detectChanges(); await fixture.whenStable(); @@ -174,7 +174,7 @@ describe('DateWidgetComponent', () => { expect(dateElement?.value).toContain('12-30-9999'); widget.field.value = '05.06.2019'; - widget.field.dateDisplayFormat = DateFnsUtils.convertMomentToDateFnsFormat('DD.MM.YYYY'); + widget.field.dateDisplayFormat = 'DD.MM.YYYY'; fixture.componentInstance.ngOnInit(); fixture.detectChanges(); @@ -233,7 +233,7 @@ describe('DateWidgetComponent', () => { }); field.isVisible = true; - field.dateDisplayFormat = DateFnsUtils.convertMomentToDateFnsFormat('MM-DD-YYYY'); + field.dateDisplayFormat = 'MM-DD-YYYY'; widget.field = field; fixture.detectChanges(); diff --git a/lib/core/src/lib/pipes/date.pipe.spec.ts b/lib/core/src/lib/pipes/date.pipe.spec.ts index 2b70cb90ecf..658bd11403a 100644 --- a/lib/core/src/lib/pipes/date.pipe.spec.ts +++ b/lib/core/src/lib/pipes/date.pipe.spec.ts @@ -21,6 +21,15 @@ import { ADFDatePipe } from './date.pipe'; describe('ADFDatePipe', () => { let datePipe: ADFDatePipe; + const dateFormats = [ + { dateFormat: 'yyyy-MM-dd' }, + { dateFormat: 'yyyy-M-d' }, + { dateFormat: 'dd-MM-yyyy' }, + { dateFormat: 'd-M-yyyy' }, + { dateFormat: 'M-d-yyyy' }, + { dateFormat: 'MM-d-yyyy' } + ]; + beforeEach(() => { TestBed.configureTestingModule({ providers: [ADFDatePipe] @@ -29,53 +38,22 @@ describe('ADFDatePipe', () => { }); it('should transform a valid date string into a Date object', () => { - const testDates = [ - { dateString: '2023-10-05', dateFormat: 'yyyy-MM-dd' }, - { dateString: '2023-10-5', dateFormat: 'yyyy-M-d' }, - { dateString: '05-10-2023', dateFormat: 'dd-MM-yyyy' }, - { dateString: '5-10-2023', dateFormat: 'd-M-yyyy' }, - { dateString: '10-5-2023', dateFormat: 'M-d-yyyy' }, - { dateString: '10-05-2023', dateFormat: 'MM-d-yyyy' } - ]; - testDates.forEach(({ dateString, dateFormat }) => { - const transformedDate = datePipe.transform(dateString, dateFormat); + const inputDate = '2023-10-05'; + + dateFormats.forEach(({ dateFormat }) => { + const transformedDate = datePipe.transform(inputDate, dateFormat); expect(transformedDate instanceof Date).toBe(true); - expect(transformedDate.getFullYear()).toBe(2023); - expect(transformedDate.getMonth()).toBe(9); // October is 9 (0-based) - expect(transformedDate.getDate()).toBe(5); }); }); it('should transform a valid date object into a Date object', () => { - const testDates = [ - { dateString: new Date(), dateFormat: 'yyyy-MM-dd' }, - { dateString: new Date(), dateFormat: 'yyyy-M-d' }, - { dateString: new Date(), dateFormat: 'dd-MM-yyyy' }, - { dateString: new Date(), dateFormat: 'd-M-yyyy' }, - { dateString: new Date(), dateFormat: 'M-d-yyyy' }, - { dateString: new Date(), dateFormat: 'MM-d-yyyy' } - ]; + const inputDate = new Date('2023-10-05'); - testDates.forEach(({ dateString, dateFormat }) => { - const transformedDate = datePipe.transform(dateString, dateFormat); - const today = new Date(); + dateFormats.forEach(({ dateFormat }) => { + const transformedDate = datePipe.transform(inputDate, dateFormat); expect(transformedDate instanceof Date).toBe(true); - expect(transformedDate.getFullYear()).toBe(today.getFullYear()); - expect(transformedDate.getMonth()).toBe(today.getMonth()); // October is 9 (0-based) - expect(transformedDate.getDate()).toBe(today.getDate()); }); }); - - it('should handle undefined input by returning the current date', () => { - const undefinedInput = undefined; - const dateFormat = 'dd-MM-yyyy'; - - const transformedDate = datePipe.transform(undefinedInput, dateFormat); - const today = new Date(); - - expect(transformedDate instanceof Date).toBe(true); - expect(transformedDate).toEqual(today); - }); }); diff --git a/lib/core/src/lib/pipes/date.pipe.ts b/lib/core/src/lib/pipes/date.pipe.ts index 1b05a434764..ac1b59d90c7 100644 --- a/lib/core/src/lib/pipes/date.pipe.ts +++ b/lib/core/src/lib/pipes/date.pipe.ts @@ -17,17 +17,12 @@ import { Pipe, PipeTransform } from '@angular/core'; import { DateFnsUtils } from '../common/utils/date-fns-utils'; -import { isDate } from 'date-fns'; +import { isValid } from 'date-fns'; @Pipe({ name: 'adfDate' }) export class ADFDatePipe implements PipeTransform { transform(value: Date | string, dateFormat: string): Date { - if (value) { - const date = typeof value === 'string' ? DateFnsUtils.parseDate(value, dateFormat) : value; - if (isDate(date)) { - return date; - } - } - return new Date(); + const date = value instanceof Date ? value : new Date(value); + return isValid(date) ? DateFnsUtils.parseDate(date, dateFormat) : date; } } diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.spec.ts b/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.spec.ts index f6fa6dec70f..28a7961cb8d 100644 --- a/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.spec.ts +++ b/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.spec.ts @@ -119,7 +119,7 @@ describe('DateWidgetComponent', () => { expect(element.querySelector('#date-field-id')).toBeDefined(); expect(element.querySelector('#date-field-id')).not.toBeNull(); const dateElement = element.querySelector('#date-field-id'); - expect(dateElement.value).toContain('9999-9-9'); + expect(dateElement.value).toContain('9-9-9999'); }); it('should show the correct format type', async () => { @@ -131,7 +131,7 @@ describe('DateWidgetComponent', () => { readOnly: 'false' }); widget.field.isVisible = true; - widget.field.dateDisplayFormat = DateFnsUtils.convertMomentToDateFnsFormat('YYYY-DD-MM'); + widget.field.dateDisplayFormat = 'YYYY-DD-MM'; widget.ngOnInit(); fixture.detectChanges(); await fixture.whenStable(); @@ -192,7 +192,7 @@ describe('DateWidgetComponent', () => { readOnly: 'false' }); field.isVisible = true; - field.dateDisplayFormat = DateFnsUtils.convertMomentToDateFnsFormat('MM-DD-YYYY'); + field.dateDisplayFormat = 'MM-DD-YYYY'; widget.field = field; widget.ngOnInit(); fixture.detectChanges(); From 27dbd03fe682c54f009d579b5ccb408668230478 Mon Sep 17 00:00:00 2001 From: SheenaMalhotra182 Date: Mon, 9 Oct 2023 22:55:47 +0530 Subject: [PATCH 17/19] [ACS-5857] reverted moment migration for DateWidget and DateCloudWidget --- .../src/lib/common/utils/date-fns-utils.ts | 2 +- .../widgets/core/form-field-validator.ts | 31 +++++----- .../widgets/core/form-field.model.spec.ts | 7 ++- .../widgets/core/form-field.model.ts | 26 +++----- .../widgets/date-time/date-time.widget.ts | 2 +- .../widgets/date/date.widget.spec.ts | 27 ++------ .../components/widgets/date/date.widget.ts | 16 +++-- .../widgets/date/date-cloud.widget.html | 8 +-- .../widgets/date/date-cloud.widget.spec.ts | 61 +++++++------------ .../widgets/date/date-cloud.widget.ts | 61 +++++++++---------- 10 files changed, 96 insertions(+), 145 deletions(-) diff --git a/lib/core/src/lib/common/utils/date-fns-utils.ts b/lib/core/src/lib/common/utils/date-fns-utils.ts index ca7840f4abd..9dd9d9c09c1 100644 --- a/lib/core/src/lib/common/utils/date-fns-utils.ts +++ b/lib/core/src/lib/common/utils/date-fns-utils.ts @@ -163,7 +163,7 @@ export class DateFnsUtils { /** * Parses a date string using the specified date format. * - * @param value - The date string to parse. + * @param date - The date string to parse. * @param dateFormat - The date format string to use for parsing. * @returns The parsed Date object. */ diff --git a/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts b/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts index c90e689210a..e3a46c1ec65 100644 --- a/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts +++ b/lib/core/src/lib/form/components/widgets/core/form-field-validator.ts @@ -17,6 +17,7 @@ /* eslint-disable @angular-eslint/component-selector */ +import moment from 'moment'; import { FormFieldTypes } from './form-field-types'; import { isNumberValue } from './form-field-utils'; import { FormFieldModel } from './form-field.model'; @@ -148,8 +149,8 @@ export class DateFieldValidator implements FormFieldValidator { // Validates that the input string is a valid date formatted as (default D-M-YYYY) static isValidDate(inputDate: string, dateFormat: string = 'D-M-YYYY'): boolean { if (inputDate) { - const date = DateFnsUtils.parseDate(inputDate, dateFormat); - return isValid(date); + const d = moment(inputDate, dateFormat, true); + return d.isValid(); } return false; @@ -164,7 +165,7 @@ export class DateFieldValidator implements FormFieldValidator { if (DateFieldValidator.isValidDate(field.value, field.dateDisplayFormat)) { return true; } - field.validationSummary.message = DateFnsUtils.convertDateFnsToMomentFormat(field.dateDisplayFormat); + field.validationSummary.message = field.dateDisplayFormat; return false; } return true; @@ -211,8 +212,8 @@ export class DateTimeFieldValidator implements FormFieldValidator { export abstract class BoundaryDateFieldValidator implements FormFieldValidator { - DATE_FORMAT_CLOUD = 'yyyy-MM-dd'; - DATE_FORMAT = 'dd-MM-yyyy'; + DATE_FORMAT_CLOUD = 'YYYY-MM-DD'; + DATE_FORMAT = 'DD-MM-YYYY'; supportedTypes = [ FormFieldTypes.DATE @@ -251,17 +252,17 @@ export class MinDateFieldValidator extends BoundaryDateFieldValidator { // remove time and timezone info let fieldValueData; if (typeof field.value === 'string') { - fieldValueData = DateFnsUtils.parseDate(field.value.split('T')[0], dateFormat); + fieldValueData = moment(field.value.split('T')[0], dateFormat); } else { fieldValueData = field.value; } const minValueDateFormat = this.extractDateFormat(field.minValue); - const min = DateFnsUtils.parseDate(field.minValue, minValueDateFormat); + const min = moment(field.minValue, minValueDateFormat); - if (isBefore(fieldValueData, min)) { + if (fieldValueData.isBefore(min)) { field.validationSummary.message = `FORM.FIELD.VALIDATOR.NOT_LESS_THAN`; - field.validationSummary.attributes.set('minValue', DateFnsUtils.formatDate(min, field.dateDisplayFormat).toLocaleUpperCase()); + field.validationSummary.attributes.set('minValue', min.format(field.dateDisplayFormat).toLocaleUpperCase()); isFieldValid = false; } return isFieldValid; @@ -281,17 +282,17 @@ export class MaxDateFieldValidator extends BoundaryDateFieldValidator { // remove time and timezone info let fieldValueData; if (typeof field.value === 'string') { - fieldValueData = DateFnsUtils.parseDate(field.value.split('T')[0], dateFormat); + fieldValueData = moment(field.value.split('T')[0], dateFormat); } else { fieldValueData = field.value; } const maxValueDateFormat = this.extractDateFormat(field.maxValue); - const max = DateFnsUtils.parseDate(field.maxValue, maxValueDateFormat); + const max = moment(field.maxValue, maxValueDateFormat); - if (isAfter(fieldValueData, max)) { + if (fieldValueData.isAfter(max)) { field.validationSummary.message = `FORM.FIELD.VALIDATOR.NOT_GREATER_THAN`; - field.validationSummary.attributes.set('maxValue', DateFnsUtils.formatDate(max, field.dateDisplayFormat).toLocaleUpperCase()); + field.validationSummary.attributes.set('maxValue', max.format(field.dateDisplayFormat).toLocaleUpperCase()); isFieldValid = false; } return isFieldValid; @@ -320,7 +321,7 @@ export class MinDateTimeFieldValidator implements FormFieldValidator { if (this.isSupported(field) && field.value && field.isVisible) { const dateFormat = field.dateDisplayFormat; - if (!DateFieldValidator.isValidDate(field.value, dateFormat)) { + if (!DateTimeFieldValidator.isValidDate(field.value, dateFormat)) { field.validationSummary.message = 'FORM.FIELD.VALIDATOR.INVALID_DATE'; isFieldValid = false; } else { @@ -366,7 +367,7 @@ export class MaxDateTimeFieldValidator implements FormFieldValidator { if (this.isSupported(field) && field.value && field.isVisible) { const dateFormat = field.dateDisplayFormat; - if (!DateFieldValidator.isValidDate(field.value, dateFormat)) { + if (!DateTimeFieldValidator.isValidDate(field.value, dateFormat)) { field.validationSummary.message = 'FORM.FIELD.VALIDATOR.INVALID_DATE'; isFieldValid = false; } else { diff --git a/lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts b/lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts index a6899f8eb50..655a00f7ed7 100644 --- a/lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts +++ b/lib/core/src/lib/form/components/widgets/core/form-field.model.spec.ts @@ -15,6 +15,7 @@ * limitations under the License. */ +import moment from 'moment'; import { FormFieldTypes } from './form-field-types'; import { FormFieldModel } from './form-field.model'; import { FormModel } from './form.model'; @@ -273,9 +274,9 @@ describe('FormFieldModel', () => { dateDisplayFormat: 'DD-MM-YYYY' }); - const currentDate = new Date(); - const expectedDate = DateFnsUtils.formatDate(currentDate, 'DD-MM-YYYY'); - const expectedDateFormat = `${DateFnsUtils.formatDate(currentDate, 'YYYY-MM-DD')}T00:00:00.000Z`; + const currentDate = moment(new Date()); + const expectedDate = moment(currentDate).format('DD-MM-YYYY'); + const expectedDateFormat = `${currentDate.format('YYYY-MM-DD')}T00:00:00.000Z`; expect(field.value).toBe(expectedDate); expect(form.values['ddmmyyy']).toEqual(expectedDateFormat); diff --git a/lib/core/src/lib/form/components/widgets/core/form-field.model.ts b/lib/core/src/lib/form/components/widgets/core/form-field.model.ts index 0c97a14eca4..dccde639428 100644 --- a/lib/core/src/lib/form/components/widgets/core/form-field.model.ts +++ b/lib/core/src/lib/form/components/widgets/core/form-field.model.ts @@ -16,6 +16,7 @@ */ /* eslint-disable @angular-eslint/component-selector */ +import moment from 'moment'; import { WidgetVisibilityModel } from '../../../models/widget-visibility.model'; import { ContainerColumnModel } from './container-column.model'; import { ErrorMessageModel } from './error-message.model'; @@ -39,7 +40,7 @@ export class FormFieldModel extends FormWidgetModel { private _isValid: boolean = true; private _required: boolean = false; - readonly defaultDateFormat: string = 'd-M-yyyy'; + readonly defaultDateFormat: string = 'D-M-YYYY'; readonly defaultDateTimeFormat: string = 'd-M-yyyy hh:mm a'; // model members @@ -190,7 +191,7 @@ export class FormFieldModel extends FormWidgetModel { this.visibilityCondition = json.visibilityCondition ? new WidgetVisibilityModel(json.visibilityCondition) : undefined; this.enableFractions = json.enableFractions; this.currency = json.currency; - this.dateDisplayFormat = DateFnsUtils.convertMomentToDateFnsFormat(json.dateDisplayFormat) || this.getDefaultDateFormat(json); + this.dateDisplayFormat = json.dateDisplayFormat || this.getDefaultDateFormat(json); this._value = this.parseValue(json); this.validationSummary = new ErrorMessageModel(); this.tooltip = json.tooltip; @@ -241,22 +242,11 @@ export class FormFieldModel extends FormWidgetModel { } private getDefaultDateFormat(jsonField: any): string { - if (jsonField.fields) { - Object.keys(jsonField.fields).forEach((el) => { - if (jsonField.fields[el]) { - jsonField.fields[el].forEach((element) => { - element.dateDisplayFormat = element.dateDisplayFormat - ? DateFnsUtils.convertMomentToDateFnsFormat(element.dateDisplayFormat) - : element.dateDisplayFormat; - }); - } - }); - } let originalType = jsonField.type; if (FormFieldTypes.isReadOnlyType(jsonField.type) && jsonField.params && jsonField.params.field) { originalType = jsonField.params.field.type; } - return originalType === FormFieldTypes.DATETIME ? this.defaultDateTimeFormat : this.defaultDateFormat; + return originalType === FormFieldTypes.DATETIME ? DateFnsUtils.convertMomentToDateFnsFormat(this.defaultDateTimeFormat) : this.defaultDateFormat; } private isTypeaheadFieldType(type: string): boolean { @@ -366,12 +356,12 @@ export class FormFieldModel extends FormWidgetModel { if (value) { let dateValue; if (isNumberValue(value)) { - dateValue = new Date(value); + dateValue = moment(value); } else { - dateValue = DateFnsUtils.parseDate(value.split('T')[0], 'YYYY-M-D'); + dateValue = moment.utc(value.split('T')[0], 'YYYY-M-D'); } - if (isValid(dateValue)) { - value = DateFnsUtils.formatDate(dateValue, this.dateDisplayFormat); + if (dateValue?.isValid()) { + value = dateValue.utc().format(this.dateDisplayFormat); } } } diff --git a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts index e45cfb4280d..64f889e2024 100644 --- a/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts +++ b/lib/core/src/lib/form/components/widgets/date-time/date-time.widget.ts @@ -46,7 +46,7 @@ export class DateTimeWidgetComponent extends WidgetComponent implements OnInit, private onDestroy$ = new Subject(); constructor(public formService: FormService, - private dateAdapter: DateAdapter, + private dateAdapter: DateAdapter, private userPreferencesService: UserPreferencesService, @Inject(MAT_DATE_FORMATS) private dateFormatConfig: MatDateFormats, private translationService: TranslationService) { diff --git a/lib/core/src/lib/form/components/widgets/date/date.widget.spec.ts b/lib/core/src/lib/form/components/widgets/date/date.widget.spec.ts index e13d2837756..7c364f8885d 100644 --- a/lib/core/src/lib/form/components/widgets/date/date.widget.spec.ts +++ b/lib/core/src/lib/form/components/widgets/date/date.widget.spec.ts @@ -16,14 +16,13 @@ */ import { ComponentFixture, TestBed } from '@angular/core/testing'; +import moment from 'moment'; import { FormFieldModel } from '../core/form-field.model'; import { FormModel } from '../core/form.model'; import { DateWidgetComponent } from './date.widget'; import { CoreTestingModule } from '../../../../testing/core.testing.module'; import { TranslateModule } from '@ngx-translate/core'; import { FormFieldTypes } from '../core/form-field-types'; -import { isSameDay } from 'date-fns'; -import { DateFnsUtils } from '../../../../common'; describe('DateWidgetComponent', () => { let widget: DateWidgetComponent; @@ -63,8 +62,8 @@ describe('DateWidgetComponent', () => { widget.ngOnInit(); - const expectedMinDate = DateFnsUtils.parseDate(minValue, widget.field.dateDisplayFormat); - expect(isSameDay(widget.minDate, expectedMinDate)).toBeTruthy(); + const expected = moment(minValue, widget.field.dateDisplayFormat); + expect(widget.minDate.isSame(expected)).toBeTruthy(); }); it('should date field be present', () => { @@ -86,8 +85,8 @@ describe('DateWidgetComponent', () => { }); widget.ngOnInit(); - const expectedMaxDate = DateFnsUtils.parseDate(maxValue, widget.field.dateDisplayFormat); - expect(isSameDay(widget.maxDate, expectedMaxDate)).toBeTruthy(); + const expected = moment(maxValue, widget.field.dateDisplayFormat); + expect(widget.maxDate.isSame(expected)).toBeTruthy(); }); it('should eval visibility on date changed', () => { @@ -250,20 +249,4 @@ describe('DateWidgetComponent', () => { expect(dateElement?.value).toContain('03-02-2020'); }); - - describe('format label', () => { - beforeEach(() => { - widget.field = new FormFieldModel(new FormModel({ taskId: '' }), { - name: 'Date', - dateDisplayFormat: 'd-M-yyyy' - }); - fixture.detectChanges(); - }); - - it('should format label correctly', () => { - const result = widget.formatDateLabel(widget.field); - - expect(result).toBe('Date (D-M-YYYY)'); - }); - }); }); diff --git a/lib/core/src/lib/form/components/widgets/date/date.widget.ts b/lib/core/src/lib/form/components/widgets/date/date.widget.ts index 4f6b8d232a2..74c916bf4be 100644 --- a/lib/core/src/lib/form/components/widgets/date/date.widget.ts +++ b/lib/core/src/lib/form/components/widgets/date/date.widget.ts @@ -32,9 +32,8 @@ import { MatDatepickerInputEvent } from '@angular/material/datepicker'; @Component({ selector: 'date-widget', providers: [ - { provide: DateAdapter, useClass: DateFnsAdapter }, - { provide: MAT_DATE_FORMATS, useValue: MAT_DATE_FNS_FORMATS } - ], + { provide: DateAdapter, useClass: MomentDateAdapter }, + { provide: MAT_DATE_FORMATS, useValue: MOMENT_DATE_FORMATS }], templateUrl: './date.widget.html', host: { '(click)': 'event($event)', @@ -63,10 +62,8 @@ export class DateWidgetComponent extends WidgetComponent implements OnInit, OnDe private onDestroy$ = new Subject(); constructor(public formService: FormService, - private dateAdapter: DateAdapter, - private userPreferencesService: UserPreferencesService, - @Inject(MAT_DATE_FORMATS) private dateFormatConfig: MatDateFormats, - private translationService: TranslationService) { + private dateAdapter: DateAdapter, + private userPreferencesService: UserPreferencesService) { super(formService); } @@ -74,9 +71,10 @@ export class DateWidgetComponent extends WidgetComponent implements OnInit, OnDe this.userPreferencesService .select(UserPreferenceValues.Locale) .pipe(takeUntil(this.onDestroy$)) - .subscribe(locale => this.dateAdapter.setLocale(DateFnsUtils.getLocaleFromString(locale))); + .subscribe(locale => this.dateAdapter.setLocale(locale)); - this.dateFormatConfig.display.dateInput = this.field.dateDisplayFormat; + const momentDateAdapter = this.dateAdapter as MomentDateAdapter; + momentDateAdapter.overrideDisplayFormat = this.field.dateDisplayFormat; if (this.field) { if (this.field.minValue) { diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.html b/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.html index 03789caed50..f65fb13fa0c 100644 --- a/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.html +++ b/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.html @@ -1,11 +1,11 @@
-
- - + { @@ -52,8 +52,8 @@ describe('DateWidgetComponent', () => { widget.ngOnInit(); - const expected = DateFnsUtils.parseDate(minValue, DATE_FORMAT_CLOUD); - expect(isSameDay(widget.minDate, expected)).toBeTruthy(); + const expected = moment(minValue, DATE_FORMAT_CLOUD); + expect(widget.minDate.isSame(expected)).toBeTruthy(); }); it('should date field be present', () => { @@ -75,8 +75,8 @@ describe('DateWidgetComponent', () => { }); widget.ngOnInit(); - const expected = DateFnsUtils.parseDate(maxValue, DATE_FORMAT_CLOUD); - expect(isSameDay(widget.maxDate, expected)).toBeTruthy(); + const expected = moment(maxValue, DATE_FORMAT_CLOUD); + expect(widget.maxDate.isSame(expected)).toBeTruthy(); }); it('should eval visibility on date changed', () => { @@ -91,8 +91,8 @@ describe('DateWidgetComponent', () => { }); widget.field = field; - const todayDate = new Date(); - widget.onDateChanged({ value: DateFnsUtils.formatDate(todayDate, DATE_FORMAT_CLOUD) }); + const todayDate = moment().format(DATE_FORMAT_CLOUD); + widget.onDateChanged({ value: todayDate }); expect(widget.onFieldChanged).toHaveBeenCalledWith(field); }); @@ -293,10 +293,9 @@ describe('DateWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const todayDate = new Date(); - const expected = DateFnsUtils.formatDate(subDays(todayDate, widget.field.minDateRangeValue), DATE_FORMAT_CLOUD); - const minDateFormatted = DateFnsUtils.formatDate(widget.minDate, DATE_FORMAT_CLOUD); - expect(minDateFormatted).toEqual(expected); + const todayDate = moment().format(DATE_FORMAT_CLOUD); + const expected = moment(todayDate).subtract(widget.field.minDateRangeValue, 'days'); + expect(widget.minDate).toEqual(expected); }); it('should min date and max date be undefined if dynamic min and max date are not set', async () => { @@ -344,10 +343,9 @@ describe('DateWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const todayDate = new Date(); - const expected = DateFnsUtils.formatDate(addDays(todayDate, widget.field.maxDateRangeValue), DATE_FORMAT_CLOUD); - const maxDateFormatted = DateFnsUtils.formatDate(widget.maxDate, DATE_FORMAT_CLOUD); - expect(maxDateFormatted).toEqual(expected); + const todayDate = moment().format(DATE_FORMAT_CLOUD); + const expected = moment(todayDate).add(widget.field.maxDateRangeValue, 'days'); + expect(widget.maxDate).toEqual(expected); }); it('should maxDate and minDate be undefined if minDateRangeValue and maxDateRangeValue are null', async () => { @@ -394,6 +392,7 @@ describe('DateWidgetComponent', () => { describe('check date validation by dynamic date ranges', () => { it('should minValue be equal to today date minus minDateRangeValue', async () => { + spyOn(widget, 'getTodaysFormattedDate').and.returnValue('2022-07-22'); widget.field = new FormFieldModel(null, { dynamicDateRangeSelection: true, maxDateRangeValue: null, @@ -405,8 +404,7 @@ describe('DateWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const currentDate = new Date(); - const expectedMinValueString = DateFnsUtils.formatDate(subDays(currentDate, 1), DATE_FORMAT_CLOUD); + const expectedMinValueString = '2022-07-21'; expect(widget.field.minValue).toEqual(expectedMinValueString); expect(widget.maxDate).toBeUndefined(); @@ -414,6 +412,7 @@ describe('DateWidgetComponent', () => { }); it('should maxValue be equal to today date plus maxDateRangeValue', async () => { + spyOn(widget, 'getTodaysFormattedDate').and.returnValue('2022-07-22'); widget.field = new FormFieldModel(null, { dynamicDateRangeSelection: true, maxDateRangeValue: 8, @@ -425,8 +424,7 @@ describe('DateWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const currentDate = new Date(); - const expectedMaxValueString = DateFnsUtils.formatDate(addDays(currentDate, 8), DATE_FORMAT_CLOUD); + const expectedMaxValueString = '2022-07-30'; expect(widget.field.maxValue).toEqual(expectedMaxValueString); expect(widget.minDate).toBeUndefined(); @@ -434,6 +432,7 @@ describe('DateWidgetComponent', () => { }); it('should maxValue and minValue be null if maxDateRangeValue and minDateRangeValue are null', async () => { + spyOn(widget, 'getTodaysFormattedDate').and.returnValue('2022-07-22'); widget.field = new FormFieldModel(null, { dynamicDateRangeSelection: true, maxDateRangeValue: null, @@ -452,6 +451,7 @@ describe('DateWidgetComponent', () => { }); it('should maxValue and minValue not be null if maxDateRangeVale and minDateRangeValue are not null', async () => { + spyOn(widget, 'getTodaysFormattedDate').and.returnValue('2022-07-22'); widget.field = new FormFieldModel(null, { dynamicDateRangeSelection: true, maxDateRangeValue: 8, @@ -463,9 +463,8 @@ describe('DateWidgetComponent', () => { fixture.detectChanges(); await fixture.whenStable(); - const currentDate = new Date(); - const expectedMaxValueString = DateFnsUtils.formatDate(addDays(currentDate, 8), DATE_FORMAT_CLOUD); - const expectedMinValueString = DateFnsUtils.formatDate(subDays(currentDate, 10), DATE_FORMAT_CLOUD); + const expectedMaxValueString = '2022-07-30'; + const expectedMinValueString = '2022-07-12'; expect(widget.field.maxValue).toEqual(expectedMaxValueString); expect(widget.field.minValue).toEqual(expectedMinValueString); @@ -543,20 +542,4 @@ describe('DateWidgetComponent', () => { expect(element.querySelector('.adf-invalid')).toBeTruthy(); }); }); - - describe('format label', () => { - beforeEach(() => { - widget.field = new FormFieldModel(new FormModel({ taskId: '' }), { - name: 'Date Field', - dateDisplayFormat: 'd-M-yyyy' - }); - fixture.detectChanges(); - }); - - it('should format label correctly', () => { - const result = widget.formatLabel(widget.field); - - expect(result).toBe('Date Field (D-M-YYYY)'); - }); - }); }); diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.ts b/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.ts index 6946a173606..8d621442499 100644 --- a/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.ts +++ b/lib/process-services-cloud/src/lib/form/components/widgets/date/date-cloud.widget.ts @@ -17,23 +17,22 @@ /* eslint-disable @angular-eslint/component-selector */ -import { Component, OnInit, ViewEncapsulation, OnDestroy, Inject } from '@angular/core'; -import { DateAdapter, MAT_DATE_FORMATS, MatDateFormats } from '@angular/material/core'; +import { Component, OnInit, ViewEncapsulation, OnDestroy } from '@angular/core'; +import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core'; +import moment, { Moment } from 'moment'; import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { - WidgetComponent, - UserPreferencesService, UserPreferenceValues, FormService, DateFnsUtils, TranslationService, FormFieldModel + MOMENT_DATE_FORMATS, MomentDateAdapter, WidgetComponent, + UserPreferencesService, UserPreferenceValues, FormService } from '@alfresco/adf-core'; import { DATE_FORMAT_CLOUD } from '../../../../models/date-format-cloud.model'; -import { DateFnsAdapter, MAT_DATE_FNS_FORMATS } from '@angular/material-date-fns-adapter'; -import { addDays, isValid, subDays } from 'date-fns'; @Component({ selector: 'date-widget', providers: [ - { provide: DateAdapter, useClass: DateFnsAdapter }, - { provide: MAT_DATE_FORMATS, useValue: MAT_DATE_FNS_FORMATS }], + { provide: DateAdapter, useClass: MomentDateAdapter }, + { provide: MAT_DATE_FORMATS, useValue: MOMENT_DATE_FORMATS }], templateUrl: './date-cloud.widget.html', styleUrls: ['./date-cloud.widget.scss'], host: { @@ -52,16 +51,14 @@ import { addDays, isValid, subDays } from 'date-fns'; export class DateCloudWidgetComponent extends WidgetComponent implements OnInit, OnDestroy { typeId = 'DateCloudWidgetComponent'; - minDate: Date; - maxDate: Date; + minDate: Moment; + maxDate: Moment; private onDestroy$ = new Subject(); constructor(public formService: FormService, - private dateAdapter: DateAdapter, - private userPreferencesService: UserPreferencesService, - @Inject(MAT_DATE_FORMATS) private dateFormatConfig: MatDateFormats, - private translationService: TranslationService) { + private dateAdapter: DateAdapter, + private userPreferencesService: UserPreferencesService) { super(formService); } @@ -69,49 +66,47 @@ export class DateCloudWidgetComponent extends WidgetComponent implements OnInit, this.userPreferencesService .select(UserPreferenceValues.Locale) .pipe(takeUntil(this.onDestroy$)) - .subscribe(locale => this.dateAdapter.setLocale(DateFnsUtils.getLocaleFromString(locale))); + .subscribe(locale => this.dateAdapter.setLocale(locale)); - this.dateFormatConfig.display.dateInput = this.field.dateDisplayFormat; + const momentDateAdapter = this.dateAdapter as MomentDateAdapter; + momentDateAdapter.overrideDisplayFormat = this.field.dateDisplayFormat; if (this.field) { if (this.field.dynamicDateRangeSelection) { - const today = new Date(); + const today = this.getTodaysFormattedDate(); if (Number.isInteger(this.field.minDateRangeValue)) { - this.minDate = subDays(today, this.field.minDateRangeValue); - this.field.minValue = DateFnsUtils.formatDate(this.minDate, DATE_FORMAT_CLOUD); + this.minDate = moment(today).subtract(this.field.minDateRangeValue, 'days'); + this.field.minValue = this.minDate.format(DATE_FORMAT_CLOUD); } if (Number.isInteger(this.field.maxDateRangeValue)) { - this.maxDate = addDays(today, this.field.maxDateRangeValue); - this.field.maxValue = DateFnsUtils.formatDate(this.maxDate, DATE_FORMAT_CLOUD); + this.maxDate = moment(today).add(this.field.maxDateRangeValue, 'days'); + this.field.maxValue = this.maxDate.format(DATE_FORMAT_CLOUD); } } else { if (this.field.minValue) { - this.minDate = DateFnsUtils.parseDate(this.field.minValue, DATE_FORMAT_CLOUD); + this.minDate = moment(this.field.minValue, DATE_FORMAT_CLOUD); } if (this.field.maxValue) { - this.maxDate = DateFnsUtils.parseDate(this.field.maxValue, DATE_FORMAT_CLOUD); + this.maxDate = moment(this.field.maxValue, DATE_FORMAT_CLOUD); } } } } + getTodaysFormattedDate() { + return moment().format(DATE_FORMAT_CLOUD); + } + ngOnDestroy() { this.onDestroy$.next(true); this.onDestroy$.complete(); } - formatLabel(field: FormFieldModel): string { - const displayName = this.translationService.instant(field.name); - const displayFormat = DateFnsUtils.convertDateFnsToMomentFormat(field.dateDisplayFormat); - - return `${displayName} (${displayFormat})`; - } - onDateChanged(newDateValue) { - const date = DateFnsUtils.parseDate(newDateValue, this.field.dateDisplayFormat); - if (isValid(date)) { - this.field.value = DateFnsUtils.formatDate(date, this.field.dateDisplayFormat); + const date = moment(newDateValue, this.field.dateDisplayFormat, true); + if (date.isValid()) { + this.field.value = date.format(this.field.dateDisplayFormat); } else { this.field.value = newDateValue; } From f41a090f8f09eaf9285216130d7f05475dc0d2e3 Mon Sep 17 00:00:00 2001 From: SheenaMalhotra182 Date: Tue, 10 Oct 2023 00:22:21 +0530 Subject: [PATCH 18/19] [ACS-5857] reverted date field back to moment in form-field-model.ts --- .../lib/form/components/widgets/core/form-field.model.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/core/src/lib/form/components/widgets/core/form-field.model.ts b/lib/core/src/lib/form/components/widgets/core/form-field.model.ts index dccde639428..bf9e8944dbd 100644 --- a/lib/core/src/lib/form/components/widgets/core/form-field.model.ts +++ b/lib/core/src/lib/form/components/widgets/core/form-field.model.ts @@ -434,13 +434,12 @@ export class FormFieldModel extends FormWidgetModel { } case FormFieldTypes.DATE: { if (typeof this.value === 'string' && this.value === 'today') { - this.value = DateFnsUtils.formatDate(new Date(), this.dateDisplayFormat); + this.value = moment(new Date()).format(this.dateDisplayFormat); } - const dateValue = DateFnsUtils.parseDate(this.value, this.dateDisplayFormat); - - if (isValid(dateValue)) { - this.form.values[this.id] = `${DateFnsUtils.formatDate(dateValue, 'YYYY-MM-DD')}T00:00:00.000Z`; + const dateValue = moment(this.value, this.dateDisplayFormat, true); + if (dateValue?.isValid()) { + this.form.values[this.id] = `${dateValue.format('YYYY-MM-DD')}T00:00:00.000Z`; } else { this.form.values[this.id] = null; this._value = this.value; From 4b8dd3e18408a1728821a78296fafd9e326b95c3 Mon Sep 17 00:00:00 2001 From: SheenaMalhotra182 Date: Tue, 10 Oct 2023 00:23:39 +0530 Subject: [PATCH 19/19] [ci:force]