From ac69ab82156ae50c45489c6528afcd3bac1aad81 Mon Sep 17 00:00:00 2001 From: Katrin Khilko Date: Mon, 9 Dec 2024 17:14:15 +0300 Subject: [PATCH 1/4] FIO-8541: replaced moment dependency with dayjs --- gulpfile.js | 6 --- package.json | 4 +- src/Element.js | 2 +- src/Webform.js | 6 ++- src/components/datetime/DateTime.js | 15 ++++-- src/components/day/Day.js | 6 +-- src/components/time/Time.js | 2 +- src/utils/calendarUtils.js | 2 +- .../conditionOperators/DateGreaterThan.js | 2 +- src/utils/moment-wrapper.js | 30 +++++++++++ yarn.lock | 52 +++---------------- 11 files changed, 61 insertions(+), 66 deletions(-) create mode 100644 src/utils/moment-wrapper.js diff --git a/gulpfile.js b/gulpfile.js index aad43eaec5..de70f0b689 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -81,14 +81,8 @@ gulp.task('embed-css', () => gulp.src('./dist/formio.embed.min.css').pipe(rename gulp.task('clean:embed-js', () => gulp.src('./dist/formio.embed.js', { read: false, allowEmpty: true }).pipe(clean())); gulp.task('embed-js', () => gulp.src('./dist/formio.embed.min.js').pipe(rename('formio.embed.js')).pipe(gulp.dest('./dist'))); -// Copy over the moment-timezones to the resource folder. -gulp.task('timezones', () => gulp.src('./node_modules/moment-timezone/data/packed/latest.json').pipe(gulp.dest('./resources'))); - // Create a new build. gulp.task('build', gulp.series( - gulp.parallel( - 'timezones' - ), gulp.parallel( 'styles-embed', 'styles-form', diff --git a/package.json b/package.json index a6656d7916..23a1635849 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "dependencies": { "@formio/bootstrap": "3.0.0-dev.98.17ba6ea", "@formio/choices.js": "^10.2.1", - "@formio/core": "2.1.0-dev.191.8c609ab", + "@formio/core": "2.1.0-dev.201.2792d73", "@formio/text-mask-addons": "^3.8.0-formio.3", "@formio/vanilla-text-mask": "^5.1.1-formio.1", "abortcontroller-polyfill": "^1.7.5", @@ -107,8 +107,6 @@ "jstimezonedetect": "^1.0.7", "jwt-decode": "^3.1.2", "lodash": "^4.17.21", - "moment": "^2.29.4", - "moment-timezone": "^0.5.44", "quill": "^2.0.2", "signature_pad": "^4.2.0", "string-hash": "^1.1.3", diff --git a/src/Element.js b/src/Element.js index f663ae9b44..8c2c17c994 100644 --- a/src/Element.js +++ b/src/Element.js @@ -3,7 +3,7 @@ import { Formio } from './Formio'; import * as FormioUtils from './utils/utils'; import { I18n } from './utils/i18n'; import _ from 'lodash'; -import moment from 'moment'; +import moment from './utils/moment-wrapper'; import maskInput from '@formio/vanilla-text-mask'; /** diff --git a/src/Webform.js b/src/Webform.js index ba65bd5079..9ee9ac9b6a 100644 --- a/src/Webform.js +++ b/src/Webform.js @@ -1,5 +1,6 @@ import _ from "lodash"; -import moment from "moment"; +import dayjs from "dayjs"; +import utc from "dayjs/plugin/utc"; import { compareVersions } from "compare-versions"; import EventEmitter from "./EventEmitter"; import i18nDefaults from "./i18n"; @@ -15,6 +16,7 @@ import { getArrayFromComponentPath, } from "./utils/utils"; import { eachComponent } from "./utils/formUtils"; +dayjs.extend(utc); // We need this here because dragula pulls in CustomEvent class that requires global to exist. if (typeof window !== 'undefined' && typeof window.global === 'undefined') { @@ -1511,7 +1513,7 @@ export default class Webform extends NestedDataComponent { submission.metadata = submission.metadata || {}; _.defaults(submission.metadata, { timezone: _.get(this, "_submission.metadata.timezone", currentTimezone()), - offset: parseInt(_.get(this, "_submission.metadata.offset", moment().utcOffset()), 10), + offset: parseInt(_.get(this, "_submission.metadata.offset", dayjs().utcOffset()), 10), origin: document.location.origin, referrer: document.referrer, browserName: navigator.appName, diff --git a/src/components/datetime/DateTime.js b/src/components/datetime/DateTime.js index 05d222bfc9..b181d93b9c 100644 --- a/src/components/datetime/DateTime.js +++ b/src/components/datetime/DateTime.js @@ -1,8 +1,17 @@ import _ from 'lodash'; -import moment from 'moment'; +import moment from '../../utils/moment-wrapper'; +import dayjs from 'dayjs'; +import utc from "dayjs/plugin/utc"; +import timezone from "dayjs/plugin/timezone"; +import customParseFormat from "dayjs/plugin/customParseFormat"; +import advancedFormat from 'dayjs/plugin/advancedFormat'; import FormioUtils from '../../utils'; import { componentValueTypes, getComponentSavedTypes } from '../../utils/utils'; import Input from '../_classes/input/Input'; +dayjs.extend(utc); +dayjs.extend(timezone); +dayjs.extend(customParseFormat); +dayjs.extend(advancedFormat); export default class DateTimeComponent extends Input { static schema(...extend) { @@ -207,8 +216,8 @@ export default class DateTimeComponent extends Input { } if (Array.isArray(value) && this.component.multiple) { - return value.map(item => _.trim(moment(item).format(format))).join(', '); + return value.map(item => _.trim(dayjs(item).format(format))).join(', '); } - return (value ? _.trim(moment(value).format(format)) : value) || ''; + return (value ? _.trim(dayjs(value).format(format)) : value) || ''; } } diff --git a/src/components/day/Day.js b/src/components/day/Day.js index 5e5ed62727..87b6a2208e 100644 --- a/src/components/day/Day.js +++ b/src/components/day/Day.js @@ -1,5 +1,5 @@ import _ from 'lodash'; -import moment from 'moment'; +import dayjs from 'dayjs'; import Field from '../_classes/field/Field'; import { boolValue, componentValueTypes, getComponentSavedTypes, getLocaleDateFormatInfo } from '../../utils/utils'; @@ -59,10 +59,10 @@ export default class DayComponent extends Field { constructor(component, options, data) { if (component.maxDate && component.maxDate.indexOf('moment(') === -1) { - component.maxDate = moment(component.maxDate, 'YYYY-MM-DD').toISOString(); + component.maxDate = dayjs(component.maxDate, 'YYYY-MM-DD').toISOString(); } if (component.minDate && component.minDate.indexOf('moment(') === -1) { - component.minDate = moment(component.minDate, 'YYYY-MM-DD').toISOString(); + component.minDate = dayjs(component.minDate, 'YYYY-MM-DD').toISOString(); } super(component, options, data); } diff --git a/src/components/time/Time.js b/src/components/time/Time.js index c762985cfa..dfd6546f53 100644 --- a/src/components/time/Time.js +++ b/src/components/time/Time.js @@ -1,4 +1,4 @@ -import moment from 'moment'; +import moment from '../../utils/moment-wrapper'; import TextFieldComponent from '../textfield/TextField'; import { getBrowserInfo } from '../../utils/utils'; diff --git a/src/utils/calendarUtils.js b/src/utils/calendarUtils.js index ff33374646..ae5c79e0f5 100644 --- a/src/utils/calendarUtils.js +++ b/src/utils/calendarUtils.js @@ -1,4 +1,4 @@ -import moment from 'moment'; +import moment from './moment-wrapper'; import _ from 'lodash'; export const CALENDAR_ERROR_MESSAGES = { diff --git a/src/utils/conditionOperators/DateGreaterThan.js b/src/utils/conditionOperators/DateGreaterThan.js index 8324ce7025..8113a2f138 100644 --- a/src/utils/conditionOperators/DateGreaterThan.js +++ b/src/utils/conditionOperators/DateGreaterThan.js @@ -1,5 +1,5 @@ import ConditionOperator from './ConditionOperator'; -import moment from 'moment'; +import moment from '../moment-wrapper'; export default class DateGeaterThan extends ConditionOperator { static get operatorKey() { return 'dateGreaterThan'; diff --git a/src/utils/moment-wrapper.js b/src/utils/moment-wrapper.js new file mode 100644 index 0000000000..65eeb2c979 --- /dev/null +++ b/src/utils/moment-wrapper.js @@ -0,0 +1,30 @@ +import dayjs from "dayjs"; +import utc from "dayjs/plugin/utc"; +import timezone from "dayjs/plugin/timezone" +import customParseFormat from 'dayjs/plugin/customParseFormat'; +import advancedFormat from 'dayjs/plugin/advancedFormat'; +import duration from 'dayjs/plugin/duration'; + +dayjs.extend(utc); +dayjs.extend(timezone); +dayjs.extend(customParseFormat); +dayjs.extend(advancedFormat); +dayjs.extend(duration); + +function moment(...args) { + return dayjs(...args); +} + +moment.utc = () => dayjs.utc(); +moment.tz = (date, timezone) => dayjs.tz(date, timezone); + + +moment.toISOString = () => { + return dayjs.isValid() ? dayjs.toISOString() : "Invalid date"; +} + +moment.format = (formatStr) => { + return dayjs(this).format(formatStr); +}; + +export default moment; diff --git a/yarn.lock b/yarn.lock index a600f82a4e..8521752790 100644 --- a/yarn.lock +++ b/yarn.lock @@ -381,10 +381,10 @@ fuse.js "^6.6.2" redux "^4.2.0" -"@formio/core@2.1.0-dev.191.8c609ab": - version "2.1.0-dev.191.8c609ab" - resolved "https://registry.yarnpkg.com/@formio/core/-/core-2.1.0-dev.191.8c609ab.tgz#2e442888c60786268ca16edc7cd26c38cbd4b773" - integrity sha512-lVj8hqddIwUJiWI6/yWF0NFl/f8QPS3ek4l6h0U1SFMPmeEdWQtcBTMLKi02gHx09kDgXhYocJIbBVVpYyqFnw== +"@formio/core@2.1.0-dev.201.2792d73": + version "2.1.0-dev.201.2792d73" + resolved "https://registry.yarnpkg.com/@formio/core/-/core-2.1.0-dev.201.2792d73.tgz#2cfaabe219a823ee7687b2ec2c7ffc355a1c5301" + integrity sha512-sGrWflkplGOb+y4JPQe1KtiQ9RYNvd1pClQbz0C1o9Gu7k1fjCXxIB2Y5dfpPKA2Xh39GHaDegbjPUrYHn9jew== dependencies: browser-cookies "^1.2.0" core-js "^3.38.0" @@ -396,7 +396,6 @@ inputmask "5.0.9" json-logic-js "^2.0.5" lodash "^4.17.21" - moment "^2.29.4" "@formio/text-mask-addons@^3.8.0-formio.3": version "3.8.0-formio.3" @@ -5524,18 +5523,6 @@ mock-local-storage@^1.1.24: core-js "^3.30.2" global "^4.3.2" -moment-timezone@^0.5.44: - version "0.5.45" - resolved "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.45.tgz#cb685acd56bac10e69d93c536366eb65aa6bcf5c" - integrity sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ== - dependencies: - moment "^2.29.4" - -moment@^2.29.4: - version "2.30.1" - resolved "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" - integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== - mrmime@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz#151082a6e06e59a9a39b46b3e14d5cfe92b3abb4" @@ -7324,7 +7311,7 @@ string-replace-loader@^3.1.0: loader-utils "^2.0.0" schema-utils "^3.0.0" -"string-width-cjs@npm:string-width@^4.2.0": +"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0: version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -7342,15 +7329,6 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -string-width@^4.1.0, string-width@^4.2.0: - version "4.2.3" - resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -7411,7 +7389,7 @@ stringifier@^1.3.0: traverse "^0.6.6" type-name "^2.0.1" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -7432,13 +7410,6 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -8501,7 +8472,7 @@ workerpool@6.2.1: resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -8527,15 +8498,6 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From b13a1e63f0405045bc0b71f1b9c0858a386b9070 Mon Sep 17 00:00:00 2001 From: Katrin Khilko Date: Fri, 27 Dec 2024 17:19:36 +0300 Subject: [PATCH 2/4] FIO-8541: moment removing --- package.json | 1 + src/utils/moment-wrapper.js | 8 +- src/utils/utils.js | 82 +++++++------------ src/widgets/CalendarWidget.js | 10 +-- .../testBasicComponentSettings/settings.js | 2 +- test/unit/DateTime.unit.js | 2 +- yarn.lock | 2 +- 7 files changed, 45 insertions(+), 62 deletions(-) diff --git a/package.json b/package.json index 23a1635849..97bb990ca0 100644 --- a/package.json +++ b/package.json @@ -92,6 +92,7 @@ "browser-md5-file": "^1.1.1", "compare-versions": "^6.1.1", "core-js": "^3.37.1", + "dayjs": "^1.11.13", "dialog-polyfill": "^0.5.6", "dom-autoscroller": "^2.3.4", "dompurify": "^3.1.6", diff --git a/src/utils/moment-wrapper.js b/src/utils/moment-wrapper.js index 65eeb2c979..9b6286a98d 100644 --- a/src/utils/moment-wrapper.js +++ b/src/utils/moment-wrapper.js @@ -4,15 +4,21 @@ import timezone from "dayjs/plugin/timezone" import customParseFormat from 'dayjs/plugin/customParseFormat'; import advancedFormat from 'dayjs/plugin/advancedFormat'; import duration from 'dayjs/plugin/duration'; +import isBetween from 'dayjs/plugin/isBetween'; dayjs.extend(utc); dayjs.extend(timezone); dayjs.extend(customParseFormat); dayjs.extend(advancedFormat); +dayjs.extend(isBetween); dayjs.extend(duration); +/** + * + * @param {...any} args + */ function moment(...args) { - return dayjs(...args); + return dayjs(...args).isValid() ? dayjs(...args) : dayjs('Invalid date'); } moment.utc = () => dayjs.utc(); diff --git a/src/utils/utils.js b/src/utils/utils.js index 907d21b581..5600eca052 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -2,8 +2,10 @@ import _ from 'lodash'; import jsonLogic from 'json-logic-js'; -import moment from 'moment-timezone/moment-timezone'; -import jtz from 'jstimezonedetect'; +import moment from './moment-wrapper'; +import dayjs from 'dayjs'; +import utc from 'dayjs/plugin/utc'; +import timezone from 'dayjs/plugin/timezone'; import { lodashOperators } from './jsonlogic/operators'; import dompurify from 'dompurify'; import { getValue } from './formUtils'; @@ -13,22 +15,25 @@ const interpolate = Evaluator.interpolate; export * from './formUtils'; +dayjs.extend(utc); +dayjs.extend(timezone); + // Configure JsonLogic lodashOperators.forEach((name) => jsonLogic.add_operation(`_${name}`, _[name])); // Retrieve Any Date jsonLogic.add_operation('getDate', (date) => { - return moment(date).toISOString(); + return dayjs(date).toISOString(); }); // Set Relative Minimum Date jsonLogic.add_operation('relativeMinDate', (relativeMinDate) => { - return moment().subtract(relativeMinDate, 'days').toISOString(); + return dayjs().subtract(relativeMinDate, 'days').toISOString(); }); // Set Relative Maximum Date jsonLogic.add_operation('relativeMaxDate', (relativeMaxDate) => { - return moment().add(relativeMaxDate, 'days').toISOString(); + return dayjs().add(relativeMaxDate, 'days').toISOString(); }); export { jsonLogic, ConditionOperators, moment }; @@ -592,22 +597,22 @@ export function getDateSetting(date) { return date.isValid() ? date.toDate() : null; } - let dateSetting = ((typeof date !== 'string') || (date.indexOf('moment(') === -1)) ? moment(date) : null; + let dateSetting = ((typeof date !== 'string') || (date.indexOf('moment(') === -1)) ? dayjs(date) : null; if (dateSetting && dateSetting.isValid()) { return dateSetting.toDate(); } dateSetting = null; try { - const value = Evaluator.evaluator(`return ${date};`, 'moment')(moment); + const value = Evaluator.evaluator(`return ${date};`, 'moment')(dayjs); if (typeof value === 'string') { - dateSetting = moment(value); + dateSetting = dayjs(value); } else if (typeof value.toDate === 'function') { - dateSetting = moment(value.toDate().toUTCString()); + dateSetting = dayjs(value.toDate().toUTCString()); } else if (value instanceof Date) { - dateSetting = moment(value); + dateSetting = dayjs(value); } } catch (e) { @@ -640,11 +645,7 @@ export function isValidDate(date) { * @returns {string} - The current timezone. */ export function currentTimezone() { - if (moment.currentTimezone) { - return moment.currentTimezone; - } - moment.currentTimezone = jtz.determine().name(); - return moment.currentTimezone; + return dayjs.tz.guess(); } /** @@ -660,7 +661,7 @@ export function offsetDate(date, timezone) { abbr: 'UTC' }; } - const dateMoment = moment(date).tz(timezone); + const dateMoment = dayjs(date).tz(timezone); return { date: new Date(date.getTime() + ((dateMoment.utcOffset() + date.getTimezoneOffset()) * 60000)), abbr: dateMoment.format('z') @@ -672,7 +673,7 @@ export function offsetDate(date, timezone) { * @returns {boolean} - TRUE if the zones are loaded; FALSE otherwise. */ export function zonesLoaded() { - return moment.zonesLoaded; + return typeof dayjs.tz === 'function'; } /** @@ -724,14 +725,11 @@ export function loadZones(url, timezone) { * @returns {Date} - The moment date object. */ export function momentDate(value, format, timezone) { - const momentDate = moment(value); - if (!timezone) { - return momentDate; - } + const momentDate = dayjs(value); if (timezone === 'UTC') { - timezone = 'Etc/UTC'; + return dayjs.utc(); } - if ((timezone !== currentTimezone() || (format && format.match(/\s(z$|z\s)/))) && moment.zonesLoaded) { + if (timezone !== currentTimezone() || (format && format.match(/\s(z$|z\s)/))) { return momentDate.tz(timezone); } return momentDate; @@ -739,55 +737,33 @@ export function momentDate(value, format, timezone) { /** * Format a date provided a value, format, and timezone object. - * @param {string} timezonesUrl - The URL to load the timezone data from. * @param {string|Date} value - The value to format. * @param {string} format - The format to format the date to. * @param {string} timezone - The timezone to format the date to. * @param {string} flatPickrInputFormat - The format to use for flatpickr input. * @returns {string} - The formatted date. */ -export function formatDate(timezonesUrl, value, format, timezone, flatPickrInputFormat) { - const momentDate = moment(value, flatPickrInputFormat || undefined); - if (timezone === currentTimezone()) { - // See if our format contains a "z" timezone character. - if (format.match(/\s(z$|z\s)/)) { - loadZones(timezonesUrl); - if (moment.zonesLoaded) { - return momentDate.tz(timezone).format(convertFormatToMoment(format)); - } - else { - return momentDate.format(convertFormatToMoment(format.replace(/\s(z$|z\s)/, ''))); - } - } - - // Return the standard format. - return momentDate.format(convertFormatToMoment(format)); - } +export function formatDate(value, format, timezone, flatPickrInputFormat) { + const date = dayjs(value, flatPickrInputFormat); + const dayjsFormat = convertFormatToMoment(format); if (timezone === 'UTC') { - const offset = offsetDate(momentDate.toDate(), 'UTC'); - return `${moment(offset.date).format(convertFormatToMoment(format))} UTC`; + return `${date.utc().format(dayjsFormat)} UTC`; } - - // Load the zones since we need timezone information. - loadZones(timezonesUrl); - if (moment.zonesLoaded && timezone) { - return momentDate.tz(timezone).format(`${convertFormatToMoment(format)} z`); - } - else { - return momentDate.format(convertFormatToMoment(format)); + if (timezone) { + return date.tz(timezone).format(`${dayjsFormat} z`); } + return date.format(dayjsFormat); } /** * Pass a format function to format within a timezone. - * @param {string} timezonesUrl - The URL to load the timezone data from. * @param {Function} formatFn - The format function to use. * @param {Date|string} date - The date to format. * @param {string} format - The format to format the date to. * @param {string} timezone - The timezone to format the date to. * @returns {string} - The formatted date. */ -export function formatOffset(timezonesUrl, formatFn, date, format, timezone) { +export function formatOffset(formatFn, date, format, timezone) { if (timezone === currentTimezone()) { return formatFn(date, format); } diff --git a/src/widgets/CalendarWidget.js b/src/widgets/CalendarWidget.js index 522269bf75..b4dfe68e2b 100644 --- a/src/widgets/CalendarWidget.js +++ b/src/widgets/CalendarWidget.js @@ -14,7 +14,7 @@ import { shouldLoadZones, loadZones, } from '../utils/utils'; -import moment from 'moment'; +import moment from '../utils/moment-wrapper'; import _ from 'lodash'; const DEFAULT_FORMAT = 'yyyy-MM-dd hh:mm a'; @@ -346,7 +346,7 @@ export default class CalendarWidget extends InputWidget { setValue(value) { const saveAsText = (this.settings.saveAs === 'text'); if (!this.calendar) { - value = value ? formatDate(this.timezonesUrl, value, convertFormatToMoment(this.settings.format), this.timezone, convertFormatToMoment(this.valueMomentFormat)) : value; + value = value ? formatDate(value, convertFormatToMoment(this.settings.format), this.timezone, convertFormatToMoment(this.valueMomentFormat)) : value; return super.setValue(value); } @@ -373,7 +373,7 @@ export default class CalendarWidget extends InputWidget { if (this.settings.saveAs === 'text' && this.componentInstance.parent && !this.settings.readOnly) { return moment(value, convertFormatToMoment(valueFormat)).format(convertFormatToMoment(valueFormat)); } - return formatDate(this.timezonesUrl, value, inputFormat, this.timezone, convertFormatToMoment(valueFormat)); + return formatDate(value, inputFormat, this.timezone, convertFormatToMoment(valueFormat)); } setErrorClasses(hasErrors) { @@ -552,9 +552,9 @@ export default class CalendarWidget extends InputWidget { const currentValue = new Date(this.getValue()); if (currentValue.toString() === date.toString()) { - return formatOffset(this.timezonesUrl, Flatpickr.formatDate.bind(Flatpickr), new Date(this.componentValue), format, this.timezone); + return formatOffset(Flatpickr.formatDate.bind(Flatpickr), new Date(this.componentValue), format, this.timezone); } - return formatOffset(this.timezonesUrl, Flatpickr.formatDate.bind(Flatpickr), date, format, this.timezone); + return formatOffset(Flatpickr.formatDate.bind(Flatpickr), date, format, this.timezone); } return Flatpickr.formatDate(date, format); diff --git a/test/forms/helpers/testBasicComponentSettings/settings.js b/test/forms/helpers/testBasicComponentSettings/settings.js index 11e4216283..f24cbdb74b 100644 --- a/test/forms/helpers/testBasicComponentSettings/settings.js +++ b/test/forms/helpers/testBasicComponentSettings/settings.js @@ -1,5 +1,5 @@ import _ from 'lodash'; -import moment from 'moment'; +import moment from '../../../../src/utils/moment-wrapper'; import basicValues from './basicValues'; export default { diff --git a/test/unit/DateTime.unit.js b/test/unit/DateTime.unit.js index 3f9738b67f..67ed0c92cb 100644 --- a/test/unit/DateTime.unit.js +++ b/test/unit/DateTime.unit.js @@ -4,7 +4,7 @@ import DateTimeComponent from '../../src/components/datetime/DateTime'; import { Formio } from '../../src/Formio'; import _ from 'lodash'; import 'flatpickr'; -import moment from 'moment'; +import moment from '../../src/utils/moment-wrapper'; import { comp1, comp2, diff --git a/yarn.lock b/yarn.lock index 8521752790..7cf52e22e8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2239,7 +2239,7 @@ date-format@^4.0.14: resolved "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz#7a8e584434fb169a521c8b7aa481f355810d9400" integrity sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg== -dayjs@^1.11.12: +dayjs@^1.11.12, dayjs@^1.11.13: version "1.11.13" resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== From 2ad0443889deefdf52a10aa6f89ab15458980215 Mon Sep 17 00:00:00 2001 From: Katrin Khilko Date: Mon, 24 Feb 2025 14:14:21 +0300 Subject: [PATCH 3/4] FIO-8541: updated core version --- package.json | 2 +- yarn.lock | 56 +++++++++++++++++++--------------------------------- 2 files changed, 21 insertions(+), 37 deletions(-) diff --git a/package.json b/package.json index e1623fe28f..febb60f540 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "dependencies": { "@formio/bootstrap": "v3.0.0-dev.121.085d187", "@formio/choices.js": "^10.2.1", - "@formio/core": "2.4.0-dev.201.69b9c54", + "@formio/core": "v2.4.0-dev.201.69b9c54", "@formio/text-mask-addons": "3.8.0-formio.4", "@formio/vanilla-text-mask": "^5.1.1-formio.1", "abortcontroller-polyfill": "^1.7.5", diff --git a/yarn.lock b/yarn.lock index e66197ce81..c2f33b5d33 100644 --- a/yarn.lock +++ b/yarn.lock @@ -223,15 +223,15 @@ fuse.js "^6.6.2" redux "^4.2.0" -"@formio/core@v2.4.0-dev.2": - version "2.4.0-dev.2" - resolved "https://registry.yarnpkg.com/@formio/core/-/core-2.4.0-dev.2.tgz#30ebab054e602c5ce7f487d853d195887e0f62b9" - integrity sha512-rodSO272z/bUqOulrCx1mkpCsuW7AHjcxV9tX5Ob7F97JV/6lxtsvxrmhPWFS63yXnecreZO5v67xrcHxBWVMg== +"@formio/core@v2.4.0-dev.201.69b9c54": + version "2.4.0-dev.201.69b9c54" + resolved "https://registry.yarnpkg.com/@formio/core/-/core-2.4.0-dev.201.69b9c54.tgz#b66016460ae575a1a6897110f6f24916755bd440" + integrity sha512-YA2u5xN83ER8aqCkN80UBT5Aw317kuFUlT2knF+ikOdzcqEPgbUE9J6yeMKERWQS+lUfw4sskbwS2vsOeJvyRA== dependencies: browser-cookies "^1.2.0" - core-js "^3.39.0" + core-js "^3.40.0" dayjs "^1.11.12" - dompurify "^3.2.3" + dompurify "^3.2.4" eventemitter3 "^5.0.0" fast-json-patch "^3.1.1" fetch-ponyfill "^7.1.0" @@ -2031,11 +2031,16 @@ core-js@^2.0.0: resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== -core-js@^3.0.0, core-js@^3.30.2, core-js@^3.37.1, core-js@^3.39.0: +core-js@^3.0.0, core-js@^3.30.2, core-js@^3.37.1: version "3.39.0" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.39.0.tgz#57f7647f4d2d030c32a72ea23a0555b2eaa30f83" integrity sha512-raM0ew0/jJUqkJ0E6e8UDtl+y/7ktFivgWvqw8dNSQeNWoSDLvQ1H/RN3aPXB9tBd4/FhyR4RDPGhsNIMsAn7g== +core-js@^3.40.0: + version "3.40.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.40.0.tgz#2773f6b06877d8eda102fc42f828176437062476" + integrity sha512-7vsMc/Lty6AGnn7uFpYT56QesI5D2Y/UkgKounk87OP9Z2H9Z8kj6jzcSGAxFmUtDOS0ntK6lbQz+Nsa0Jj6mQ== + core-util-is@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -2433,13 +2438,20 @@ domexception@^4.0.0: dependencies: webidl-conversions "^7.0.0" -dompurify@^3.1.6, dompurify@^3.2.3: +dompurify@^3.1.6: version "3.2.3" resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.2.3.tgz#05dd2175225324daabfca6603055a09b2382a4cd" integrity sha512-U1U5Hzc2MO0oW3DF+G9qYN0aT7atAou4AgI0XjWz061nyBPbdxkfdhfy5uMgGn6+oLFCfn44ZGbdDqCzVmlOWA== optionalDependencies: "@types/trusted-types" "^2.0.7" +dompurify@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.2.4.tgz#af5a5a11407524431456cf18836c55d13441cd8e" + integrity sha512-ysFSFEDVduQpyhzAob/kkuJjf5zWkZD8/A9ywSp1byueyuCfHamrCBa14/Oc2iiB0e51B+NpxSl5gmzn+Ms/mg== + optionalDependencies: + "@types/trusted-types" "^2.0.7" + downloadjs@^1.4.7: version "1.4.7" resolved "https://registry.yarnpkg.com/downloadjs/-/downloadjs-1.4.7.tgz#f69f96f940e0d0553dac291139865a3cd0101e3c" @@ -5556,7 +5568,6 @@ mock-local-storage@^1.1.24: core-js "^3.30.2" global "^4.3.2" - mrmime@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-2.0.0.tgz#151082a6e06e59a9a39b46b3e14d5cfe92b3abb4" @@ -7448,15 +7459,6 @@ string-width@^1.0.1, string-width@^1.0.2: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -string-width@^4.1.0, string-width@^4.2.0: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -7542,13 +7544,6 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -8671,17 +8666,6 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" - -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From c04e7d2fa05a653bc78b92a95773fba8c8929b0e Mon Sep 17 00:00:00 2001 From: Katrin Khilko Date: Mon, 24 Feb 2025 14:42:29 +0300 Subject: [PATCH 4/4] FIO-8541: removed unused variable --- src/utils/utils.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/utils/utils.js b/src/utils/utils.js index e2a430e677..a9550ae86c 100644 --- a/src/utils/utils.js +++ b/src/utils/utils.js @@ -714,6 +714,12 @@ export function loadZones(url, timezone) { * @returns {Date} - The moment date object. */ +/** + * + * @param value + * @param format + * @param timezone + */ export function momentDate(value, format, timezone) { const momentDate = dayjs(value); if (timezone === 'UTC') { @@ -761,15 +767,8 @@ export function formatOffset(formatFn, date, format, timezone) { return `${formatFn(offsetDate(date, 'UTC').date, format)} UTC`; } - // Load the zones since we need timezone information. - loadZones(timezonesUrl); - if (moment.zonesLoaded) { - const offset = offsetDate(date, timezone); - return `${formatFn(offset.date, format)} ${offset.abbr}`; - } - else { - return formatFn(date, format); - } + const offset = offsetDate(date, timezone); + return `${formatFn(offset.date, format)} ${offset.abbr}`; } /**