@ukhomeoffice/cop-react-form-renderer 6.15.3-alpha → 6.15.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/CollectionSummary/BannerStrip.scss +4 -0
- package/dist/components/CollectionSummary/CollectionSummary.js +2 -2
- package/dist/components/CollectionSummary/SummaryCard.js +2 -2
- package/dist/components/FormComponent/Collection.js +2 -2
- package/dist/components/FormComponent/Container.js +2 -2
- package/dist/components/FormComponent/FormComponent.js +2 -2
- package/dist/components/FormComponent/helpers/addLabel.js +3 -2
- package/dist/components/FormPage/FormPage.js +28 -17
- package/dist/components/FormPage/FormPage.test.js +53 -0
- package/dist/components/FormRenderer/FormRenderer.js +7 -12
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-component-show-when-in-component-and-page.json +62 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-hidden-page-same-component-reused.json +61 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/forms/form-page-same-component-reused-one-shown.json +74 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/cop-airpax-change-what-happened-before.json +300 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-component-show-when-in-component-and-page.json +6 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-hidden-page-same-component-reused.json +6 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/input/data-page-same-component-reused-one-shown.json +8 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/cop-airpax-change-what-happened-after.json +280 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-component-show-when-in-component-and-page-removed.json +5 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-hidden-page-same-component-reused-removed.json +5 -0
- package/dist/components/FormRenderer/clear-uncompleted-routes/test-data/output/data-page-same-component-reused-one-shown-removed.json +7 -0
- package/dist/components/FormRenderer/helpers/clearOutUncompletedRoutes.js +259 -289
- package/dist/components/FormRenderer/helpers/clearOutUncompletedRoutes.test.js +68 -27
- package/dist/components/FormRenderer/helpers/clearOutUncompletedRoutesUtils.js +381 -0
- package/dist/components/FormRenderer/helpers/clearOutUncompletedRoutesUtils.test.js +559 -0
- package/dist/components/FormRenderer/onCYAAction.js +12 -0
- package/dist/components/FormRenderer/onCYAAction.test.js +5 -0
- package/dist/components/FormRenderer/onPageAction.js +0 -1
- package/dist/components/PageActions/ActionButton.js +2 -2
- package/dist/components/SummaryList/SummaryList.js +2 -2
- package/dist/components/TaskList/TaskList.js +2 -2
- package/dist/hooks/useGetRequest.js +15 -15
- package/dist/hooks/useRefData.js +3 -2
- package/dist/utils/CollectionPage/getQuickEditPage.js +2 -2
- package/dist/utils/Component/getComponentTests/getComponent.multifile.test.js +2 -1
- package/dist/utils/Component/getDefaultValueFromConfig.js +2 -1
- package/dist/utils/Condition/meetsCondition.js +26 -12
- package/dist/utils/Condition/meetsCondition.test.js +21 -0
- package/dist/utils/Data/getAutocompleteSource.js +68 -51
- package/dist/utils/Data/getAutocompleteSource.test.js +31 -18
- package/dist/utils/Operate/doesContainValue.js +34 -0
- package/dist/utils/Operate/doesContainValue.test.js +75 -0
- package/dist/utils/Operate/runPageOperations.js +2 -0
- package/dist/utils/Validate/validateOnPageLoad.js +23 -0
- package/dist/utils/Validate/validateOnPageLoad.test.js +88 -0
- package/package.json +4 -4
- package/dist/components/FormRenderer/helpers/deleteNodeByPath.js +0 -29
- package/dist/components/FormRenderer/helpers/deleteNodeByPath.test.js +0 -56
|
@@ -4,6 +4,9 @@ var _index = _interopRequireDefault(require("./index"));
|
|
|
4
4
|
var _formHiddenComponent = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/forms/form-hidden-component.json"));
|
|
5
5
|
var _dataHiddenComponent = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/input/data-hidden-component.json"));
|
|
6
6
|
var _dataHiddenComponentRemoved = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/output/data-hidden-component-removed.json"));
|
|
7
|
+
var _formHiddenComponentShowWhenInComponentAndPage = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/forms/form-hidden-component-show-when-in-component-and-page.json"));
|
|
8
|
+
var _dataHiddenComponentShowWhenInComponentAndPage = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/input/data-hidden-component-show-when-in-component-and-page.json"));
|
|
9
|
+
var _dataHiddenComponentShowWhenInComponentAndPageRemoved = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/output/data-hidden-component-show-when-in-component-and-page-removed.json"));
|
|
7
10
|
var _formHiddenEmbeddedComponent = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/forms/form-hidden-embedded-component.json"));
|
|
8
11
|
var _dataHiddenEmbeddedComponent = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/input/data-hidden-embedded-component.json"));
|
|
9
12
|
var _dataHiddenEmbeddedComponentRemoved = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/output/data-hidden-embedded-component-removed.json"));
|
|
@@ -34,6 +37,12 @@ var _dataNestedAnswersHiddenByOptionRemoved = _interopRequireDefault(require("..
|
|
|
34
37
|
var _formHiddenPage = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/forms/form-hidden-page.json"));
|
|
35
38
|
var _dataHiddenPage = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/input/data-hidden-page.json"));
|
|
36
39
|
var _dataHiddenPageRemoved = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/output/data-hidden-page-removed.json"));
|
|
40
|
+
var _formHiddenPageSameComponentReused = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/forms/form-hidden-page-same-component-reused.json"));
|
|
41
|
+
var _dataHiddenPageSameComponentReused = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/input/data-hidden-page-same-component-reused.json"));
|
|
42
|
+
var _dataHiddenPageSameComponentReusedRemoved = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/output/data-hidden-page-same-component-reused-removed.json"));
|
|
43
|
+
var _formPageSameComponentReusedOneShown = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/forms/form-page-same-component-reused-one-shown.json"));
|
|
44
|
+
var _dataPageSameComponentReusedOneShown = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/input/data-page-same-component-reused-one-shown.json"));
|
|
45
|
+
var _dataPageSameComponentReusedOneShownRemoved = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/output/data-page-same-component-reused-one-shown-removed.json"));
|
|
37
46
|
var _formHiddenPageComponentUsedElsewhere = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/forms/form-hidden-page-component-used-elsewhere.json"));
|
|
38
47
|
var _dataHiddenPageComponentUsedElsewhere = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/input/data-hidden-page-component-used-elsewhere.json"));
|
|
39
48
|
var _dataHiddenPageComponentUsedElsewhereRemoved = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/output/data-hidden-page-component-used-elsewhere-removed.json"));
|
|
@@ -79,9 +88,13 @@ var _copMandecRemoveUnspentConvictionsAfter = _interopRequireDefault(require("..
|
|
|
79
88
|
var _formCopAirpax = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/forms/form-cop-airpax.json"));
|
|
80
89
|
var _copAirpaxRemovePhotosBefore = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/input/cop-airpax-remove-photos-before.json"));
|
|
81
90
|
var _copAirpaxRemovePhotosAfter = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/output/cop-airpax-remove-photos-after.json"));
|
|
91
|
+
var _copAirpaxChangeWhatHappenedBefore = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/input/cop-airpax-change-what-happened-before.json"));
|
|
92
|
+
var _copAirpaxChangeWhatHappenedAfter = _interopRequireDefault(require("../clear-uncompleted-routes/test-data/output/cop-airpax-change-what-happened-after.json"));
|
|
82
93
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
83
94
|
// Hidden component
|
|
84
95
|
|
|
96
|
+
// Hidden component with show_when in page and component
|
|
97
|
+
|
|
85
98
|
// Hidden embedded component
|
|
86
99
|
|
|
87
100
|
// Hidden collection component
|
|
@@ -102,6 +115,10 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
|
|
|
102
115
|
|
|
103
116
|
// Hidden page
|
|
104
117
|
|
|
118
|
+
// Hidden page containing same component reused
|
|
119
|
+
|
|
120
|
+
// should show component when reused but only one show_when true
|
|
121
|
+
|
|
105
122
|
// Hidden page with component used elsewhere
|
|
106
123
|
|
|
107
124
|
// Hidden component with show_when rule referring to a collection
|
|
@@ -137,85 +154,103 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
|
|
|
137
154
|
describe('FormRenderer', () => {
|
|
138
155
|
describe('helpers', () => {
|
|
139
156
|
describe('clearOutUncompletedRoutes', () => {
|
|
140
|
-
it('should remove hidden component', () => {
|
|
157
|
+
it('should remove hidden component.', () => {
|
|
141
158
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenComponent.default));
|
|
142
159
|
const form = JSON.parse(JSON.stringify(_formHiddenComponent.default));
|
|
143
160
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
144
161
|
expect(result).toEqual(_dataHiddenComponentRemoved.default);
|
|
145
162
|
});
|
|
146
|
-
it('should remove hidden component
|
|
163
|
+
it('should remove hidden component with show_when in page and component.', () => {
|
|
164
|
+
const submissionData = JSON.parse(JSON.stringify(_dataHiddenComponentShowWhenInComponentAndPage.default));
|
|
165
|
+
const form = JSON.parse(JSON.stringify(_formHiddenComponentShowWhenInComponentAndPage.default));
|
|
166
|
+
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
167
|
+
expect(result).toEqual(_dataHiddenComponentShowWhenInComponentAndPageRemoved.default);
|
|
168
|
+
});
|
|
169
|
+
it('should remove hidden component embedded in page.', () => {
|
|
147
170
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenEmbeddedComponent.default));
|
|
148
171
|
const form = JSON.parse(JSON.stringify(_formHiddenEmbeddedComponent.default));
|
|
149
172
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
150
173
|
expect(result).toEqual(_dataHiddenEmbeddedComponentRemoved.default);
|
|
151
174
|
});
|
|
152
|
-
it('should remove hidden collection component', () => {
|
|
175
|
+
it('should remove hidden collection component.', () => {
|
|
153
176
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenCollectionComponent.default));
|
|
154
177
|
const form = JSON.parse(JSON.stringify(_formHiddenCollectionComponent.default));
|
|
155
178
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
156
179
|
expect(result).toEqual(_dataHiddenCollectionComponentRemoved.default);
|
|
157
180
|
});
|
|
158
|
-
it('should remove hidden embedded collection component', () => {
|
|
181
|
+
it('should remove hidden embedded collection component.', () => {
|
|
159
182
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenEmbeddedCollectionComponent.default));
|
|
160
183
|
const form = JSON.parse(JSON.stringify(_formHiddenEmbeddedCollectionComponent.default));
|
|
161
184
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
162
185
|
expect(result).toEqual(_dataHiddenEmbeddedCollectionComponentRemoved.default);
|
|
163
186
|
});
|
|
164
|
-
it('should remove hidden containerised component', () => {
|
|
187
|
+
it('should remove hidden containerised component.', () => {
|
|
165
188
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenContainerisedComponent.default));
|
|
166
189
|
const form = JSON.parse(JSON.stringify(_formHiddenContainerisedComponent.default));
|
|
167
190
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
168
191
|
expect(result).toEqual(_dataHiddenContainerisedComponentRemoved.default);
|
|
169
192
|
});
|
|
170
|
-
it('should remove hidden multi-level containerised components', () => {
|
|
193
|
+
it('should remove hidden multi-level containerised components.', () => {
|
|
171
194
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenMultilevelContainerisedComponent.default));
|
|
172
195
|
const form = JSON.parse(JSON.stringify(_formHiddenMultilevelContainerisedComponent.default));
|
|
173
196
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
174
197
|
expect(result).toEqual(_dataHiddenMultilevelContainerisedComponentRemoved.default);
|
|
175
198
|
});
|
|
176
|
-
it('should remove hidden leaf-level in a multi-level containerised component', () => {
|
|
199
|
+
it('should remove hidden leaf-level in a multi-level containerised component.', () => {
|
|
177
200
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenMultilevelContainerisedComponentLeafHidden.default));
|
|
178
201
|
const form = JSON.parse(JSON.stringify(_formHiddenMultilevelContainerisedComponentLeafHidden.default));
|
|
179
202
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
180
203
|
expect(result).toEqual(_dataHiddenMultilevelContainerisedComponentLeafHiddenRemoved.default);
|
|
181
204
|
});
|
|
182
|
-
it('should remove hidden component with options', () => {
|
|
205
|
+
it('should remove hidden component with options.', () => {
|
|
183
206
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenOptions.default));
|
|
184
207
|
const form = JSON.parse(JSON.stringify(_formHiddenOptions.default));
|
|
185
208
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
186
209
|
expect(result).toEqual(_dataHiddenOptionsRemoved.default);
|
|
187
210
|
});
|
|
188
|
-
it('should remove hidden component with nested questions in options', () => {
|
|
211
|
+
it('should remove hidden component with nested questions in options.', () => {
|
|
189
212
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenComponentWithNestedQuestions.default));
|
|
190
213
|
const form = JSON.parse(JSON.stringify(_formHiddenComponentWithNestedQuestions.default));
|
|
191
214
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
192
215
|
expect(result).toEqual(_dataHiddenComponentWithNestedQuestionsRemoved.default);
|
|
193
216
|
});
|
|
194
|
-
it('should remove answers associated with unselected options in a containerised component', () => {
|
|
217
|
+
it('should remove answers associated with unselected options in a containerised component.', () => {
|
|
195
218
|
const submissionData = JSON.parse(JSON.stringify(_dataNestedAnswersHiddenByOption.default));
|
|
196
219
|
const form = JSON.parse(JSON.stringify(_formNestedAnswersHiddenByOption.default));
|
|
197
220
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
198
221
|
expect(result).toEqual(_dataNestedAnswersHiddenByOptionRemoved.default);
|
|
199
222
|
});
|
|
200
|
-
it('should remove hidden page', () => {
|
|
223
|
+
it('should remove hidden page.', () => {
|
|
201
224
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenPage.default));
|
|
202
225
|
const form = JSON.parse(JSON.stringify(_formHiddenPage.default));
|
|
203
226
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
204
227
|
expect(result).toEqual(_dataHiddenPageRemoved.default);
|
|
205
228
|
});
|
|
206
|
-
it('should remove
|
|
229
|
+
it('should remove hidden page with same component reused.', () => {
|
|
230
|
+
const submissionData = JSON.parse(JSON.stringify(_dataHiddenPageSameComponentReused.default));
|
|
231
|
+
const form = JSON.parse(JSON.stringify(_formHiddenPageSameComponentReused.default));
|
|
232
|
+
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
233
|
+
expect(result).toEqual(_dataHiddenPageSameComponentReusedRemoved.default);
|
|
234
|
+
});
|
|
235
|
+
it('should show component when reused but only one show_when true.', () => {
|
|
236
|
+
const submissionData = JSON.parse(JSON.stringify(_dataPageSameComponentReusedOneShown.default));
|
|
237
|
+
const form = JSON.parse(JSON.stringify(_formPageSameComponentReusedOneShown.default));
|
|
238
|
+
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
239
|
+
expect(result).toEqual(_dataPageSameComponentReusedOneShownRemoved.default);
|
|
240
|
+
});
|
|
241
|
+
it('should remove a hidden collection on a page.', () => {
|
|
207
242
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenPageCollection.default));
|
|
208
243
|
const form = JSON.parse(JSON.stringify(_formHiddenPageCollection.default));
|
|
209
244
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
210
245
|
expect(result).toEqual(_dataHiddenPageCollectionRemoved.default);
|
|
211
246
|
});
|
|
212
|
-
it('hidden component with show_when rule referring to a collection', () => {
|
|
247
|
+
it('hidden component with show_when rule referring to a collection.', () => {
|
|
213
248
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenComponentReferringToCollection.default));
|
|
214
249
|
const form = JSON.parse(JSON.stringify(_formHiddenComponentReferringToCollection.default));
|
|
215
250
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
216
251
|
expect(result).toEqual(_dataHiddenComponentReferringToCollectionRemoved.default);
|
|
217
252
|
});
|
|
218
|
-
it('hidden component with show_when rule referring to a hidden collection', () => {
|
|
253
|
+
it('hidden component with show_when rule referring to a hidden collection.', () => {
|
|
219
254
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenComponentReferringToHiddenCollection.default));
|
|
220
255
|
const form = JSON.parse(JSON.stringify(_formHiddenComponentReferringToHiddenCollection.default));
|
|
221
256
|
try {
|
|
@@ -225,84 +260,90 @@ describe('FormRenderer', () => {
|
|
|
225
260
|
expect(error.message).toContain('It is not possible to reliably clean hidden data when a component is dependent');
|
|
226
261
|
}
|
|
227
262
|
});
|
|
228
|
-
it('should remove hidden collection components whether they are dependent on data inside or outside the collection', () => {
|
|
263
|
+
it('should remove hidden collection components whether they are dependent on data inside or outside the collection.', () => {
|
|
229
264
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenCollectionComponentDependentOnExternalData.default));
|
|
230
265
|
const form = JSON.parse(JSON.stringify(_formHiddenCollectionComponentDependentOnExternalData.default));
|
|
231
266
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
232
267
|
expect(result).toEqual(_dataHiddenCollectionComponentDependentOnExternalDataRemoved.default);
|
|
233
268
|
});
|
|
234
|
-
it('should not remove component on hidden page if component used elsewhere', () => {
|
|
269
|
+
it('should not remove component on hidden page if component used elsewhere.', () => {
|
|
235
270
|
const submissionData = JSON.parse(JSON.stringify(_dataHiddenPageComponentUsedElsewhere.default));
|
|
236
271
|
const form = JSON.parse(JSON.stringify(_formHiddenPageComponentUsedElsewhere.default));
|
|
237
272
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
238
273
|
expect(result).toEqual(_dataHiddenPageComponentUsedElsewhereRemoved.default);
|
|
239
274
|
});
|
|
240
|
-
it('chained show_whens should be resolved from the end of the chain backup to the start', () => {
|
|
275
|
+
it('chained show_whens should be resolved from the end of the chain backup to the start.', () => {
|
|
241
276
|
const submissionData = JSON.parse(JSON.stringify(_dataChainedComponentShowWhens.default));
|
|
242
277
|
const form = JSON.parse(JSON.stringify(_formChainedComponentShowWhens.default));
|
|
243
278
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
244
279
|
expect(result).toEqual(_dataChainedComponentShowWhensRemoved.default);
|
|
245
280
|
});
|
|
246
|
-
it('chained show_whens when top level dependency is field within refdata object', () => {
|
|
281
|
+
it('chained show_whens when top level dependency is field within refdata object.', () => {
|
|
247
282
|
const submissionData = JSON.parse(JSON.stringify(_dataChainedComponentShowWhensRefdata.default));
|
|
248
283
|
const form = JSON.parse(JSON.stringify(_formChainedComponentShowWhensRefdata.default));
|
|
249
284
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
250
285
|
expect(result).toEqual(_dataChainedComponentShowWhensRefdataRemoved.default);
|
|
251
286
|
});
|
|
252
|
-
it('chained show_whens should be resolved from the end of the chain backup to the start, even if the target and dependent components are in containers thus having segmented paths', () => {
|
|
287
|
+
it('chained show_whens should be resolved from the end of the chain backup to the start, even if the target and dependent components are in containers thus having segmented paths.', () => {
|
|
253
288
|
const submissionData = JSON.parse(JSON.stringify(_dataChainedComponentShowWhensContainerised.default));
|
|
254
289
|
const form = JSON.parse(JSON.stringify(_formChainedComponentShowWhensContainerised.default));
|
|
255
290
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
256
291
|
expect(result).toEqual(_dataChainedComponentShowWhensContainerisedRemoved.default);
|
|
257
292
|
});
|
|
258
|
-
it('chained show_whens when the component at the end of the chain is hidden indirectly via page show_when', () => {
|
|
293
|
+
it('chained show_whens when the component at the end of the chain is hidden indirectly via page show_when.', () => {
|
|
259
294
|
const submissionData = JSON.parse(JSON.stringify(_dataChainedShowWhensPageHidden.default));
|
|
260
295
|
const form = JSON.parse(JSON.stringify(_formChainedShowWhensPageHidden.default));
|
|
261
296
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
262
297
|
expect(result).toEqual(_dataChainedShowWhensPageHiddenRemoved.default);
|
|
263
298
|
});
|
|
264
|
-
it('chained show_whens when the dependent component is nested single question', () => {
|
|
299
|
+
it('chained show_whens when the dependent component is nested single question.', () => {
|
|
265
300
|
const submissionData = JSON.parse(JSON.stringify(_dataChainedComponentShowWhensDependentComponentNested.default));
|
|
266
301
|
const form = JSON.parse(JSON.stringify(_formChainedComponentShowWhensDependentComponentNested.default));
|
|
267
302
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
268
303
|
expect(result).toEqual(_dataChainedComponentShowWhensDependentComponentNestedRemoved.default);
|
|
269
304
|
});
|
|
270
|
-
it('chained show_whens when the target component is nested', () => {
|
|
305
|
+
it('chained show_whens when the target component is nested.', () => {
|
|
271
306
|
const submissionData = JSON.parse(JSON.stringify(_dataChainedComponentShowWhensTargetComponentNested.default));
|
|
272
307
|
const form = JSON.parse(JSON.stringify(_formChainedComponentShowWhensTargetComponentNested.default));
|
|
273
308
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
274
309
|
expect(result).toEqual(_dataChainedComponentShowWhensTargetComponentNestedRemoved.default);
|
|
275
310
|
});
|
|
276
|
-
it('chained show_whens when the dependent component is nested entire block', () => {
|
|
311
|
+
it('chained show_whens when the dependent component is nested entire block.', () => {
|
|
277
312
|
const submissionData = JSON.parse(JSON.stringify(_dataChainedComponentShowWhensDependentComponentNestedBlock.default));
|
|
278
313
|
const form = JSON.parse(JSON.stringify(_formChainedComponentShowWhensDependentComponentNestedBlock.default));
|
|
279
314
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
280
315
|
expect(result).toEqual(_dataChainedComponentShowWhensDependentComponentNestedBlockRemoved.default);
|
|
281
316
|
});
|
|
282
|
-
it('business interests removed from mandec', () => {
|
|
317
|
+
it('business interests removed from mandec.', () => {
|
|
283
318
|
const submissionData = JSON.parse(JSON.stringify(_copMandecRemoveBusinessInterestsBefore.default));
|
|
284
319
|
const form = JSON.parse(JSON.stringify(_formCopMandec.default));
|
|
285
320
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
286
321
|
expect(result).toEqual(_copMandecRemoveBusinessInterestsAfter.default);
|
|
287
322
|
});
|
|
288
|
-
it('criminality removed from mandec', () => {
|
|
323
|
+
it('criminality removed from mandec.', () => {
|
|
289
324
|
const submissionData = JSON.parse(JSON.stringify(_copMandecRemoveCriminalityBefore.default));
|
|
290
325
|
const form = JSON.parse(JSON.stringify(_formCopMandec.default));
|
|
291
326
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
292
327
|
expect(result).toEqual(_copMandecRemoveCriminalityAfter.default);
|
|
293
328
|
});
|
|
294
|
-
it('Unspent convictions removed from mandec', () => {
|
|
329
|
+
it('Unspent convictions removed from mandec.', () => {
|
|
295
330
|
const submissionData = JSON.parse(JSON.stringify(_copMandecRemoveUnspentConvictionsBefore.default));
|
|
296
331
|
const form = JSON.parse(JSON.stringify(_formCopMandec.default));
|
|
297
332
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
298
333
|
expect(result).toEqual(_copMandecRemoveUnspentConvictionsAfter.default);
|
|
299
334
|
});
|
|
300
|
-
it('photos removed from airpax', () => {
|
|
335
|
+
it('photos removed from airpax.', () => {
|
|
301
336
|
const submissionData = JSON.parse(JSON.stringify(_copAirpaxRemovePhotosBefore.default));
|
|
302
337
|
const form = JSON.parse(JSON.stringify(_formCopAirpax.default));
|
|
303
338
|
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
304
339
|
expect(result).toEqual(_copAirpaxRemovePhotosAfter.default);
|
|
305
340
|
});
|
|
341
|
+
it('airpax change whatHappened to hide whoDecidedSelection.', () => {
|
|
342
|
+
const submissionData = JSON.parse(JSON.stringify(_copAirpaxChangeWhatHappenedBefore.default));
|
|
343
|
+
const form = JSON.parse(JSON.stringify(_formCopAirpax.default));
|
|
344
|
+
const result = _index.default.clearOutUncompletedRoutes(form, submissionData);
|
|
345
|
+
expect(result).toEqual(_copAirpaxChangeWhatHappenedAfter.default);
|
|
346
|
+
});
|
|
306
347
|
});
|
|
307
348
|
});
|
|
308
349
|
});
|
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.toArray = exports.removeObjectWithOnlySingleIdField = exports.removeEmptyArraysAndUnusedCollectionIDs = exports.pruneCollectionEntry = exports.isShowEntity = exports.getNestedQuestionPath = exports.getImmediateParent = exports.getDependencyObjectFromPath = exports.getDependencies = exports.findComponentDefinitionInForm = exports.deleteNodeByPath = exports.deleteNodeAndOptions = exports.deleteCorrespondingMetaInfo = exports.deleteComponentData = exports.addValue = void 0;
|
|
7
|
+
var _Condition = _interopRequireDefault(require("../../../utils/Condition"));
|
|
8
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
|
+
/* eslint-disable no-param-reassign */
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Add a value to a map of arrays. If the key exists, append the value to the array.
|
|
13
|
+
* If not, create the map entry with that key.
|
|
14
|
+
*
|
|
15
|
+
* @param {*} key
|
|
16
|
+
* @param {*} value
|
|
17
|
+
* @param {*} multiMap
|
|
18
|
+
*/
|
|
19
|
+
const addValue = (key, value, multiMap) => {
|
|
20
|
+
if (!multiMap.has(key)) {
|
|
21
|
+
multiMap.set(key, []);
|
|
22
|
+
}
|
|
23
|
+
multiMap.get(key).push(value);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Given a path, remove a node from this path within an object.
|
|
28
|
+
*
|
|
29
|
+
* @param {Object} payload Javascript object from which the node will be deleted. Updated by the method.
|
|
30
|
+
* @param {String} path A string containing a decimal point delimited path specifying the node to delete.
|
|
31
|
+
* @return {void}, obj above updated.
|
|
32
|
+
*/
|
|
33
|
+
exports.addValue = addValue;
|
|
34
|
+
const deleteNodeByPath = (payload, path) => {
|
|
35
|
+
if (Array.isArray(payload)) {
|
|
36
|
+
// If payload is an array, recursively call deleteNodeByPath on each element
|
|
37
|
+
for (let i = 0; i < payload.length; i += 1) {
|
|
38
|
+
deleteNodeByPath(payload[i], path);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const keys = path.split('.');
|
|
42
|
+
let current = payload;
|
|
43
|
+
for (let i = 0; i < keys.length - 1; i += 1) {
|
|
44
|
+
current = current[keys[i]];
|
|
45
|
+
if (current === undefined) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (current[keys[keys.length - 1]]) {
|
|
50
|
+
delete current[keys[keys.length - 1]];
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Return the immediate parent of a path string passed in.
|
|
56
|
+
* Useful for processing 'options' in a form, as nested fieldIds are placed in the payload at
|
|
57
|
+
* the same level in the heirarchy as the option question they relate to.
|
|
58
|
+
*
|
|
59
|
+
* @param {String} path Decimal point delimited path.
|
|
60
|
+
* @returns {String} Immediate parent of the path passed in.
|
|
61
|
+
*/
|
|
62
|
+
exports.deleteNodeByPath = deleteNodeByPath;
|
|
63
|
+
const getImmediateParent = path => {
|
|
64
|
+
if (typeof path !== 'string' || !path.includes('.')) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
const parts = path.split('.');
|
|
68
|
+
parts.pop();
|
|
69
|
+
return parts.join('.');
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Questions can be nested within options, eg if you answer 'yes' to a radio question, this can
|
|
74
|
+
* reveal additional nested questions.
|
|
75
|
+
* The path of the fields from these nested questions are at the same level as the original option
|
|
76
|
+
* answer, so this utility derives the nested question path from the option path.
|
|
77
|
+
*
|
|
78
|
+
* @param {String} optionPath Decimal point delimited path
|
|
79
|
+
* @param {String} nestedFieldId fieldId (dataname) of the nested question within the above option
|
|
80
|
+
* @returns {String} Fully qualified path of the nested question
|
|
81
|
+
*/
|
|
82
|
+
exports.getImmediateParent = getImmediateParent;
|
|
83
|
+
const getNestedQuestionPath = (optionPath, nestedFieldId) => {
|
|
84
|
+
const parentPath = getImmediateParent(optionPath);
|
|
85
|
+
return parentPath ? "".concat(parentPath, ".").concat(nestedFieldId) : nestedFieldId;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* If the component has options, go through each option removing the data for any nested fields.
|
|
90
|
+
* Required as nested options are in the payload at the same heirarchical level.
|
|
91
|
+
|
|
92
|
+
* @param {Object} payload Javascript object from which the node will be deleted. Updated by the method.
|
|
93
|
+
* @param {String} path A string containing a decimal point delimited path specifying the node to delete.
|
|
94
|
+
* @param {Object} component The form component representing the path being deleted
|
|
95
|
+
* @return {void}, obj above updated.
|
|
96
|
+
*/
|
|
97
|
+
exports.getNestedQuestionPath = getNestedQuestionPath;
|
|
98
|
+
const deleteNodeAndOptions = (payload, path, component) => {
|
|
99
|
+
var _component$data;
|
|
100
|
+
deleteNodeByPath(payload, path);
|
|
101
|
+
// 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.
|
|
102
|
+
if (component !== null && component !== void 0 && (_component$data = component.data) !== null && _component$data !== void 0 && _component$data.options) {
|
|
103
|
+
var _component$data2;
|
|
104
|
+
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 => {
|
|
105
|
+
var _option$nested;
|
|
106
|
+
(_option$nested = option.nested) === null || _option$nested === void 0 || _option$nested.forEach(nested => {
|
|
107
|
+
deleteNodeByPath(payload, getNestedQuestionPath(path, nested.fieldId));
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Pruning a collection payload may have resulted in objects that are only left with their 'id' field, which isn't data
|
|
115
|
+
* but added by the renderer to find the activeId. If so, remove these objects entirely as they have been pruned.
|
|
116
|
+
*
|
|
117
|
+
* @param {Array} array Array of objects. Each object which has only 1 remaining field called 'id' should be removed.
|
|
118
|
+
* @return {void}, array above updated.
|
|
119
|
+
*/
|
|
120
|
+
exports.deleteNodeAndOptions = deleteNodeAndOptions;
|
|
121
|
+
const removeObjectWithOnlySingleIdField = array => {
|
|
122
|
+
for (let i = array.length - 1; i >= 0; i -= 1) {
|
|
123
|
+
const obj = array[i];
|
|
124
|
+
if (Object.keys(obj).length === 1 && Object.keys(obj)[0] === 'id') {
|
|
125
|
+
array.splice(i, 1);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Helper method to establish all the payload paths (dependencies) that an entity (page or component) is
|
|
132
|
+
* dependent on through its show_when rule.
|
|
133
|
+
*
|
|
134
|
+
* This will be used to build a graph of chained dependencies to establish in which order
|
|
135
|
+
* to resolve dependencies. The exact rule is not required at this point, just the dependencies.
|
|
136
|
+
*
|
|
137
|
+
* The form specification allows complex show_when blocks including 1...n levels of nesting, so
|
|
138
|
+
* recursively search through the show_when block looking for all 'field' data items.
|
|
139
|
+
*
|
|
140
|
+
* @param {Object} entity Entity whose show_when rule is to be searched for 'field' data items within.
|
|
141
|
+
* @returns {Set} Set of payload paths that the entity (page or component) is dependent on.
|
|
142
|
+
*/
|
|
143
|
+
exports.removeObjectWithOnlySingleIdField = removeObjectWithOnlySingleIdField;
|
|
144
|
+
const getDependencies = entity => {
|
|
145
|
+
const findShowWhenFields = (showWhenObject, showWhenFields) => {
|
|
146
|
+
if (typeof showWhenObject === 'object' && showWhenObject !== null) {
|
|
147
|
+
if (Array.isArray(showWhenObject)) {
|
|
148
|
+
showWhenObject.forEach(value => {
|
|
149
|
+
findShowWhenFields(value, showWhenFields);
|
|
150
|
+
});
|
|
151
|
+
} else {
|
|
152
|
+
Object.keys(showWhenObject).forEach(key => {
|
|
153
|
+
if (key === 'field') {
|
|
154
|
+
showWhenFields.push(showWhenObject[key]);
|
|
155
|
+
}
|
|
156
|
+
findShowWhenFields(showWhenObject[key], showWhenFields);
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return showWhenFields;
|
|
161
|
+
};
|
|
162
|
+
return entity.show_when ? new Set(findShowWhenFields(entity.show_when, []) || []) : null;
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Some show_when field values point to data items that are within objects provided by
|
|
167
|
+
* external calls to refdata, eg modeOfTransport.id. These won't map directly to the path
|
|
168
|
+
* keyed components in the allComponents map, so go back up levels in the path until we find
|
|
169
|
+
* the component that creates this field.
|
|
170
|
+
*
|
|
171
|
+
* This component might not be found at all, as the dependency might be on a field that is either
|
|
172
|
+
* provided by cop-ui (eg jobHolderStaffDetails.linemanagerEmail), or by the "addToFormData" function
|
|
173
|
+
* (eg epmsSubmitted). These will be leaf level in the dependency chain so component is not required.
|
|
174
|
+
*
|
|
175
|
+
* @param {String} optionPath Decimal point delimited path
|
|
176
|
+
* @param {String} nestedFieldId fieldId (dataname) of the nested question within the above option
|
|
177
|
+
* @returns {String} Fully qualified path of the nested question
|
|
178
|
+
*
|
|
179
|
+
*/
|
|
180
|
+
exports.getDependencies = getDependencies;
|
|
181
|
+
const getDependencyObjectFromPath = (dependencyPath, allComponents) => {
|
|
182
|
+
const segments = dependencyPath.split(".");
|
|
183
|
+
for (let i = segments.length; i > 0; i -= 1) {
|
|
184
|
+
const currentPath = segments.slice(0, i).join(".");
|
|
185
|
+
const dependencyObject = allComponents.get(currentPath);
|
|
186
|
+
if (dependencyObject) return dependencyObject;
|
|
187
|
+
}
|
|
188
|
+
return null;
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
*
|
|
193
|
+
* Evaluate the show_when rule to establish if the component should be shown (and the
|
|
194
|
+
* payload data should not be pruned). If there is no show_when rule, then return true.
|
|
195
|
+
*
|
|
196
|
+
* @param {*} entity A page or component that may have a show_when rule associated with it
|
|
197
|
+
* @param {*} data The payload data used to evaluate the show_when rule
|
|
198
|
+
* @returns {boolean} true if the show_when rule evaluate to true, or there is no show_when rule
|
|
199
|
+
*/
|
|
200
|
+
exports.getDependencyObjectFromPath = getDependencyObjectFromPath;
|
|
201
|
+
const isShowEntity = (entity, data) => {
|
|
202
|
+
var _entity$show_when;
|
|
203
|
+
// If there is no rule set, then the entity can be shown
|
|
204
|
+
if (!entity.show_when) {
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
if (((_entity$show_when = entity.show_when) === null || _entity$show_when === void 0 ? void 0 : _entity$show_when.type) === "or") {
|
|
208
|
+
return _Condition.default.meetsOne(entity, data);
|
|
209
|
+
}
|
|
210
|
+
return _Condition.default.meetsAll(entity, data);
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
*
|
|
215
|
+
* Components can be assigned to pages in 2 ways in the form specification:
|
|
216
|
+
*
|
|
217
|
+
* 1 - They can be included in the page's components array with the 'use' field, e.g.
|
|
218
|
+
* {
|
|
219
|
+
* "use": "port"
|
|
220
|
+
* }
|
|
221
|
+
* This "use" value will normally match a component's id, but can match its fieldId
|
|
222
|
+
* NB. In this case, a show_when rule can be applied here, which will supercede any show_when in the component. e.g.
|
|
223
|
+
*
|
|
224
|
+
* {
|
|
225
|
+
* "use": "port",
|
|
226
|
+
* "show_when": ....
|
|
227
|
+
* }
|
|
228
|
+
*
|
|
229
|
+
* 2 - The entire component can be embedded as an entry in the page's component array.
|
|
230
|
+
*
|
|
231
|
+
*
|
|
232
|
+
* @param {*} componentId The id of the component to find in the form.
|
|
233
|
+
* @param {*} componentByIdMap A map of all the form's components keyed on Id, for better performance than searching the form.
|
|
234
|
+
* @param {*} componentByFieldIdMap A map of all the form's components keyed on fieldId, for better performance than searching the form.
|
|
235
|
+
* @returns {Object} A cloned component object, containing the full definition of that component.
|
|
236
|
+
*/
|
|
237
|
+
exports.isShowEntity = isShowEntity;
|
|
238
|
+
const findComponentDefinitionInForm = (pageComponentDef, componentByIdMap, componentByFieldIdMap) => {
|
|
239
|
+
var _ref, _componentByIdMap$get;
|
|
240
|
+
const componentInForm = (_ref = (_componentByIdMap$get = componentByIdMap.get(pageComponentDef.use)) !== null && _componentByIdMap$get !== void 0 ? _componentByIdMap$get : componentByFieldIdMap.get(pageComponentDef.use)) !== null && _ref !== void 0 ? _ref : pageComponentDef;
|
|
241
|
+
if (pageComponentDef.use && pageComponentDef.show_when) {
|
|
242
|
+
componentInForm.show_when = pageComponentDef.show_when;
|
|
243
|
+
}
|
|
244
|
+
// Retun clone of component, so subsequent processing can make changes to it without changing the form
|
|
245
|
+
return JSON.parse(JSON.stringify(componentInForm));
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
*
|
|
250
|
+
* When documents are added to the payload of type multifile, they are also added to a section of the payload
|
|
251
|
+
* 'meta', specifically an array 'documents'. When we remove the multifile elements, we need to remove
|
|
252
|
+
* the corresponding meta.document entries.
|
|
253
|
+
*
|
|
254
|
+
* @param {*} component The component definition being deleted that needs corresponding meta data also deleted
|
|
255
|
+
* @param {*} collectionDataObject The payload containing the file data being deleted (for which the corresponding meta needs deleting)
|
|
256
|
+
* @param {*} formData The entire payload, which will include the meta section
|
|
257
|
+
* @returns {void}, as the formData will be updated in situ
|
|
258
|
+
*/
|
|
259
|
+
exports.findComponentDefinitionInForm = findComponentDefinitionInForm;
|
|
260
|
+
const deleteCorrespondingMetaInfo = (component, collectionDataObject, formData) => {
|
|
261
|
+
const {
|
|
262
|
+
meta: {
|
|
263
|
+
documents
|
|
264
|
+
}
|
|
265
|
+
} = formData;
|
|
266
|
+
const fileDataBeingDeleted = collectionDataObject[component.fieldId];
|
|
267
|
+
if (!documents || !fileDataBeingDeleted) return;
|
|
268
|
+
const fileDataAsArray = Array.isArray(fileDataBeingDeleted) ? fileDataBeingDeleted : [fileDataBeingDeleted];
|
|
269
|
+
// Iterate backwards to avoid index shifting when removing elements
|
|
270
|
+
for (let i = fileDataAsArray.length - 1; i >= 0; i -= 1) {
|
|
271
|
+
const matchIndex = documents.findIndex(metaDocument => metaDocument.url === fileDataAsArray[i].url);
|
|
272
|
+
if (matchIndex !== -1) {
|
|
273
|
+
documents.splice(matchIndex, 1);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* After the payload has been cleansed of individual data items, empty arrays and objects may remain.
|
|
280
|
+
* Removing an array (when the payload for a collection) may leave a redundant activeId field. The active Id
|
|
281
|
+
* fields are not part of the payload data, but added by the react renderer to track which collection object
|
|
282
|
+
* is currently being worked on, so can be removed.
|
|
283
|
+
*
|
|
284
|
+
* To tidy this all up, recursively empty arrays and their associated "ActiveId" fields from a nested payload.
|
|
285
|
+
*
|
|
286
|
+
* This function traverses a given payload, which can be an array or an object, and performs the following operations:
|
|
287
|
+
* 1. If an empty array is found inside an array, it is removed using `splice`.
|
|
288
|
+
* 2. If an empty array is found inside an object:
|
|
289
|
+
* - It is removed from the object.
|
|
290
|
+
* - If there is a corresponding `<key>ActiveId` field, that field is also removed.
|
|
291
|
+
* 3. The function operates recursively to handle deeply nested structures.
|
|
292
|
+
*
|
|
293
|
+
* @param {any} payload - The input data structure, which can be an array or an object.
|
|
294
|
+
*
|
|
295
|
+
*/
|
|
296
|
+
exports.deleteCorrespondingMetaInfo = deleteCorrespondingMetaInfo;
|
|
297
|
+
const removeEmptyArraysAndUnusedCollectionIDs = payload => {
|
|
298
|
+
if (Array.isArray(payload)) {
|
|
299
|
+
for (let i = payload.length - 1; i >= 0; i -= 1) {
|
|
300
|
+
if (Array.isArray(payload[i]) && payload[i].length === 0) {
|
|
301
|
+
payload.splice(i, 1);
|
|
302
|
+
} else {
|
|
303
|
+
removeEmptyArraysAndUnusedCollectionIDs(payload[i]); // Recurse for nested structures
|
|
304
|
+
}
|
|
305
|
+
// When unwinding out of the recursion, we may have emptied an object which is the remaining element of an
|
|
306
|
+
// array, in which case remove the element
|
|
307
|
+
if (typeof payload[i] === 'object' && Object.keys(payload[i]).length === 0) {
|
|
308
|
+
payload.splice(i, 1);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
} else if (payload !== null && typeof payload === 'object') {
|
|
312
|
+
Object.keys(payload).forEach(key => {
|
|
313
|
+
if (Array.isArray(payload[key]) && payload[key].length === 0) {
|
|
314
|
+
// If the array being removed has an activeId associated with it, remove it
|
|
315
|
+
if (payload["".concat(key, "ActiveId")]) {
|
|
316
|
+
delete payload["".concat(key, "ActiveId")];
|
|
317
|
+
}
|
|
318
|
+
delete payload["".concat(key, "ActiveId")];
|
|
319
|
+
if (payload[key]) {
|
|
320
|
+
delete payload[key];
|
|
321
|
+
}
|
|
322
|
+
} else {
|
|
323
|
+
removeEmptyArraysAndUnusedCollectionIDs(payload[key]); // Recurse for nested structures
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Delete a component's payload item from the overall payload.
|
|
331
|
+
* A component can be defined in >1 places in the form spec. To cater for this,
|
|
332
|
+
* if the componentsToKeep counter tells us that there is > 1 uses of this component
|
|
333
|
+
* still unaccounted for in the form then don't delete, but reduce the count by 1.
|
|
334
|
+
*
|
|
335
|
+
* When the counter reaches 1 we know all other occurences of the component have been resolved
|
|
336
|
+
* so it is safe to delete.
|
|
337
|
+
*
|
|
338
|
+
* @param {*} payload The form payload from which to delete the component data
|
|
339
|
+
* @param {*} path The payload path of the component
|
|
340
|
+
* @param {*} component The component whose data we should attempt to delete
|
|
341
|
+
* @param {*} componentsToKeep A list of all components with a count of their number of uses in the form
|
|
342
|
+
*/
|
|
343
|
+
exports.removeEmptyArraysAndUnusedCollectionIDs = removeEmptyArraysAndUnusedCollectionIDs;
|
|
344
|
+
const deleteComponentData = (payload, path, component, componentsToKeep) => {
|
|
345
|
+
if (componentsToKeep[path] > 1) {
|
|
346
|
+
componentsToKeep[path] -= 1;
|
|
347
|
+
} else {
|
|
348
|
+
deleteNodeAndOptions(payload, path, component);
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
*
|
|
354
|
+
* Takes a single page collection payload object and removes the payload items specified in the componentsToPrune list
|
|
355
|
+
* as long as they don't appear in the componentsToKeep list.
|
|
356
|
+
* Additionally, if the component type is multifile, remove the corresponding data entries that will have been created
|
|
357
|
+
* in the meta section of the payload by the form renderer.
|
|
358
|
+
*
|
|
359
|
+
* @param {Set} pathsToKeep paths that we cannot delete from the collectionDataObject
|
|
360
|
+
* @param {Map} componentsToPrune paths that we should delete, as long as they are not in the pathsToKeep
|
|
361
|
+
* @param {Object} collectionDataObject the payload from which to delete the paths
|
|
362
|
+
* @param {Object} formData The form data, whose meta section may include corresponding documents entries for multifile entries
|
|
363
|
+
*/
|
|
364
|
+
exports.deleteComponentData = deleteComponentData;
|
|
365
|
+
const pruneCollectionEntry = (pathsToKeep, componentsToPrune, collectionDataObject, formData) => {
|
|
366
|
+
componentsToPrune.forEach(component => {
|
|
367
|
+
if (!pathsToKeep.has(component.fieldId)) {
|
|
368
|
+
if (component.type === "multifile") {
|
|
369
|
+
deleteCorrespondingMetaInfo(component, collectionDataObject, formData);
|
|
370
|
+
}
|
|
371
|
+
deleteNodeAndOptions(collectionDataObject, component.fieldId, component);
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
};
|
|
375
|
+
|
|
376
|
+
/*
|
|
377
|
+
* Converts an object to an array if it isn't already, for use when combining show when rules.
|
|
378
|
+
*/
|
|
379
|
+
exports.pruneCollectionEntry = pruneCollectionEntry;
|
|
380
|
+
const toArray = value => Array.isArray(value) ? value : [value];
|
|
381
|
+
exports.toArray = toArray;
|