@formio/js 5.1.0-dev.6086.0b0957a → 5.1.0-dev.6094.90c04d1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Changelog.md +57 -402
- package/dist/formio.form.js +7 -7
- package/dist/formio.form.min.js +1 -1
- package/dist/formio.form.min.js.LICENSE.txt +1 -1
- package/dist/formio.full.js +7 -7
- package/dist/formio.full.min.js +1 -1
- package/dist/formio.full.min.js.LICENSE.txt +1 -1
- package/dist/formio.utils.js +2 -2
- package/dist/formio.utils.min.js +1 -1
- package/dist/formio.utils.min.js.LICENSE.txt +1 -1
- package/lib/cjs/Webform.js +5 -3
- package/lib/cjs/components/datetime/DateTime.d.ts +1 -1
- package/lib/cjs/components/datetime/DateTime.js +14 -12
- package/lib/cjs/components/selectboxes/SelectBoxes.js +3 -0
- package/lib/cjs/components/textfield/TextField.js +2 -2
- package/lib/cjs/utils/utils.d.ts +27 -28
- package/lib/cjs/utils/utils.js +64 -89
- package/lib/cjs/widgets/CalendarWidget.d.ts +0 -7
- package/lib/cjs/widgets/CalendarWidget.js +17 -36
- package/lib/mjs/Webform.js +5 -3
- package/lib/mjs/components/datetime/DateTime.d.ts +1 -1
- package/lib/mjs/components/datetime/DateTime.js +14 -12
- package/lib/mjs/components/selectboxes/SelectBoxes.js +3 -0
- package/lib/mjs/components/textfield/TextField.js +2 -2
- package/lib/mjs/utils/utils.d.ts +27 -28
- package/lib/mjs/utils/utils.js +58 -82
- package/lib/mjs/widgets/CalendarWidget.d.ts +0 -7
- package/lib/mjs/widgets/CalendarWidget.js +18 -37
- package/package.json +3 -2
@@ -51,29 +51,6 @@ class CalendarWidget extends InputWidget_1.default {
|
|
51
51
|
else if (this.settings.time_24hr) {
|
52
52
|
this.settings.format = this.settings.format.replace(/hh:mm a$/g, 'HH:mm');
|
53
53
|
}
|
54
|
-
this.zoneLoading = false;
|
55
|
-
this.timezonesUrl = `${Formio_1.Formio.cdn['moment-timezone']}/data/packed/latest.json`;
|
56
|
-
}
|
57
|
-
/**
|
58
|
-
* Load the timezones.
|
59
|
-
* @returns {boolean} TRUE if the zones are loading, FALSE otherwise.
|
60
|
-
*/
|
61
|
-
loadZones() {
|
62
|
-
const timezone = this.timezone;
|
63
|
-
if (this.zoneLoading) {
|
64
|
-
return true;
|
65
|
-
}
|
66
|
-
if (!(0, utils_1.zonesLoaded)() && (0, utils_1.shouldLoadZones)(timezone)) {
|
67
|
-
this.zoneLoading = true;
|
68
|
-
(0, utils_1.loadZones)(this.timezonesUrl, timezone).then(() => {
|
69
|
-
this.zoneLoading = false;
|
70
|
-
this.emit('redraw');
|
71
|
-
});
|
72
|
-
// Return zones are loading.
|
73
|
-
return true;
|
74
|
-
}
|
75
|
-
// Zones are already loaded.
|
76
|
-
return false;
|
77
54
|
}
|
78
55
|
attach(input) {
|
79
56
|
var _a;
|
@@ -85,7 +62,7 @@ class CalendarWidget extends InputWidget_1.default {
|
|
85
62
|
};
|
86
63
|
this.closedOn = 0;
|
87
64
|
this.valueFormat = (this.settings.saveAs === 'date') ? ISO_8601_FORMAT : this.settings.dateFormat || ISO_8601_FORMAT;
|
88
|
-
this.valueMomentFormat = (0, utils_1.
|
65
|
+
this.valueMomentFormat = (0, utils_1.convertFormatToDayjs)(this.valueFormat);
|
89
66
|
const isReadOnly = this.settings.readOnly;
|
90
67
|
this.settings.minDate = isReadOnly ? null : (0, utils_1.getDateSetting)(this.settings.minDate);
|
91
68
|
this.settings.maxDate = isReadOnly ? null : (0, utils_1.getDateSetting)(this.settings.maxDate);
|
@@ -249,9 +226,9 @@ class CalendarWidget extends InputWidget_1.default {
|
|
249
226
|
*/
|
250
227
|
getDateValue(date, format, useTimezone) {
|
251
228
|
if (useTimezone) {
|
252
|
-
return (0, utils_1.
|
229
|
+
return (0, utils_1.dayjsDate)(date, this.valueFormat, this.timezone).format((0, utils_1.convertFormatToDayjs)(format));
|
253
230
|
}
|
254
|
-
return (0, moment_1.default)(date).format((0, utils_1.
|
231
|
+
return (0, moment_1.default)(date).format((0, utils_1.convertFormatToDayjs)(format));
|
255
232
|
}
|
256
233
|
/**
|
257
234
|
* Return the value of the selected date.
|
@@ -283,13 +260,17 @@ class CalendarWidget extends InputWidget_1.default {
|
|
283
260
|
setValue(value) {
|
284
261
|
const saveAsText = (this.settings.saveAs === 'text');
|
285
262
|
if (!this.calendar) {
|
286
|
-
value = value ? (0, utils_1.formatDate)(
|
263
|
+
value = value ? (0, utils_1.formatDate)(value, (0, utils_1.convertFormatToDayjs)(this.settings.format), this.timezone, (0, utils_1.convertFormatToDayjs)(this.valueMomentFormat)) : value;
|
287
264
|
return super.setValue(value);
|
288
265
|
}
|
289
|
-
|
266
|
+
// If the component is a textfield that does not have timezone information included in the string value then skip
|
267
|
+
// the timezone offset
|
268
|
+
if (this.component.type === 'textfield' && !(0, utils_1.hasEncodedTimezone)(value)) {
|
269
|
+
this.settings.skipOffset = true;
|
270
|
+
}
|
290
271
|
if (value) {
|
291
|
-
if (!saveAsText && this.settings.readOnly
|
292
|
-
this.calendar.setDate((0, utils_1.
|
272
|
+
if (!saveAsText && this.settings.readOnly) {
|
273
|
+
this.calendar.setDate((0, utils_1.dayjsDate)(value, this.valueFormat, this.timezone).format(), false);
|
293
274
|
}
|
294
275
|
else if (this.isValueISO8601(value)) {
|
295
276
|
this.calendar.setDate(value, false);
|
@@ -306,9 +287,9 @@ class CalendarWidget extends InputWidget_1.default {
|
|
306
287
|
const inputFormat = format || this.dateFormat;
|
307
288
|
const valueFormat = this.calendar ? this.valueFormat : this.settings.dateFormat;
|
308
289
|
if (this.settings.saveAs === 'text' && this.componentInstance.parent && !this.settings.readOnly) {
|
309
|
-
return (0, moment_1.default)(value, (0, utils_1.
|
290
|
+
return (0, moment_1.default)(value, (0, utils_1.convertFormatToDayjs)(valueFormat)).format((0, utils_1.convertFormatToDayjs)(valueFormat));
|
310
291
|
}
|
311
|
-
return (0, utils_1.formatDate)(
|
292
|
+
return (0, utils_1.formatDate)(value, inputFormat, this.timezone, (0, utils_1.convertFormatToDayjs)(valueFormat));
|
312
293
|
}
|
313
294
|
setErrorClasses(hasErrors) {
|
314
295
|
if (!this.input) {
|
@@ -401,7 +382,7 @@ class CalendarWidget extends InputWidget_1.default {
|
|
401
382
|
const relatedTarget = event.relatedTarget ? event.relatedTarget : activeElement;
|
402
383
|
if (!(isIEBrowser && !relatedTarget) && !this.isCalendarElement(relatedTarget)) {
|
403
384
|
const inputValue = this.calendar.input.value;
|
404
|
-
const dateValue = inputValue ? (0, moment_1.default)(this.calendar.input.value, (0, utils_1.
|
385
|
+
const dateValue = inputValue ? (0, moment_1.default)(this.calendar.input.value, (0, utils_1.convertFormatToDayjs)(this.valueFormat)).toDate() : inputValue;
|
405
386
|
this.calendar.setDate(dateValue, true, this.settings.altFormat);
|
406
387
|
}
|
407
388
|
else if (!this.calendar.input.value && this.calendar.config.noCalendar) {
|
@@ -453,14 +434,14 @@ class CalendarWidget extends InputWidget_1.default {
|
|
453
434
|
return (date, format) => {
|
454
435
|
// Only format this if this is the altFormat and the form is readOnly.
|
455
436
|
if (this.settings.readOnly && (format === this.settings.altFormat)) {
|
456
|
-
if (!this.settings.enableTime || this.
|
437
|
+
if (!this.settings.enableTime || this.settings.skipOffset) {
|
457
438
|
return Flatpickr.formatDate(date, format);
|
458
439
|
}
|
459
440
|
const currentValue = new Date(this.getValue());
|
460
441
|
if (currentValue.toString() === date.toString()) {
|
461
|
-
return (0, utils_1.formatOffset)(
|
442
|
+
return (0, utils_1.formatOffset)(Flatpickr.formatDate.bind(Flatpickr), new Date(this.componentValue), format, this.timezone);
|
462
443
|
}
|
463
|
-
return (0, utils_1.formatOffset)(
|
444
|
+
return (0, utils_1.formatOffset)(Flatpickr.formatDate.bind(Flatpickr), date, format, this.timezone);
|
464
445
|
}
|
465
446
|
return Flatpickr.formatDate(date, format);
|
466
447
|
};
|
package/lib/mjs/Webform.js
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
import _ from 'lodash';
|
2
|
-
import moment from 'moment';
|
3
2
|
import { compareVersions } from 'compare-versions';
|
4
3
|
import EventEmitter from './EventEmitter';
|
5
4
|
import i18nDefaults from './i18n';
|
@@ -8,6 +7,7 @@ import Components from './components/Components';
|
|
8
7
|
import NestedDataComponent from './components/_classes/nesteddata/NestedDataComponent';
|
9
8
|
import { fastCloneDeep, currentTimezone, unescapeHTML, getStringFromComponentPath, convertStringToHTMLElement, getArrayFromComponentPath, } from './utils/utils';
|
10
9
|
import { eachComponent } from './utils/formUtils';
|
10
|
+
import dayjs from "dayjs";
|
11
11
|
// We need this here because dragula pulls in CustomEvent class that requires global to exist.
|
12
12
|
if (typeof window !== 'undefined' && typeof window.global === 'undefined') {
|
13
13
|
window.global = window;
|
@@ -659,7 +659,9 @@ export default class Webform extends NestedDataComponent {
|
|
659
659
|
const rebuild = this.rebuild() || Promise.resolve();
|
660
660
|
return rebuild.then(() => {
|
661
661
|
this.emit('formLoad', form);
|
662
|
-
this.
|
662
|
+
if (!this.options.server) {
|
663
|
+
this.triggerCaptcha();
|
664
|
+
}
|
663
665
|
// Make sure to trigger onChange after a render event occurs to speed up form rendering.
|
664
666
|
setTimeout(() => {
|
665
667
|
this.onChange(flags);
|
@@ -1315,7 +1317,7 @@ export default class Webform extends NestedDataComponent {
|
|
1315
1317
|
submission.metadata = submission.metadata || {};
|
1316
1318
|
_.defaults(submission.metadata, {
|
1317
1319
|
timezone: _.get(this, '_submission.metadata.timezone', currentTimezone()),
|
1318
|
-
offset: parseInt(_.get(this, '_submission.metadata.offset',
|
1320
|
+
offset: parseInt(_.get(this, '_submission.metadata.offset', dayjs().utcOffset()), 10),
|
1319
1321
|
origin: document.location.origin,
|
1320
1322
|
referrer: document.referrer,
|
1321
1323
|
browserName: navigator.appName,
|
@@ -17,7 +17,7 @@ export default class DateTimeComponent extends Input {
|
|
17
17
|
};
|
18
18
|
static savedValueTypes(schema: any): string[];
|
19
19
|
get emptyValue(): string;
|
20
|
-
get
|
20
|
+
get dayjsFormat(): string;
|
21
21
|
createWrapper(): boolean;
|
22
22
|
checkValidity(data: any, dirty: any, rowData: any): boolean;
|
23
23
|
getValueAsString(value: any, options: any): any;
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import _ from 'lodash';
|
2
|
-
import
|
2
|
+
import dayjs from 'dayjs';
|
3
3
|
import FormioUtils from '../../utils';
|
4
4
|
import { componentValueTypes, fastCloneDeep, getComponentSavedTypes } from '../../utils/utils';
|
5
5
|
import Input from '../_classes/input/Input';
|
@@ -147,8 +147,8 @@ export default class DateTimeComponent extends Input {
|
|
147
147
|
get emptyValue() {
|
148
148
|
return '';
|
149
149
|
}
|
150
|
-
get
|
151
|
-
return FormioUtils.
|
150
|
+
get dayjsFormat() {
|
151
|
+
return FormioUtils.convertFormatToDayjs(this.component.format);
|
152
152
|
}
|
153
153
|
isEmpty(value = this.dataValue) {
|
154
154
|
if (value && (value.toString() === 'Invalid Date')) {
|
@@ -157,12 +157,14 @@ export default class DateTimeComponent extends Input {
|
|
157
157
|
return super.isEmpty(value);
|
158
158
|
}
|
159
159
|
formatValue(input) {
|
160
|
-
|
161
|
-
|
160
|
+
if (dayjs(input).isValid()) {
|
161
|
+
return dayjs.utc(input).toISOString();
|
162
|
+
}
|
163
|
+
return input;
|
162
164
|
}
|
163
165
|
isEqual(valueA, valueB = this.dataValue) {
|
164
166
|
return (this.isEmpty(valueA) && this.isEmpty(valueB))
|
165
|
-
||
|
167
|
+
|| dayjs.utc(valueA).format(this.dayjsFormat) === dayjs.utc(valueB).format(this.dayjsFormat);
|
166
168
|
}
|
167
169
|
createWrapper() {
|
168
170
|
return false;
|
@@ -178,18 +180,18 @@ export default class DateTimeComponent extends Input {
|
|
178
180
|
return super.checkValidity(data, dirty, rowData);
|
179
181
|
}
|
180
182
|
getValueAsString(value, options) {
|
181
|
-
let format = FormioUtils.
|
182
|
-
format += format.match(/z$/) ? '' : ' z';
|
183
|
+
let format = FormioUtils.convertFormatToDayjs(this.component.format);
|
183
184
|
const timezone = this.timezone;
|
184
185
|
if (value && !this.attached && timezone) {
|
186
|
+
format += format.match(/z$/) ? '' : ' z';
|
185
187
|
if (Array.isArray(value) && this.component.multiple) {
|
186
|
-
return value.map(item => _.trim(FormioUtils.
|
188
|
+
return value.map(item => _.trim(FormioUtils.dayjsDate(item, format, timezone, options).format(format))).join(', ');
|
187
189
|
}
|
188
|
-
return _.trim(FormioUtils.
|
190
|
+
return _.trim(FormioUtils.dayjsDate(value, format, timezone, options).format(format));
|
189
191
|
}
|
190
192
|
if (Array.isArray(value) && this.component.multiple) {
|
191
|
-
return value.map(item => _.trim(
|
193
|
+
return value.map(item => _.trim(dayjs(item).format(format))).join(', ');
|
192
194
|
}
|
193
|
-
return (value ? _.trim(
|
195
|
+
return (value ? _.trim(dayjs(value).format(format)) : value) || '';
|
194
196
|
}
|
195
197
|
}
|
@@ -86,8 +86,8 @@ export default class TextFieldComponent extends Input {
|
|
86
86
|
locale: this.component.widget.locale || this.options.language,
|
87
87
|
saveAs: 'text'
|
88
88
|
};
|
89
|
-
// update originalComponent to include widget settings after component initialization
|
90
|
-
// originalComponent is used to restore the component (and widget) after evaluating field logic
|
89
|
+
// update originalComponent to include widget settings after component initialization
|
90
|
+
// originalComponent is used to restore the component (and widget) after evaluating field logic
|
91
91
|
this.originalComponent = FormioUtils.fastCloneDeep(this.component);
|
92
92
|
}
|
93
93
|
}
|
package/lib/mjs/utils/utils.d.ts
CHANGED
@@ -164,9 +164,9 @@ export function guid(): string;
|
|
164
164
|
/**
|
165
165
|
* Return a translated date setting.
|
166
166
|
* @param {string|Date} date - The date to translate.
|
167
|
-
* @returns {(null|
|
167
|
+
* @returns {(null|dayjs.Dayjs)} - The translated date.
|
168
168
|
*/
|
169
|
-
export function getDateSetting(date: string | Date): (null |
|
169
|
+
export function getDateSetting(date: string | Date): (null | dayjs.Dayjs);
|
170
170
|
/**
|
171
171
|
* Returns true if the date is a valid date. False otherwise.
|
172
172
|
* @param {Date|string} date - The date to check for validity.
|
@@ -182,56 +182,45 @@ export function currentTimezone(): string;
|
|
182
182
|
* Get an offset date provided a date object and timezone object.
|
183
183
|
* @param {Date} date - The date to offset.
|
184
184
|
* @param {string} timezone - The timezone to offset the date to.
|
185
|
-
* @returns {Date} - The offset date.
|
185
|
+
* @returns {{date: Date, abbr: string}} - The offset date.
|
186
186
|
*/
|
187
|
-
export function offsetDate(date: Date, timezone: string):
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
*/
|
192
|
-
export function zonesLoaded(): boolean;
|
187
|
+
export function offsetDate(date: Date, timezone: string): {
|
188
|
+
date: Date;
|
189
|
+
abbr: string;
|
190
|
+
};
|
193
191
|
/**
|
194
|
-
* Returns if we should
|
192
|
+
* Returns if we should handle a timezone difference.
|
195
193
|
* @param {string} timezone - The timezone to check if we should load the zones.
|
196
|
-
* @returns {boolean} - TRUE if we should
|
194
|
+
* @returns {boolean} - TRUE if we should handle timezones; FALSE otherwise.
|
197
195
|
*/
|
198
|
-
export function
|
196
|
+
export function shouldHandleTimezone(timezone: string): boolean;
|
199
197
|
/**
|
200
|
-
*
|
201
|
-
* @param {string}
|
202
|
-
* @param {string} timezone - The timezone to load.
|
203
|
-
* @returns {Promise<any> | *} - Resolves when the zones for this timezone are loaded.
|
204
|
-
*/
|
205
|
-
export function loadZones(url: string, timezone: string): Promise<any> | any;
|
206
|
-
/**
|
207
|
-
* Get the moment date object for translating dates with timezones.
|
208
|
-
* @param {string|Date} value - The value to convert into a moment date.
|
198
|
+
* Get the Dayjs date object for translating dates with timezones.
|
199
|
+
* @param {string|Date} value - The value to convert into a dayjs date.
|
209
200
|
* @param {string} format - The format to convert the date to.
|
210
201
|
* @param {string} timezone - The timezone to convert the date to.
|
211
202
|
* @param {object} options - The options object
|
212
|
-
* @returns {
|
203
|
+
* @returns {dayjs.Dayjs} - The dayjs date object.
|
213
204
|
*/
|
214
|
-
export function
|
205
|
+
export function dayjsDate(value: string | Date, format: string, timezone: string, options: object): dayjs.Dayjs;
|
215
206
|
/**
|
216
207
|
* Format a date provided a value, format, and timezone object.
|
217
|
-
* @param {string} timezonesUrl - The URL to load the timezone data from.
|
218
208
|
* @param {string|Date} value - The value to format.
|
219
209
|
* @param {string} format - The format to format the date to.
|
220
210
|
* @param {string} timezone - The timezone to format the date to.
|
221
211
|
* @param {string} flatPickrInputFormat - The format to use for flatpickr input.
|
222
212
|
* @returns {string} - The formatted date.
|
223
213
|
*/
|
224
|
-
export function formatDate(
|
214
|
+
export function formatDate(value: string | Date, format: string, timezone: string, flatPickrInputFormat: string): string;
|
225
215
|
/**
|
226
216
|
* Pass a format function to format within a timezone.
|
227
|
-
* @param {string} timezonesUrl - The URL to load the timezone data from.
|
228
217
|
* @param {Function} formatFn - The format function to use.
|
229
218
|
* @param {Date|string} date - The date to format.
|
230
219
|
* @param {string} format - The format to format the date to.
|
231
220
|
* @param {string} timezone - The timezone to format the date to.
|
232
221
|
* @returns {string} - The formatted date.
|
233
222
|
*/
|
234
|
-
export function formatOffset(
|
223
|
+
export function formatOffset(formatFn: Function, date: Date | string, format: string, timezone: string): string;
|
235
224
|
/**
|
236
225
|
* Returns the local date format information.
|
237
226
|
* @param {Intl.LocalesArgument} locale - The locale to get the date format for.
|
@@ -249,7 +238,7 @@ export function convertFormatToFlatpickr(format: string): string;
|
|
249
238
|
* @param {string} format - The format to convert.
|
250
239
|
* @returns {string} - The converted format.
|
251
240
|
*/
|
252
|
-
export function
|
241
|
+
export function convertFormatToDayjs(format: string): string;
|
253
242
|
/**
|
254
243
|
* Convert the format from the angular-datepicker module to mask format.
|
255
244
|
* @param {string} format - The format to convert.
|
@@ -490,6 +479,15 @@ export function getFocusableElements(element: HTMLElement): NodeList<HTMLElement
|
|
490
479
|
* @returns {Array<string>|null} - The saved types for the component
|
491
480
|
*/
|
492
481
|
export function getComponentSavedTypes(fullSchema: import('@formio/core').Component): Array<string> | null;
|
482
|
+
/**
|
483
|
+
* Checks if a string has timezone information encoded in it
|
484
|
+
* Example: 2024-01-01T00:00:00Z -> true
|
485
|
+
* Example: 2024-01-01T00:00:00+03:00 -> true
|
486
|
+
* Example: 2011-05-03T00:00:00 -> false
|
487
|
+
* @param {string} value the string value to check
|
488
|
+
* @returns {boolean} if value has encoded timezone
|
489
|
+
*/
|
490
|
+
export function hasEncodedTimezone(value: string): boolean;
|
493
491
|
export * from "./formUtils";
|
494
492
|
/**
|
495
493
|
* Map values through unfold and return first non-nil value.
|
@@ -507,6 +505,7 @@ export namespace componentValueTypes {
|
|
507
505
|
let any: string;
|
508
506
|
}
|
509
507
|
export function interpolateErrors(component: Component, errors: FieldError[], interpolateFn: Function): [];
|
508
|
+
import dayjs from "dayjs";
|
510
509
|
import ConditionOperators from './conditionOperators';
|
511
510
|
import { Evaluator } from './Evaluator';
|
512
511
|
export const interpolate: typeof Evaluator.interpolate;
|
package/lib/mjs/utils/utils.js
CHANGED
@@ -9,6 +9,13 @@ import { getValue } from './formUtils';
|
|
9
9
|
import { Evaluator } from './Evaluator';
|
10
10
|
import ConditionOperators from './conditionOperators';
|
11
11
|
import { convertShowToBoolean } from '@formio/core';
|
12
|
+
import dayjs from "dayjs";
|
13
|
+
import utc from 'dayjs/plugin/utc';
|
14
|
+
import timezone from 'dayjs/plugin/timezone';
|
15
|
+
import advancedFormat from 'dayjs/plugin/advancedFormat';
|
16
|
+
dayjs.extend(timezone);
|
17
|
+
dayjs.extend(advancedFormat);
|
18
|
+
dayjs.extend(utc);
|
12
19
|
const interpolate = Evaluator.interpolate;
|
13
20
|
export * from './formUtils';
|
14
21
|
// Configure JsonLogic
|
@@ -505,7 +512,7 @@ export function guid() {
|
|
505
512
|
/**
|
506
513
|
* Return a translated date setting.
|
507
514
|
* @param {string|Date} date - The date to translate.
|
508
|
-
* @returns {(null|
|
515
|
+
* @returns {(null|dayjs.Dayjs)} - The translated date.
|
509
516
|
*/
|
510
517
|
export function getDateSetting(date) {
|
511
518
|
if (_.isNil(date) || _.isNaN(date) || date === '') {
|
@@ -525,13 +532,13 @@ export function getDateSetting(date) {
|
|
525
532
|
try {
|
526
533
|
const value = Evaluator.evaluator(`return ${date};`, 'moment')(moment);
|
527
534
|
if (typeof value === 'string') {
|
528
|
-
dateSetting =
|
535
|
+
dateSetting = dayjs(value);
|
529
536
|
}
|
530
537
|
else if (typeof value.toDate === 'function') {
|
531
|
-
dateSetting =
|
538
|
+
dateSetting = dayjs(value.toDate().toUTCString());
|
532
539
|
}
|
533
540
|
else if (value instanceof Date) {
|
534
|
-
dateSetting =
|
541
|
+
dateSetting = dayjs(value);
|
535
542
|
}
|
536
543
|
}
|
537
544
|
catch (e) {
|
@@ -559,17 +566,17 @@ export function isValidDate(date) {
|
|
559
566
|
* @returns {string} - The current timezone.
|
560
567
|
*/
|
561
568
|
export function currentTimezone() {
|
562
|
-
if (
|
563
|
-
return
|
569
|
+
if (dayjs.currentTimezone) {
|
570
|
+
return dayjs.currentTimezone;
|
564
571
|
}
|
565
|
-
|
566
|
-
return
|
572
|
+
dayjs.currentTimezone = jtz.determine().name();
|
573
|
+
return dayjs.currentTimezone;
|
567
574
|
}
|
568
575
|
/**
|
569
576
|
* Get an offset date provided a date object and timezone object.
|
570
577
|
* @param {Date} date - The date to offset.
|
571
578
|
* @param {string} timezone - The timezone to offset the date to.
|
572
|
-
* @returns {Date} - The offset date.
|
579
|
+
* @returns {{date: Date, abbr: string}} - The offset date.
|
573
580
|
*/
|
574
581
|
export function offsetDate(date, timezone) {
|
575
582
|
if (timezone === 'UTC') {
|
@@ -578,134 +585,89 @@ export function offsetDate(date, timezone) {
|
|
578
585
|
abbr: 'UTC'
|
579
586
|
};
|
580
587
|
}
|
581
|
-
const dateMoment =
|
588
|
+
const dateMoment = dayjs(date).tz(timezone);
|
582
589
|
return {
|
583
590
|
date: new Date(date.getTime() + ((dateMoment.utcOffset() + date.getTimezoneOffset()) * 60000)),
|
584
591
|
abbr: dateMoment.format('z')
|
585
592
|
};
|
586
593
|
}
|
587
594
|
/**
|
588
|
-
* Returns if
|
589
|
-
* @returns {boolean} - TRUE if the zones are loaded; FALSE otherwise.
|
590
|
-
*/
|
591
|
-
export function zonesLoaded() {
|
592
|
-
return moment.zonesLoaded;
|
593
|
-
}
|
594
|
-
/**
|
595
|
-
* Returns if we should load the zones.
|
595
|
+
* Returns if we should handle a timezone difference.
|
596
596
|
* @param {string} timezone - The timezone to check if we should load the zones.
|
597
|
-
* @returns {boolean} - TRUE if we should
|
597
|
+
* @returns {boolean} - TRUE if we should handle timezones; FALSE otherwise.
|
598
598
|
*/
|
599
|
-
export function
|
600
|
-
|
601
|
-
return false;
|
602
|
-
}
|
603
|
-
return true;
|
604
|
-
}
|
605
|
-
/**
|
606
|
-
* Externally load the timezone data.
|
607
|
-
* @param {string} url - The URL to load the timezone data from.
|
608
|
-
* @param {string} timezone - The timezone to load.
|
609
|
-
* @returns {Promise<any> | *} - Resolves when the zones for this timezone are loaded.
|
610
|
-
*/
|
611
|
-
export function loadZones(url, timezone) {
|
612
|
-
if (timezone && !shouldLoadZones(timezone)) {
|
613
|
-
// Return non-resolving promise.
|
614
|
-
return new Promise(_.noop);
|
615
|
-
}
|
616
|
-
if (moment.zonesPromise) {
|
617
|
-
return moment.zonesPromise;
|
618
|
-
}
|
619
|
-
return moment.zonesPromise = fetch(url)
|
620
|
-
.then(resp => resp.json().then(zones => {
|
621
|
-
moment.tz.load(zones);
|
622
|
-
moment.zonesLoaded = true;
|
623
|
-
// Trigger a global event that the timezones have finished loading.
|
624
|
-
if (document && document.createEvent && document.body && document.body.dispatchEvent) {
|
625
|
-
var event = document.createEvent('Event');
|
626
|
-
event.initEvent('zonesLoaded', true, true);
|
627
|
-
document.body.dispatchEvent(event);
|
628
|
-
}
|
629
|
-
}));
|
599
|
+
export function shouldHandleTimezone(timezone) {
|
600
|
+
return !(timezone === currentTimezone() || timezone === 'UTC');
|
630
601
|
}
|
631
602
|
/**
|
632
|
-
* Get the
|
633
|
-
* @param {string|Date} value - The value to convert into a
|
603
|
+
* Get the Dayjs date object for translating dates with timezones.
|
604
|
+
* @param {string|Date} value - The value to convert into a dayjs date.
|
634
605
|
* @param {string} format - The format to convert the date to.
|
635
606
|
* @param {string} timezone - The timezone to convert the date to.
|
636
607
|
* @param {object} options - The options object
|
637
|
-
* @returns {
|
608
|
+
* @returns {dayjs.Dayjs} - The dayjs date object.
|
638
609
|
*/
|
639
|
-
export function
|
640
|
-
const
|
610
|
+
export function dayjsDate(value, format, timezone, options) {
|
611
|
+
const dayjsDate = dayjs(value);
|
641
612
|
if (!timezone) {
|
642
|
-
return
|
613
|
+
return dayjsDate;
|
643
614
|
}
|
644
615
|
if (timezone === 'UTC') {
|
645
616
|
timezone = 'Etc/UTC';
|
646
617
|
}
|
647
|
-
if ((timezone !== currentTimezone() || (format && format.match(/\s(z$|z\s)/))) && (
|
648
|
-
return
|
618
|
+
if ((timezone !== currentTimezone() || (format && format.match(/\s(z$|z\s)/))) && (shouldHandleTimezone(timezone) || options?.email)) {
|
619
|
+
return dayjsDate.tz(timezone);
|
649
620
|
}
|
650
|
-
return
|
621
|
+
return dayjsDate;
|
651
622
|
}
|
652
623
|
/**
|
653
624
|
* Format a date provided a value, format, and timezone object.
|
654
|
-
* @param {string} timezonesUrl - The URL to load the timezone data from.
|
655
625
|
* @param {string|Date} value - The value to format.
|
656
626
|
* @param {string} format - The format to format the date to.
|
657
627
|
* @param {string} timezone - The timezone to format the date to.
|
658
628
|
* @param {string} flatPickrInputFormat - The format to use for flatpickr input.
|
659
629
|
* @returns {string} - The formatted date.
|
660
630
|
*/
|
661
|
-
export function formatDate(
|
662
|
-
const
|
631
|
+
export function formatDate(value, format, timezone, flatPickrInputFormat) {
|
632
|
+
const dayjsDate = dayjs(value, flatPickrInputFormat || undefined);
|
663
633
|
if (timezone === currentTimezone()) {
|
664
634
|
// See if our format contains a "z" timezone character.
|
665
635
|
if (format.match(/\s(z$|z\s)/)) {
|
666
|
-
|
667
|
-
|
668
|
-
return momentDate.tz(timezone).format(convertFormatToMoment(format));
|
636
|
+
if (shouldHandleTimezone(timezone)) {
|
637
|
+
return dayjsDate.tz(timezone).format(convertFormatToDayjs(format));
|
669
638
|
}
|
670
639
|
else {
|
671
|
-
return
|
640
|
+
return dayjsDate.format(convertFormatToDayjs(format.replace(/\s(z$|z\s)/, '')));
|
672
641
|
}
|
673
642
|
}
|
674
643
|
// Return the standard format.
|
675
|
-
return
|
644
|
+
return dayjsDate.format(convertFormatToDayjs(format));
|
676
645
|
}
|
677
646
|
if (timezone === 'UTC') {
|
678
|
-
const offset = offsetDate(
|
679
|
-
return `${
|
680
|
-
}
|
681
|
-
// Load the zones since we need timezone information.
|
682
|
-
loadZones(timezonesUrl);
|
683
|
-
if (moment.zonesLoaded && timezone) {
|
684
|
-
return momentDate.tz(timezone).format(`${convertFormatToMoment(format)} z`);
|
647
|
+
const offset = offsetDate(dayjsDate.toDate(), 'UTC');
|
648
|
+
return `${dayjs(offset.date).format(convertFormatToDayjs(format))} UTC`;
|
685
649
|
}
|
686
|
-
|
687
|
-
return
|
650
|
+
if (shouldHandleTimezone(timezone)) {
|
651
|
+
return dayjsDate.tz(timezone).format(`${convertFormatToDayjs(format)} z`);
|
688
652
|
}
|
653
|
+
return dayjsDate.format(convertFormatToDayjs(format));
|
689
654
|
}
|
690
655
|
/**
|
691
656
|
* Pass a format function to format within a timezone.
|
692
|
-
* @param {string} timezonesUrl - The URL to load the timezone data from.
|
693
657
|
* @param {Function} formatFn - The format function to use.
|
694
658
|
* @param {Date|string} date - The date to format.
|
695
659
|
* @param {string} format - The format to format the date to.
|
696
660
|
* @param {string} timezone - The timezone to format the date to.
|
697
661
|
* @returns {string} - The formatted date.
|
698
662
|
*/
|
699
|
-
export function formatOffset(
|
663
|
+
export function formatOffset(formatFn, date, format, timezone) {
|
700
664
|
if (timezone === currentTimezone()) {
|
701
665
|
return formatFn(date, format);
|
702
666
|
}
|
703
667
|
if (timezone === 'UTC') {
|
704
668
|
return `${formatFn(offsetDate(date, 'UTC').date, format)} UTC`;
|
705
669
|
}
|
706
|
-
|
707
|
-
loadZones(timezonesUrl);
|
708
|
-
if (moment.zonesLoaded) {
|
670
|
+
if (shouldHandleTimezone(timezone)) {
|
709
671
|
const offset = offsetDate(date, timezone);
|
710
672
|
return `${formatFn(offset.date, format)} ${offset.abbr}`;
|
711
673
|
}
|
@@ -762,7 +724,7 @@ export function convertFormatToFlatpickr(format) {
|
|
762
724
|
* @param {string} format - The format to convert.
|
763
725
|
* @returns {string} - The converted format.
|
764
726
|
*/
|
765
|
-
export function
|
727
|
+
export function convertFormatToDayjs(format) {
|
766
728
|
return format
|
767
729
|
// Year conversion.
|
768
730
|
.replace(/y/g, 'Y')
|
@@ -1554,3 +1516,17 @@ export const interpolateErrors = (component, errors, interpolateFn) => {
|
|
1554
1516
|
return { ...error, message: unescapeHTML(interpolateFn(toInterpolate, context)), context: { ...context } };
|
1555
1517
|
});
|
1556
1518
|
};
|
1519
|
+
/**
|
1520
|
+
* Checks if a string has timezone information encoded in it
|
1521
|
+
* Example: 2024-01-01T00:00:00Z -> true
|
1522
|
+
* Example: 2024-01-01T00:00:00+03:00 -> true
|
1523
|
+
* Example: 2011-05-03T00:00:00 -> false
|
1524
|
+
* @param {string} value the string value to check
|
1525
|
+
* @returns {boolean} if value has encoded timezone
|
1526
|
+
*/
|
1527
|
+
export function hasEncodedTimezone(value) {
|
1528
|
+
if (typeof value !== 'string') {
|
1529
|
+
return false;
|
1530
|
+
}
|
1531
|
+
return (value.substring(value.length - 1) === 'z' || value.substring(value.length - 1) === 'Z' || value.match(/[+|-][0-9]{2}:[0-9]{2}$/));
|
1532
|
+
}
|
@@ -22,13 +22,6 @@ export default class CalendarWidget extends InputWidget {
|
|
22
22
|
minDate: string;
|
23
23
|
maxDate: string;
|
24
24
|
};
|
25
|
-
zoneLoading: boolean;
|
26
|
-
timezonesUrl: string;
|
27
|
-
/**
|
28
|
-
* Load the timezones.
|
29
|
-
* @returns {boolean} TRUE if the zones are loading, FALSE otherwise.
|
30
|
-
*/
|
31
|
-
loadZones(): boolean;
|
32
25
|
attach(input: any): Promise<any>;
|
33
26
|
defaultFormat: {
|
34
27
|
date: string;
|