@ukhomeoffice/cop-react-form-renderer 5.45.1 → 5.48.1-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/CollectionSummary.js +13 -1
- package/dist/components/CollectionSummary/SummaryCard.js +19 -20
- package/dist/components/CollectionSummary/SummaryCard.scss +1 -1
- package/dist/components/CollectionSummary/SummaryCard.test.js +20 -20
- package/dist/components/FormRenderer/FormRenderer.js +3 -2
- package/dist/components/FormRenderer/helpers/canActionProceed.js +5 -1
- package/dist/components/FormRenderer/helpers/canActionProceed.test.js +38 -2
- package/dist/components/FormRenderer/onPageAction.js +2 -2
- package/dist/utils/Validate/additional/index.js +6 -4
- package/dist/utils/Validate/additional/mustBeUniqueInCollection.js +35 -0
- package/dist/utils/Validate/additional/mustBeUniqueInCollection.test.js +127 -0
- package/dist/utils/Validate/validateComponent.js +1 -1
- package/package.json +2 -2
|
@@ -187,6 +187,10 @@ var CollectionSummary = function CollectionSummary(_ref) {
|
|
|
187
187
|
},
|
|
188
188
|
onAction: onAction
|
|
189
189
|
}), data.map(function (entry, index) {
|
|
190
|
+
var isInError = errors.filter(function (e) {
|
|
191
|
+
return e.entryId === entry.id;
|
|
192
|
+
}).length > 0;
|
|
193
|
+
var finalConfig = _objectSpread(_objectSpread({}, config.card), isInError && config.errorCard ? config.errorCard : {});
|
|
190
194
|
var key = "".concat(config.fieldId, ".summaryCard").concat(entry.id);
|
|
191
195
|
return /*#__PURE__*/_react.default.createElement(_SummaryCardValidationContext.default, {
|
|
192
196
|
entryId: entry.id,
|
|
@@ -198,7 +202,7 @@ var CollectionSummary = function CollectionSummary(_ref) {
|
|
|
198
202
|
index: index
|
|
199
203
|
}),
|
|
200
204
|
masterPage: masterPage,
|
|
201
|
-
config:
|
|
205
|
+
config: finalConfig || {},
|
|
202
206
|
onChange: onSummaryCardChange,
|
|
203
207
|
onDuplicate: onDuplicate,
|
|
204
208
|
onDelete: function onDelete() {
|
|
@@ -234,6 +238,14 @@ CollectionSummary.propTypes = {
|
|
|
234
238
|
fieldsToIgnore: _propTypes.default.arrayOf(_propTypes.default.string)
|
|
235
239
|
})
|
|
236
240
|
}),
|
|
241
|
+
errorCard: _propTypes.default.shape({
|
|
242
|
+
banners: _propTypes.default.arrayOf(_propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.shape({})])),
|
|
243
|
+
title: _propTypes.default.string,
|
|
244
|
+
details: _propTypes.default.string,
|
|
245
|
+
duplicateAction: _propTypes.default.shape({
|
|
246
|
+
fieldsToIgnore: _propTypes.default.arrayOf(_propTypes.default.string)
|
|
247
|
+
})
|
|
248
|
+
}),
|
|
237
249
|
confirmation: _propTypes.default.shape({
|
|
238
250
|
message: _propTypes.default.string,
|
|
239
251
|
label: _propTypes.default.string
|
|
@@ -4,7 +4,7 @@ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" ==
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
-
exports.default = exports.DEFAULT_TITLE = exports.
|
|
7
|
+
exports.default = exports.DEFAULT_TITLE = exports.DEFAULT_EDIT_LABEL = exports.DEFAULT_DUPLICATE_BUTTON_LABEL = exports.DEFAULT_DETAILS_TITLE = exports.DEFAULT_DELETE_BUTTON_LABEL = exports.DEFAULT_CLASS = exports.DEFAULT_CHANGE_BUTTON_LABEL = exports.DEFAULT_CHANGE_BUTTON_CLASS = void 0;
|
|
8
8
|
var _copReactComponents = require("@ukhomeoffice/cop-react-components");
|
|
9
9
|
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
10
10
|
var _react = _interopRequireWildcard(require("react"));
|
|
@@ -40,10 +40,10 @@ var DEFAULT_CHANGE_BUTTON_LABEL = exports.DEFAULT_CHANGE_BUTTON_LABEL = 'Change'
|
|
|
40
40
|
var DEFAULT_DELETE_BUTTON_LABEL = exports.DEFAULT_DELETE_BUTTON_LABEL = 'Delete';
|
|
41
41
|
var DEFAULT_EDIT_LABEL = exports.DEFAULT_EDIT_LABEL = 'Quick Edit';
|
|
42
42
|
var DEFAULT_DUPLICATE_BUTTON_LABEL = exports.DEFAULT_DUPLICATE_BUTTON_LABEL = 'Duplicate';
|
|
43
|
-
var
|
|
44
|
-
var
|
|
43
|
+
var DEFAULT_DETAILS_TITLE = exports.DEFAULT_DETAILS_TITLE = 'Full details';
|
|
44
|
+
var DEFAULT_CHANGE_BUTTON_CLASS = exports.DEFAULT_CHANGE_BUTTON_CLASS = 'secondary';
|
|
45
45
|
var SummaryCard = function SummaryCard(_ref) {
|
|
46
|
-
var _config$changeAction2, _config$changeAction3, _config$duplicateActi, _config$deleteAction,
|
|
46
|
+
var _config$changeAction2, _config$changeAction3, _config$duplicateActi, _config$deleteAction, _masterPage$childPage;
|
|
47
47
|
var id = _ref.id,
|
|
48
48
|
entryData = _ref.entryData,
|
|
49
49
|
config = _ref.config,
|
|
@@ -57,12 +57,12 @@ var SummaryCard = function SummaryCard(_ref) {
|
|
|
57
57
|
formData = _ref.formData,
|
|
58
58
|
masterPage = _ref.masterPage,
|
|
59
59
|
hideDetails = _ref.hideDetails,
|
|
60
|
-
|
|
60
|
+
inError = _ref.inError;
|
|
61
61
|
var _useState = (0, _react.useState)(false),
|
|
62
62
|
_useState2 = _slicedToArray(_useState, 2),
|
|
63
63
|
quickEdit = _useState2[0],
|
|
64
64
|
setQuickEdit = _useState2[1];
|
|
65
|
-
var classes = _copReactComponents.Utils.classBuilder(DEFAULT_CLASS, classModifiers,
|
|
65
|
+
var classes = _copReactComponents.Utils.classBuilder(DEFAULT_CLASS, classModifiers, inError ? 'error' : '');
|
|
66
66
|
var quickEditPage = (0, _react.useMemo)(function () {
|
|
67
67
|
return (0, _getQuickEditPage.default)(config.quickEdit, pages, entryData);
|
|
68
68
|
}, [pages, config, entryData, quickEdit]);
|
|
@@ -152,7 +152,7 @@ var SummaryCard = function SummaryCard(_ref) {
|
|
|
152
152
|
className: classes('header-content-detail')
|
|
153
153
|
}, _copReactComponents.Utils.interpolateString(config.details, entryData))), /*#__PURE__*/_react.default.createElement("div", {
|
|
154
154
|
className: classes('header-actions')
|
|
155
|
-
}, config.quickEdit &&
|
|
155
|
+
}, config.quickEdit && /*#__PURE__*/_react.default.createElement(_copReactComponents.Button, {
|
|
156
156
|
id: "".concat(id, ".quickEditButton"),
|
|
157
157
|
onClick: function onClick() {
|
|
158
158
|
return setQuickEdit(function (prevState) {
|
|
@@ -167,8 +167,8 @@ var SummaryCard = function SummaryCard(_ref) {
|
|
|
167
167
|
var _config$changeAction;
|
|
168
168
|
return onChange((_config$changeAction = config.changeAction) === null || _config$changeAction === void 0 ? void 0 : _config$changeAction.page, entryData.id);
|
|
169
169
|
},
|
|
170
|
-
classModifiers:
|
|
171
|
-
},
|
|
170
|
+
classModifiers: ((_config$changeAction2 = config.changeAction) === null || _config$changeAction2 === void 0 ? void 0 : _config$changeAction2.classModifiers) || DEFAULT_CHANGE_BUTTON_CLASS
|
|
171
|
+
}, ((_config$changeAction3 = config.changeAction) === null || _config$changeAction3 === void 0 ? void 0 : _config$changeAction3.label) || DEFAULT_CHANGE_BUTTON_LABEL), config.duplicateAction && typeof onDuplicate === 'function' && /*#__PURE__*/_react.default.createElement(_copReactComponents.Button, {
|
|
172
172
|
id: "".concat(id, ".duplicateButton"),
|
|
173
173
|
onClick: function onClick() {
|
|
174
174
|
onDuplicate(entryData);
|
|
@@ -180,7 +180,7 @@ var SummaryCard = function SummaryCard(_ref) {
|
|
|
180
180
|
return onDelete(entryData);
|
|
181
181
|
},
|
|
182
182
|
classModifiers: "secondary"
|
|
183
|
-
},
|
|
183
|
+
}, ((_config$deleteAction = config.deleteAction) === null || _config$deleteAction === void 0 ? void 0 : _config$deleteAction.label) || DEFAULT_DELETE_BUTTON_LABEL))), quickEdit && quickEditPage && /*#__PURE__*/_react.default.createElement(_FormPage.default, {
|
|
184
184
|
page: quickEditPage,
|
|
185
185
|
onAction: function onAction(action, patch) {
|
|
186
186
|
return _onAction(action, patch);
|
|
@@ -189,7 +189,7 @@ var SummaryCard = function SummaryCard(_ref) {
|
|
|
189
189
|
}), /*#__PURE__*/_react.default.createElement("div", {
|
|
190
190
|
className: classes('body')
|
|
191
191
|
}, !hideDetails && /*#__PURE__*/_react.default.createElement(_copReactComponents.Details, {
|
|
192
|
-
summary:
|
|
192
|
+
summary: config.detailsTitle || DEFAULT_DETAILS_TITLE,
|
|
193
193
|
className: "details"
|
|
194
194
|
}, masterPage === null || masterPage === void 0 || (_masterPage$childPage = masterPage.childPages) === null || _masterPage$childPage === void 0 ? void 0 : _masterPage$childPage.map(function (childPage) {
|
|
195
195
|
var _childPage$summaryLay;
|
|
@@ -235,22 +235,21 @@ SummaryCard.propTypes = {
|
|
|
235
235
|
details: _propTypes.default.string,
|
|
236
236
|
changeAction: _propTypes.default.shape({
|
|
237
237
|
label: _propTypes.default.string,
|
|
238
|
-
|
|
239
|
-
|
|
238
|
+
page: _propTypes.default.string.isRequired,
|
|
239
|
+
classModifiers: _propTypes.default.string
|
|
240
240
|
}),
|
|
241
241
|
deleteAction: _propTypes.default.shape({
|
|
242
|
-
label: _propTypes.default.string
|
|
243
|
-
isDuplicateLabel: _propTypes.default.string
|
|
242
|
+
label: _propTypes.default.string
|
|
244
243
|
}),
|
|
245
244
|
duplicateAction: _propTypes.default.shape({
|
|
246
|
-
label: _propTypes.default.string
|
|
247
|
-
isDuplicateLabel: _propTypes.default.string
|
|
245
|
+
label: _propTypes.default.string
|
|
248
246
|
}),
|
|
249
247
|
quickEdit: _propTypes.default.shape({
|
|
250
248
|
components: _propTypes.default.arrayOf(_propTypes.default.shape({
|
|
251
249
|
use: _propTypes.default.string
|
|
252
250
|
}))
|
|
253
|
-
})
|
|
251
|
+
}),
|
|
252
|
+
detailsTitle: _propTypes.default.string
|
|
254
253
|
}).isRequired,
|
|
255
254
|
masterPage: _propTypes.default.shape({
|
|
256
255
|
childPages: _propTypes.default.arrayOf(_propTypes.default.shape({
|
|
@@ -266,7 +265,7 @@ SummaryCard.propTypes = {
|
|
|
266
265
|
parentCollectionName: _propTypes.default.string.isRequired,
|
|
267
266
|
formData: _propTypes.default.shape({}).isRequired,
|
|
268
267
|
hideDetails: _propTypes.default.bool,
|
|
269
|
-
|
|
268
|
+
inError: _propTypes.default.bool
|
|
270
269
|
};
|
|
271
270
|
SummaryCard.defaultProps = {
|
|
272
271
|
classModifiers: null,
|
|
@@ -275,6 +274,6 @@ SummaryCard.defaultProps = {
|
|
|
275
274
|
onDuplicate: null,
|
|
276
275
|
onQuickEdit: null,
|
|
277
276
|
hideDetails: false,
|
|
278
|
-
|
|
277
|
+
inError: false
|
|
279
278
|
};
|
|
280
279
|
var _default = exports.default = SummaryCard;
|
|
@@ -204,7 +204,7 @@ describe('components.CollectionSummary.SummaryCard', function () {
|
|
|
204
204
|
expect(headerDetails.textContent).toEqual("".concat(ENTRY.detailsText, " that are interpolated"));
|
|
205
205
|
});
|
|
206
206
|
describe('Change action button', function () {
|
|
207
|
-
var
|
|
207
|
+
var inErrorValue = true;
|
|
208
208
|
var onChangeArgs = [];
|
|
209
209
|
var onChangeCalls = 0;
|
|
210
210
|
var ON_CHANGE = function ON_CHANGE(page, id) {
|
|
@@ -213,7 +213,7 @@ describe('components.CollectionSummary.SummaryCard', function () {
|
|
|
213
213
|
id: id
|
|
214
214
|
});
|
|
215
215
|
onChangeCalls += 1;
|
|
216
|
-
|
|
216
|
+
inErrorValue = false;
|
|
217
217
|
};
|
|
218
218
|
beforeEach(function () {
|
|
219
219
|
onChangeArgs = [];
|
|
@@ -252,7 +252,7 @@ describe('components.CollectionSummary.SummaryCard', function () {
|
|
|
252
252
|
id: ENTRY.id
|
|
253
253
|
});
|
|
254
254
|
});
|
|
255
|
-
it('should render correctly when
|
|
255
|
+
it('should render correctly when inError is true', function () {
|
|
256
256
|
var CONFIG = {
|
|
257
257
|
changeAction: {
|
|
258
258
|
label: 'Change label',
|
|
@@ -270,7 +270,7 @@ describe('components.CollectionSummary.SummaryCard', function () {
|
|
|
270
270
|
masterPage: {
|
|
271
271
|
childPages: []
|
|
272
272
|
},
|
|
273
|
-
|
|
273
|
+
inError: inErrorValue
|
|
274
274
|
})),
|
|
275
275
|
container = _renderWithValidation7.container;
|
|
276
276
|
var _checkSetup7 = checkSetup(container),
|
|
@@ -286,8 +286,8 @@ describe('components.CollectionSummary.SummaryCard', function () {
|
|
|
286
286
|
id: ENTRY.id
|
|
287
287
|
});
|
|
288
288
|
|
|
289
|
-
// Check that the
|
|
290
|
-
expect(
|
|
289
|
+
// Check that the inError prop is now false
|
|
290
|
+
expect(inErrorValue).toBe(false);
|
|
291
291
|
});
|
|
292
292
|
it('should use the default label when one is not provided', function () {
|
|
293
293
|
var CONFIG = {
|
|
@@ -630,7 +630,7 @@ describe('components.CollectionSummary.SummaryCard', function () {
|
|
|
630
630
|
masterPage: {
|
|
631
631
|
childPages: []
|
|
632
632
|
},
|
|
633
|
-
|
|
633
|
+
inError: true
|
|
634
634
|
})),
|
|
635
635
|
container = _renderWithValidation20.container;
|
|
636
636
|
var _checkSetup19 = checkSetup(container),
|
|
@@ -672,7 +672,7 @@ describe('components.CollectionSummary.SummaryCard', function () {
|
|
|
672
672
|
masterPage: {
|
|
673
673
|
childPages: []
|
|
674
674
|
},
|
|
675
|
-
|
|
675
|
+
inError: true
|
|
676
676
|
})),
|
|
677
677
|
container = _renderWithValidation21.container;
|
|
678
678
|
var _checkSetup20 = checkSetup(container),
|
|
@@ -735,7 +735,7 @@ describe('components.CollectionSummary.SummaryCard', function () {
|
|
|
735
735
|
masterPage: {
|
|
736
736
|
childPages: []
|
|
737
737
|
},
|
|
738
|
-
|
|
738
|
+
inError: true
|
|
739
739
|
}))),
|
|
740
740
|
container = _renderWithValidation22.container;
|
|
741
741
|
var _checkSetup21 = checkSetup(container),
|
|
@@ -782,7 +782,7 @@ describe('components.CollectionSummary.SummaryCard', function () {
|
|
|
782
782
|
childPages: []
|
|
783
783
|
},
|
|
784
784
|
onQuickEdit: function onQuickEdit() {},
|
|
785
|
-
|
|
785
|
+
inError: true
|
|
786
786
|
}))), container = _renderWithValidation23.container;
|
|
787
787
|
_checkSetup22 = checkSetup(container), headerActionDiv = _checkSetup22.headerActionDiv;
|
|
788
788
|
expect(headerActionDiv.children.length).toEqual(1);
|
|
@@ -896,7 +896,7 @@ describe('components.CollectionSummary.SummaryCard', function () {
|
|
|
896
896
|
masterPage: {
|
|
897
897
|
childPages: []
|
|
898
898
|
},
|
|
899
|
-
|
|
899
|
+
inError: true
|
|
900
900
|
})),
|
|
901
901
|
container = _renderWithValidation24.container;
|
|
902
902
|
var _checkSetup23 = checkSetup(container),
|
|
@@ -944,7 +944,7 @@ describe('components.CollectionSummary.SummaryCard', function () {
|
|
|
944
944
|
masterPage: {
|
|
945
945
|
childPages: []
|
|
946
946
|
},
|
|
947
|
-
|
|
947
|
+
inError: true
|
|
948
948
|
}), {
|
|
949
949
|
hooks: hooks
|
|
950
950
|
}),
|
|
@@ -996,7 +996,7 @@ describe('components.CollectionSummary.SummaryCard', function () {
|
|
|
996
996
|
masterPage: {
|
|
997
997
|
childPages: []
|
|
998
998
|
},
|
|
999
|
-
|
|
999
|
+
inError: true
|
|
1000
1000
|
}), {
|
|
1001
1001
|
hooks: hooks
|
|
1002
1002
|
}), container = _renderWithValidation26.container;
|
|
@@ -1081,7 +1081,7 @@ describe('components.CollectionSummary.SummaryCard', function () {
|
|
|
1081
1081
|
masterPage: {
|
|
1082
1082
|
childPages: []
|
|
1083
1083
|
},
|
|
1084
|
-
|
|
1084
|
+
inError: true
|
|
1085
1085
|
}), {
|
|
1086
1086
|
hooks: hooks
|
|
1087
1087
|
}), container = _renderWithValidation27.container;
|
|
@@ -1122,11 +1122,11 @@ describe('components.CollectionSummary.SummaryCard', function () {
|
|
|
1122
1122
|
}, _callee8);
|
|
1123
1123
|
})));
|
|
1124
1124
|
it('should apply changes if no errors are present', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee10() {
|
|
1125
|
-
var
|
|
1125
|
+
var inErrorValue, ON_SUBMIT_CALLS, hooks, ON_QUICK_EDIT_CALLS, ON_QUICK_EDIT, _renderWithValidation28, container, _checkSetup27, headerActionDiv, editButton, quickEdit, component, componentInput, quickEditButtons, saveButton;
|
|
1126
1126
|
return _regeneratorRuntime().wrap(function _callee10$(_context10) {
|
|
1127
1127
|
while (1) switch (_context10.prev = _context10.next) {
|
|
1128
1128
|
case 0:
|
|
1129
|
-
|
|
1129
|
+
inErrorValue = true;
|
|
1130
1130
|
ON_SUBMIT_CALLS = [];
|
|
1131
1131
|
hooks = {
|
|
1132
1132
|
onSubmit: function onSubmit(type, patch) {
|
|
@@ -1137,7 +1137,7 @@ describe('components.CollectionSummary.SummaryCard', function () {
|
|
|
1137
1137
|
ON_QUICK_EDIT = function ON_QUICK_EDIT(_ref12) {
|
|
1138
1138
|
var target = _ref12.target;
|
|
1139
1139
|
ON_QUICK_EDIT_CALLS.push(target);
|
|
1140
|
-
|
|
1140
|
+
inErrorValue = false;
|
|
1141
1141
|
};
|
|
1142
1142
|
_renderWithValidation28 = (0, _setupTests.renderWithValidation)( /*#__PURE__*/_react2.default.createElement(_SummaryCard.default, {
|
|
1143
1143
|
id: ID,
|
|
@@ -1157,7 +1157,7 @@ describe('components.CollectionSummary.SummaryCard', function () {
|
|
|
1157
1157
|
masterPage: {
|
|
1158
1158
|
childPages: []
|
|
1159
1159
|
},
|
|
1160
|
-
|
|
1160
|
+
inError: inErrorValue
|
|
1161
1161
|
}), {
|
|
1162
1162
|
hooks: hooks
|
|
1163
1163
|
}), container = _renderWithValidation28.container;
|
|
@@ -1193,8 +1193,8 @@ describe('components.CollectionSummary.SummaryCard', function () {
|
|
|
1193
1193
|
testText: 'new value'
|
|
1194
1194
|
});
|
|
1195
1195
|
|
|
1196
|
-
// Check that the
|
|
1197
|
-
expect(
|
|
1196
|
+
// Check that the inError prop is now false
|
|
1197
|
+
expect(inErrorValue).toBe(false);
|
|
1198
1198
|
case 20:
|
|
1199
1199
|
case "end":
|
|
1200
1200
|
return _context10.stop();
|
|
@@ -157,6 +157,7 @@ var InternalFormRenderer = function InternalFormRenderer(_ref2) {
|
|
|
157
157
|
var _useValidation = (0, _hooks.useValidation)(),
|
|
158
158
|
addErrors = _useValidation.addErrors,
|
|
159
159
|
clearErrors = _useValidation.clearErrors,
|
|
160
|
+
errors = _useValidation.errors,
|
|
160
161
|
validate = _useValidation.validate;
|
|
161
162
|
|
|
162
163
|
// Need to set submission data when going back
|
|
@@ -356,7 +357,7 @@ var InternalFormRenderer = function InternalFormRenderer(_ref2) {
|
|
|
356
357
|
page: formState.page,
|
|
357
358
|
pages: [].concat(pages),
|
|
358
359
|
onAction: function onAction(action, patch, patchLabel) {
|
|
359
|
-
(0, _onPageAction.default)(action, patch, patchLabel, hooks, data, formState, validate, onPageChange, type, pages, components, pageId, setPagePoint, currentTask, setData, hubDetails, setSubmitted, addErrors, submitting, setSubmitting);
|
|
360
|
+
(0, _onPageAction.default)(action, patch, patchLabel, hooks, data, formState, validate, onPageChange, type, pages, components, pageId, setPagePoint, currentTask, setData, hubDetails, setSubmitted, addErrors, submitting, setSubmitting, errors);
|
|
360
361
|
},
|
|
361
362
|
onChange: onChange,
|
|
362
363
|
hashLink: hashLink,
|
|
@@ -367,7 +368,7 @@ var InternalFormRenderer = function InternalFormRenderer(_ref2) {
|
|
|
367
368
|
page: formState.page,
|
|
368
369
|
onCollectionChange: onChange,
|
|
369
370
|
onAction: function onAction(action, patch, patchLabel) {
|
|
370
|
-
(0, _onPageAction.default)(action, patch, patchLabel, hooks, data, formState, validate, onPageChange, type, pages, components, pageId, setPagePoint, currentTask, setData, hubDetails, setSubmitted, addErrors, submitting, setSubmitting);
|
|
371
|
+
(0, _onPageAction.default)(action, patch, patchLabel, hooks, data, formState, validate, onPageChange, type, pages, components, pageId, setPagePoint, currentTask, setData, hubDetails, setSubmitted, addErrors, submitting, setSubmitting, errors);
|
|
371
372
|
},
|
|
372
373
|
hashLink: hashLink,
|
|
373
374
|
classModifiers: formState.page.classModifiers,
|
|
@@ -11,10 +11,14 @@ exports.default = void 0;
|
|
|
11
11
|
* @param {object} action The action object we're assessing.
|
|
12
12
|
* @param {object} page The page configuration object this action relates to.
|
|
13
13
|
* @param {Function} pageValidator A function to validate the page.
|
|
14
|
+
* @param {Array} errors An array of existing errors.
|
|
14
15
|
* @returns A boolean where `true` means the action can proceed and `false` means it cannot.
|
|
15
16
|
*/
|
|
16
|
-
var canActionProceed = function canActionProceed(action, page, pageValidator) {
|
|
17
|
+
var canActionProceed = function canActionProceed(action, page, pageValidator, errors) {
|
|
17
18
|
if (action.validate) {
|
|
19
|
+
if (action.checkPreexistingErrors && errors.length !== 0) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
18
22
|
return pageValidator(page).length === 0;
|
|
19
23
|
}
|
|
20
24
|
return true;
|
|
@@ -27,7 +27,7 @@ describe('components.FormRenderer.helpers.canActionProceed', function () {
|
|
|
27
27
|
a: 'Bravo'
|
|
28
28
|
}
|
|
29
29
|
};
|
|
30
|
-
expect((0, _canActionProceed.default)(ACTION, PAGE, _Validate.default.page)).toBeTruthy();
|
|
30
|
+
expect((0, _canActionProceed.default)(ACTION, PAGE, _Validate.default.page, [])).toBeTruthy();
|
|
31
31
|
});
|
|
32
32
|
it('should return false when the page is invalid', function () {
|
|
33
33
|
var ACTION = {
|
|
@@ -42,6 +42,42 @@ describe('components.FormRenderer.helpers.canActionProceed', function () {
|
|
|
42
42
|
}],
|
|
43
43
|
formData: {}
|
|
44
44
|
};
|
|
45
|
-
expect((0, _canActionProceed.default)(ACTION, PAGE, _Validate.default.page)).toBeFalsy();
|
|
45
|
+
expect((0, _canActionProceed.default)(ACTION, PAGE, _Validate.default.page, [])).toBeFalsy();
|
|
46
|
+
});
|
|
47
|
+
it('should return false when the action has checkPreexistingErrors and errors is not empty', function () {
|
|
48
|
+
var ACTION = {
|
|
49
|
+
validate: true,
|
|
50
|
+
checkPreexistingErrors: true
|
|
51
|
+
};
|
|
52
|
+
var PAGE = {
|
|
53
|
+
components: [{
|
|
54
|
+
id: 'a',
|
|
55
|
+
fieldId: 'a',
|
|
56
|
+
label: 'Alpha',
|
|
57
|
+
required: true
|
|
58
|
+
}],
|
|
59
|
+
formData: {
|
|
60
|
+
a: 'value'
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
expect((0, _canActionProceed.default)(ACTION, PAGE, _Validate.default.page, ['anError'])).toBeFalsy();
|
|
64
|
+
});
|
|
65
|
+
it('should return true when the action has checkPreexistingErrors and errors is empty', function () {
|
|
66
|
+
var ACTION = {
|
|
67
|
+
validate: true,
|
|
68
|
+
checkPreexistingErrors: true
|
|
69
|
+
};
|
|
70
|
+
var PAGE = {
|
|
71
|
+
components: [{
|
|
72
|
+
id: 'a',
|
|
73
|
+
fieldId: 'a',
|
|
74
|
+
label: 'Alpha',
|
|
75
|
+
required: true
|
|
76
|
+
}],
|
|
77
|
+
formData: {
|
|
78
|
+
a: 'value'
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
expect((0, _canActionProceed.default)(ACTION, PAGE, _Validate.default.page, [])).toBeTruthy();
|
|
46
82
|
});
|
|
47
83
|
});
|
|
@@ -19,7 +19,7 @@ function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input ==
|
|
|
19
19
|
// (patch captures payload-ready field name and value,
|
|
20
20
|
// patchLabel captures non-ID values
|
|
21
21
|
// for display purposes after submission.)
|
|
22
|
-
var onPageAction = function onPageAction(action, patch, patchLabel, hooks, data, formState, validate, onPageChange, type, pages, components, pageId, setPagePoint, currentTask, setData, hubDetails, setSubmitted, addErrors, submitting, setSubmitting) {
|
|
22
|
+
var onPageAction = function onPageAction(action, patch, patchLabel, hooks, data, formState, validate, onPageChange, type, pages, components, pageId, setPagePoint, currentTask, setData, hubDetails, setSubmitted, addErrors, submitting, setSubmitting, existingErrors) {
|
|
23
23
|
// Save a copy of data in case submit errors and we need to revert
|
|
24
24
|
var preSubmitData = _objectSpread({}, data);
|
|
25
25
|
var form = formState;
|
|
@@ -42,7 +42,7 @@ var onPageAction = function onPageAction(action, patch, patchLabel, hooks, data,
|
|
|
42
42
|
|
|
43
43
|
// Check to see whether the action is able to proceed, which in
|
|
44
44
|
// in the case of a submission will validate the fields in the page.
|
|
45
|
-
if (_helpers.default.canActionProceed(action, form.page, validate.page) && (!submitting || action.ignoreSubmittingFlag)) {
|
|
45
|
+
if (_helpers.default.canActionProceed(action, form.page, validate.page, existingErrors) && (!submitting || action.ignoreSubmittingFlag)) {
|
|
46
46
|
_patch = _helpers.default.cleanHiddenNestedData(_patch, form.page);
|
|
47
47
|
setSubmitting(true);
|
|
48
48
|
if (action.addToFormData) {
|
|
@@ -15,6 +15,7 @@ var _mustBeShorterThan = _interopRequireDefault(require("./mustBeShorterThan"));
|
|
|
15
15
|
var _mustBeGreaterThan = _interopRequireDefault(require("./mustBeGreaterThan"));
|
|
16
16
|
var _mustBeLessThan = _interopRequireDefault(require("./mustBeLessThan"));
|
|
17
17
|
var _mustBeNumbersOnly = _interopRequireDefault(require("./mustBeNumbersOnly"));
|
|
18
|
+
var _mustBeUniqueInCollection = _interopRequireDefault(require("./mustBeUniqueInCollection"));
|
|
18
19
|
var _mustEnterAtLeastOne = _interopRequireDefault(require("./mustEnterAtLeastOne"));
|
|
19
20
|
var _mustHaveLessThanDecimalPlaces = _interopRequireDefault(require("./mustHaveLessThanDecimalPlaces"));
|
|
20
21
|
var _mustNotContainSql = _interopRequireDefault(require("./mustNotContainSql"));
|
|
@@ -34,19 +35,20 @@ var functions = {
|
|
|
34
35
|
mustBeLongerThan: _mustBeLongerThan.default,
|
|
35
36
|
mustBeNumbersOnly: _mustBeNumbersOnly.default,
|
|
36
37
|
mustBeShorterThan: _mustBeShorterThan.default,
|
|
38
|
+
mustBeUniqueInCollection: _mustBeUniqueInCollection.default,
|
|
37
39
|
mustEnterAtLeastOne: _mustEnterAtLeastOne.default,
|
|
38
40
|
mustHaveLessThanDecimalPlaces: _mustHaveLessThanDecimalPlaces.default,
|
|
39
41
|
mustNotContainSql: _mustNotContainSql.default,
|
|
40
42
|
mustSelectOnlyOne: _mustSelectOnlyOne.default
|
|
41
43
|
};
|
|
42
|
-
var additionalValidation = function additionalValidation(value, config, component) {
|
|
44
|
+
var additionalValidation = function additionalValidation(value, config, component, formData) {
|
|
43
45
|
var fn = functions[config.function];
|
|
44
46
|
if (typeof fn === 'function') {
|
|
45
|
-
return fn(value, config, component) ? undefined : config.message;
|
|
47
|
+
return fn(value, config, component, formData) ? undefined : config.message;
|
|
46
48
|
}
|
|
47
49
|
return undefined;
|
|
48
50
|
};
|
|
49
|
-
var runAdditionalComponentValidation = function runAdditionalComponentValidation(component, value) {
|
|
51
|
+
var runAdditionalComponentValidation = function runAdditionalComponentValidation(component, value, formData) {
|
|
50
52
|
// We only care when we have a value - if we don't have one but want one, set `required: true`.
|
|
51
53
|
// eslint-disable-next-line no-extra-boolean-cast
|
|
52
54
|
if (!!value) {
|
|
@@ -55,7 +57,7 @@ var runAdditionalComponentValidation = function runAdditionalComponentValidation
|
|
|
55
57
|
component.additionalValidation.forEach(function (config) {
|
|
56
58
|
// If we've already encountered an error, don't run any more validators.
|
|
57
59
|
if (!error) {
|
|
58
|
-
error = additionalValidation(value, config, component);
|
|
60
|
+
error = additionalValidation(value, config, component, formData);
|
|
59
61
|
}
|
|
60
62
|
});
|
|
61
63
|
return error;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _getCollectionPageActiveId = _interopRequireDefault(require("../../CollectionPage/getCollectionPageActiveId"));
|
|
8
|
+
var _getCollectionPageData = _interopRequireDefault(require("../../CollectionPage/getCollectionPageData"));
|
|
9
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
10
|
+
/**
|
|
11
|
+
* @param {*} value - the value to check.
|
|
12
|
+
* @param {string} config.collectionPath - the path to the collection within formData
|
|
13
|
+
* @param {object} component - the component definition
|
|
14
|
+
* @param {object} formData - the current form data
|
|
15
|
+
* @returns true if components value is not the same in any other entry in the collection
|
|
16
|
+
*/
|
|
17
|
+
var mustBeUniqueInCollection = function mustBeUniqueInCollection(value, config, component, formData) {
|
|
18
|
+
if (!value || !formData) {
|
|
19
|
+
// null, undefined and empty strings should be picked up by the required flag
|
|
20
|
+
// and not considered here as they would be valid for optional fields.
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
var activeId = (0, _getCollectionPageActiveId.default)(config.collectionPath, formData);
|
|
24
|
+
var collectionData = (0, _getCollectionPageData.default)(config.collectionPath, formData);
|
|
25
|
+
var result = collectionData === null || collectionData === void 0 ? void 0 : collectionData.some(function (entry) {
|
|
26
|
+
// Don't compare it to itself
|
|
27
|
+
if (entry.id === activeId) {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
;
|
|
31
|
+
return entry[component.id] === value;
|
|
32
|
+
});
|
|
33
|
+
return !result;
|
|
34
|
+
};
|
|
35
|
+
var _default = exports.default = mustBeUniqueInCollection;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _mustBeUniqueInCollection = _interopRequireDefault(require("./mustBeUniqueInCollection"));
|
|
4
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
5
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
6
|
+
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; }
|
|
7
|
+
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; }
|
|
8
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
9
|
+
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
|
|
10
|
+
function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
11
|
+
describe('utils', function () {
|
|
12
|
+
describe('Validate', function () {
|
|
13
|
+
describe('additional', function () {
|
|
14
|
+
describe('mustBeUniqueInCollection', function () {
|
|
15
|
+
var COMPONENT = {
|
|
16
|
+
id: 'firstName',
|
|
17
|
+
type: 'text',
|
|
18
|
+
label: 'First name',
|
|
19
|
+
fieldId: 'firstName',
|
|
20
|
+
additionalValidation: [{
|
|
21
|
+
function: 'mustBeUniqueInCollection',
|
|
22
|
+
collectionPath: 'names',
|
|
23
|
+
message: 'Should be unique'
|
|
24
|
+
}]
|
|
25
|
+
};
|
|
26
|
+
var CONFIG = {
|
|
27
|
+
function: 'mustBeUniqueInCollection',
|
|
28
|
+
collectionPath: 'names',
|
|
29
|
+
message: 'Should be unique'
|
|
30
|
+
};
|
|
31
|
+
var VALUE = 'NAME';
|
|
32
|
+
test('should return true given no value', function () {
|
|
33
|
+
var result = (0, _mustBeUniqueInCollection.default)(undefined, CONFIG, COMPONENT, {});
|
|
34
|
+
expect(result).toBeTruthy();
|
|
35
|
+
});
|
|
36
|
+
test('should return true given no formData', function () {
|
|
37
|
+
var result = (0, _mustBeUniqueInCollection.default)(1, CONFIG, COMPONENT, undefined);
|
|
38
|
+
expect(result).toBeTruthy();
|
|
39
|
+
});
|
|
40
|
+
test('should return true for first entry in a collection', function () {
|
|
41
|
+
var FORM_DATA = {
|
|
42
|
+
namesActiveId: 1,
|
|
43
|
+
names: [{
|
|
44
|
+
id: 1,
|
|
45
|
+
firstName: VALUE
|
|
46
|
+
}]
|
|
47
|
+
};
|
|
48
|
+
var result = (0, _mustBeUniqueInCollection.default)(VALUE, CONFIG, COMPONENT, FORM_DATA);
|
|
49
|
+
expect(result).toBeTruthy();
|
|
50
|
+
});
|
|
51
|
+
test('should return true if other entries do not have the same value for this field', function () {
|
|
52
|
+
var FORM_DATA = {
|
|
53
|
+
namesActiveId: 3,
|
|
54
|
+
names: [{
|
|
55
|
+
id: 1,
|
|
56
|
+
firstName: 'alpha'
|
|
57
|
+
}, {
|
|
58
|
+
id: 2,
|
|
59
|
+
firstName: 'bravo'
|
|
60
|
+
}, {
|
|
61
|
+
id: 3,
|
|
62
|
+
firstName: VALUE
|
|
63
|
+
}]
|
|
64
|
+
};
|
|
65
|
+
var result = (0, _mustBeUniqueInCollection.default)(VALUE, CONFIG, COMPONENT, FORM_DATA);
|
|
66
|
+
expect(result).toBeTruthy();
|
|
67
|
+
});
|
|
68
|
+
test('should return false if other entries do have the same value for this field', function () {
|
|
69
|
+
var FORM_DATA = {
|
|
70
|
+
namesActiveId: 3,
|
|
71
|
+
names: [{
|
|
72
|
+
id: 1,
|
|
73
|
+
firstName: VALUE
|
|
74
|
+
}, {
|
|
75
|
+
id: 2,
|
|
76
|
+
firstName: 'bravo'
|
|
77
|
+
}, {
|
|
78
|
+
id: 3,
|
|
79
|
+
firstName: VALUE
|
|
80
|
+
}]
|
|
81
|
+
};
|
|
82
|
+
var result = (0, _mustBeUniqueInCollection.default)(VALUE, CONFIG, COMPONENT, FORM_DATA);
|
|
83
|
+
expect(result).toBeFalsy();
|
|
84
|
+
});
|
|
85
|
+
test('should return false if other entries do have the same value for this field within a nested collection', function () {
|
|
86
|
+
var NESTED_VALUE = 'delta';
|
|
87
|
+
var FORM_DATA = {
|
|
88
|
+
namesActiveId: 3,
|
|
89
|
+
names: [{
|
|
90
|
+
id: 1,
|
|
91
|
+
firstName: 'alpha'
|
|
92
|
+
}, {
|
|
93
|
+
id: 2,
|
|
94
|
+
firstName: 'bravo'
|
|
95
|
+
}, {
|
|
96
|
+
id: 3,
|
|
97
|
+
firstName: VALUE,
|
|
98
|
+
surnamesActiveId: 2,
|
|
99
|
+
surnames: [{
|
|
100
|
+
id: 1,
|
|
101
|
+
surname: 'delta'
|
|
102
|
+
}, {
|
|
103
|
+
id: 2,
|
|
104
|
+
surname: 'delta'
|
|
105
|
+
}]
|
|
106
|
+
}]
|
|
107
|
+
};
|
|
108
|
+
var COMPONENT_NESTED = {
|
|
109
|
+
id: 'surname',
|
|
110
|
+
type: 'text',
|
|
111
|
+
label: 'Surname',
|
|
112
|
+
fieldId: 'surname',
|
|
113
|
+
additionalValidation: [{
|
|
114
|
+
function: 'mustBeUniqueInCollection',
|
|
115
|
+
collectionPath: 'names.surname',
|
|
116
|
+
message: 'Should be unique'
|
|
117
|
+
}]
|
|
118
|
+
};
|
|
119
|
+
var result = (0, _mustBeUniqueInCollection.default)(NESTED_VALUE, _objectSpread(_objectSpread({}, CONFIG), {}, {
|
|
120
|
+
collectionPath: 'names.surnames'
|
|
121
|
+
}), COMPONENT_NESTED, FORM_DATA);
|
|
122
|
+
expect(result).toBeFalsy();
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
});
|
|
@@ -95,7 +95,7 @@ var validateComponent = function validateComponent(component, outerData, formDat
|
|
|
95
95
|
error = (0, _validateRegex.default)(value, component.label, component.pattern, component.custom_errors);
|
|
96
96
|
}
|
|
97
97
|
if (!error && component.additionalValidation) {
|
|
98
|
-
error = (0, _additional.default)(component, value);
|
|
98
|
+
error = (0, _additional.default)(component, value, formData);
|
|
99
99
|
if (component.type === _models.ComponentTypes.DATE && error) {
|
|
100
100
|
properties = {
|
|
101
101
|
day: true,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ukhomeoffice/cop-react-form-renderer",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.48.1-alpha",
|
|
4
4
|
"private": false,
|
|
5
5
|
"scripts": {
|
|
6
6
|
"clean": "rimraf dist",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"post-compile": "rimraf dist/*.test.* dist/**/*.test.* dist/**/*.stories.* dist/docs dist/assets"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@ukhomeoffice/cop-react-components": "^3.15.
|
|
19
|
+
"@ukhomeoffice/cop-react-components": "^3.15.8-alpha",
|
|
20
20
|
"axios": "^0.23.0",
|
|
21
21
|
"dayjs": "^1.11.0",
|
|
22
22
|
"govuk-frontend": "^4.3.1",
|