@ukhomeoffice/cop-react-form-renderer 6.14.8 → 6.15.0-alpha
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/CollectionSummary/BannerStrip.scss +0 -4
- package/dist/components/FormPage/FormPage.js +10 -8
- package/dist/components/FormRenderer/FormRenderer.js +10 -5
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-chained-component-show-whens-containerised.json +119 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-chained-component-show-whens-dependent-component-nested-block.json +112 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-chained-component-show-whens-dependent-component-nested.json +105 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-chained-component-show-whens-refdata.json +105 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-chained-component-show-whens-target-component-nested.json +98 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-chained-component-show-whens.json +105 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-chained-show-whens-page-hidden.json +112 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-cop-airpax.json +26407 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-cop-mandec.json +9404 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-collection-component-dependent-on-external-data.json +157 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-collection-component.json +85 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-component-referring-to-collection.json +172 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-component-referring-to-hidden-collection.json +201 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-component-with-nested-questions.json +111 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-component.json +57 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-containerised-component.json +96 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-embedded-collection-component.json +82 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-embedded-component.json +54 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-multilevel-containerised-component-leaf-hidden.json +105 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-multilevel-containerised-component.json +105 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-options.json +98 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-page-collection.json +127 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-page-component-used-elsewhere.json +108 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-page.json +95 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-nested-answers-hidden-by-option.json +111 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/cop-airpax-remove-photos-before.json +384 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/cop-mandec-remove-business-interests-before.json +140 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/cop-mandec-remove-criminality-before.json +186 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-chained-component-show-whens-containerised.json +11 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-chained-component-show-whens-dependent-component-nested-block.json +10 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-chained-component-show-whens-dependent-component-nested.json +9 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-chained-component-show-whens-refdata.json +11 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-chained-component-show-whens-target-component-nested.json +9 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-chained-component-show-whens.json +9 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-chained-show-whens-page-hidden.json +9 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-collection-component-dependent-on-external-data.json +26 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-collection-component.json +15 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-component-referring-to-collection.json +25 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-component-referring-to-hidden-collection.json +26 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-component-with-nested-questions.json +12 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-component.json +5 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-containerised-component.json +11 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-embedded-collection-component.json +15 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-embedded-component.json +5 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-multilevel-containerised-component-leaf-hidden.json +14 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-multilevel-containerised-component.json +14 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-options.json +10 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-page-collection.json +18 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-page-component-used-elsewhere.json +9 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-page.json +9 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-nested-answers-hidden-by-option.json +12 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/cop-airpax-remove-photos-after.json +355 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/cop-mandec-base-file.json +80 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/cop-mandec-remove-business-interests-after.json +122 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/cop-mandec-remove-criminality-after.json +86 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-chained-component-show-whens-containerised-removed.json +11 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-chained-component-show-whens-dependent-component-nested-block-removed.json +7 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-chained-component-show-whens-dependent-component-nested-removed.json +7 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-chained-component-show-whens-refdata-removed.json +7 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-chained-component-show-whens-removed.json +7 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-chained-component-show-whens-target-component-nested-removed.json +6 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-chained-show-whens-page-hidden-removed.json +6 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-collection-component-dependent-on-external-data-removed.json +23 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-collection-component-removed.json +4 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-component-referring-to-collection-removed.json +21 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-component-referring-to-hidden-collection-removed.json +6 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-component-removed.json +4 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-component-with-nested-questions-removed.json +10 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-containerised-component-removed.json +10 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-embedded-collection-component-removed.json +4 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-embedded-component-removed.json +4 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-multilevel-containerised-component-leaf-hidden-removed.json +13 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-multilevel-containerised-component-removed.json +10 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-options-removed.json +8 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-page-collection-removed.json +15 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-page-component-used-elsewhere-removed.json +5 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-page-removed.json +4 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-nested-answers-hidden-by-option-removed.json +11 -0
- package/dist/components/FormRenderer/helpers/clearOutUncompletedRoutes.js +346 -0
- package/dist/components/FormRenderer/helpers/clearOutUncompletedRoutes.test.js +298 -0
- package/dist/components/FormRenderer/helpers/deleteNodeByPath.js +26 -0
- package/dist/components/FormRenderer/helpers/deleteNodeByPath.test.js +56 -0
- package/dist/components/FormRenderer/helpers/index.js +3 -1
- package/dist/components/FormRenderer/onPageAction.js +7 -0
- package/dist/components/FormRenderer/onPageAction.test.js +5 -0
- package/dist/utils/CollectionPage/mergeCollectionPages.js +1 -0
- package/dist/utils/Component/getDefaultValueFromConfig.js +1 -2
- package/dist/utils/Condition/meetsCondition.js +12 -26
- package/dist/utils/Condition/meetsCondition.test.js +0 -21
- package/dist/utils/Data/getAutocompleteSource.js +51 -68
- package/dist/utils/Data/getAutocompleteSource.test.js +18 -31
- package/package.json +2 -2
- package/dist/utils/Validate/validateOnPageLoad.js +0 -23
- package/dist/utils/Validate/validateOnPageLoad.test.js +0 -88
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"externalField": "externalField-value",
|
|
3
|
+
"items": [
|
|
4
|
+
{
|
|
5
|
+
"id": "da056129-34e9-4218-8e98-574856977727",
|
|
6
|
+
"itemCategory": "alcohol",
|
|
7
|
+
"itemSubCategory": "itemSubCategory-value",
|
|
8
|
+
"brandText": "brandText-value",
|
|
9
|
+
"externalDependency": "externalDependency-value"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"id": "da056129-34e9-4218-8e98-574856977727",
|
|
13
|
+
"itemCategory": "NOT-alcohol",
|
|
14
|
+
"itemSubCategory": "itemSubCategory-value"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"id": "da056129-34e9-4218-8e98-574856977727",
|
|
18
|
+
"itemCategory": "weapons",
|
|
19
|
+
"itemSubCategory": "NOT-ARM",
|
|
20
|
+
"brandText": "brandText-value"
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"type": "Example form",
|
|
3
|
+
"alpha": "alpha-value",
|
|
4
|
+
"bravo": "bravo-value",
|
|
5
|
+
"items": [
|
|
6
|
+
{
|
|
7
|
+
"id": "da056129-34e9-4218-8e98-574856977727",
|
|
8
|
+
"itemCategory": "NOT-alcohol",
|
|
9
|
+
"itemSubCategory": "itemSubCategory-value",
|
|
10
|
+
"brandText": "brandText-value",
|
|
11
|
+
"abvDetails": "abv-value"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"id": "da056129-34e9-4218-8e98-574856977727",
|
|
15
|
+
"itemCategory": "weapons",
|
|
16
|
+
"itemSubCategory": "NOT-ARM",
|
|
17
|
+
"brandText": "brandText-value",
|
|
18
|
+
"firearmCheck": "firearmCheck-value"
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"items": [
|
|
3
|
+
{
|
|
4
|
+
"id": "da056129-34e9-4218-8e98-574856977727",
|
|
5
|
+
"itemCategory": "NOT-alcohol",
|
|
6
|
+
"itemSubCategory": "itemSubCategory-value"
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"id": "da056129-34e9-4218-8e98-574856977727",
|
|
10
|
+
"itemCategory": "weapons",
|
|
11
|
+
"itemSubCategory": "NOT-ARM",
|
|
12
|
+
"brandText": "brandText-value"
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
}
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _mergeCollectionPages = _interopRequireDefault(require("../../../utils/CollectionPage/mergeCollectionPages"));
|
|
8
|
+
var _deleteNodeByPath = _interopRequireDefault(require("./deleteNodeByPath"));
|
|
9
|
+
var _Condition = _interopRequireDefault(require("../../../utils/Condition"));
|
|
10
|
+
var _optionIsSelected = _interopRequireDefault(require("../../../utils/Component/optionIsSelected"));
|
|
11
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
|
+
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; }
|
|
13
|
+
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) { _defineProperty(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; }
|
|
14
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
15
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
16
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /* eslint-disable no-param-reassign */
|
|
17
|
+
function removeObjectWithSingleIdFieldInPlace(array) {
|
|
18
|
+
for (let i = array.length - 1; i >= 0; i -= 1) {
|
|
19
|
+
const obj = array[i];
|
|
20
|
+
if (Object.keys(obj).length === 1 && Object.keys(obj)[0] === 'id') {
|
|
21
|
+
array.splice(i, 1); // Remove the object at index i
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const getImmediateParent = path => {
|
|
26
|
+
if (typeof path !== 'string' || !path.includes('.')) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
const parts = path.split('.');
|
|
30
|
+
parts.pop();
|
|
31
|
+
return parts.join('.');
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The nested fieldIds are placed in the payload at the same level in the heirarchy as the option question they relate to
|
|
36
|
+
*/
|
|
37
|
+
const getNestedQuestionPath = (optionPath, nestedFieldId) => {
|
|
38
|
+
const parentPath = getImmediateParent(optionPath);
|
|
39
|
+
return parentPath ? "".concat(parentPath, ".").concat(nestedFieldId) : nestedFieldId;
|
|
40
|
+
};
|
|
41
|
+
const recursivelyMapFieldsAndDeleteHiddenNested = (page, component, path, allComponents, componentsToKeep, formData) => {
|
|
42
|
+
var _component$data;
|
|
43
|
+
// Many component, such as warnings, html and details do not have data so we can ignore them
|
|
44
|
+
if (!component.fieldId) return;
|
|
45
|
+
path = path ? "".concat(path, ".").concat(component.fieldId) : component.fieldId;
|
|
46
|
+
|
|
47
|
+
// Components can be referenced from more than one page. We need to keep track of the count of each component path, to avoid pruning paths that exist elsewhere
|
|
48
|
+
componentsToKeep[path] = (componentsToKeep[path] || 0) + 1;
|
|
49
|
+
|
|
50
|
+
// add the fully qualified path to the component, which will be required when resolving the dependencies later
|
|
51
|
+
component.path = path;
|
|
52
|
+
|
|
53
|
+
// If the parent page has a rule, this overides the component rule
|
|
54
|
+
if (page.show_when) component.show_when = page.show_when;
|
|
55
|
+
|
|
56
|
+
// this is the master repository of all components
|
|
57
|
+
allComponents.set(path, component);
|
|
58
|
+
if (component.components) {
|
|
59
|
+
component.components.forEach(c => {
|
|
60
|
+
recursivelyMapFieldsAndDeleteHiddenNested(page, c, path, allComponents, componentsToKeep, formData);
|
|
61
|
+
});
|
|
62
|
+
} else if (component !== null && component !== void 0 && (_component$data = component.data) !== null && _component$data !== void 0 && _component$data.options) {
|
|
63
|
+
var _component$data2;
|
|
64
|
+
/**
|
|
65
|
+
* Perform processing for any options, and any options containing nested questions.
|
|
66
|
+
* - set hidden nested questions when the parent option is not selected
|
|
67
|
+
* - any nested questions must be treated as components which can be shown/hidden
|
|
68
|
+
*/
|
|
69
|
+
component === null || component === void 0 || (_component$data2 = component.data) === null || _component$data2 === void 0 || (_component$data2 = _component$data2.options) === null || _component$data2 === void 0 || _component$data2.forEach(option => {
|
|
70
|
+
if (option.nested) {
|
|
71
|
+
if (!(0, _optionIsSelected.default)(formData[component.id], option)) {
|
|
72
|
+
option.nested.forEach(nestedComponent => {
|
|
73
|
+
// It is safe to delete this now, as we know this data item can not be required as the associated option is not selected
|
|
74
|
+
(0, _deleteNodeByPath.default)(formData, getNestedQuestionPath(path, nestedComponent.fieldId));
|
|
75
|
+
});
|
|
76
|
+
} else {
|
|
77
|
+
// If the option is selected, then add any nested components to the allComponents list. If the nested block has a show_when, pass it down to the child questions
|
|
78
|
+
const blockShowWhen = option.show_when;
|
|
79
|
+
option.nested.forEach(nestedComponent => {
|
|
80
|
+
if (blockShowWhen) nestedComponent.show_when = blockShowWhen;
|
|
81
|
+
recursivelyMapFieldsAndDeleteHiddenNested(page, nestedComponent, getImmediateParent(path), allComponents, componentsToKeep, formData);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
const findShowWhenFields = (element, showWhenFields) => {
|
|
89
|
+
if (typeof element === 'object' && element !== null) {
|
|
90
|
+
if (Array.isArray(element)) {
|
|
91
|
+
element.forEach(value => {
|
|
92
|
+
findShowWhenFields(value, showWhenFields);
|
|
93
|
+
});
|
|
94
|
+
} else {
|
|
95
|
+
Object.keys(element).forEach(key => {
|
|
96
|
+
if (key === 'field') {
|
|
97
|
+
showWhenFields.push(element[key]);
|
|
98
|
+
}
|
|
99
|
+
findShowWhenFields(element[key], showWhenFields);
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return showWhenFields;
|
|
104
|
+
};
|
|
105
|
+
function getDependencies(entity) {
|
|
106
|
+
let dependencies = null;
|
|
107
|
+
if (entity.show_when) {
|
|
108
|
+
var _findShowWhenFields;
|
|
109
|
+
// Set dependencies. Maybe multiple as show_whens can be compound and nested
|
|
110
|
+
dependencies = new Set();
|
|
111
|
+
const showWhenFields = [];
|
|
112
|
+
(_findShowWhenFields = findShowWhenFields(entity.show_when, showWhenFields)) === null || _findShowWhenFields === void 0 || _findShowWhenFields.forEach(showWhenField => {
|
|
113
|
+
dependencies.add(showWhenField);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
return dependencies;
|
|
117
|
+
}
|
|
118
|
+
function addEntityToGraph(entity, componentDependencies, allDependencyRelationships) {
|
|
119
|
+
if (componentDependencies) {
|
|
120
|
+
allDependencyRelationships.set(entity.path, componentDependencies);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
const recursivelyMapDependencies = (component, allDependencyRelationships) => {
|
|
124
|
+
// Non data components can be ignored - can we remove this when doing the allcomponents thing?
|
|
125
|
+
if (!component.fieldId) return;
|
|
126
|
+
const componentDependencies = getDependencies(component);
|
|
127
|
+
addEntityToGraph(component, componentDependencies, allDependencyRelationships);
|
|
128
|
+
if (component.components) {
|
|
129
|
+
component.components.forEach(c => {
|
|
130
|
+
recursivelyMapDependencies(c, allDependencyRelationships);
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
/**
|
|
135
|
+
* Some show_when field values point to data items that are within objects provided by external calls to refdata, eg modeOfTransport.id
|
|
136
|
+
* These won't map directly to the path keyed components in allComponents, so go back up levels in the path until we find the component.
|
|
137
|
+
* The neighbour component might not be found at all, as the dependency might be on a field that is either provided by cop-ui (eg jobHolderStaffDetails.linemanagerEmail),
|
|
138
|
+
* or by the "addToFormData" function (eg epmsSubmitted). These will be leaf level in a dependency chain so component is not required.
|
|
139
|
+
*/
|
|
140
|
+
|
|
141
|
+
const getNeighbourObjectFromPath = (neighbourPath, allComponents) => {
|
|
142
|
+
const segments = neighbourPath.split(".");
|
|
143
|
+
for (let i = segments.length; i > 0; i -= 1) {
|
|
144
|
+
const currentPath = segments.slice(0, i).join(".");
|
|
145
|
+
const neighbour = allComponents.get(currentPath);
|
|
146
|
+
if (neighbour) return neighbour;
|
|
147
|
+
}
|
|
148
|
+
return null;
|
|
149
|
+
};
|
|
150
|
+
const isShowEntity = (entity, data) => {
|
|
151
|
+
var _entity$show_when;
|
|
152
|
+
// If there is no rule set, then the entity can be shown
|
|
153
|
+
if (!entity.show_when) {
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
if (((_entity$show_when = entity.show_when) === null || _entity$show_when === void 0 ? void 0 : _entity$show_when.type) === "or") {
|
|
157
|
+
return _Condition.default.meetsOne(entity, data);
|
|
158
|
+
}
|
|
159
|
+
return _Condition.default.meetsAll(entity, data);
|
|
160
|
+
};
|
|
161
|
+
const pruneSingleComponent = (formData, path, component, componentsToKeep) => {
|
|
162
|
+
// If there is more than one entry for this component, then it is being used elsewhere in a visible page. Don't prune, but reduce the count by 1
|
|
163
|
+
if (componentsToKeep[path] > 1) {
|
|
164
|
+
componentsToKeep[path] -= 1;
|
|
165
|
+
} else {
|
|
166
|
+
var _component$data3;
|
|
167
|
+
(0, _deleteNodeByPath.default)(formData, path);
|
|
168
|
+
// If the component has options, go through each option removing the data for any nested fields. Required as nested options are in the payload at the same heirarchical level.
|
|
169
|
+
if (component !== null && component !== void 0 && (_component$data3 = component.data) !== null && _component$data3 !== void 0 && _component$data3.options) {
|
|
170
|
+
var _component$data4;
|
|
171
|
+
component === null || component === void 0 || (_component$data4 = component.data) === null || _component$data4 === void 0 || (_component$data4 = _component$data4.options) === null || _component$data4 === void 0 || _component$data4.forEach(option => {
|
|
172
|
+
var _option$nested;
|
|
173
|
+
(_option$nested = option.nested) === null || _option$nested === void 0 || _option$nested.forEach(nested => {
|
|
174
|
+
(0, _deleteNodeByPath.default)(formData, getNestedQuestionPath(path, nested.fieldId));
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
const recursivelyResolveDependencies = (visited, dependentEntity, dependencyRelationships, form, formData, allComponents, componentsToKeep, allCollections) => {
|
|
181
|
+
if (visited.has(dependentEntity.id)) return;
|
|
182
|
+
visited.add(dependentEntity.id);
|
|
183
|
+
const neighbours = dependencyRelationships.get(dependentEntity.path);
|
|
184
|
+
neighbours === null || neighbours === void 0 || neighbours.forEach(neighbourPath => {
|
|
185
|
+
const neighbour = getNeighbourObjectFromPath(neighbourPath, allComponents);
|
|
186
|
+
if (neighbour) {
|
|
187
|
+
if (!visited.has(neighbour.id)) {
|
|
188
|
+
recursivelyResolveDependencies(visited, neighbour, dependencyRelationships, form, formData, allComponents, componentsToKeep, allCollections);
|
|
189
|
+
}
|
|
190
|
+
} else {
|
|
191
|
+
// Refactor out helper methods
|
|
192
|
+
const arrayNamePattern = /([a-zA-Z_$][\w$]*)\[\d+\]/;
|
|
193
|
+
const match = neighbourPath.match(arrayNamePattern);
|
|
194
|
+
if (match) {
|
|
195
|
+
const collectionName = match[1];
|
|
196
|
+
const collection = allCollections.get(collectionName);
|
|
197
|
+
if (collection) {
|
|
198
|
+
var _collection$childPage;
|
|
199
|
+
(_collection$childPage = collection.childPages) === null || _collection$childPage === void 0 || _collection$childPage.forEach(childPage => {
|
|
200
|
+
if (childPage.show_when) {
|
|
201
|
+
const message = "It is not possible to reliably clean hidden data when a component is dependent on a \n collection's data, and that collection is itself dependent on data elsewhere in the form.\n The dependency path is ".concat(neighbourPath, ", and the chained show_when is ").concat(JSON.stringify(childPage.show_when), ".\n The form will need to be changed to break this chained dependency");
|
|
202
|
+
throw new Error(message);
|
|
203
|
+
}
|
|
204
|
+
;
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
// Whilst unravelling the recursion, we can start pruning from the leaf upwards
|
|
211
|
+
if (!isShowEntity(dependentEntity, formData)) {
|
|
212
|
+
pruneSingleComponent(formData, dependentEntity.path, dependentEntity, componentsToKeep);
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
const findComponentDefinitionInForm = (useComponentInPage, form) => {
|
|
216
|
+
var _ref, _form$components$find;
|
|
217
|
+
const componentInForm = (_ref = (_form$components$find = form.components.find(c => c.fieldId === useComponentInPage.use)) !== null && _form$components$find !== void 0 ? _form$components$find : form.components.find(c => c.id === useComponentInPage.use)) !== null && _ref !== void 0 ? _ref : useComponentInPage;
|
|
218
|
+
// Retun clone of component, so subsequent processing can make changes to it without changing the form
|
|
219
|
+
return JSON.parse(JSON.stringify(componentInForm));
|
|
220
|
+
};
|
|
221
|
+
const deleteCorrespondingMetaInfo = (component, collectionDataObject, formData) => {
|
|
222
|
+
const {
|
|
223
|
+
meta: {
|
|
224
|
+
documents
|
|
225
|
+
}
|
|
226
|
+
} = formData;
|
|
227
|
+
const fileDataBeingDeleted = collectionDataObject[component.fieldId];
|
|
228
|
+
if (!documents || !fileDataBeingDeleted) return;
|
|
229
|
+
const fileDataAsArray = Array.isArray(fileDataBeingDeleted) ? fileDataBeingDeleted : [fileDataBeingDeleted];
|
|
230
|
+
const metaDocumentIndex = documents.findIndex(document => fileDataAsArray.some(fileItem => document.url === fileItem.url));
|
|
231
|
+
if (metaDocumentIndex !== -1) {
|
|
232
|
+
documents.splice(metaDocumentIndex, 1);
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
const pruneCollectionEntry = (pathsToKeep, componentsToPrune, collectionDataObject, formData) => {
|
|
236
|
+
componentsToPrune.forEach(component => {
|
|
237
|
+
if (!pathsToKeep.has(component.fieldId)) {
|
|
238
|
+
var _component$data5;
|
|
239
|
+
if (component.type === "multifile") {
|
|
240
|
+
deleteCorrespondingMetaInfo(component, collectionDataObject, formData);
|
|
241
|
+
}
|
|
242
|
+
(0, _deleteNodeByPath.default)(collectionDataObject, component.fieldId);
|
|
243
|
+
|
|
244
|
+
// REFACTOR
|
|
245
|
+
// If the component has options, go through each option removing the data for any nested fields. Required as nested options are in the payload at the same heirarchical level.
|
|
246
|
+
if (component !== null && component !== void 0 && (_component$data5 = component.data) !== null && _component$data5 !== void 0 && _component$data5.options) {
|
|
247
|
+
var _component$data6;
|
|
248
|
+
component === null || component === void 0 || (_component$data6 = component.data) === null || _component$data6 === void 0 || (_component$data6 = _component$data6.options) === null || _component$data6 === void 0 || _component$data6.forEach(option => {
|
|
249
|
+
var _option$nested2;
|
|
250
|
+
(_option$nested2 = option.nested) === null || _option$nested2 === void 0 || _option$nested2.forEach(nested => {
|
|
251
|
+
(0, _deleteNodeByPath.default)(collectionDataObject, getNestedQuestionPath(component.fieldId, nested.fieldId));
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
};
|
|
258
|
+
function removeEmptyArraysAndUnusedCollectionIDs(payload) {
|
|
259
|
+
if (Array.isArray(payload)) {
|
|
260
|
+
for (let i = payload.length - 1; i >= 0; i -= 1) {
|
|
261
|
+
if (Array.isArray(payload[i]) && payload[i].length === 0) {
|
|
262
|
+
payload.splice(i, 1);
|
|
263
|
+
} else {
|
|
264
|
+
removeEmptyArraysAndUnusedCollectionIDs(payload[i]); // Recurse for nested structures
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
} else if (payload !== null && typeof payload === 'object') {
|
|
268
|
+
Object.keys(payload).forEach(key => {
|
|
269
|
+
if (Array.isArray(payload[key]) && payload[key].length === 0) {
|
|
270
|
+
// If the array being removed has an activeId associated with it, remove it
|
|
271
|
+
delete payload["".concat(key, "ActiveId")];
|
|
272
|
+
delete payload[key]; // Remove the empty array
|
|
273
|
+
} else {
|
|
274
|
+
removeEmptyArraysAndUnusedCollectionIDs(payload[key]); // Recurse for nested structures
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
const clearOutUncompletedRoutes = (form, formData) => {
|
|
280
|
+
// Recurse through the whole form, building a map of all fields and their owning component id.
|
|
281
|
+
// This is required to build the component->dependency graph in the next step, as the dependencies reference fields, not components.
|
|
282
|
+
|
|
283
|
+
const condensedPages = (0, _mergeCollectionPages.default)(form.pages);
|
|
284
|
+
const allComponents = new Map();
|
|
285
|
+
const componentsToKeep = {};
|
|
286
|
+
const allCollections = new Map();
|
|
287
|
+
condensedPages === null || condensedPages === void 0 || condensedPages.forEach(page => {
|
|
288
|
+
if (page.childPages) {
|
|
289
|
+
allCollections.set(page.collection.name, page);
|
|
290
|
+
} else {
|
|
291
|
+
var _page$components;
|
|
292
|
+
(_page$components = page.components) === null || _page$components === void 0 || _page$components.forEach(useComponentInPage => {
|
|
293
|
+
const componentObj = findComponentDefinitionInForm(useComponentInPage, form);
|
|
294
|
+
recursivelyMapFieldsAndDeleteHiddenNested(page, componentObj, null, allComponents, componentsToKeep, formData);
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
const allDependencyRelationships = new Map();
|
|
299
|
+
allComponents === null || allComponents === void 0 || allComponents.forEach(component => {
|
|
300
|
+
recursivelyMapDependencies(component, allDependencyRelationships);
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
// Visit all components with 'show_whens' and resolve the dependency. Only delete the data at the leaf element, or when un-winding the recursion
|
|
304
|
+
// to deal with the edge case that an element is dependent on a data item that is hidden by a different constraint
|
|
305
|
+
const visited = new Set();
|
|
306
|
+
allDependencyRelationships === null || allDependencyRelationships === void 0 || allDependencyRelationships.forEach((neighbours, dependentEntityPath) => {
|
|
307
|
+
const dependentEntity = allComponents.get(dependentEntityPath);
|
|
308
|
+
if (!visited.has(dependentEntity.id)) {
|
|
309
|
+
recursivelyResolveDependencies(visited, dependentEntity, allDependencyRelationships, form, formData, allComponents, componentsToKeep, allCollections);
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
allCollections === null || allCollections === void 0 || allCollections.forEach((collection, collectionName) => {
|
|
313
|
+
const collectionDataArray = formData[collectionName];
|
|
314
|
+
collectionDataArray === null || collectionDataArray === void 0 || collectionDataArray.forEach(collectionDataEntry => {
|
|
315
|
+
var _collection$childPage2;
|
|
316
|
+
// The forms are written such that a show_when in a collection array object can be evaluated against the data relative to that data object
|
|
317
|
+
// OR against the data relative to the root of the form. To achieve that, we'll copy the collection object to the root of the form before evaluating
|
|
318
|
+
const dataForEvaluation = _objectSpread(_objectSpread({}, formData), collectionDataEntry);
|
|
319
|
+
const pathsToKeep = new Set();
|
|
320
|
+
const componentsToPrune = new Map();
|
|
321
|
+
(_collection$childPage2 = collection.childPages) === null || _collection$childPage2 === void 0 || _collection$childPage2.forEach(childPage => {
|
|
322
|
+
var _childPage$components;
|
|
323
|
+
const showPage = isShowEntity(childPage, dataForEvaluation);
|
|
324
|
+
(_childPage$components = childPage.components) === null || _childPage$components === void 0 || _childPage$components.forEach(useComponentInPage => {
|
|
325
|
+
const componentObj = findComponentDefinitionInForm(useComponentInPage, form);
|
|
326
|
+
|
|
327
|
+
// Non-data components can be ignored (eg html)
|
|
328
|
+
if (!componentObj.fieldId) return;
|
|
329
|
+
const showComponentOnPage = isShowEntity(useComponentInPage, dataForEvaluation);
|
|
330
|
+
if (showPage && showComponentOnPage && isShowEntity(componentObj, dataForEvaluation)) {
|
|
331
|
+
// There may be 2 components with the same path (eg quantity in EAB2), so don't delete hidden components if they are required elsewhere
|
|
332
|
+
pathsToKeep.add(componentObj.fieldId);
|
|
333
|
+
} else {
|
|
334
|
+
componentsToPrune.set(componentObj.id, componentObj);
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
pruneCollectionEntry(pathsToKeep, componentsToPrune, collectionDataEntry, formData);
|
|
339
|
+
});
|
|
340
|
+
// Pruning this collection may have resulted in objects that are only left with their 'id' field, which isn't data but added by the renderer to find the activeId. If so, remove these objects
|
|
341
|
+
if (collectionDataArray) removeObjectWithSingleIdFieldInPlace(collectionDataArray);
|
|
342
|
+
});
|
|
343
|
+
removeEmptyArraysAndUnusedCollectionIDs(formData);
|
|
344
|
+
return formData;
|
|
345
|
+
};
|
|
346
|
+
var _default = exports.default = clearOutUncompletedRoutes;
|