From fe83a48080b4ee86b60cbdf7bf04ba7bdfcf7ba5 Mon Sep 17 00:00:00 2001 From: SheenaMalhotra182 Date: Fri, 29 Sep 2023 19:13:42 +0530 Subject: [PATCH] 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.html | 2 +- .../components/widgets/date/date.widget.ts | 20 +++-- 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 +++-- 16 files changed, 245 insertions(+), 176 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 59f21e2c37..3c545ae6c9 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 3333224624..91fe58672b 100644 --- a/lib/core/src/lib/common/utils/date-fns-utils.ts +++ b/lib/core/src/lib/common/utils/date-fns-utils.ts @@ -86,7 +86,9 @@ export class DateFnsUtils { static momentToDateFnsMap = { D: 'd', Y: 'y', - A: 'a' + A: 'a', + Z: 'XXX', + T: `'T'` }; /** @@ -95,7 +97,8 @@ export class DateFnsUtils { static dateFnsToMomentMap = { d: 'D', y: 'Y', - a: 'A' + a: 'A', + xxx: 'Z' }; /** @@ -105,6 +108,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); @@ -151,4 +162,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 4e990d9a5b..275348bb75 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 7a696d019a..921aa6453c 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 0537d098a8..a6899f8eb5 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 a85fb69e8a..5a2607e925 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 f2081c71ad..d3487f71e9 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 cd8a60f8b7..e72b95d6d1 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.html b/lib/core/src/lib/form/components/widgets/date/date.widget.html index 309510e9af..2e38127903 100644 --- a/lib/core/src/lib/form/components/widgets/date/date.widget.html +++ b/lib/core/src/lib/form/components/widgets/date/date.widget.html @@ -1,6 +1,6 @@
- , private userPreferencesService: UserPreferencesService, @Inject(MAT_DATE_FORMATS) private dateFormatConfig: MatDateFormats, - protected dateFormatTranslationService: DateFormatTranslationService) { + private translationService: TranslationService) { super(formService); } @@ -76,8 +77,8 @@ export class DateWidgetComponent extends WidgetComponent implements OnInit, OnDe this.dateFormatConfig.display.dateInput = this.field.dateDisplayFormat; if (this.field) { - this.minDate = isValid(this.field.minValue) ? this.dateFormatTranslationService.format(new Date(this.field.minValue), this.DATE_FORMAT) : this.field.minValue; - this.maxDate = isValid(this.field.maxValue) ? this.dateFormatTranslationService.format(new Date(this.field.maxValue), this.DATE_FORMAT) : this.field.maxValue; + this.minDate = isValid(this.field.minValue) ? DateFnsUtils.formatDate(new Date(this.field.minValue), this.DATE_FORMAT) : this.field.minValue; + this.maxDate = isValid(this.field.maxValue) ? DateFnsUtils.formatDate(new Date(this.field.maxValue), this.DATE_FORMAT) : this.field.maxValue; } } @@ -86,10 +87,17 @@ export class DateWidgetComponent extends WidgetComponent implements OnInit, OnDe 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; } diff --git a/lib/core/src/lib/pipes/date.pipe.spec.ts b/lib/core/src/lib/pipes/date.pipe.spec.ts index a2ccc3ed65..ae4d29fd17 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 6bb180984d..a04f85703f 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 792920117d..83b0a3a129 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 e8fe51b499..03789caed5 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; }