@ukhomeoffice/cop-react-form-renderer 6.14.9 → 6.15.2-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.
Files changed (97) hide show
  1. package/dist/components/CollectionSummary/BannerStrip.scss +0 -4
  2. package/dist/components/FormPage/FormPage.js +10 -8
  3. package/dist/components/FormRenderer/FormRenderer.js +10 -5
  4. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-chained-component-show-whens-containerised.json +119 -0
  5. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-chained-component-show-whens-dependent-component-nested-block.json +112 -0
  6. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-chained-component-show-whens-dependent-component-nested.json +105 -0
  7. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-chained-component-show-whens-refdata.json +105 -0
  8. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-chained-component-show-whens-target-component-nested.json +98 -0
  9. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-chained-component-show-whens.json +105 -0
  10. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-chained-show-whens-page-hidden.json +112 -0
  11. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-cop-airpax.json +26407 -0
  12. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-cop-mandec.json +9404 -0
  13. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-collection-component-dependent-on-external-data.json +157 -0
  14. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-collection-component.json +85 -0
  15. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-component-referring-to-collection.json +172 -0
  16. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-component-referring-to-hidden-collection.json +201 -0
  17. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-component-with-nested-questions.json +111 -0
  18. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-component.json +57 -0
  19. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-containerised-component.json +96 -0
  20. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-embedded-collection-component.json +82 -0
  21. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-embedded-component.json +54 -0
  22. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-multilevel-containerised-component-leaf-hidden.json +105 -0
  23. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-multilevel-containerised-component.json +105 -0
  24. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-options.json +98 -0
  25. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-page-collection.json +127 -0
  26. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-page-component-used-elsewhere.json +108 -0
  27. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-page.json +95 -0
  28. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-nested-answers-hidden-by-option.json +111 -0
  29. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/cop-airpax-remove-photos-before.json +384 -0
  30. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/cop-mandec-remove-business-interests-before.json +140 -0
  31. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/cop-mandec-remove-criminality-before.json +186 -0
  32. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-chained-component-show-whens-containerised.json +11 -0
  33. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-chained-component-show-whens-dependent-component-nested-block.json +10 -0
  34. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-chained-component-show-whens-dependent-component-nested.json +9 -0
  35. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-chained-component-show-whens-refdata.json +11 -0
  36. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-chained-component-show-whens-target-component-nested.json +9 -0
  37. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-chained-component-show-whens.json +9 -0
  38. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-chained-show-whens-page-hidden.json +9 -0
  39. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-collection-component-dependent-on-external-data.json +26 -0
  40. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-collection-component.json +15 -0
  41. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-component-referring-to-collection.json +25 -0
  42. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-component-referring-to-hidden-collection.json +26 -0
  43. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-component-with-nested-questions.json +12 -0
  44. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-component.json +5 -0
  45. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-containerised-component.json +11 -0
  46. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-embedded-collection-component.json +15 -0
  47. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-embedded-component.json +5 -0
  48. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-multilevel-containerised-component-leaf-hidden.json +14 -0
  49. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-multilevel-containerised-component.json +14 -0
  50. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-options.json +10 -0
  51. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-page-collection.json +18 -0
  52. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-page-component-used-elsewhere.json +9 -0
  53. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-page.json +9 -0
  54. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-nested-answers-hidden-by-option.json +12 -0
  55. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/cop-airpax-remove-photos-after.json +355 -0
  56. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/cop-mandec-base-file.json +80 -0
  57. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/cop-mandec-remove-business-interests-after.json +122 -0
  58. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/cop-mandec-remove-criminality-after.json +86 -0
  59. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-chained-component-show-whens-containerised-removed.json +11 -0
  60. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-chained-component-show-whens-dependent-component-nested-block-removed.json +7 -0
  61. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-chained-component-show-whens-dependent-component-nested-removed.json +7 -0
  62. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-chained-component-show-whens-refdata-removed.json +7 -0
  63. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-chained-component-show-whens-removed.json +7 -0
  64. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-chained-component-show-whens-target-component-nested-removed.json +6 -0
  65. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-chained-show-whens-page-hidden-removed.json +6 -0
  66. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-collection-component-dependent-on-external-data-removed.json +23 -0
  67. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-collection-component-removed.json +4 -0
  68. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-component-referring-to-collection-removed.json +21 -0
  69. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-component-referring-to-hidden-collection-removed.json +6 -0
  70. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-component-removed.json +4 -0
  71. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-component-with-nested-questions-removed.json +10 -0
  72. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-containerised-component-removed.json +10 -0
  73. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-embedded-collection-component-removed.json +4 -0
  74. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-embedded-component-removed.json +4 -0
  75. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-multilevel-containerised-component-leaf-hidden-removed.json +13 -0
  76. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-multilevel-containerised-component-removed.json +10 -0
  77. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-options-removed.json +8 -0
  78. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-page-collection-removed.json +15 -0
  79. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-page-component-used-elsewhere-removed.json +5 -0
  80. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-page-removed.json +4 -0
  81. package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-nested-answers-hidden-by-option-removed.json +11 -0
  82. package/dist/components/FormRenderer/helpers/clearOutUncompletedRoutes.js +346 -0
  83. package/dist/components/FormRenderer/helpers/clearOutUncompletedRoutes.test.js +298 -0
  84. package/dist/components/FormRenderer/helpers/deleteNodeByPath.js +26 -0
  85. package/dist/components/FormRenderer/helpers/deleteNodeByPath.test.js +56 -0
  86. package/dist/components/FormRenderer/helpers/index.js +3 -1
  87. package/dist/components/FormRenderer/onPageAction.js +7 -0
  88. package/dist/components/FormRenderer/onPageAction.test.js +5 -0
  89. package/dist/utils/CollectionPage/mergeCollectionPages.js +1 -0
  90. package/dist/utils/Component/getDefaultValueFromConfig.js +1 -2
  91. package/dist/utils/Condition/meetsCondition.js +12 -26
  92. package/dist/utils/Condition/meetsCondition.test.js +0 -21
  93. package/dist/utils/Data/getAutocompleteSource.js +51 -68
  94. package/dist/utils/Data/getAutocompleteSource.test.js +18 -31
  95. package/package.json +2 -2
  96. package/dist/utils/Validate/validateOnPageLoad.js +0 -23
  97. package/dist/utils/Validate/validateOnPageLoad.test.js +0 -88
@@ -0,0 +1,7 @@
1
+ {
2
+ "type": "Example form",
3
+ "personKnown": "yes",
4
+ "telephone": "telephone-value",
5
+ "gamma": "gamma-value",
6
+ "epsilon": "epsilon-value"
7
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "type": "Example form",
3
+ "alpha": "alpha-value",
4
+ "personKnown": "yes",
5
+ "epsilon": "epsilon-value"
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "type": "Example form",
3
+ "personKnown": "yes",
4
+ "telephone": "telephone-value",
5
+ "epsilon": "epsilon-value"
6
+ }
@@ -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,6 @@
1
+ {
2
+ "type": "Example form",
3
+ "whatHappened": "show-drugs",
4
+ "alpha": "alpha-value",
5
+ "bravo": "bravo-value"
6
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "type": "Example form",
3
+ "alpha": "alpha-value"
4
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "type": "Example form",
3
+ "alpha": "alpha-value",
4
+ "bravo": "bravo-value",
5
+ "person": {
6
+ "name":"name-value"
7
+ },
8
+ "gamma": "gamma-value",
9
+ "epsilon": "epsilon-value"
10
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "type": "Example form",
3
+ "alpha": "alpha-value",
4
+ "bravo": "bravo-value",
5
+ "person": {
6
+ "telephone": "telephone-value"
7
+ },
8
+ "gamma": "gamma-value",
9
+ "epsilon": "epsilon-value"
10
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "type": "Example form",
3
+ "alpha": "alpha-value",
4
+ "bravo": "bravo-value",
5
+ "person": {
6
+ "name": "name-value",
7
+ "address": {
8
+ "street": "street-value"
9
+ }
10
+ },
11
+ "gamma": "gamma-value",
12
+ "epsilon": "epsilon-value"
13
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "type": "Example form",
3
+ "alpha": "alpha-value",
4
+ "bravo": "bravo-value",
5
+ "person": {
6
+ "name": "name-value"
7
+ },
8
+ "gamma": "gamma-value",
9
+ "epsilon": "epsilon-value"
10
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "type": "Example form",
3
+ "alpha": "alpha-value",
4
+ "bravo": "bravo-value",
5
+ "name":"name-value",
6
+ "gamma": "gamma-value",
7
+ "epsilon": "epsilon-value"
8
+ }
@@ -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,5 @@
1
+ {
2
+ "type": "Example form",
3
+ "alpha": "alpha-value",
4
+ "bravo": "bravo-value"
5
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "type": "Example form",
3
+ "alpha": "alpha-value"
4
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "type": "Example form",
3
+ "alpha": "alpha-value",
4
+ "bravo": "bravo-value",
5
+ "person": {
6
+ "telephoneKnown": "no",
7
+ "name":"name-value"
8
+ },
9
+ "gamma": "gamma-value",
10
+ "epsilon": "epsilon-value"
11
+ }
@@ -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;