@wavemaker/react-runtime 11.15.3-rc.647481 → 11.15.4-rc.647493
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/components/basic/richtexteditor/index.js +53 -9
- package/components/chart/index.js +2 -11
- package/components/common/AppSpinner.js +4 -1
- package/components/container/panel/components/panel-content/index.js +18 -0
- package/components/container/wizard/index.js +1 -1
- package/components/data/form/base-form/index.js +156 -105
- package/components/data/form/form-context.js +17 -1
- package/components/data/form/form-controller/hooks/index.js +127 -0
- package/components/data/form/form-controller/utils.js +52 -1
- package/components/data/form/form-controller/withFormController.js +10 -162
- package/components/data/form/form-dynamic-section/index.js +46 -0
- package/components/data/form/form-dynamic-section/props.js +5 -0
- package/components/data/form/index.js +5 -0
- package/components/data/list/hooks/useListEffects.js +10 -3
- package/components/data/list/hooks/useListEventHandlers.js +20 -15
- package/components/data/list/index.js +7 -8
- package/components/data/list/utils/list-helpers.js +21 -1
- package/components/data/list/utils/list-widget-methods.js +2 -0
- package/components/data/list/utils/widget-instance-utils.js +82 -0
- package/components/data/pagination/components/BasicPagination.js +1 -0
- package/components/data/pagination/components/PageSizeSelector.js +11 -3
- package/components/data/pagination/index.js +1 -2
- package/components/data/table/hooks/useServerSideSorting.js +10 -16
- package/components/data/table/index.js +55 -57
- package/components/data/table/utils/buildSelectionColumns.js +23 -32
- package/components/data/table/utils/index.js +7 -2
- package/components/dialogs/index.js +6 -0
- package/components/input/default/checkbox/index.js +5 -2
- package/components/input/epoch/date/components/DatePickerPopover.js +17 -2
- package/components/input/epoch/date/index.js +21 -17
- package/components/input/epoch/datetime/index.js +2 -4
- package/components/navigation/popover/index.js +8 -21
- package/components/page/partial-container/index.js +19 -1
- package/context/WidgetProvider.js +28 -14
- package/core/proxy-service.js +1 -2
- package/core/util/compare.js +6 -0
- package/higherOrder/BasePage.js +1 -1
- package/higherOrder/withBaseWrapper.js +22 -8
- package/libs/index.js +3 -10
- package/libs/prefab/index.js +20 -0
- package/package-lock.json +111 -82
- package/package.json +2 -2
- package/utils/lib-error-skipper.js +5 -2
- package/utils/state-persistance.js +42 -33
- package/utils/widget-cleanup-util.js +30 -0
- package/variables/live-variable.js +18 -0
|
@@ -27,6 +27,7 @@ var _PrefabContext = require("../../../../context/PrefabContext");
|
|
|
27
27
|
var _events = require("../../../../core/constants/events");
|
|
28
28
|
var _merge = _interopRequireDefault(require("lodash-es/merge"));
|
|
29
29
|
var _formUtils = require("../../../../utils/form-utils");
|
|
30
|
+
var _utils3 = require("../../table/utils");
|
|
30
31
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof3(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t2 in e) "default" !== _t2 && {}.hasOwnProperty.call(e, _t2) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t2)) && (i.get || i.set) ? o(f, _t2, i) : f[_t2] = e[_t2]); return f; })(e, t); }
|
|
31
32
|
var __jsx = _react["default"].createElement;
|
|
32
33
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
@@ -34,7 +35,7 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
|
|
|
34
35
|
var DEFAULT_CLASS = "panel app-panel app-form";
|
|
35
36
|
var BaseForm = function BaseForm(WrappedComponent) {
|
|
36
37
|
var ControlledForm = function ControlledForm(FormProps) {
|
|
37
|
-
var _prefabContext$formAr, _props$listener, _props$
|
|
38
|
+
var _prefabContext$formAr, _props$listener, _props$listener12;
|
|
38
39
|
// setting up default props for form
|
|
39
40
|
var props = _objectSpread(_objectSpread({}, _props.defaultProps), FormProps);
|
|
40
41
|
var parentFormRef = (0, _formContext.useFormRef)();
|
|
@@ -45,9 +46,6 @@ var BaseForm = function BaseForm(WrappedComponent) {
|
|
|
45
46
|
var parentForm = props.parentForm || (prefabContext === null || prefabContext === void 0 ? void 0 : prefabContext.parentForm);
|
|
46
47
|
var isParentList = props.isParentList !== undefined ? props.isParentList : (prefabContext === null || prefabContext === void 0 ? void 0 : prefabContext.isParentList) || false;
|
|
47
48
|
var formArrayIndex = props.formArrayIndex !== undefined ? props.formArrayIndex : (_prefabContext$formAr = prefabContext === null || prefabContext === void 0 ? void 0 : prefabContext.formArrayIndex) !== null && _prefabContext$formAr !== void 0 ? _prefabContext$formAr : -1;
|
|
48
|
-
|
|
49
|
-
// For child forms, use childdatasetnode if provided, otherwise use form name as fallback
|
|
50
|
-
var effectiveChildDatasetNode = parentForm ? (prefabContext === null || prefabContext === void 0 ? void 0 : prefabContext.parentListName) || props.parentListName || props.childdatasetnode || props.name : undefined;
|
|
51
49
|
var isInsideWizard = props.isInsideWizard || false;
|
|
52
50
|
var formRef = (0, _react.useRef)(null);
|
|
53
51
|
var _useState = (0, _react.useState)({}),
|
|
@@ -68,19 +66,45 @@ var BaseForm = function BaseForm(WrappedComponent) {
|
|
|
68
66
|
}),
|
|
69
67
|
statusMessage = _useState5[0],
|
|
70
68
|
setStatusMessage = _useState5[1];
|
|
71
|
-
|
|
69
|
+
|
|
70
|
+
// Use context to get parent form's data (instance-specific, not shared widget proxy)
|
|
71
|
+
var parentFormDataContext = (0, _formContext.useParentFormData)();
|
|
72
|
+
var parentFormData = parentForm ? parentFormDataContext === null || parentFormDataContext === void 0 ? void 0 : parentFormDataContext.formdata : undefined;
|
|
73
|
+
|
|
74
|
+
// For child forms, determine the correct data key dynamically.
|
|
75
|
+
// - If parent has an array at parentListName, this is a direct list child → use parentListName
|
|
76
|
+
// - Otherwise, use childdatasetnode (nested object child)
|
|
77
|
+
var effectiveChildDatasetNode = (0, _react.useMemo)(function () {
|
|
78
|
+
if (!parentForm) return undefined;
|
|
79
|
+
|
|
80
|
+
// Check if parentListName exists as an array in parent's data
|
|
81
|
+
if (props.parentListName && parentFormDataContext !== null && parentFormDataContext !== void 0 && parentFormDataContext.formdata) {
|
|
82
|
+
var dataAtParentListName = (0, _get["default"])(parentFormDataContext.formdata, props.parentListName);
|
|
83
|
+
if (Array.isArray(dataAtParentListName)) {
|
|
84
|
+
return props.parentListName;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// Fall back to childdatasetnode or name
|
|
88
|
+
return props.childdatasetnode || props.name;
|
|
89
|
+
}, [parentForm, parentFormDataContext === null || parentFormDataContext === void 0 ? void 0 : parentFormDataContext.formdata, props.parentListName, props.childdatasetnode, props.name]);
|
|
72
90
|
var _useState6 = (0, _react.useState)(),
|
|
73
91
|
childFormData = _useState6[0],
|
|
74
92
|
setChildFormData = _useState6[1];
|
|
93
|
+
|
|
94
|
+
// Track current form's data to provide to children via context
|
|
95
|
+
var _useState7 = (0, _react.useState)(null),
|
|
96
|
+
currentFormData = _useState7[0],
|
|
97
|
+
setCurrentFormData = _useState7[1];
|
|
75
98
|
var messageRef = (0, _react.useRef)(null);
|
|
76
|
-
var
|
|
77
|
-
showViewMode =
|
|
78
|
-
setShowViewMode =
|
|
99
|
+
var _useState8 = (0, _react.useState)(false),
|
|
100
|
+
showViewMode = _useState8[0],
|
|
101
|
+
setShowViewMode = _useState8[1];
|
|
79
102
|
var lastResetFormDataRef = (0, _react.useRef)(null);
|
|
80
103
|
var childFormUnsubscribeRef = (0, _react.useRef)(null);
|
|
81
104
|
var parentFormUnsubscribeRef = (0, _react.useRef)(null);
|
|
82
105
|
var validationMessagesRef = (0, _react.useRef)([]);
|
|
83
|
-
var
|
|
106
|
+
var formIdRef = (0, _react.useRef)(Math.random().toString(36).substring(2, 15));
|
|
107
|
+
var widgetFormData = props.name && (_props$listener = props.listener) !== null && _props$listener !== void 0 && (_props$listener = _props$listener.Widgets) !== null && _props$listener !== void 0 && (_props$listener = _props$listener[props.name]) !== null && _props$listener !== void 0 && _props$listener.formdata && Object.keys(props.listener.Widgets[props.name].formdata).length > 0 ? props.listener.Widgets[props.name].formdata : props.formdata;
|
|
84
108
|
var formDataref = (0, _react.useRef)(null);
|
|
85
109
|
var updateFormData = function updateFormData(data) {
|
|
86
110
|
if (typeof data === "function") {
|
|
@@ -112,13 +136,23 @@ var BaseForm = function BaseForm(WrappedComponent) {
|
|
|
112
136
|
|
|
113
137
|
// update valid state
|
|
114
138
|
(0, _react.useEffect)(function () {
|
|
115
|
-
var _props$
|
|
116
|
-
if ((_props$
|
|
139
|
+
var _props$listener2;
|
|
140
|
+
if ((_props$listener2 = props.listener) !== null && _props$listener2 !== void 0 && _props$listener2.onChange && props.name) {
|
|
117
141
|
props.listener.onChange(props.name, {
|
|
118
142
|
valid: isValid
|
|
119
143
|
});
|
|
120
144
|
}
|
|
121
145
|
}, [isValid]);
|
|
146
|
+
|
|
147
|
+
// Helper function to notify listeners of form data output changes
|
|
148
|
+
// Cleans internal properties before emitting
|
|
149
|
+
var notifyDataOutput = function notifyDataOutput(data) {
|
|
150
|
+
var _props$listener3, _props$listener3$onCh;
|
|
151
|
+
var cleanedData = (0, _utils3.cleanRowData)(data);
|
|
152
|
+
(_props$listener3 = props.listener) === null || _props$listener3 === void 0 || (_props$listener3$onCh = _props$listener3.onChange) === null || _props$listener3$onCh === void 0 || _props$listener3$onCh.call(_props$listener3, props.name, {
|
|
153
|
+
dataoutput: cleanedData
|
|
154
|
+
});
|
|
155
|
+
};
|
|
122
156
|
var childFormEventListeners = function childFormEventListeners() {
|
|
123
157
|
if (parentForm && props.name) {
|
|
124
158
|
// Listen for parent relationship events (context, acknowledgments, etc.)
|
|
@@ -233,7 +267,7 @@ var BaseForm = function BaseForm(WrappedComponent) {
|
|
|
233
267
|
isListForm = data.isListForm,
|
|
234
268
|
formArrayIndex = data.formArrayIndex;
|
|
235
269
|
if (childdatasetnode && formData) {
|
|
236
|
-
var _props$listener4
|
|
270
|
+
var _props$listener4;
|
|
237
271
|
// Get current parent form values
|
|
238
272
|
var currentParentData = getValues();
|
|
239
273
|
|
|
@@ -297,9 +331,7 @@ var BaseForm = function BaseForm(WrappedComponent) {
|
|
|
297
331
|
}, 0);
|
|
298
332
|
|
|
299
333
|
// Emit the updated parent form data
|
|
300
|
-
(
|
|
301
|
-
dataoutput: updatedParentData
|
|
302
|
-
});
|
|
334
|
+
notifyDataOutput(updatedParentData);
|
|
303
335
|
}
|
|
304
336
|
});
|
|
305
337
|
return function () {
|
|
@@ -308,17 +340,17 @@ var BaseForm = function BaseForm(WrappedComponent) {
|
|
|
308
340
|
}
|
|
309
341
|
};
|
|
310
342
|
var parentFormFieldRegisterListeners = function parentFormFieldRegisterListeners() {
|
|
311
|
-
var _props$
|
|
343
|
+
var _props$listener5;
|
|
312
344
|
// Only set up listeners for parent forms (forms that have child forms), not for child forms themselves
|
|
313
|
-
if (!parentForm && props.name && (_props$
|
|
345
|
+
if (!parentForm && props.name && (_props$listener5 = props.listener) !== null && _props$listener5 !== void 0 && _props$listener5.Widgets) {
|
|
314
346
|
var unsubscribe = _events.EVENTEMITTER_METHODS.CHILD_FORM_FIELD_REGISTER_ON(props.name, function (data) {
|
|
315
|
-
var _props$
|
|
347
|
+
var _props$listener6;
|
|
316
348
|
var childFormName = data.childFormName,
|
|
317
349
|
widget = data.widget,
|
|
318
350
|
widgetProps = data.widgetProps,
|
|
319
351
|
formKey = data.formKey,
|
|
320
352
|
fieldName = data.fieldName;
|
|
321
|
-
if (childFormName && widget && formKey && fieldName && (_props$
|
|
353
|
+
if (childFormName && widget && formKey && fieldName && (_props$listener6 = props.listener) !== null && _props$listener6 !== void 0 && (_props$listener6 = _props$listener6.Widgets) !== null && _props$listener6 !== void 0 && _props$listener6[props.name]) {
|
|
322
354
|
// Ensure the form structure exists in the parent form's widgetsContext
|
|
323
355
|
var parentFormContext = props.listener.Widgets[props.name];
|
|
324
356
|
parentFormContext.formfields = parentFormContext.formfields || {};
|
|
@@ -346,25 +378,31 @@ var BaseForm = function BaseForm(WrappedComponent) {
|
|
|
346
378
|
// This prevents unnecessary resets when formdata prop reference changes but values are the same
|
|
347
379
|
|
|
348
380
|
(0, _react.useEffect)(function () {
|
|
349
|
-
if (parentFormData) {
|
|
381
|
+
if (parentFormData && effectiveChildDatasetNode) {
|
|
350
382
|
var childData;
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
383
|
+
|
|
384
|
+
// Get data at the effective node
|
|
385
|
+
var dataAtNode = (0, _get["default"])(parentFormData, effectiveChildDatasetNode);
|
|
386
|
+
var isArrayData = Array.isArray(dataAtNode);
|
|
387
|
+
if (isArrayData && formArrayIndex >= 0) {
|
|
388
|
+
// This form is a direct child of a list - read from array index
|
|
389
|
+
if (formArrayIndex < dataAtNode.length) {
|
|
390
|
+
childData = dataAtNode[formArrayIndex];
|
|
356
391
|
} else {
|
|
357
|
-
|
|
392
|
+
// New list item, no data yet
|
|
393
|
+
childData = {};
|
|
358
394
|
}
|
|
359
|
-
} else if (effectiveChildDatasetNode) {
|
|
360
|
-
// Regular child forms use object properties: parentForm.formdata[childDatasetNode]
|
|
361
|
-
childData = (0, _get["default"])(parentFormData, effectiveChildDatasetNode);
|
|
362
395
|
} else {
|
|
363
|
-
|
|
396
|
+
// This is a nested object child - read the property directly
|
|
397
|
+
childData = dataAtNode;
|
|
398
|
+
// If no data, use empty object for new records
|
|
399
|
+
if (childData === undefined || childData === null) {
|
|
400
|
+
childData = {};
|
|
401
|
+
}
|
|
364
402
|
}
|
|
365
403
|
setChildFormData(childData);
|
|
366
404
|
}
|
|
367
|
-
}, [parentFormData,
|
|
405
|
+
}, [parentFormData, effectiveChildDatasetNode, formArrayIndex]);
|
|
368
406
|
|
|
369
407
|
// Register child form with parent form if parentForm exists
|
|
370
408
|
(0, _react.useEffect)(function () {
|
|
@@ -438,6 +476,17 @@ var BaseForm = function BaseForm(WrappedComponent) {
|
|
|
438
476
|
}
|
|
439
477
|
}
|
|
440
478
|
}, [props.formdata, widgetFormData, childFormData, reset, getValues, props.parentForm]);
|
|
479
|
+
|
|
480
|
+
// Initialize currentFormData for root forms or when data is first available
|
|
481
|
+
// This ensures child forms can read from context on initial render
|
|
482
|
+
(0, _react.useEffect)(function () {
|
|
483
|
+
if (!parentForm && currentFormData === null) {
|
|
484
|
+
var initialData = widgetFormData || props.formdata;
|
|
485
|
+
if (initialData && (0, _typeof2["default"])(initialData) === "object" && !Array.isArray(initialData)) {
|
|
486
|
+
setCurrentFormData(initialData);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
}, [parentForm, currentFormData, widgetFormData, props.formdata]);
|
|
441
490
|
function debouncedFilter() {
|
|
442
491
|
var debouncedFilter = (0, _lodashEs.debounce)(filter, 250);
|
|
443
492
|
debouncedFilter();
|
|
@@ -536,8 +585,8 @@ var BaseForm = function BaseForm(WrappedComponent) {
|
|
|
536
585
|
scrollToElement(formEl);
|
|
537
586
|
}
|
|
538
587
|
} else {
|
|
539
|
-
var _props$
|
|
540
|
-
props === null || props === void 0 || (_props$
|
|
588
|
+
var _props$listener7;
|
|
589
|
+
props === null || props === void 0 || (_props$listener7 = props.listener) === null || _props$listener7 === void 0 || (_props$listener7 = _props$listener7.App) === null || _props$listener7 === void 0 || _props$listener7.notifyApp(template, type, true);
|
|
541
590
|
}
|
|
542
591
|
} else {
|
|
543
592
|
setStatusMessage({
|
|
@@ -583,8 +632,8 @@ var BaseForm = function BaseForm(WrappedComponent) {
|
|
|
583
632
|
* DRY helper to avoid repeating this pattern.
|
|
584
633
|
*/
|
|
585
634
|
var exposeValidationMessages = (0, _react.useCallback)(function (validationMessages) {
|
|
586
|
-
var _props$
|
|
587
|
-
if ((_props$
|
|
635
|
+
var _props$listener8;
|
|
636
|
+
if ((_props$listener8 = props.listener) !== null && _props$listener8 !== void 0 && (_props$listener8 = _props$listener8.Widgets) !== null && _props$listener8 !== void 0 && _props$listener8[props.name]) {
|
|
588
637
|
props.listener.Widgets[props.name].validationMessages = validationMessages;
|
|
589
638
|
}
|
|
590
639
|
if (formRef.current) {
|
|
@@ -597,8 +646,8 @@ var BaseForm = function BaseForm(WrappedComponent) {
|
|
|
597
646
|
* DRY helper for shared iteration setup.
|
|
598
647
|
*/
|
|
599
648
|
var getFormFieldsForValidation = (0, _react.useCallback)(function () {
|
|
600
|
-
var _props$
|
|
601
|
-
var formFieldsToValidate = ((_props$
|
|
649
|
+
var _props$listener9;
|
|
650
|
+
var formFieldsToValidate = ((_props$listener9 = props.listener) === null || _props$listener9 === void 0 || (_props$listener9 = _props$listener9.Widgets) === null || _props$listener9 === void 0 || (_props$listener9 = _props$listener9[props.name]) === null || _props$listener9 === void 0 ? void 0 : _props$listener9.formfields) || formfields;
|
|
602
651
|
var allFieldKeys = Object.keys(formFieldsToValidate);
|
|
603
652
|
var prefix = props.name || "";
|
|
604
653
|
return {
|
|
@@ -641,7 +690,7 @@ var BaseForm = function BaseForm(WrappedComponent) {
|
|
|
641
690
|
});
|
|
642
691
|
}, [buildValidationMessagesCore, control]);
|
|
643
692
|
var validateFieldsOnSubmit = (0, _react.useCallback)(/*#__PURE__*/(0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee2() {
|
|
644
|
-
var isValid, childForms, validationResults,
|
|
693
|
+
var isValid, childForms, validationResults, currentFormValidState, validationMessages, _props$listener0;
|
|
645
694
|
return _regenerator["default"].wrap(function _callee2$(_context2) {
|
|
646
695
|
while (1) switch (_context2.prev = _context2.next) {
|
|
647
696
|
case 0:
|
|
@@ -661,19 +710,19 @@ var BaseForm = function BaseForm(WrappedComponent) {
|
|
|
661
710
|
validationResults = _context2.sent;
|
|
662
711
|
isValid = validationResults.every(Boolean);
|
|
663
712
|
case 7:
|
|
664
|
-
|
|
665
|
-
validationMessages = buildValidationMessages();
|
|
666
|
-
exposeValidationMessages(validationMessages);
|
|
667
|
-
_context2.next = 11;
|
|
713
|
+
_context2.next = 9;
|
|
668
714
|
return trigger();
|
|
669
|
-
case
|
|
715
|
+
case 9:
|
|
670
716
|
currentFormValidState = _context2.sent;
|
|
717
|
+
// Build and expose validation messages AFTER trigger so control.getFieldState() has latest errors
|
|
718
|
+
validationMessages = buildValidationMessages();
|
|
719
|
+
exposeValidationMessages(validationMessages);
|
|
671
720
|
if (!(!isValid || !currentFormValidState)) {
|
|
672
721
|
_context2.next = 16;
|
|
673
722
|
break;
|
|
674
723
|
}
|
|
675
724
|
if (!currentFormValidState) {
|
|
676
|
-
props === null || props === void 0 || (_props$
|
|
725
|
+
props === null || props === void 0 || (_props$listener0 = props.listener) === null || _props$listener0 === void 0 || _props$listener0.onChange(props.name, {
|
|
677
726
|
valid: false,
|
|
678
727
|
errors: errors
|
|
679
728
|
});
|
|
@@ -701,13 +750,13 @@ var BaseForm = function BaseForm(WrappedComponent) {
|
|
|
701
750
|
};
|
|
702
751
|
var handleFormSubmit = /*#__PURE__*/function () {
|
|
703
752
|
var _ref3 = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee3(data, e, operationType) {
|
|
704
|
-
var _props$
|
|
705
|
-
var formWidgets, filteredData, mergedData, result, formData;
|
|
753
|
+
var _props$listener1, _props$onSubmit;
|
|
754
|
+
var formWidgets, filteredData, mergedData, result, formData, cleanedFormData, cleanedMergedData;
|
|
706
755
|
return _regenerator["default"].wrap(function _callee3$(_context3) {
|
|
707
756
|
while (1) switch (_context3.prev = _context3.next) {
|
|
708
757
|
case 0:
|
|
709
758
|
e = e || new Event("submit");
|
|
710
|
-
formWidgets = (_props$
|
|
759
|
+
formWidgets = (_props$listener1 = props.listener) === null || _props$listener1 === void 0 || (_props$listener1 = _props$listener1.Widgets) === null || _props$listener1 === void 0 || (_props$listener1 = _props$listener1[props.name]) === null || _props$listener1 === void 0 ? void 0 : _props$listener1.dataoutput;
|
|
711
760
|
if (formWidgets && Object.keys(formWidgets).length > 0) {
|
|
712
761
|
data = updateFormDataOutput(data, formWidgets);
|
|
713
762
|
}
|
|
@@ -730,14 +779,16 @@ var BaseForm = function BaseForm(WrappedComponent) {
|
|
|
730
779
|
return _context3.abrupt("return");
|
|
731
780
|
case 11:
|
|
732
781
|
// Transform flat data to nested structure
|
|
733
|
-
formData = transformToNestedObject(mergedData); //
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
782
|
+
formData = transformToNestedObject(mergedData); // Clean internal properties before submission
|
|
783
|
+
cleanedFormData = (0, _utils3.cleanRowData)(formData);
|
|
784
|
+
cleanedMergedData = (0, _utils3.cleanRowData)(mergedData); // Handle form submission with cleaned data
|
|
785
|
+
notifyDataOutput(cleanedMergedData);
|
|
786
|
+
_context3.next = 17;
|
|
787
|
+
return executeFormSubmit(cleanedFormData, operationType);
|
|
788
|
+
case 17:
|
|
789
|
+
// Execute onSubmit hook with cleaned data
|
|
790
|
+
props === null || props === void 0 || (_props$onSubmit = props.onSubmit) === null || _props$onSubmit === void 0 || _props$onSubmit.call(props, e, props, cleanedFormData);
|
|
791
|
+
case 18:
|
|
741
792
|
case "end":
|
|
742
793
|
return _context3.stop();
|
|
743
794
|
}
|
|
@@ -774,12 +825,6 @@ var BaseForm = function BaseForm(WrappedComponent) {
|
|
|
774
825
|
});
|
|
775
826
|
return result;
|
|
776
827
|
};
|
|
777
|
-
var notifyDataOutput = function notifyDataOutput(data) {
|
|
778
|
-
var _props$listener11, _props$listener11$onC;
|
|
779
|
-
(_props$listener11 = props.listener) === null || _props$listener11 === void 0 || (_props$listener11$onC = _props$listener11.onChange) === null || _props$listener11$onC === void 0 || _props$listener11$onC.call(_props$listener11, props.name, {
|
|
780
|
-
dataoutput: data
|
|
781
|
-
});
|
|
782
|
-
};
|
|
783
828
|
var executeFormSubmit = /*#__PURE__*/function () {
|
|
784
829
|
var _ref4 = (0, _asyncToGenerator2["default"])(/*#__PURE__*/_regenerator["default"].mark(function _callee4(formData, operationType) {
|
|
785
830
|
var firstParam;
|
|
@@ -1101,7 +1146,7 @@ var BaseForm = function BaseForm(WrappedComponent) {
|
|
|
1101
1146
|
setShowViewMode(false);
|
|
1102
1147
|
}
|
|
1103
1148
|
function setFormData(data) {
|
|
1104
|
-
var _props$
|
|
1149
|
+
var _props$listener10;
|
|
1105
1150
|
if (!data || (0, _typeof2["default"])(data) !== "object" || Array.isArray(data)) {
|
|
1106
1151
|
return;
|
|
1107
1152
|
}
|
|
@@ -1112,7 +1157,9 @@ var BaseForm = function BaseForm(WrappedComponent) {
|
|
|
1112
1157
|
reset(cleanedData);
|
|
1113
1158
|
// Update the ref to track this as the last reset formdata
|
|
1114
1159
|
lastResetFormDataRef.current = cleanedData;
|
|
1115
|
-
|
|
1160
|
+
// Update context so child forms see the latest data
|
|
1161
|
+
setCurrentFormData(cleanedData);
|
|
1162
|
+
if ((_props$listener10 = props.listener) !== null && _props$listener10 !== void 0 && _props$listener10.Widgets && props.name) {
|
|
1116
1163
|
props.listener.Widgets[props.name].formdata = cleanedData;
|
|
1117
1164
|
}
|
|
1118
1165
|
if (props["form-type"] === "live-filter") {
|
|
@@ -1134,16 +1181,16 @@ var BaseForm = function BaseForm(WrappedComponent) {
|
|
|
1134
1181
|
setShowViewMode(true);
|
|
1135
1182
|
}
|
|
1136
1183
|
var fields = (0, _react.useMemo)(function () {
|
|
1137
|
-
var _props$
|
|
1184
|
+
var _props$listener11;
|
|
1138
1185
|
var newFields = [];
|
|
1139
|
-
var Widgets = ((_props$
|
|
1186
|
+
var Widgets = ((_props$listener11 = props.listener) === null || _props$listener11 === void 0 || (_props$listener11 = _props$listener11.Widgets) === null || _props$listener11 === void 0 || (_props$listener11 = _props$listener11[props.name]) === null || _props$listener11 === void 0 ? void 0 : _props$listener11.formfields) || {};
|
|
1140
1187
|
Object.keys(Widgets).forEach(function (key) {
|
|
1141
1188
|
if (!key.includes("formWidget") && Widgets[key]) {
|
|
1142
1189
|
newFields.push(Widgets[key]);
|
|
1143
1190
|
}
|
|
1144
1191
|
});
|
|
1145
1192
|
return newFields;
|
|
1146
|
-
}, [(_props$
|
|
1193
|
+
}, [(_props$listener12 = props.listener) === null || _props$listener12 === void 0 ? void 0 : _props$listener12.Widgets[props.name], props.name]);
|
|
1147
1194
|
|
|
1148
1195
|
// Call onDataSourceChange when formfields change
|
|
1149
1196
|
(0, _react.useEffect)(function () {
|
|
@@ -1166,8 +1213,13 @@ var BaseForm = function BaseForm(WrappedComponent) {
|
|
|
1166
1213
|
// Helper function to reset form with new data
|
|
1167
1214
|
var resetFormWithData = function resetFormWithData(newData) {
|
|
1168
1215
|
var cleanNulls = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
|
1216
|
+
if (newData._wmListItemId) {
|
|
1217
|
+
return;
|
|
1218
|
+
}
|
|
1169
1219
|
reset(newData);
|
|
1170
1220
|
lastResetFormDataRef.current = newData;
|
|
1221
|
+
// Update context so child forms can read this instance's data
|
|
1222
|
+
setCurrentFormData(newData);
|
|
1171
1223
|
};
|
|
1172
1224
|
(0, _react.useEffect)(function () {
|
|
1173
1225
|
// Added for wizard validations please do not remove the blow emit code changes.
|
|
@@ -1187,46 +1239,33 @@ var BaseForm = function BaseForm(WrappedComponent) {
|
|
|
1187
1239
|
emit();
|
|
1188
1240
|
var serialized = JSON.stringify(values);
|
|
1189
1241
|
if (serialized !== lastEmittedValuesSerialized.current) {
|
|
1190
|
-
var _props$listener15;
|
|
1191
1242
|
lastEmittedValuesSerialized.current = serialized;
|
|
1243
|
+
|
|
1244
|
+
// Update context so child forms see the latest data
|
|
1245
|
+
setCurrentFormData(values);
|
|
1246
|
+
|
|
1192
1247
|
// For child forms, emit data update event to parent form
|
|
1193
|
-
if
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
}
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
_events.EVENTEMITTER_METHODS.CHILD_FORM_DATA_UPDATE_EMIT(parentForm, {
|
|
1211
|
-
childFormName: props.name,
|
|
1212
|
-
childdatasetnode: effectiveChildDatasetNode,
|
|
1213
|
-
formData: values,
|
|
1214
|
-
childFormInstance: {
|
|
1215
|
-
getValues: getValues,
|
|
1216
|
-
reset: reset,
|
|
1217
|
-
setFormData: setFormData
|
|
1218
|
-
},
|
|
1219
|
-
isListForm: false
|
|
1220
|
-
});
|
|
1221
|
-
}
|
|
1248
|
+
// Determine if this is a list child by checking if parent has an array at our node
|
|
1249
|
+
if (parentForm && effectiveChildDatasetNode) {
|
|
1250
|
+
var parentData = parentFormDataContext === null || parentFormDataContext === void 0 ? void 0 : parentFormDataContext.formdata;
|
|
1251
|
+
var dataAtNode = parentData ? (0, _get["default"])(parentData, effectiveChildDatasetNode) : undefined;
|
|
1252
|
+
var isActuallyListChild = Array.isArray(dataAtNode);
|
|
1253
|
+
_events.EVENTEMITTER_METHODS.CHILD_FORM_DATA_UPDATE_EMIT(parentForm, {
|
|
1254
|
+
childFormName: props.name,
|
|
1255
|
+
childdatasetnode: effectiveChildDatasetNode,
|
|
1256
|
+
formArrayIndex: isActuallyListChild && formArrayIndex >= 0 ? formArrayIndex : undefined,
|
|
1257
|
+
formData: (0, _utils3.cleanRowData)(values),
|
|
1258
|
+
childFormInstance: {
|
|
1259
|
+
getValues: getValues,
|
|
1260
|
+
reset: reset,
|
|
1261
|
+
setFormData: setFormData
|
|
1262
|
+
},
|
|
1263
|
+
isListForm: isActuallyListChild
|
|
1264
|
+
});
|
|
1222
1265
|
}
|
|
1223
1266
|
|
|
1224
1267
|
// Emit current form's dataoutput
|
|
1225
|
-
|
|
1226
|
-
props.listener.onChange(props.name, {
|
|
1227
|
-
dataoutput: getValues()
|
|
1228
|
-
});
|
|
1229
|
-
}
|
|
1268
|
+
notifyDataOutput(getValues());
|
|
1230
1269
|
}
|
|
1231
1270
|
});
|
|
1232
1271
|
return function () {
|
|
@@ -1284,18 +1323,30 @@ var BaseForm = function BaseForm(WrappedComponent) {
|
|
|
1284
1323
|
// if parentFormRef is not null, register methods to parent form with form name as key
|
|
1285
1324
|
(0, _react.useImperativeHandle)(parentFormRef, function () {
|
|
1286
1325
|
var existing = (parentFormRef === null || parentFormRef === void 0 ? void 0 : parentFormRef.current) || {};
|
|
1287
|
-
return _objectSpread(_objectSpread({}, existing), {}, (0, _defineProperty2["default"])({},
|
|
1326
|
+
return _objectSpread(_objectSpread({}, existing), {}, (0, _defineProperty2["default"])({}, formIdRef.current, {
|
|
1288
1327
|
formreset: formreset,
|
|
1289
1328
|
validateFieldsOnSubmit: validateFieldsOnSubmit
|
|
1290
1329
|
}));
|
|
1291
|
-
}, [props.name, formreset, validateFieldsOnSubmit]);
|
|
1292
|
-
|
|
1330
|
+
}, [props.name, formIdRef.current, formreset, validateFieldsOnSubmit]);
|
|
1331
|
+
|
|
1332
|
+
// Provide current form's data to children via context
|
|
1333
|
+
// This ensures each form instance provides its own data, solving the
|
|
1334
|
+
// shared widget proxy problem for forms inside lists
|
|
1335
|
+
var parentFormDataContextValue = (0, _react.useMemo)(function () {
|
|
1336
|
+
return {
|
|
1337
|
+
formdata: currentFormData,
|
|
1338
|
+
formName: props.name
|
|
1339
|
+
};
|
|
1340
|
+
}, [currentFormData, props.name]);
|
|
1341
|
+
return __jsx(_formContext.ParentFormDataContext.Provider, {
|
|
1342
|
+
value: parentFormDataContextValue
|
|
1343
|
+
}, __jsx(_formContext.FormProvider, {
|
|
1293
1344
|
value: ref,
|
|
1294
1345
|
isViewMode: showViewMode
|
|
1295
1346
|
}, __jsx(WrappedComponent, (0, _extends2["default"])({}, formProps, {
|
|
1296
1347
|
formWidgets: formfields,
|
|
1297
1348
|
formfields: formfields
|
|
1298
|
-
})));
|
|
1349
|
+
}))));
|
|
1299
1350
|
};
|
|
1300
1351
|
return ControlledForm;
|
|
1301
1352
|
};
|
|
@@ -5,7 +5,7 @@ var _typeof = require("@babel/runtime/helpers/typeof");
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", {
|
|
6
6
|
value: true
|
|
7
7
|
});
|
|
8
|
-
exports.useIsViewMode = exports.useFormRef = exports.useFormContext = exports["default"] = exports.FormProvider = void 0;
|
|
8
|
+
exports.useParentFormData = exports.useIsViewMode = exports.useFormRef = exports.useFormContext = exports["default"] = exports.ParentFormDataContext = exports.FormProvider = void 0;
|
|
9
9
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
10
10
|
var _react = _interopRequireWildcard(require("react"));
|
|
11
11
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t2 in e) "default" !== _t2 && {}.hasOwnProperty.call(e, _t2) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t2)) && (i.get || i.set) ? o(f, _t2, i) : f[_t2] = e[_t2]); return f; })(e, t); }
|
|
@@ -13,6 +13,22 @@ var __jsx = _react["default"].createElement;
|
|
|
13
13
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
14
14
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2["default"])(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
15
15
|
var FormContext = /*#__PURE__*/(0, _react.createContext)(null);
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* ParentFormDataContext provides instance-specific form data to child forms.
|
|
19
|
+
*
|
|
20
|
+
* This solves the problem where multiple instances of the same form exist inside
|
|
21
|
+
* a list (e.g., DeptEmpContactForm2 at index 0, 1, 2). The shared Widgets proxy
|
|
22
|
+
* (Widgets["DeptEmpContactForm2"].formdata) is contaminated across instances.
|
|
23
|
+
*
|
|
24
|
+
* With this context, each form instance provides its own formdata, and child forms
|
|
25
|
+
* consume from the nearest parent provider - naturally scoping to the correct instance.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
var ParentFormDataContext = exports.ParentFormDataContext = /*#__PURE__*/(0, _react.createContext)(null);
|
|
29
|
+
var useParentFormData = exports.useParentFormData = function useParentFormData() {
|
|
30
|
+
return (0, _react.useContext)(ParentFormDataContext);
|
|
31
|
+
};
|
|
16
32
|
var FormProvider = exports.FormProvider = function FormProvider(_ref) {
|
|
17
33
|
var value = _ref.value,
|
|
18
34
|
isViewMode = _ref.isViewMode,
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.useValidationRules = exports.useHTMLValidationProps = exports.useFormRegistration = exports.useExternalDataSync = exports.useDefaultValueSync = void 0;
|
|
8
|
+
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
9
|
+
var _react = require("react");
|
|
10
|
+
var _validationContrustor = require("../validation-contrustor");
|
|
11
|
+
// Custom hooks for better separation of concerns
|
|
12
|
+
var useFormRegistration = exports.useFormRegistration = function useFormRegistration(name, fieldProxy, contextFormRef) {
|
|
13
|
+
var hasRegisteredRef = (0, _react.useRef)(false);
|
|
14
|
+
(0, _react.useEffect)(function () {
|
|
15
|
+
if (contextFormRef !== null && contextFormRef !== void 0 && contextFormRef.registerFormWidget && fieldProxy && !hasRegisteredRef.current) {
|
|
16
|
+
contextFormRef.registerFormWidget(name, fieldProxy);
|
|
17
|
+
hasRegisteredRef.current = true;
|
|
18
|
+
}
|
|
19
|
+
}, [fieldProxy, name, contextFormRef]);
|
|
20
|
+
};
|
|
21
|
+
var useExternalDataSync = exports.useExternalDataSync = function useExternalDataSync(datavalue, fieldRef) {
|
|
22
|
+
(0, _react.useEffect)(function () {
|
|
23
|
+
if (fieldRef.current && datavalue !== undefined) {
|
|
24
|
+
var currentValue = fieldRef.current.value;
|
|
25
|
+
if (currentValue !== datavalue) {
|
|
26
|
+
fieldRef.current.onChange(datavalue);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}, [datavalue]);
|
|
30
|
+
};
|
|
31
|
+
var useDefaultValueSync = exports.useDefaultValueSync = function useDefaultValueSync(defaultvalue, datavalue, fieldRef) {
|
|
32
|
+
var hasInitializedRef = (0, _react.useRef)(false);
|
|
33
|
+
var prevDefaultValueRef = (0, _react.useRef)(defaultvalue);
|
|
34
|
+
(0, _react.useEffect)(function () {
|
|
35
|
+
if (!fieldRef.current) return;
|
|
36
|
+
|
|
37
|
+
// Initial sync: only when datavalue is undefined and we haven't initialized yet
|
|
38
|
+
if (!hasInitializedRef.current && defaultvalue !== undefined && datavalue === undefined) {
|
|
39
|
+
var currentValue = fieldRef.current.value;
|
|
40
|
+
if (currentValue === undefined || currentValue === null || currentValue === "") {
|
|
41
|
+
fieldRef.current.onChange(defaultvalue);
|
|
42
|
+
hasInitializedRef.current = true;
|
|
43
|
+
}
|
|
44
|
+
prevDefaultValueRef.current = defaultvalue;
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Dynamic defaultvalue sync: when defaultvalue prop changes (e.g. conditional default from toggle)
|
|
49
|
+
// React Hook Form's Controller uses defaultValue only at registration; we must sync on prop change
|
|
50
|
+
if (prevDefaultValueRef.current !== defaultvalue) {
|
|
51
|
+
var _currentValue = fieldRef.current.value;
|
|
52
|
+
// Only update if current value matches previous default - user hasn't typed something different
|
|
53
|
+
var valueWasFromDefault = _currentValue === prevDefaultValueRef.current || prevDefaultValueRef.current === "" && (_currentValue === undefined || _currentValue === null || _currentValue === "");
|
|
54
|
+
if (valueWasFromDefault) {
|
|
55
|
+
fieldRef.current.onChange(defaultvalue);
|
|
56
|
+
}
|
|
57
|
+
prevDefaultValueRef.current = defaultvalue;
|
|
58
|
+
}
|
|
59
|
+
}, [defaultvalue, datavalue]);
|
|
60
|
+
};
|
|
61
|
+
var useValidationRules = exports.useValidationRules = function useValidationRules(validationType, validators, asyncValidators, required, maxchars, regexp, validationmessage, minvalue, maxvalue, form) {
|
|
62
|
+
if (validationType === "none") {
|
|
63
|
+
return {};
|
|
64
|
+
}
|
|
65
|
+
var combinedValidators = [].concat((0, _toConsumableArray2["default"])(validators || []), (0, _toConsumableArray2["default"])(asyncValidators || []));
|
|
66
|
+
var hasValidatorType = function hasValidatorType(type) {
|
|
67
|
+
return validators === null || validators === void 0 ? void 0 : validators.some(function (v) {
|
|
68
|
+
return typeof v !== "function" && v.type === type;
|
|
69
|
+
});
|
|
70
|
+
};
|
|
71
|
+
if (required && !hasValidatorType("required")) {
|
|
72
|
+
combinedValidators.push({
|
|
73
|
+
type: "required",
|
|
74
|
+
validator: true,
|
|
75
|
+
errorMessage: validationmessage || "This field is required"
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
if (maxchars !== undefined) {
|
|
79
|
+
combinedValidators.push({
|
|
80
|
+
type: "maxchars",
|
|
81
|
+
validator: maxchars,
|
|
82
|
+
errorMessage: validationmessage || "Maximum length is ".concat(maxchars, " characters.")
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
var normalizedMin = minvalue !== undefined && minvalue !== null && minvalue !== "" ? Number(minvalue) : undefined;
|
|
86
|
+
var normalizedMax = maxvalue !== undefined && maxvalue !== null && maxvalue !== "" ? Number(maxvalue) : undefined;
|
|
87
|
+
if (normalizedMin !== undefined && !Number.isNaN(normalizedMin)) {
|
|
88
|
+
combinedValidators.push({
|
|
89
|
+
type: "minvalue",
|
|
90
|
+
validator: normalizedMin,
|
|
91
|
+
errorMessage: validationmessage || "Value must be greater than or equal to ".concat(normalizedMin, ".")
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
if (normalizedMax !== undefined && !Number.isNaN(normalizedMax)) {
|
|
95
|
+
combinedValidators.push({
|
|
96
|
+
type: "maxvalue",
|
|
97
|
+
validator: normalizedMax,
|
|
98
|
+
errorMessage: validationmessage || "Value must be less than or equal to ".concat(normalizedMax, ".")
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
if (regexp) {
|
|
102
|
+
combinedValidators.push({
|
|
103
|
+
type: "regexp",
|
|
104
|
+
validator: regexp,
|
|
105
|
+
errorMessage: validationmessage || "Invalid format."
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
return (0, _validationContrustor.createValidationRules)(combinedValidators, form);
|
|
109
|
+
};
|
|
110
|
+
var useHTMLValidationProps = exports.useHTMLValidationProps = function useHTMLValidationProps(validationType, required, maxchars, regexp) {
|
|
111
|
+
return (0, _react.useMemo)(function () {
|
|
112
|
+
if (validationType !== "html") {
|
|
113
|
+
return {};
|
|
114
|
+
}
|
|
115
|
+
var htmlProps = {};
|
|
116
|
+
if (required) {
|
|
117
|
+
htmlProps.required = true;
|
|
118
|
+
}
|
|
119
|
+
if (maxchars) {
|
|
120
|
+
htmlProps.maxLength = maxchars;
|
|
121
|
+
}
|
|
122
|
+
if (regexp) {
|
|
123
|
+
htmlProps.pattern = typeof regexp === "string" ? regexp : regexp.source;
|
|
124
|
+
}
|
|
125
|
+
return htmlProps;
|
|
126
|
+
}, [validationType, required, maxchars, regexp]);
|
|
127
|
+
};
|