@ukhomeoffice/cop-react-form-renderer 4.13.1-alpha → 4.14.3
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/components/CollectionPage/CollectionPage.js +1 -0
- package/dist/components/FormComponent/Collection.js +2 -0
- package/dist/components/FormComponent/Container.js +4 -2
- package/dist/components/FormComponent/Container.test.js +18 -8
- package/dist/components/FormComponent/FormComponent.js +7 -3
- package/dist/components/FormPage/FormPage.js +2 -0
- package/dist/utils/CheckYourAnswers/getCYARowsForCollectionPage.js +4 -1
- package/dist/utils/CheckYourAnswers/getCYARowsForPage.js +4 -1
- package/dist/utils/Component/elevateNestedComponents.js +52 -0
- package/dist/utils/Component/elevateNestedComponents.test.js +92 -0
- package/dist/utils/Component/getComponent.js +7 -13
- package/dist/utils/Component/index.js +3 -0
- package/dist/utils/FormPage/useComponent.js +53 -10
- package/dist/utils/FormPage/useComponent.test.js +62 -5
- package/dist/utils/Validate/validateComponent.js +0 -1
- package/dist/utils/Validate/validateComponent.test.js +8 -8
- package/package.json +2 -2
|
@@ -120,6 +120,7 @@ var CollectionPage = function CollectionPage(_ref) {
|
|
|
120
120
|
}),
|
|
121
121
|
onAction: onInnerPageAction,
|
|
122
122
|
onWrapperChange: onInnerPageChange,
|
|
123
|
+
onTopLevelChange: onPageChange,
|
|
123
124
|
classBlock: classBlock,
|
|
124
125
|
classModifiers: classModifiers,
|
|
125
126
|
className: className
|
|
@@ -57,6 +57,7 @@ var Collection = function Collection(_ref) {
|
|
|
57
57
|
_value = _ref.value,
|
|
58
58
|
formData = _ref.formData,
|
|
59
59
|
onChange = _ref.onChange,
|
|
60
|
+
onTopLevelChange = _ref.onTopLevelChange,
|
|
60
61
|
wrap = _ref.wrap;
|
|
61
62
|
|
|
62
63
|
var _useState = (0, _react.useState)(_value),
|
|
@@ -195,6 +196,7 @@ var Collection = function Collection(_ref) {
|
|
|
195
196
|
value: item,
|
|
196
197
|
formData: formData,
|
|
197
198
|
onChange: onCollectionChange,
|
|
199
|
+
onTopLevelChange: onTopLevelChange,
|
|
198
200
|
wrap: wrap
|
|
199
201
|
}));
|
|
200
202
|
}), !config.disableAddAndRemove && /*#__PURE__*/_react.default.createElement(_copReactComponents.ButtonGroup, null, /*#__PURE__*/_react.default.createElement(_copReactComponents.Button, {
|
|
@@ -15,7 +15,7 @@ var _utils = _interopRequireDefault(require("../../utils"));
|
|
|
15
15
|
|
|
16
16
|
var _FormComponent = _interopRequireDefault(require("./FormComponent"));
|
|
17
17
|
|
|
18
|
-
var _excluded = ["container", "value", "formData", "onChange", "wrap"];
|
|
18
|
+
var _excluded = ["container", "value", "formData", "onChange", "wrap", "onTopLevelChange"];
|
|
19
19
|
|
|
20
20
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
21
21
|
|
|
@@ -40,6 +40,7 @@ var Container = function Container(_ref) {
|
|
|
40
40
|
formData = _ref.formData,
|
|
41
41
|
onChange = _ref.onChange,
|
|
42
42
|
wrap = _ref.wrap,
|
|
43
|
+
onTopLevelChange = _ref.onTopLevelChange,
|
|
43
44
|
attrs = _objectWithoutProperties(_ref, _excluded);
|
|
44
45
|
|
|
45
46
|
var onComponentChange = function onComponentChange(_ref2) {
|
|
@@ -88,7 +89,8 @@ var Container = function Container(_ref) {
|
|
|
88
89
|
formData: formData,
|
|
89
90
|
value: val || defaultValue,
|
|
90
91
|
wrap: wrap,
|
|
91
|
-
onChange: onComponentChange
|
|
92
|
+
onChange: onComponentChange,
|
|
93
|
+
onTopLevelChange: onTopLevelChange
|
|
92
94
|
}));
|
|
93
95
|
}));
|
|
94
96
|
};
|
|
@@ -212,7 +212,7 @@ describe('components.FormComponent.Container', function () {
|
|
|
212
212
|
}, _callee3);
|
|
213
213
|
})));
|
|
214
214
|
it('should handle a change to a file type component appropriately', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee4() {
|
|
215
|
-
var FILE_ID, ON_CHANGE_EVENTS, ON_CHANGE, CONTAINER, _renderWithValidation4, container, c, formGroup, input, FILE_EXTENSION, FILE_NAME, FILE_TYPE, str, blob, FILE, containerChangeValue, metaChangeValue;
|
|
215
|
+
var FILE_ID, ON_CHANGE_EVENTS, ON_CHANGE, ON_TOP_LEVEL_CHANGE_EVENTS, ON_TOP_LEVEL_CHANGE, CONTAINER, _renderWithValidation4, container, c, formGroup, input, FILE_EXTENSION, FILE_NAME, FILE_TYPE, str, blob, FILE, containerChangeValue, metaChangeValue;
|
|
216
216
|
|
|
217
217
|
return regeneratorRuntime.wrap(function _callee4$(_context4) {
|
|
218
218
|
while (1) {
|
|
@@ -225,6 +225,12 @@ describe('components.FormComponent.Container', function () {
|
|
|
225
225
|
ON_CHANGE_EVENTS.push(e);
|
|
226
226
|
};
|
|
227
227
|
|
|
228
|
+
ON_TOP_LEVEL_CHANGE_EVENTS = [];
|
|
229
|
+
|
|
230
|
+
ON_TOP_LEVEL_CHANGE = function ON_TOP_LEVEL_CHANGE(e) {
|
|
231
|
+
ON_TOP_LEVEL_CHANGE_EVENTS.push(e);
|
|
232
|
+
};
|
|
233
|
+
|
|
228
234
|
CONTAINER = {
|
|
229
235
|
id: ID,
|
|
230
236
|
fieldId: ID,
|
|
@@ -241,7 +247,8 @@ describe('components.FormComponent.Container', function () {
|
|
|
241
247
|
component: CONTAINER,
|
|
242
248
|
value: FORM_DATA[ID],
|
|
243
249
|
formData: FORM_DATA,
|
|
244
|
-
onChange: ON_CHANGE
|
|
250
|
+
onChange: ON_CHANGE,
|
|
251
|
+
onTopLevelChange: ON_TOP_LEVEL_CHANGE
|
|
245
252
|
})), container = _renderWithValidation4.container; // Get hold of the text input.
|
|
246
253
|
|
|
247
254
|
c = container.childNodes[0];
|
|
@@ -258,22 +265,25 @@ describe('components.FormComponent.Container', function () {
|
|
|
258
265
|
type: FILE_TYPE
|
|
259
266
|
});
|
|
260
267
|
|
|
261
|
-
_userEvent.default.upload(input, FILE); //
|
|
268
|
+
_userEvent.default.upload(input, FILE); // Expect one call for the regular onChange event, this can change
|
|
269
|
+
// depending on whether the Container is on a normal page or regular page.
|
|
262
270
|
|
|
263
271
|
|
|
264
|
-
expect(ON_CHANGE_EVENTS.length).toEqual(
|
|
272
|
+
expect(ON_CHANGE_EVENTS.length).toEqual(1);
|
|
273
|
+
expect(ON_CHANGE_EVENTS[0].target.name).toEqual(ID); // Expect one call for changing the meta data at top level formData.
|
|
274
|
+
// Meta changes should occur at top-level regardless of where the component is.
|
|
265
275
|
|
|
266
|
-
expect(
|
|
267
|
-
expect(
|
|
276
|
+
expect(ON_TOP_LEVEL_CHANGE_EVENTS.length).toEqual(1);
|
|
277
|
+
expect(ON_TOP_LEVEL_CHANGE_EVENTS[0].target.name).toEqual(_constants.META_PROPERTY);
|
|
268
278
|
containerChangeValue = JSON.parse(JSON.stringify(ON_CHANGE_EVENTS[0].target.value));
|
|
269
|
-
metaChangeValue = JSON.parse(JSON.stringify(
|
|
279
|
+
metaChangeValue = JSON.parse(JSON.stringify(ON_TOP_LEVEL_CHANGE_EVENTS[0].target.value));
|
|
270
280
|
expect(metaChangeValue.documents.length).toEqual(2); // Existing one, plus this new one.
|
|
271
281
|
|
|
272
282
|
expect(metaChangeValue.documents[1]).toMatchObject(_objectSpread(_objectSpread({}, containerChangeValue[FILE_ID]), {}, {
|
|
273
283
|
field: "".concat(ID, ".").concat(FILE_ID)
|
|
274
284
|
}));
|
|
275
285
|
|
|
276
|
-
case
|
|
286
|
+
case 25:
|
|
277
287
|
case "end":
|
|
278
288
|
return _context4.stop();
|
|
279
289
|
}
|
|
@@ -25,7 +25,7 @@ var _Container = _interopRequireDefault(require("./Container"));
|
|
|
25
25
|
|
|
26
26
|
var _helpers = require("./helpers");
|
|
27
27
|
|
|
28
|
-
var _excluded = ["component", "value", "formData", "wrap", "onChange"];
|
|
28
|
+
var _excluded = ["component", "value", "formData", "wrap", "onChange", "onTopLevelChange"];
|
|
29
29
|
|
|
30
30
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
31
31
|
|
|
@@ -63,6 +63,7 @@ var FormComponent = function FormComponent(_ref) {
|
|
|
63
63
|
formData = _ref.formData,
|
|
64
64
|
wrap = _ref.wrap,
|
|
65
65
|
onChange = _ref.onChange,
|
|
66
|
+
onTopLevelChange = _ref.onTopLevelChange,
|
|
66
67
|
attrs = _objectWithoutProperties(_ref, _excluded);
|
|
67
68
|
|
|
68
69
|
var _useHooks = (0, _hooks.useHooks)(),
|
|
@@ -103,6 +104,7 @@ var FormComponent = function FormComponent(_ref) {
|
|
|
103
104
|
container: component,
|
|
104
105
|
wrap: wrap,
|
|
105
106
|
onChange: onComponentChange,
|
|
107
|
+
onTopLevelChange: onTopLevelChange,
|
|
106
108
|
value: value || _utils.default.Component.defaultValue(component),
|
|
107
109
|
formData: formData
|
|
108
110
|
}));
|
|
@@ -119,13 +121,14 @@ var FormComponent = function FormComponent(_ref) {
|
|
|
119
121
|
config: component,
|
|
120
122
|
wrap: wrap,
|
|
121
123
|
onChange: onComponentChange,
|
|
124
|
+
onTopLevelChange: onTopLevelChange,
|
|
122
125
|
value: value || _utils.default.Component.defaultValue(component),
|
|
123
126
|
formData: formData
|
|
124
127
|
}));
|
|
125
128
|
}
|
|
126
129
|
|
|
127
130
|
var changeMetaDocuments = function changeMetaDocuments(document) {
|
|
128
|
-
|
|
131
|
+
onTopLevelChange({
|
|
129
132
|
target: {
|
|
130
133
|
name: _utils.default.Meta.name,
|
|
131
134
|
value: _utils.default.Meta.documents.setForField(document, formData, component.full_path)
|
|
@@ -174,7 +177,8 @@ FormComponent.propTypes = {
|
|
|
174
177
|
value: _propTypes.default.any,
|
|
175
178
|
formData: _propTypes.default.any,
|
|
176
179
|
wrap: _propTypes.default.bool,
|
|
177
|
-
onChange: _propTypes.default.func
|
|
180
|
+
onChange: _propTypes.default.func,
|
|
181
|
+
onTopLevelChange: _propTypes.default.func
|
|
178
182
|
};
|
|
179
183
|
FormComponent.defaultProps = {
|
|
180
184
|
wrap: true
|
|
@@ -56,6 +56,7 @@ var FormPage = function FormPage(_ref) {
|
|
|
56
56
|
var page = _ref.page,
|
|
57
57
|
_onAction = _ref.onAction,
|
|
58
58
|
onWrapperChange = _ref.onWrapperChange,
|
|
59
|
+
onTopLevelChange = _ref.onTopLevelChange,
|
|
59
60
|
classBlock = _ref.classBlock,
|
|
60
61
|
classModifiers = _ref.classModifiers,
|
|
61
62
|
className = _ref.className;
|
|
@@ -102,6 +103,7 @@ var FormPage = function FormPage(_ref) {
|
|
|
102
103
|
key: index,
|
|
103
104
|
component: component,
|
|
104
105
|
onChange: onWrapperChange || onPageChange,
|
|
106
|
+
onTopLevelChange: onTopLevelChange || onPageChange,
|
|
105
107
|
value: page.formData[component.fieldId] || patch[component.fieldId],
|
|
106
108
|
formData: page.formData
|
|
107
109
|
});
|
|
@@ -7,6 +7,8 @@ exports.default = void 0;
|
|
|
7
7
|
|
|
8
8
|
var _copReactComponents = require("@ukhomeoffice/cop-react-components");
|
|
9
9
|
|
|
10
|
+
var _elevateNestedComponents = _interopRequireDefault(require("../Component/elevateNestedComponents"));
|
|
11
|
+
|
|
10
12
|
var _models = require("../../models");
|
|
11
13
|
|
|
12
14
|
var _getCYARowsForContainer = _interopRequireDefault(require("./getCYARowsForContainer"));
|
|
@@ -24,13 +26,14 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
|
|
|
24
26
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
25
27
|
|
|
26
28
|
var getContainerForPage = function getContainerForPage(page, item, labelCount, full_path) {
|
|
29
|
+
var allComponents = (0, _elevateNestedComponents.default)(page.components, item);
|
|
27
30
|
return {
|
|
28
31
|
id: item.id,
|
|
29
32
|
fieldId: item.id,
|
|
30
33
|
type: _models.ComponentTypes.CONTAINER,
|
|
31
34
|
required: true,
|
|
32
35
|
full_path: full_path,
|
|
33
|
-
components:
|
|
36
|
+
components: allComponents.map(function (component) {
|
|
34
37
|
return _objectSpread(_objectSpread({}, component), {}, {
|
|
35
38
|
label: _copReactComponents.Utils.interpolateString(component.label, _objectSpread(_objectSpread({}, item), {}, {
|
|
36
39
|
index: labelCount
|
|
@@ -5,6 +5,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
|
|
8
|
+
var _elevateNestedComponents = _interopRequireDefault(require("../Component/elevateNestedComponents"));
|
|
9
|
+
|
|
8
10
|
var _models = require("../../models");
|
|
9
11
|
|
|
10
12
|
var _FormPage = _interopRequireDefault(require("../FormPage"));
|
|
@@ -41,7 +43,8 @@ var getCYARowsForPage = function getCYARowsForPage(page, onAction) {
|
|
|
41
43
|
return (0, _getCYARowsForCollectionPage.default)(page, onAction);
|
|
42
44
|
}
|
|
43
45
|
|
|
44
|
-
var
|
|
46
|
+
var allComponents = (0, _elevateNestedComponents.default)(page.components, page.formData);
|
|
47
|
+
var rows = allComponents.filter(function (c) {
|
|
45
48
|
return (0, _showComponentCYA.default)(c, page.formData);
|
|
46
49
|
}).flatMap(function (component) {
|
|
47
50
|
switch (component.type) {
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Iterates over an array of components and brings any nested
|
|
10
|
+
* components that should be visible into the top level array.
|
|
11
|
+
* The values provided in data are used to determine if any
|
|
12
|
+
* nested components should be visible.
|
|
13
|
+
*
|
|
14
|
+
* Given this structure in the components array:
|
|
15
|
+
* - Radios
|
|
16
|
+
* - Radio Option 1 (Not selected)
|
|
17
|
+
* - Nested 1
|
|
18
|
+
* - Nested 2
|
|
19
|
+
* - Radio Option 2 (Selected)
|
|
20
|
+
* - Nested 3
|
|
21
|
+
* - Text Input
|
|
22
|
+
*
|
|
23
|
+
* The result will be the following array:
|
|
24
|
+
* - Radios
|
|
25
|
+
* - Nested 3
|
|
26
|
+
* - Text Input
|
|
27
|
+
*
|
|
28
|
+
* @param {*} components An array of components.
|
|
29
|
+
* @param {*} data A chunk of form data used to determine if
|
|
30
|
+
* any nested components are visible or not.
|
|
31
|
+
* @returns A new array consisting of components interspersed
|
|
32
|
+
* with any visible nested components.
|
|
33
|
+
*/
|
|
34
|
+
var elevateNestedComponents = function elevateNestedComponents(components, data) {
|
|
35
|
+
var allComponents = [];
|
|
36
|
+
components === null || components === void 0 ? void 0 : components.forEach(function (component) {
|
|
37
|
+
var _component$data, _component$data$optio;
|
|
38
|
+
|
|
39
|
+
allComponents.push(component);
|
|
40
|
+
(_component$data = component.data) === null || _component$data === void 0 ? void 0 : (_component$data$optio = _component$data.options) === null || _component$data$optio === void 0 ? void 0 : _component$data$optio.forEach(function (option) {
|
|
41
|
+
// If this option has nested components and is
|
|
42
|
+
// selected, then add its nested components to the array.
|
|
43
|
+
if (Array.isArray(option.nested) && data[component.id] === option.value) {
|
|
44
|
+
allComponents = allComponents.concat(option.nested);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
return allComponents;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
var _default = elevateNestedComponents;
|
|
52
|
+
exports.default = _default;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _elevateNestedComponents = _interopRequireDefault(require("./elevateNestedComponents"));
|
|
4
|
+
|
|
5
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
6
|
+
|
|
7
|
+
describe('utils.Component.elevateNestedComponents', function () {
|
|
8
|
+
it('should return an empty array if components is undefined', function () {
|
|
9
|
+
var DATA = {
|
|
10
|
+
alpha: 'abc'
|
|
11
|
+
};
|
|
12
|
+
expect((0, _elevateNestedComponents.default)(undefined, DATA)).toEqual([]);
|
|
13
|
+
});
|
|
14
|
+
it('should return an empty array if components is null', function () {
|
|
15
|
+
var DATA = {
|
|
16
|
+
alpha: 'abc'
|
|
17
|
+
};
|
|
18
|
+
expect((0, _elevateNestedComponents.default)(null, DATA)).toEqual([]);
|
|
19
|
+
});
|
|
20
|
+
it('should return an empty array if components is empty', function () {
|
|
21
|
+
var DATA = {
|
|
22
|
+
alpha: 'abc'
|
|
23
|
+
};
|
|
24
|
+
expect((0, _elevateNestedComponents.default)([], DATA)).toEqual([]);
|
|
25
|
+
});
|
|
26
|
+
it('should return the original components if none have nested components', function () {
|
|
27
|
+
var COMPONENTS = [{
|
|
28
|
+
id: 'textComp'
|
|
29
|
+
}, {
|
|
30
|
+
id: 'radiosComp',
|
|
31
|
+
data: {
|
|
32
|
+
options: [{
|
|
33
|
+
label: 'Yes',
|
|
34
|
+
value: 'yes'
|
|
35
|
+
}, {
|
|
36
|
+
label: 'No',
|
|
37
|
+
value: 'no'
|
|
38
|
+
}]
|
|
39
|
+
}
|
|
40
|
+
}];
|
|
41
|
+
var DATA = {
|
|
42
|
+
alpha: 'abc'
|
|
43
|
+
};
|
|
44
|
+
expect((0, _elevateNestedComponents.default)(COMPONENTS, DATA)).toEqual(COMPONENTS);
|
|
45
|
+
});
|
|
46
|
+
it('should return the original components if data is null', function () {
|
|
47
|
+
var COMPONENTS = [{
|
|
48
|
+
id: 'textComp'
|
|
49
|
+
}, {
|
|
50
|
+
id: 'radiosComp',
|
|
51
|
+
data: {
|
|
52
|
+
options: [{
|
|
53
|
+
label: 'Yes',
|
|
54
|
+
value: 'yes'
|
|
55
|
+
}, {
|
|
56
|
+
label: 'No',
|
|
57
|
+
value: 'no'
|
|
58
|
+
}]
|
|
59
|
+
}
|
|
60
|
+
}];
|
|
61
|
+
expect((0, _elevateNestedComponents.default)(COMPONENTS, null)).toEqual(COMPONENTS);
|
|
62
|
+
});
|
|
63
|
+
it('should return the original array with elevated nested components when they are visible', function () {
|
|
64
|
+
var COMPONENTS = [{
|
|
65
|
+
id: 'textComp'
|
|
66
|
+
}, {
|
|
67
|
+
id: 'radiosComp',
|
|
68
|
+
data: {
|
|
69
|
+
options: [{
|
|
70
|
+
label: 'Yes',
|
|
71
|
+
value: 'yes',
|
|
72
|
+
nested: [{
|
|
73
|
+
id: 'nestedOne'
|
|
74
|
+
}, {
|
|
75
|
+
id: 'nestedTwo'
|
|
76
|
+
}]
|
|
77
|
+
}, {
|
|
78
|
+
label: 'No',
|
|
79
|
+
value: 'no'
|
|
80
|
+
}]
|
|
81
|
+
}
|
|
82
|
+
}];
|
|
83
|
+
var DATA = {
|
|
84
|
+
radiosComp: 'yes'
|
|
85
|
+
};
|
|
86
|
+
expect((0, _elevateNestedComponents.default)(COMPONENTS, DATA)).toEqual([].concat(COMPONENTS, [{
|
|
87
|
+
id: 'nestedOne'
|
|
88
|
+
}, {
|
|
89
|
+
id: 'nestedTwo'
|
|
90
|
+
}]));
|
|
91
|
+
});
|
|
92
|
+
});
|
|
@@ -25,23 +25,12 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
|
|
|
25
25
|
|
|
26
26
|
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
27
27
|
|
|
28
|
-
var setupChildrenJSX = function setupChildrenJSX(options, config) {
|
|
29
|
-
options.forEach(function (option) {
|
|
30
|
-
if (!Array.isArray(option.nested)) {
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
option.children = getChildrenJsx(config, option.nested);
|
|
35
|
-
});
|
|
36
|
-
};
|
|
37
28
|
/**
|
|
38
29
|
* Separate function for each component type for the sake of
|
|
39
30
|
* code clarity - having the additional bits and pieces in the
|
|
40
31
|
* switch statement increases the cyclomatic complexity and
|
|
41
32
|
* makes it much harder to follow what's going on.
|
|
42
33
|
*/
|
|
43
|
-
|
|
44
|
-
|
|
45
34
|
var getAutocomplete = function getAutocomplete(config) {
|
|
46
35
|
var attrs = (0, _cleanAttributes.default)(config);
|
|
47
36
|
|
|
@@ -59,7 +48,6 @@ var getCheckboxes = function getCheckboxes(config) {
|
|
|
59
48
|
options = val;
|
|
60
49
|
});
|
|
61
50
|
|
|
62
|
-
setupChildrenJSX(options, config);
|
|
63
51
|
var attrs = (0, _cleanAttributes.default)(config);
|
|
64
52
|
return /*#__PURE__*/_react.default.createElement(_copReactComponents.Checkboxes, _extends({}, attrs, {
|
|
65
53
|
options: options
|
|
@@ -118,7 +106,13 @@ var getRadios = function getRadios(config) {
|
|
|
118
106
|
options = val;
|
|
119
107
|
});
|
|
120
108
|
|
|
121
|
-
|
|
109
|
+
options.forEach(function (option) {
|
|
110
|
+
if (!Array.isArray(option.nested)) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
option.children = getChildrenJsx(config, option.nested);
|
|
115
|
+
});
|
|
122
116
|
var attrs = (0, _cleanAttributes.default)(config);
|
|
123
117
|
return /*#__PURE__*/_react.default.createElement(_copReactComponents.Radios, _extends({}, attrs, {
|
|
124
118
|
options: options
|
|
@@ -7,6 +7,8 @@ exports.default = void 0;
|
|
|
7
7
|
|
|
8
8
|
var _cleanAttributes = _interopRequireDefault(require("./cleanAttributes"));
|
|
9
9
|
|
|
10
|
+
var _elevateNestedComponents = _interopRequireDefault(require("./elevateNestedComponents"));
|
|
11
|
+
|
|
10
12
|
var _getComponent = _interopRequireDefault(require("./getComponent"));
|
|
11
13
|
|
|
12
14
|
var _getDefaultValue = _interopRequireDefault(require("./getDefaultValue"));
|
|
@@ -23,6 +25,7 @@ var Component = {
|
|
|
23
25
|
clean: _cleanAttributes.default,
|
|
24
26
|
defaultValue: _getDefaultValue.default,
|
|
25
27
|
editable: _isEditable.default,
|
|
28
|
+
elevateNested: _elevateNestedComponents.default,
|
|
26
29
|
get: _getComponent.default,
|
|
27
30
|
show: _showComponent.default,
|
|
28
31
|
wrap: _wrapInFormGroup.default
|
|
@@ -11,6 +11,47 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
|
|
|
11
11
|
|
|
12
12
|
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
13
13
|
|
|
14
|
+
var getComponentToUse = function getComponentToUse(toUse, formComponents) {
|
|
15
|
+
var path = toUse.use.split('.');
|
|
16
|
+
var firstId = path.shift();
|
|
17
|
+
|
|
18
|
+
var wrapper = _objectSpread({}, formComponents.find(function (fc) {
|
|
19
|
+
return fc.id === firstId;
|
|
20
|
+
}));
|
|
21
|
+
|
|
22
|
+
var parent = wrapper;
|
|
23
|
+
|
|
24
|
+
var _loop = function _loop() {
|
|
25
|
+
var id = path.shift();
|
|
26
|
+
|
|
27
|
+
if (Array.isArray(parent.components)) {
|
|
28
|
+
// Filter the parent components down to just the one referenced
|
|
29
|
+
// by the current id.
|
|
30
|
+
parent.components = parent.components.filter(function (c) {
|
|
31
|
+
return c.id === id;
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
if (parent.components.length > 0) {
|
|
35
|
+
// Make the found child the parent so we can iterate.
|
|
36
|
+
parent = parent.components[0];
|
|
37
|
+
} else {
|
|
38
|
+
// If no child was found, there can be no parent.
|
|
39
|
+
parent = undefined;
|
|
40
|
+
}
|
|
41
|
+
} else {
|
|
42
|
+
// We cannot find the child with this id if there are no child
|
|
43
|
+
// components on this parent.
|
|
44
|
+
parent = undefined;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
while (parent && path.length > 0) {
|
|
49
|
+
_loop();
|
|
50
|
+
} // If we missed a nested reference along the way, don't return the wrapper.
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
return parent ? wrapper : undefined;
|
|
54
|
+
};
|
|
14
55
|
/**
|
|
15
56
|
* Use an existing component from the formComponents, overriding any properties
|
|
16
57
|
* where appropriate.
|
|
@@ -18,17 +59,19 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
|
|
|
18
59
|
* @param {Array} formComponents An array of existing components on the form.
|
|
19
60
|
* @returns A component configuration object.
|
|
20
61
|
*/
|
|
62
|
+
|
|
63
|
+
|
|
21
64
|
var useComponent = function useComponent(toUse, formComponents) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
65
|
+
if (toUse) {
|
|
66
|
+
var component = getComponentToUse(toUse, formComponents);
|
|
67
|
+
|
|
68
|
+
if (component) {
|
|
69
|
+
var fieldId = toUse.fieldId || component.fieldId;
|
|
70
|
+
return _objectSpread(_objectSpread(_objectSpread({}, component), toUse), {}, {
|
|
71
|
+
cya_label: component.label || component.cya_label,
|
|
72
|
+
fieldId: fieldId
|
|
73
|
+
});
|
|
74
|
+
}
|
|
32
75
|
}
|
|
33
76
|
|
|
34
77
|
return _objectSpread({}, toUse);
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
var _models = require("../../models");
|
|
4
|
+
|
|
3
5
|
var _useComponent = _interopRequireDefault(require("./useComponent"));
|
|
4
6
|
|
|
5
7
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -13,27 +15,45 @@ function _defineProperty(obj, key, value) { if (key in obj) { Object.definePrope
|
|
|
13
15
|
describe('utils', function () {
|
|
14
16
|
describe('FormPage', function () {
|
|
15
17
|
describe('useComponent', function () {
|
|
18
|
+
var ZULU = {
|
|
19
|
+
id: 'z',
|
|
20
|
+
fieldId: 'z',
|
|
21
|
+
label: 'Zulu',
|
|
22
|
+
type: _models.ComponentTypes.TEXT
|
|
23
|
+
};
|
|
24
|
+
var CONTAINER = {
|
|
25
|
+
id: 'container',
|
|
26
|
+
fieldId: 'container',
|
|
27
|
+
label: 'Container',
|
|
28
|
+
type: _models.ComponentTypes.CONTAINER,
|
|
29
|
+
components: [{
|
|
30
|
+
id: 'f',
|
|
31
|
+
fieldId: 'f',
|
|
32
|
+
label: 'Foxtrot',
|
|
33
|
+
type: _models.ComponentTypes.TEXT
|
|
34
|
+
}, ZULU]
|
|
35
|
+
};
|
|
16
36
|
var FORM_COMPONENTS = [{
|
|
17
37
|
id: 'a',
|
|
18
38
|
fieldId: 'a',
|
|
19
39
|
label: 'Alpha',
|
|
20
|
-
type:
|
|
40
|
+
type: _models.ComponentTypes.TEXT
|
|
21
41
|
}, {
|
|
22
42
|
id: 'b',
|
|
23
43
|
fieldId: 'b',
|
|
24
44
|
label: 'Bravo',
|
|
25
|
-
type:
|
|
45
|
+
type: _models.ComponentTypes.TEXT
|
|
26
46
|
}, {
|
|
27
47
|
id: 'c',
|
|
28
48
|
fieldId: 'c',
|
|
29
49
|
label: 'Charlie',
|
|
30
|
-
type:
|
|
50
|
+
type: _models.ComponentTypes.TEXT
|
|
31
51
|
}, {
|
|
32
52
|
id: 'd',
|
|
33
53
|
fieldId: 'd',
|
|
34
54
|
cya_label: 'Delta',
|
|
35
|
-
type:
|
|
36
|
-
}];
|
|
55
|
+
type: _models.ComponentTypes.TEXT
|
|
56
|
+
}, CONTAINER];
|
|
37
57
|
it('should handle a null toUse configuration', function () {
|
|
38
58
|
var TO_USE = null;
|
|
39
59
|
expect((0, _useComponent.default)(TO_USE, FORM_COMPONENTS)).toEqual({});
|
|
@@ -107,6 +127,43 @@ describe('utils', function () {
|
|
|
107
127
|
label: TO_USE.label
|
|
108
128
|
}));
|
|
109
129
|
});
|
|
130
|
+
it('should handle a container', function () {
|
|
131
|
+
var TO_USE = {
|
|
132
|
+
use: CONTAINER.id
|
|
133
|
+
};
|
|
134
|
+
expect((0, _useComponent.default)(TO_USE, FORM_COMPONENTS)).toEqual(_objectSpread(_objectSpread({
|
|
135
|
+
use: CONTAINER.id
|
|
136
|
+
}, CONTAINER), {}, {
|
|
137
|
+
cya_label: CONTAINER.label
|
|
138
|
+
}));
|
|
139
|
+
});
|
|
140
|
+
it('should handle a component nested inside a container', function () {
|
|
141
|
+
var ID = "".concat(CONTAINER.id, ".").concat(ZULU.id);
|
|
142
|
+
var TO_USE = {
|
|
143
|
+
use: ID
|
|
144
|
+
};
|
|
145
|
+
expect((0, _useComponent.default)(TO_USE, FORM_COMPONENTS)).toEqual(_objectSpread(_objectSpread({
|
|
146
|
+
use: ID
|
|
147
|
+
}, CONTAINER), {}, {
|
|
148
|
+
cya_label: CONTAINER.label,
|
|
149
|
+
components: [ZULU // Foxtrot is not included
|
|
150
|
+
]
|
|
151
|
+
}));
|
|
152
|
+
});
|
|
153
|
+
it('should handle an unrecognised container reference', function () {
|
|
154
|
+
var ID = "unrecognised.".concat(ZULU.id);
|
|
155
|
+
var TO_USE = {
|
|
156
|
+
use: ID
|
|
157
|
+
};
|
|
158
|
+
expect((0, _useComponent.default)(TO_USE, FORM_COMPONENTS)).toEqual(TO_USE);
|
|
159
|
+
});
|
|
160
|
+
it('should handle an unrecognised component within a container', function () {
|
|
161
|
+
var ID = "".concat(CONTAINER.id, ".unrecognised");
|
|
162
|
+
var TO_USE = {
|
|
163
|
+
use: ID
|
|
164
|
+
};
|
|
165
|
+
expect((0, _useComponent.default)(TO_USE, FORM_COMPONENTS)).toEqual(TO_USE);
|
|
166
|
+
});
|
|
110
167
|
});
|
|
111
168
|
});
|
|
112
169
|
});
|
|
@@ -79,7 +79,6 @@ var validateComponent = function validateComponent(component, outerData, formDat
|
|
|
79
79
|
error = message;
|
|
80
80
|
break;
|
|
81
81
|
|
|
82
|
-
case _models.ComponentTypes.CHECKBOXES:
|
|
83
82
|
case _models.ComponentTypes.RADIOS:
|
|
84
83
|
var nestedErrors = [];
|
|
85
84
|
(_component$data$optio = component.data.options) === null || _component$data$optio === void 0 ? void 0 : _component$data$optio.forEach(function (option) {
|
|
@@ -200,19 +200,19 @@ describe('utils.Validate.Component', function () {
|
|
|
200
200
|
});
|
|
201
201
|
});
|
|
202
202
|
describe('when the component has a nested component', function () {
|
|
203
|
-
it
|
|
203
|
+
it('should return no error when the radio component contains nested components without errors', function () {
|
|
204
204
|
var NESTED_ID = 'nestedId';
|
|
205
205
|
var NESTED_VALUE = 'nestedValue';
|
|
206
206
|
|
|
207
207
|
var FORMDATA = _defineProperty({}, NESTED_ID, NESTED_VALUE);
|
|
208
208
|
|
|
209
209
|
var COMPONENT = {
|
|
210
|
-
type:
|
|
210
|
+
type: 'radios',
|
|
211
211
|
id: 'a',
|
|
212
212
|
data: {
|
|
213
213
|
options: [{
|
|
214
214
|
nested: [{
|
|
215
|
-
type:
|
|
215
|
+
type: 'text',
|
|
216
216
|
fieldId: NESTED_ID,
|
|
217
217
|
id: NESTED_ID,
|
|
218
218
|
required: true
|
|
@@ -222,16 +222,16 @@ describe('utils.Validate.Component', function () {
|
|
|
222
222
|
};
|
|
223
223
|
expect((0, _validateComponent.default)(COMPONENT, undefined, FORMDATA)).toBeUndefined();
|
|
224
224
|
});
|
|
225
|
-
it
|
|
225
|
+
it('should return an error when the radio component contains nested components with errors', function () {
|
|
226
226
|
var NESTED_ID = 'nestedId';
|
|
227
227
|
var FORMDATA = {};
|
|
228
228
|
var COMPONENT = {
|
|
229
|
-
type:
|
|
229
|
+
type: 'radios',
|
|
230
230
|
id: 'a',
|
|
231
231
|
data: {
|
|
232
232
|
options: [{
|
|
233
233
|
nested: [{
|
|
234
|
-
type:
|
|
234
|
+
type: 'text',
|
|
235
235
|
fieldId: NESTED_ID,
|
|
236
236
|
id: NESTED_ID,
|
|
237
237
|
required: true
|
|
@@ -244,10 +244,10 @@ describe('utils.Validate.Component', function () {
|
|
|
244
244
|
error: "Field is required"
|
|
245
245
|
}]);
|
|
246
246
|
});
|
|
247
|
-
it
|
|
247
|
+
it('should return no error when a non selected radio component contains nested components with errors', function () {
|
|
248
248
|
var NESTED_ID = 'nestedId';
|
|
249
249
|
var COMPONENT = {
|
|
250
|
-
type:
|
|
250
|
+
type: 'radios',
|
|
251
251
|
id: 'a',
|
|
252
252
|
data: {
|
|
253
253
|
options: [{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ukhomeoffice/cop-react-form-renderer",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.14.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"scripts": {
|
|
6
6
|
"clean": "rimraf dist",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"post-compile": "rimraf dist/*.test.* dist/**/*.test.* dist/**/*.stories.* dist/docs dist/assets"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@ukhomeoffice/cop-react-components": "2.2.3
|
|
19
|
+
"@ukhomeoffice/cop-react-components": "2.2.3",
|
|
20
20
|
"axios": "^0.23.0",
|
|
21
21
|
"dayjs": "^1.11.0",
|
|
22
22
|
"govuk-frontend": "^4.3.1",
|