@formio/js 5.3.6 → 5.4.0
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/dist/formio.builder.css +31 -5
- package/dist/formio.builder.min.css +1 -1
- package/dist/formio.embed.css +1 -1
- package/dist/formio.embed.js +1 -1
- package/dist/formio.embed.min.css +1 -1
- package/dist/formio.embed.min.js +1 -1
- package/dist/formio.embed.min.js.LICENSE.txt +1 -1
- package/dist/formio.form.css +31 -5
- package/dist/formio.form.js +2837 -2818
- package/dist/formio.form.min.css +1 -1
- package/dist/formio.form.min.js +1 -1
- package/dist/formio.form.min.js.LICENSE.txt +1 -1
- package/dist/formio.full.css +31 -5
- package/dist/formio.full.js +3442 -3403
- package/dist/formio.full.min.css +1 -1
- package/dist/formio.full.min.js +1 -1
- package/dist/formio.full.min.js.LICENSE.txt +1 -1
- package/dist/formio.js +1152 -1154
- package/dist/formio.min.js +1 -1
- package/dist/formio.min.js.LICENSE.txt +1 -1
- package/dist/formio.utils.js +1084 -1086
- package/dist/formio.utils.min.js +1 -1
- package/dist/formio.utils.min.js.LICENSE.txt +1 -1
- package/lib/cjs/Embed.js +28 -1
- package/lib/cjs/Form.d.ts +4 -2
- package/lib/cjs/Form.js +2 -2
- package/lib/cjs/FormBuilder.d.ts +2 -2
- package/lib/cjs/FormBuilder.js +1 -1
- package/lib/cjs/Formio.js +1 -1
- package/lib/cjs/PDF.js +2 -0
- package/lib/cjs/PDFBuilder.js +6 -1
- package/lib/cjs/Webform.d.ts +1 -0
- package/lib/cjs/Webform.js +50 -1
- package/lib/cjs/WebformBuilder.js +29 -1
- package/lib/cjs/Wizard.d.ts +1 -0
- package/lib/cjs/Wizard.js +11 -0
- package/lib/cjs/components/Components.d.ts +3 -0
- package/lib/cjs/components/_classes/component/Component.d.ts +13 -3
- package/lib/cjs/components/_classes/component/Component.js +167 -47
- package/lib/cjs/components/_classes/component/editForm/Component.edit.conditional.js +1 -1
- package/lib/cjs/components/_classes/component/editForm/Component.edit.data.d.ts +7 -0
- package/lib/cjs/components/_classes/component/editForm/Component.edit.data.js +2 -1
- package/lib/cjs/components/_classes/component/editForm/utils.d.ts +1 -0
- package/lib/cjs/components/_classes/component/editForm/utils.js +3 -0
- package/lib/cjs/components/_classes/nested/NestedComponent.js +5 -0
- package/lib/cjs/components/address/Address.js +18 -0
- package/lib/cjs/components/datagrid/DataGrid.js +12 -2
- package/lib/cjs/components/datamap/DataMap.d.ts +1 -0
- package/lib/cjs/components/datamap/DataMap.js +37 -4
- package/lib/cjs/components/datetime/DateTime.js +11 -1
- package/lib/cjs/components/day/Day.d.ts +0 -15
- package/lib/cjs/components/day/Day.js +8 -17
- package/lib/cjs/components/editgrid/EditGrid.js +11 -1
- package/lib/cjs/components/fieldset/Fieldset.js +1 -0
- package/lib/cjs/components/file/File.d.ts +3 -1
- package/lib/cjs/components/file/File.js +62 -17
- package/lib/cjs/components/form/Form.js +3 -1
- package/lib/cjs/components/number/Number.d.ts +1 -0
- package/lib/cjs/components/number/Number.js +18 -0
- package/lib/cjs/components/select/Select.js +5 -1
- package/lib/cjs/components/signature/Signature.js +5 -5
- package/lib/cjs/components/signature/editForm/Signature.edit.display.d.ts +0 -6
- package/lib/cjs/components/signature/editForm/Signature.edit.display.js +0 -1
- package/lib/cjs/components/table/editForm/Table.edit.display.d.ts +27 -0
- package/lib/cjs/components/table/editForm/Table.edit.display.js +10 -0
- package/lib/cjs/formio.form.js +2 -5
- package/lib/cjs/package.json +1 -1
- package/lib/cjs/providers/storage/azure.js +9 -3
- package/lib/cjs/templates/index.d.ts +3 -0
- package/lib/cjs/translations/en.d.ts +2 -0
- package/lib/cjs/translations/en.js +2 -0
- package/lib/cjs/utils/i18n.d.ts +1 -0
- package/lib/cjs/utils/i18n.js +2 -0
- package/lib/cjs/utils/index.d.ts +1 -1
- package/lib/cjs/utils/utils.d.ts +1 -1
- package/lib/cjs/utils/utils.js +23 -6
- package/lib/cjs/widgets/CalendarWidget.js +1 -1
- package/lib/mjs/Embed.js +26 -1
- package/lib/mjs/Form.d.ts +4 -2
- package/lib/mjs/Form.js +2 -2
- package/lib/mjs/FormBuilder.d.ts +2 -2
- package/lib/mjs/FormBuilder.js +1 -1
- package/lib/mjs/Formio.js +1 -1
- package/lib/mjs/PDF.js +2 -0
- package/lib/mjs/PDFBuilder.js +6 -1
- package/lib/mjs/Webform.d.ts +1 -0
- package/lib/mjs/Webform.js +48 -1
- package/lib/mjs/WebformBuilder.js +28 -1
- package/lib/mjs/Wizard.d.ts +1 -0
- package/lib/mjs/Wizard.js +12 -1
- package/lib/mjs/components/Components.d.ts +3 -0
- package/lib/mjs/components/_classes/component/Component.d.ts +13 -3
- package/lib/mjs/components/_classes/component/Component.js +164 -46
- package/lib/mjs/components/_classes/component/editForm/Component.edit.conditional.js +1 -1
- package/lib/mjs/components/_classes/component/editForm/Component.edit.data.d.ts +7 -0
- package/lib/mjs/components/_classes/component/editForm/Component.edit.data.js +2 -1
- package/lib/mjs/components/_classes/component/editForm/utils.d.ts +1 -0
- package/lib/mjs/components/_classes/component/editForm/utils.js +3 -0
- package/lib/mjs/components/_classes/nested/NestedComponent.js +5 -0
- package/lib/mjs/components/address/Address.js +17 -0
- package/lib/mjs/components/datagrid/DataGrid.js +14 -1
- package/lib/mjs/components/datamap/DataMap.d.ts +1 -0
- package/lib/mjs/components/datamap/DataMap.js +36 -4
- package/lib/mjs/components/datetime/DateTime.js +11 -1
- package/lib/mjs/components/day/Day.d.ts +0 -15
- package/lib/mjs/components/day/Day.js +8 -17
- package/lib/mjs/components/editgrid/EditGrid.js +11 -1
- package/lib/mjs/components/fieldset/Fieldset.js +1 -0
- package/lib/mjs/components/file/File.d.ts +3 -1
- package/lib/mjs/components/file/File.js +60 -15
- package/lib/mjs/components/form/Form.js +3 -1
- package/lib/mjs/components/number/Number.d.ts +1 -0
- package/lib/mjs/components/number/Number.js +17 -0
- package/lib/mjs/components/select/Select.js +5 -1
- package/lib/mjs/components/signature/Signature.js +1 -1
- package/lib/mjs/components/signature/editForm/Signature.edit.display.d.ts +0 -6
- package/lib/mjs/components/signature/editForm/Signature.edit.display.js +0 -1
- package/lib/mjs/components/table/editForm/Table.edit.display.d.ts +27 -0
- package/lib/mjs/components/table/editForm/Table.edit.display.js +10 -0
- package/lib/mjs/formio.form.js +4 -7
- package/lib/mjs/package.json +1 -1
- package/lib/mjs/providers/storage/azure.js +9 -3
- package/lib/mjs/templates/index.d.ts +3 -0
- package/lib/mjs/translations/en.d.ts +2 -0
- package/lib/mjs/translations/en.js +2 -0
- package/lib/mjs/utils/i18n.d.ts +1 -0
- package/lib/mjs/utils/i18n.js +2 -0
- package/lib/mjs/utils/index.d.ts +1 -1
- package/lib/mjs/utils/utils.d.ts +1 -1
- package/lib/mjs/utils/utils.js +22 -6
- package/lib/mjs/widgets/CalendarWidget.js +2 -2
- package/package.json +8 -6
|
@@ -166,25 +166,19 @@ export default class DayComponent extends Field {
|
|
|
166
166
|
};
|
|
167
167
|
}
|
|
168
168
|
get days() {
|
|
169
|
-
|
|
170
|
-
return this._days;
|
|
171
|
-
}
|
|
172
|
-
this._days = [
|
|
169
|
+
const days = [
|
|
173
170
|
{ value: '', label: _.get(this.component, 'fields.day.placeholder', '') },
|
|
174
171
|
];
|
|
175
172
|
for (let x = 1; x <= 31; x++) {
|
|
176
|
-
|
|
173
|
+
days.push({
|
|
177
174
|
value: x,
|
|
178
175
|
label: x.toString(),
|
|
179
176
|
});
|
|
180
177
|
}
|
|
181
|
-
return
|
|
178
|
+
return days;
|
|
182
179
|
}
|
|
183
180
|
get months() {
|
|
184
|
-
|
|
185
|
-
return this._months;
|
|
186
|
-
}
|
|
187
|
-
this._months = [
|
|
181
|
+
const months = [
|
|
188
182
|
{
|
|
189
183
|
value: '',
|
|
190
184
|
label: _.get(this.component, 'fields.month.placeholder') ||
|
|
@@ -203,24 +197,21 @@ export default class DayComponent extends Field {
|
|
|
203
197
|
{ value: 11, label: 'November' },
|
|
204
198
|
{ value: 12, label: 'December' },
|
|
205
199
|
];
|
|
206
|
-
return
|
|
200
|
+
return months;
|
|
207
201
|
}
|
|
208
202
|
get years() {
|
|
209
|
-
|
|
210
|
-
return this._years;
|
|
211
|
-
}
|
|
212
|
-
this._years = [
|
|
203
|
+
const years = [
|
|
213
204
|
{ value: '', label: _.get(this.component, 'fields.year.placeholder', '') },
|
|
214
205
|
];
|
|
215
206
|
const minYears = _.get(this.component, 'fields.year.minYear', 1900) || 1900;
|
|
216
207
|
const maxYears = _.get(this.component, 'fields.year.maxYear', 2030) || 2030;
|
|
217
208
|
for (let x = minYears; x <= maxYears; x++) {
|
|
218
|
-
|
|
209
|
+
years.push({
|
|
219
210
|
value: x,
|
|
220
211
|
label: x.toString(),
|
|
221
212
|
});
|
|
222
213
|
}
|
|
223
|
-
return
|
|
214
|
+
return years;
|
|
224
215
|
}
|
|
225
216
|
setErrorClasses(elements, dirty, hasError) {
|
|
226
217
|
super.setErrorClasses(elements, dirty, hasError);
|
|
@@ -538,7 +538,7 @@ export default class EditGridComponent extends NestedArrayComponent {
|
|
|
538
538
|
isVisibleInRow: (component) => this.isComponentVisibleInRow(component, flattenedComponents),
|
|
539
539
|
getView: (component, data) => {
|
|
540
540
|
const instance = flattenedComponents[component.key];
|
|
541
|
-
const view = instance ? instance.getView(
|
|
541
|
+
const view = instance ? instance.getView(instance.dataValue) : '';
|
|
542
542
|
// If there is an html tag in view, don't allow it to be injected in template
|
|
543
543
|
const htmlTagRegExp = new RegExp('<(.*?)>');
|
|
544
544
|
return typeof view === 'string' &&
|
|
@@ -948,9 +948,19 @@ export default class EditGridComponent extends NestedArrayComponent {
|
|
|
948
948
|
}
|
|
949
949
|
const column = _.clone(col);
|
|
950
950
|
const options = _.clone(this.options);
|
|
951
|
+
const rootSubmissionTz = _.get(this.root, 'options.submissionTimezone');
|
|
952
|
+
if (rootSubmissionTz && !options.submissionTimezone) {
|
|
953
|
+
options.submissionTimezone = rootSubmissionTz;
|
|
954
|
+
}
|
|
951
955
|
options.name += `[${rowIndex}]`;
|
|
952
956
|
options.row = `${rowIndex}-${colIndex}`;
|
|
953
957
|
options.rowIndex = rowIndex;
|
|
958
|
+
if (this.submissionTimezone) {
|
|
959
|
+
options.submissionTimezone = this.submissionTimezone;
|
|
960
|
+
if (column.type === 'datetime') {
|
|
961
|
+
column.widget = { ...column.widget, submissionTimezone: this.submissionTimezone };
|
|
962
|
+
}
|
|
963
|
+
}
|
|
954
964
|
options.onChange = (flags = {}, changed, modified) => {
|
|
955
965
|
if (changed.instance.root?.id && this.root?.id !== changed.instance.root.id) {
|
|
956
966
|
changed.instance.root?.triggerChange?.(flags, changed, modified);
|
|
@@ -30,6 +30,8 @@ export default class FileComponent extends Field {
|
|
|
30
30
|
} | undefined;
|
|
31
31
|
isSyncing: boolean | undefined;
|
|
32
32
|
abortUploads: any[] | undefined;
|
|
33
|
+
pendingfiles: any;
|
|
34
|
+
resolvedFiles: any[] | undefined;
|
|
33
35
|
get dataReady(): Promise<any>;
|
|
34
36
|
loadImage(fileInfo: any): any;
|
|
35
37
|
get emptyValue(): never[];
|
|
@@ -147,7 +149,7 @@ export default class FileComponent extends Field {
|
|
|
147
149
|
getMultipartOptions(fileToSync: any): any;
|
|
148
150
|
uploadFile(fileToSync: any): Promise<any>;
|
|
149
151
|
upload(): Promise<void | {
|
|
150
|
-
fileToSync:
|
|
152
|
+
fileToSync: any;
|
|
151
153
|
fileInfo: any;
|
|
152
154
|
}[]>;
|
|
153
155
|
syncFiles(): Promise<void>;
|
|
@@ -96,6 +96,8 @@ export default class FileComponent extends Field {
|
|
|
96
96
|
};
|
|
97
97
|
this.isSyncing = false;
|
|
98
98
|
this.abortUploads = [];
|
|
99
|
+
this.pendingfiles = [];
|
|
100
|
+
this.resolvedFiles = [];
|
|
99
101
|
}
|
|
100
102
|
get dataReady() {
|
|
101
103
|
return this.filesReady || Promise.resolve();
|
|
@@ -695,22 +697,42 @@ export default class FileComponent extends Field {
|
|
|
695
697
|
};
|
|
696
698
|
}
|
|
697
699
|
// Check file minimum size
|
|
698
|
-
if (this.component.fileMinSize
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
700
|
+
if (this.component.fileMinSize) {
|
|
701
|
+
const interpolatedMinSize = this.interpolate(this.component.fileMinSize, this.evalContext());
|
|
702
|
+
// This case is when the user entered fileMinSize expression, but did not enter or made a typo when
|
|
703
|
+
// setting the fileMinSize variable in the config of the project
|
|
704
|
+
if (!interpolatedMinSize) {
|
|
705
|
+
return {
|
|
706
|
+
status: 'error',
|
|
707
|
+
message: 'Please, check the entered parameters',
|
|
708
|
+
};
|
|
709
|
+
}
|
|
710
|
+
if (!this.validateMinSize(file, interpolatedMinSize)) {
|
|
711
|
+
return {
|
|
712
|
+
status: 'error',
|
|
713
|
+
message: this.t('fileTooSmall', {
|
|
714
|
+
size: interpolatedMinSize,
|
|
715
|
+
}),
|
|
716
|
+
};
|
|
717
|
+
}
|
|
705
718
|
}
|
|
706
719
|
// Check file maximum size
|
|
707
|
-
if (this.component.fileMaxSize
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
720
|
+
if (this.component.fileMaxSize) {
|
|
721
|
+
const interpolatedMaxSize = this.interpolate(this.component.fileMaxSize, this.evalContext());
|
|
722
|
+
if (!interpolatedMaxSize) {
|
|
723
|
+
return {
|
|
724
|
+
status: 'error',
|
|
725
|
+
message: 'Please, check the entered parameters',
|
|
726
|
+
};
|
|
727
|
+
}
|
|
728
|
+
if (!this.validateMaxSize(file, interpolatedMaxSize)) {
|
|
729
|
+
return {
|
|
730
|
+
status: 'error',
|
|
731
|
+
message: this.t('fileTooBig', {
|
|
732
|
+
size: interpolatedMaxSize,
|
|
733
|
+
}),
|
|
734
|
+
};
|
|
735
|
+
}
|
|
714
736
|
}
|
|
715
737
|
return {};
|
|
716
738
|
}
|
|
@@ -966,7 +988,23 @@ export default class FileComponent extends Field {
|
|
|
966
988
|
fileInfo,
|
|
967
989
|
};
|
|
968
990
|
}
|
|
969
|
-
|
|
991
|
+
if (fileToSync.status === "success") {
|
|
992
|
+
const uploadedFile = this.resolvedFiles.find(x => x.fileToSync.originalName === fileToSync.originalName);
|
|
993
|
+
return {
|
|
994
|
+
fileToSync: uploadedFile.fileToSync,
|
|
995
|
+
fileInfo: uploadedFile.fileInfo,
|
|
996
|
+
};
|
|
997
|
+
}
|
|
998
|
+
const pendingFile = this.pendingfiles.find(x => x.name === fileToSync.name);
|
|
999
|
+
if (pendingFile) {
|
|
1000
|
+
fileInfo = await pendingFile.fileInfoProm;
|
|
1001
|
+
}
|
|
1002
|
+
else {
|
|
1003
|
+
const promInfo = this.uploadFile(fileToSync);
|
|
1004
|
+
this.pendingfiles.push({ name: fileToSync.name, fileInfoProm: promInfo });
|
|
1005
|
+
fileInfo = await promInfo;
|
|
1006
|
+
}
|
|
1007
|
+
this.pendingfiles = this.pendingfiles.filter(x => x.name !== fileToSync.name);
|
|
970
1008
|
fileToSync.status = 'success';
|
|
971
1009
|
fileToSync.message = this.t('Succefully uploaded');
|
|
972
1010
|
fileInfo.originalName = fileToSync.originalName;
|
|
@@ -991,6 +1029,10 @@ export default class FileComponent extends Field {
|
|
|
991
1029
|
finally {
|
|
992
1030
|
delete fileToSync.progress;
|
|
993
1031
|
this.redraw();
|
|
1032
|
+
const fileExists = this.resolvedFiles.find(x => x.fileInfo.originalName === fileToSync.originalName);
|
|
1033
|
+
if (!fileExists && fileToSync.status !== 'error') {
|
|
1034
|
+
this.resolvedFiles.push({ fileToSync, fileInfo });
|
|
1035
|
+
}
|
|
994
1036
|
}
|
|
995
1037
|
return {
|
|
996
1038
|
fileToSync,
|
|
@@ -1007,6 +1049,9 @@ export default class FileComponent extends Field {
|
|
|
1007
1049
|
this.delete(),
|
|
1008
1050
|
this.upload(),
|
|
1009
1051
|
]);
|
|
1052
|
+
if (filesToUpload.length !== this.filesToSync?.filesToUpload?.length) {
|
|
1053
|
+
return;
|
|
1054
|
+
}
|
|
1010
1055
|
this.filesToSync.filesToDelete = filesToDelete
|
|
1011
1056
|
.filter((file) => file.fileToSync?.status === 'error')
|
|
1012
1057
|
.map((file) => file.fileToSync);
|
|
@@ -561,9 +561,11 @@ export default class FormComponent extends Component {
|
|
|
561
561
|
* @returns {*|boolean} - TRUE if the subform should be submitted, FALSE if it should not.
|
|
562
562
|
*/
|
|
563
563
|
get shouldSubmit() {
|
|
564
|
+
const hiddenByJsonOnly = !this.hasCondition() && this.component.hidden;
|
|
564
565
|
return (this.subFormReady &&
|
|
565
566
|
(!this.component.hasOwnProperty('reference') || this.component.reference) &&
|
|
566
|
-
!this.shouldConditionallyClear()
|
|
567
|
+
!this.shouldConditionallyClear() &&
|
|
568
|
+
!(hiddenByJsonOnly && this.component.clearOnHide));
|
|
567
569
|
}
|
|
568
570
|
/**
|
|
569
571
|
* Returns the data for the subform.
|
|
@@ -34,6 +34,7 @@ export default class NumberComponent extends Input {
|
|
|
34
34
|
* @returns {number} a parsed number
|
|
35
35
|
*/
|
|
36
36
|
parseNumber(value: string): number;
|
|
37
|
+
normalizeValue(value: any, flags?: {}, emptyValue?: null): any;
|
|
37
38
|
setInputMask(input: any): void;
|
|
38
39
|
getValueAt(index: any): number | null;
|
|
39
40
|
setValueAt(index: any, value: any, flags?: {}): void;
|
|
@@ -141,6 +141,23 @@ export default class NumberComponent extends Input {
|
|
|
141
141
|
return parseFloat(value);
|
|
142
142
|
}
|
|
143
143
|
}
|
|
144
|
+
normalizeValue(value, flags = {}, emptyValue = this.emptyValue) {
|
|
145
|
+
if (typeof value === 'string') {
|
|
146
|
+
const result = this.parseNumber(value);
|
|
147
|
+
value = _.isNaN(result) ? this.emptyValue : result;
|
|
148
|
+
}
|
|
149
|
+
if (this.component?.multiple && Array.isArray(value)) {
|
|
150
|
+
const normilizedValues = value.map((val) => {
|
|
151
|
+
if (typeof val === 'string') {
|
|
152
|
+
const result = this.parseNumber(val);
|
|
153
|
+
return _.isNaN(result) ? this.emptyValue : result;
|
|
154
|
+
}
|
|
155
|
+
return val;
|
|
156
|
+
});
|
|
157
|
+
value = normilizedValues;
|
|
158
|
+
}
|
|
159
|
+
return super.normalizeValue(value, flags, emptyValue);
|
|
160
|
+
}
|
|
144
161
|
setInputMask(input) {
|
|
145
162
|
let numberPattern = '[0-9';
|
|
146
163
|
numberPattern += this.decimalSeparator || '';
|
|
@@ -522,7 +522,7 @@ export default class SelectComponent extends ListComponent {
|
|
|
522
522
|
noUpdateEvent: true,
|
|
523
523
|
});
|
|
524
524
|
}
|
|
525
|
-
else if (this.shouldAddDefaultValue && !this.options.readOnly) {
|
|
525
|
+
else if (this.shouldAddDefaultValue && !this.options.readOnly && this.root && !this.root.submissionSet) {
|
|
526
526
|
// If a default value is provided then select it.
|
|
527
527
|
const defaultValue = this.defaultValue;
|
|
528
528
|
if (!this.isEmpty(defaultValue)) {
|
|
@@ -1366,6 +1366,10 @@ export default class SelectComponent extends ListComponent {
|
|
|
1366
1366
|
}
|
|
1367
1367
|
_.set(submission.metadata.selectData, this.path, templateData);
|
|
1368
1368
|
}
|
|
1369
|
+
else if (!this.templateData[templateValue] &&
|
|
1370
|
+
this.isEmpty(value)) {
|
|
1371
|
+
_.unset(this.root.submission, `metadata.selectData.${this.path}`);
|
|
1372
|
+
}
|
|
1369
1373
|
if (flags.resetValue && this.root?.submission && !this.options.readOnly) {
|
|
1370
1374
|
const submission = this.root.submission;
|
|
1371
1375
|
if (!submission.metadata) {
|
|
@@ -57,7 +57,7 @@ export default class SignatureComponent extends Input {
|
|
|
57
57
|
this.component.height = '200px';
|
|
58
58
|
}
|
|
59
59
|
if (this.component.keepOverlayRatio &&
|
|
60
|
-
this.options
|
|
60
|
+
this.options.pdf &&
|
|
61
61
|
this.component.overlay?.width &&
|
|
62
62
|
this.component.overlay?.height) {
|
|
63
63
|
this.ratio = this.component.overlay?.width / this.component.overlay?.height;
|
|
@@ -7,7 +7,6 @@ declare const _default: ({
|
|
|
7
7
|
placeholder: string;
|
|
8
8
|
weight: number;
|
|
9
9
|
conditional?: undefined;
|
|
10
|
-
customConditional?: undefined;
|
|
11
10
|
ignore?: undefined;
|
|
12
11
|
} | {
|
|
13
12
|
type: string;
|
|
@@ -24,7 +23,6 @@ declare const _default: ({
|
|
|
24
23
|
};
|
|
25
24
|
};
|
|
26
25
|
weight: number;
|
|
27
|
-
customConditional?: undefined;
|
|
28
26
|
ignore?: undefined;
|
|
29
27
|
} | {
|
|
30
28
|
weight: number;
|
|
@@ -32,9 +30,6 @@ declare const _default: ({
|
|
|
32
30
|
label: string;
|
|
33
31
|
tooltip: string;
|
|
34
32
|
key: string;
|
|
35
|
-
customConditional: ({ options }: {
|
|
36
|
-
options: any;
|
|
37
|
-
}) => boolean;
|
|
38
33
|
input: boolean;
|
|
39
34
|
placeholder?: undefined;
|
|
40
35
|
conditional?: undefined;
|
|
@@ -49,6 +44,5 @@ declare const _default: ({
|
|
|
49
44
|
placeholder?: undefined;
|
|
50
45
|
weight?: undefined;
|
|
51
46
|
conditional?: undefined;
|
|
52
|
-
customConditional?: undefined;
|
|
53
47
|
})[];
|
|
54
48
|
export default _default;
|
|
@@ -46,7 +46,6 @@ export default [
|
|
|
46
46
|
label: 'Keep Overlay Aspect Ratio',
|
|
47
47
|
tooltip: 'If checked, the field will have the same aspect ratio as its preview.',
|
|
48
48
|
key: 'keepOverlayRatio',
|
|
49
|
-
customConditional: ({ options }) => options?.editForm?.display === 'pdf',
|
|
50
49
|
input: true,
|
|
51
50
|
},
|
|
52
51
|
{
|
|
@@ -10,6 +10,8 @@ declare const _default: ({
|
|
|
10
10
|
validate?: undefined;
|
|
11
11
|
autofocus?: undefined;
|
|
12
12
|
overrideEditForm?: undefined;
|
|
13
|
+
multiple?: undefined;
|
|
14
|
+
customConditional?: undefined;
|
|
13
15
|
dataSrc?: undefined;
|
|
14
16
|
data?: undefined;
|
|
15
17
|
defaultValue?: undefined;
|
|
@@ -27,6 +29,8 @@ declare const _default: ({
|
|
|
27
29
|
autofocus: boolean;
|
|
28
30
|
overrideEditForm: boolean;
|
|
29
31
|
ignore?: undefined;
|
|
32
|
+
multiple?: undefined;
|
|
33
|
+
customConditional?: undefined;
|
|
30
34
|
dataSrc?: undefined;
|
|
31
35
|
data?: undefined;
|
|
32
36
|
defaultValue?: undefined;
|
|
@@ -42,6 +46,25 @@ declare const _default: ({
|
|
|
42
46
|
validate?: undefined;
|
|
43
47
|
autofocus?: undefined;
|
|
44
48
|
overrideEditForm?: undefined;
|
|
49
|
+
multiple?: undefined;
|
|
50
|
+
customConditional?: undefined;
|
|
51
|
+
dataSrc?: undefined;
|
|
52
|
+
data?: undefined;
|
|
53
|
+
defaultValue?: undefined;
|
|
54
|
+
} | {
|
|
55
|
+
label: string;
|
|
56
|
+
multiple: boolean;
|
|
57
|
+
key: string;
|
|
58
|
+
type: string;
|
|
59
|
+
input: boolean;
|
|
60
|
+
tooltip: string;
|
|
61
|
+
customConditional: string;
|
|
62
|
+
weight: number;
|
|
63
|
+
ignore?: undefined;
|
|
64
|
+
placeholder?: undefined;
|
|
65
|
+
validate?: undefined;
|
|
66
|
+
autofocus?: undefined;
|
|
67
|
+
overrideEditForm?: undefined;
|
|
45
68
|
dataSrc?: undefined;
|
|
46
69
|
data?: undefined;
|
|
47
70
|
defaultValue?: undefined;
|
|
@@ -57,6 +80,8 @@ declare const _default: ({
|
|
|
57
80
|
validate?: undefined;
|
|
58
81
|
autofocus?: undefined;
|
|
59
82
|
overrideEditForm?: undefined;
|
|
83
|
+
multiple?: undefined;
|
|
84
|
+
customConditional?: undefined;
|
|
60
85
|
dataSrc?: undefined;
|
|
61
86
|
data?: undefined;
|
|
62
87
|
defaultValue?: undefined;
|
|
@@ -80,5 +105,7 @@ declare const _default: ({
|
|
|
80
105
|
validate?: undefined;
|
|
81
106
|
autofocus?: undefined;
|
|
82
107
|
overrideEditForm?: undefined;
|
|
108
|
+
multiple?: undefined;
|
|
109
|
+
customConditional?: undefined;
|
|
83
110
|
})[];
|
|
84
111
|
export default _default;
|
|
@@ -67,6 +67,16 @@ export default [
|
|
|
67
67
|
placeholder: 'Number of Columns',
|
|
68
68
|
tooltip: 'Enter the number or columns that should be displayed by this table.',
|
|
69
69
|
},
|
|
70
|
+
{
|
|
71
|
+
label: "Column Headers",
|
|
72
|
+
multiple: true,
|
|
73
|
+
key: "header",
|
|
74
|
+
type: "textfield",
|
|
75
|
+
input: true,
|
|
76
|
+
tooltip: 'Enter header names for the columns',
|
|
77
|
+
customConditional: "if(instance && instance.dataValue && Array.isArray(instance.dataValue)) {\r\n const isAllowToAddHeader = instance.dataValue.length < data.numCols;\r\n const addBtn = _.get(instance, 'refs.addButton[0]', null);\r\n if(addBtn) {\r\n isAllowToAddHeader? addBtn.removeAttribute('disabled'): addBtn.setAttribute('disabled', 'disabled');\r\n }\r\n} ",
|
|
78
|
+
weight: 3,
|
|
79
|
+
},
|
|
70
80
|
{
|
|
71
81
|
type: 'checkbox',
|
|
72
82
|
label: 'Clone Row Components',
|
package/lib/mjs/formio.form.js
CHANGED
|
@@ -7,7 +7,7 @@ import Templates from './templates/Templates';
|
|
|
7
7
|
import Providers from './providers';
|
|
8
8
|
import Widgets from './widgets';
|
|
9
9
|
import Form, { FormOptions } from './Form';
|
|
10
|
-
import Utils, { Evaluator, registerEvaluator
|
|
10
|
+
import Utils, { DefaultEvaluator, Evaluator, registerEvaluator } from './utils';
|
|
11
11
|
import Licenses from './licenses';
|
|
12
12
|
import EventEmitter from './EventEmitter';
|
|
13
13
|
import Webform from './Webform';
|
|
@@ -90,12 +90,9 @@ export function registerModule(mod, defaultFn = null, options = {}) {
|
|
|
90
90
|
break;
|
|
91
91
|
default:
|
|
92
92
|
if (defaultFn) {
|
|
93
|
-
|
|
94
|
-
console.warn('Unknown module option', key);
|
|
95
|
-
}
|
|
93
|
+
defaultFn(key, mod);
|
|
96
94
|
break;
|
|
97
95
|
}
|
|
98
|
-
console.log('Unknown module option', key);
|
|
99
96
|
}
|
|
100
97
|
}
|
|
101
98
|
}
|
|
@@ -108,7 +105,7 @@ export function useModule(defaultFn = null) {
|
|
|
108
105
|
plugins = _.isArray(plugins)
|
|
109
106
|
? plugins
|
|
110
107
|
: [
|
|
111
|
-
plugins
|
|
108
|
+
plugins
|
|
112
109
|
];
|
|
113
110
|
plugins.forEach((plugin) => {
|
|
114
111
|
if (Array.isArray(plugin)) {
|
|
@@ -129,4 +126,4 @@ export function useModule(defaultFn = null) {
|
|
|
129
126
|
Formio.use = useModule();
|
|
130
127
|
export { Formio as FormioCore } from './Formio';
|
|
131
128
|
// Export the components.
|
|
132
|
-
export { Components, Displays, Providers, Widgets, Templates, Utils, Form, Formio, Licenses, EventEmitter, Webform, DefaultEvaluator, FormOptions
|
|
129
|
+
export { Components, Displays, Providers, Widgets, Templates, Utils, Form, Formio, Licenses, EventEmitter, Webform, DefaultEvaluator, FormOptions };
|
package/lib/mjs/package.json
CHANGED
|
@@ -30,9 +30,15 @@ function azure(formio) {
|
|
|
30
30
|
downloadFile(file) {
|
|
31
31
|
return formio.makeRequest('file', `${formio.formUrl}/storage/azure?name=${XHR.trim(file.name)}`, 'GET');
|
|
32
32
|
},
|
|
33
|
-
deleteFile
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
deleteFile(fileInfo, options) {
|
|
34
|
+
const name = XHR.trim(fileInfo.name);
|
|
35
|
+
const key = XHR.trim(fileInfo.key);
|
|
36
|
+
return formio.makeRequest('', `${formio.formUrl}/storage/azure?name=${encodeURIComponent(name)}&key=${encodeURIComponent(key)}`, 'delete').then((response) => {
|
|
37
|
+
return {
|
|
38
|
+
success: true,
|
|
39
|
+
key: response?.key || key,
|
|
40
|
+
};
|
|
41
|
+
});
|
|
36
42
|
},
|
|
37
43
|
};
|
|
38
44
|
}
|
|
@@ -76,4 +76,6 @@ export default {
|
|
|
76
76
|
requiredDayEmpty: '{{ field }} is required',
|
|
77
77
|
requiredMonthField: '{{ field }} is required',
|
|
78
78
|
requiredYearField: '{{ field }} is required',
|
|
79
|
+
fileTooSmall: 'File is too small; it must be at least {{ size }}',
|
|
80
|
+
fileTooBig: 'File is too big; it must be at most {{ size }}'
|
|
79
81
|
};
|
package/lib/mjs/utils/i18n.d.ts
CHANGED
package/lib/mjs/utils/i18n.js
CHANGED
|
@@ -12,6 +12,7 @@ for (const lang in i18n.resources) {
|
|
|
12
12
|
export class I18n {
|
|
13
13
|
languages = i18Defaults;
|
|
14
14
|
language = 'en';
|
|
15
|
+
originalLanguage = 'en';
|
|
15
16
|
currentLanguage = i18Defaults.en;
|
|
16
17
|
constructor(languages = {}) {
|
|
17
18
|
this.setLanguages(languages);
|
|
@@ -66,6 +67,7 @@ export class I18n {
|
|
|
66
67
|
return new I18n();
|
|
67
68
|
}
|
|
68
69
|
changeLanguage(language, ready = null) {
|
|
70
|
+
this.originalLanguage = language;
|
|
69
71
|
if (!this.languages[language]) {
|
|
70
72
|
language = 'en';
|
|
71
73
|
}
|
package/lib/mjs/utils/index.d.ts
CHANGED
|
@@ -94,7 +94,7 @@ declare const FormioUtils: {
|
|
|
94
94
|
offsetDate(date: Date, timezone: string): Date;
|
|
95
95
|
zonesLoaded(): boolean;
|
|
96
96
|
shouldLoadZones(timezone: string): boolean;
|
|
97
|
-
loadZones(url: string,
|
|
97
|
+
loadZones(url: string, _timezone: any): any;
|
|
98
98
|
momentDate(value: string | Date, format: string, timezone: string, options: object): Date;
|
|
99
99
|
formatDate(timezonesUrl: string, value: string | Date, format: string, timezone: string, flatPickrInputFormat: string): string;
|
|
100
100
|
formatOffset(timezonesUrl: string, formatFn: Function, date: string | Date, format: string, timezone: string): string;
|
package/lib/mjs/utils/utils.d.ts
CHANGED
|
@@ -202,7 +202,7 @@ export function shouldLoadZones(timezone: string): boolean;
|
|
|
202
202
|
* @param {string} timezone - The timezone to load.
|
|
203
203
|
* @returns {Promise<any> | *} - Resolves when the zones for this timezone are loaded.
|
|
204
204
|
*/
|
|
205
|
-
export function loadZones(url: string,
|
|
205
|
+
export function loadZones(url: string, _timezone: any): Promise<any> | any;
|
|
206
206
|
/**
|
|
207
207
|
* Get the moment date object for translating dates with timezones.
|
|
208
208
|
* @param {string|Date} value - The value to convert into a moment date.
|
package/lib/mjs/utils/utils.js
CHANGED
|
@@ -217,6 +217,16 @@ export function checkSimpleConditional(component, condition, row, data, instance
|
|
|
217
217
|
}
|
|
218
218
|
else {
|
|
219
219
|
const value = getComponentActualValue(conditionComponentPath, data, row);
|
|
220
|
+
// When inside a DataGrid/EditGrid, construct a row-indexed path so that
|
|
221
|
+
// operators like isEmpty can look up the correct row's component instance.
|
|
222
|
+
let operatorPath = conditionComponentPath;
|
|
223
|
+
const dataParent = getDataParentComponent(instance);
|
|
224
|
+
if (dataParent && !_.isNil(instance?.rowIndex)) {
|
|
225
|
+
const parentPath = dataParent.paths?.localPath;
|
|
226
|
+
if (parentPath && conditionComponentPath.startsWith(`${parentPath}.`)) {
|
|
227
|
+
operatorPath = conditionComponentPath.replace(`${parentPath}.`, `${parentPath}[${instance.rowIndex}].`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
220
230
|
const СonditionOperator = ConditionOperators[operator];
|
|
221
231
|
return СonditionOperator
|
|
222
232
|
? new СonditionOperator().getResult({
|
|
@@ -224,7 +234,7 @@ export function checkSimpleConditional(component, condition, row, data, instance
|
|
|
224
234
|
comparedValue,
|
|
225
235
|
instance,
|
|
226
236
|
component,
|
|
227
|
-
path:
|
|
237
|
+
path: operatorPath,
|
|
228
238
|
})
|
|
229
239
|
: true;
|
|
230
240
|
}
|
|
@@ -275,7 +285,11 @@ export function getComponentActualValue(compPath, data, row) {
|
|
|
275
285
|
*/
|
|
276
286
|
export function checkCustomConditional(component, custom, row, data, form, variable, onError, instance) {
|
|
277
287
|
if (typeof custom === 'string') {
|
|
278
|
-
custom = `
|
|
288
|
+
custom = `
|
|
289
|
+
var ${variable} = true;
|
|
290
|
+
${custom};
|
|
291
|
+
return ${variable};
|
|
292
|
+
`;
|
|
279
293
|
}
|
|
280
294
|
const value = instance && instance.evaluate
|
|
281
295
|
? instance.evaluate(custom, { row, data, form })
|
|
@@ -606,14 +620,16 @@ export function shouldLoadZones(timezone) {
|
|
|
606
620
|
* @param {string} timezone - The timezone to load.
|
|
607
621
|
* @returns {Promise<any> | *} - Resolves when the zones for this timezone are loaded.
|
|
608
622
|
*/
|
|
609
|
-
export function loadZones(url,
|
|
610
|
-
if (
|
|
611
|
-
|
|
612
|
-
return new Promise(_.noop);
|
|
623
|
+
export function loadZones(url, _timezone) {
|
|
624
|
+
if (moment.zonesLoaded) {
|
|
625
|
+
return Promise.resolve();
|
|
613
626
|
}
|
|
614
627
|
if (moment.zonesPromise) {
|
|
615
628
|
return moment.zonesPromise;
|
|
616
629
|
}
|
|
630
|
+
// Always load the full packed dataset once. The previous optimization skipped fetch when the
|
|
631
|
+
// display timezone matched the runtime zone, but moment-timezone still needs `tz.load()` for
|
|
632
|
+
// `.tz(ianaName)` and `z` formatting to work; otherwise conversions silently match server local time.
|
|
617
633
|
return (moment.zonesPromise = fetch(url).then((resp) => resp.json().then((zones) => {
|
|
618
634
|
moment.tz.load(zones);
|
|
619
635
|
moment.zonesLoaded = true;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Formio } from '../Formio';
|
|
2
2
|
import InputWidget from './InputWidget';
|
|
3
|
-
import { convertFormatToFlatpickr, convertFormatToMask, convertFormatToMoment, formatDate, formatOffset, getBrowserInfo, getDateSetting, getLocaleDateFormatInfo, momentDate, zonesLoaded,
|
|
3
|
+
import { convertFormatToFlatpickr, convertFormatToMask, convertFormatToMoment, formatDate, formatOffset, getBrowserInfo, getDateSetting, getLocaleDateFormatInfo, momentDate, zonesLoaded, loadZones, hasEncodedTimezone, } from '../utils';
|
|
4
4
|
import moment from 'moment';
|
|
5
5
|
import _ from 'lodash';
|
|
6
6
|
const DEFAULT_FORMAT = 'yyyy-MM-dd hh:mm a';
|
|
@@ -56,7 +56,7 @@ export default class CalendarWidget extends InputWidget {
|
|
|
56
56
|
if (this.zoneLoading) {
|
|
57
57
|
return true;
|
|
58
58
|
}
|
|
59
|
-
if (!zonesLoaded()
|
|
59
|
+
if (!zonesLoaded()) {
|
|
60
60
|
this.zoneLoading = true;
|
|
61
61
|
loadZones(this.timezonesUrl, timezone).then(() => {
|
|
62
62
|
this.zoneLoading = false;
|