@kineticdata/react 5.1.0-rc.2 → 5.1.0

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 (37) hide show
  1. package/lib/apis/core/authentication.js +2 -2
  2. package/lib/apis/core/securityPolicyDefinitions.test.js +4 -4
  3. package/lib/apis/http.js +9 -2
  4. package/lib/apis/system/index.js +86 -1
  5. package/lib/apis/task/index.js +10 -8
  6. package/lib/components/common/BridgeSelect.js +2 -1
  7. package/lib/components/common/FormSelect.js +2 -1
  8. package/lib/components/common/TableInput.js +74 -29
  9. package/lib/components/common/TeamSelect.js +2 -1
  10. package/lib/components/common/UserSelect.js +2 -1
  11. package/lib/components/common/authentication/AuthenticationContainer.js +50 -27
  12. package/lib/components/core/file_resource/FileResourceForm.js +2 -2
  13. package/lib/components/core/space/SpaceForm.js +37 -8
  14. package/lib/components/core/submission/SubmissionForm.js +124 -0
  15. package/lib/components/core/webapi/WebApiForm.js +111 -126
  16. package/lib/components/form/Form.helpers.js +1 -1
  17. package/lib/components/form/Form.js +198 -142
  18. package/lib/components/index.js +5 -1
  19. package/lib/components/system/SystemBackgroundTasksTable.js +83 -0
  20. package/lib/components/system/SystemSecurityForm.js +69 -0
  21. package/lib/components/system/spaces/SystemSpaceForm.js +44 -16
  22. package/lib/components/task/builder/Connector.js +19 -8
  23. package/lib/components/task/builder/ConnectorForm.js +1 -1
  24. package/lib/components/task/builder/Node.js +10 -3
  25. package/lib/components/task/builder/NodeForm.js +51 -22
  26. package/lib/components/task/builder/NodeParametersForm.js +5 -2
  27. package/lib/components/task/builder/SvgCanvas.js +13 -4
  28. package/lib/components/task/builder/TaskDefinitionConfigForm.js +113 -0
  29. package/lib/components/task/builder/TreeBuilder.js +25 -7
  30. package/lib/components/task/builder/builder.redux.js +159 -52
  31. package/lib/components/task/builder/helpers.js +5 -3
  32. package/lib/components/task/builder/models.js +84 -12
  33. package/lib/components/task/errors/RunErrorTable.js +1 -1
  34. package/lib/components/task/runs/CreateManualTriggerForm.js +15 -24
  35. package/lib/components/task/workflows/WorkflowForm.js +67 -85
  36. package/lib/index.js +1 -0
  37. package/package.json +2 -2
@@ -1,6 +1,6 @@
1
1
  import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
2
2
  import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
3
- import { get, Map } from 'immutable';
3
+ import { fromJS, get, Map } from 'immutable';
4
4
  import t from 'prop-types';
5
5
  import { generateForm } from '../../form/Form';
6
6
  import { updateSpace, fetchSpace, fetchAttributeDefinitions, fetchLocales, fetchTimezones, fetchSecurityPolicyDefinitions } from '../../../apis';
@@ -12,7 +12,7 @@ var dataSources = function dataSources() {
12
12
  space: {
13
13
  fn: fetchSpace,
14
14
  params: [{
15
- include: 'attributesMap,securityPolicies,details'
15
+ include: 'allowedIps,attributesMap,securityPolicies,details'
16
16
  }],
17
17
  transform: function transform(result) {
18
18
  return result.space;
@@ -117,22 +117,22 @@ var securityEndpoints = {
117
117
  defaultFormDisplay: {
118
118
  endpoint: 'Default Form Display',
119
119
  label: 'Default Form Display',
120
- types: ['Space', 'Form']
120
+ types: ['Form']
121
121
  },
122
122
  defaultFormModification: {
123
123
  endpoint: 'Default Form Modification',
124
124
  label: 'Default Form Modification',
125
- types: ['Space', 'Form']
125
+ types: ['Form']
126
126
  },
127
127
  defaultSubmissionAccess: {
128
128
  endpoint: 'Default Submission Access',
129
129
  label: 'Default Submission Access',
130
- types: ['Space', 'Form', 'Submission']
130
+ types: ['Form', 'Submission']
131
131
  },
132
132
  defaultSubmissionModification: {
133
133
  endpoint: 'Default Submission Modification',
134
134
  label: 'Default Submission Modification',
135
- types: ['Space', 'Form', 'Submission']
135
+ types: ['Form', 'Submission']
136
136
  }
137
137
  };
138
138
 
@@ -446,13 +446,42 @@ var fields = function fields() {
446
446
  });
447
447
  },
448
448
  initialValue: get(space, 'securityPolicies')
449
+ }, {
450
+ name: 'allowedIps',
451
+ label: 'Allowed IPs',
452
+ type: 'select',
453
+ options: function options() {
454
+ return fromJS([{
455
+ name: 'description',
456
+ label: 'Description',
457
+ type: 'text'
458
+ }, {
459
+ name: 'value',
460
+ label: 'IP Range',
461
+ type: 'text'
462
+ }]);
463
+ },
464
+ visible: function visible(_ref34) {
465
+ var values = _ref34.values;
466
+ return values.get('allowedIpsEnabled', false);
467
+ },
468
+ initialValue: get(space, 'allowedIps', []),
469
+ serialize: function serialize(_ref35) {
470
+ var values = _ref35.values;
471
+ return values.get('allowedIpsEnabled', false) ? values.get('allowedIps') : [];
472
+ }
473
+ }, {
474
+ name: 'allowedIpsEnabled',
475
+ label: 'Enabled Allowed IP Restrictions?',
476
+ type: 'checkbox',
477
+ initialValue: get(space, 'allowedIpsEnabled', false) || false
449
478
  }, {
450
479
  name: 'attributesMap',
451
480
  label: 'Attributes',
452
481
  type: 'attributes',
453
482
  required: false,
454
- options: function options(_ref34) {
455
- var attributeDefinitions = _ref34.attributeDefinitions;
483
+ options: function options(_ref36) {
484
+ var attributeDefinitions = _ref36.attributeDefinitions;
456
485
  return attributeDefinitions;
457
486
  },
458
487
  initialValue: get(space, 'attributesMap')
@@ -0,0 +1,124 @@
1
+ import { List, getIn } from 'immutable';
2
+ import { fetchSubmission, updateSubmission } from '../../../apis';
3
+ import { generateForm } from '../../form/Form';
4
+ import moment from 'moment';
5
+
6
+ var dataSources = function dataSources(_ref) {
7
+ var submissionId = _ref.submissionId;
8
+ return {
9
+ submission: {
10
+ fn: fetchSubmission,
11
+ params: [{
12
+ id: submissionId,
13
+ include: 'details,values,form,form.fields,form.fields.details,form.pages'
14
+ }],
15
+ transform: function transform(result) {
16
+ return result.submission;
17
+ }
18
+ }
19
+ };
20
+ };
21
+
22
+ var handleSubmit = function handleSubmit(_ref2) {
23
+ var id = _ref2.submissionId;
24
+ return function (values) {
25
+ return updateSubmission({
26
+ id: id,
27
+ values: values.toJS()
28
+ }).then(function (_ref3) {
29
+ var submission = _ref3.submission,
30
+ error = _ref3.error;
31
+
32
+ if (error) {
33
+ throw error.statusCode === 400 && error.message || 'There was an error saving the submission';
34
+ }
35
+
36
+ return submission;
37
+ });
38
+ };
39
+ };
40
+
41
+ var traverseElement = function traverseElement(traverse, iteratee, acc) {
42
+ var element = traverse.get(0);
43
+ var elements = traverse.shift();
44
+ var childElements = element.get('elements', List());
45
+ var result = iteratee(element, acc); // If the current element has child elements make a recursive call.
46
+
47
+ if (childElements.size > 0) {
48
+ result = traverseElement(childElements, iteratee, result);
49
+ }
50
+
51
+ if (elements.size > 0) {
52
+ return traverseElement(elements, iteratee, result);
53
+ }
54
+
55
+ return result;
56
+ };
57
+
58
+ var convertRenderType = function convertRenderType(element) {
59
+ if (element.get('renderType') === 'dropdown') {
60
+ return element.get('choicesResourceName') ? 'text' : 'select';
61
+ } else if (element.get('renderType') === 'checkbox') {
62
+ return 'text-multi';
63
+ } else if (element.get('renderType') === 'attachment') {
64
+ return 'text';
65
+ }
66
+
67
+ return element.get('renderType');
68
+ };
69
+
70
+ var getInitialValue = function getInitialValue(submission, element, type) {
71
+ var name = element.get('name');
72
+ var isAttachment = element.get('renderType') === 'attachment';
73
+ var value = getIn(submission, ['values', name], element.get('renderType') === 'checkbox' ? List() : '') || '';
74
+ return isAttachment ? JSON.stringify(List.isList(value) ? value.toJS() : value) : type === 'datetime' ? moment(value).format('yyyy-MM-DDThh:mm') : type === 'date' ? moment(value).format('yyyy-MM-DD') : value;
75
+ };
76
+
77
+ var serializer = function serializer(element, type) {
78
+ return function (_ref4) {
79
+ var values = _ref4.values;
80
+ var name = element.get('name');
81
+ return type === 'datetime' ? moment(values.get(name)).format() : values.get(name);
82
+ };
83
+ }; // If the element uses bridged options then the `choices` value represents the
84
+ // label/value mapping from and not actual choices.
85
+
86
+
87
+ var getChoices = function getChoices(element) {
88
+ return !!element.get('choicesResourceName') ? List() : element.get('choices');
89
+ };
90
+
91
+ var fields = function fields() {
92
+ return function (_ref5) {
93
+ var submission = _ref5.submission;
94
+
95
+ if (submission) {
96
+ var pages = submission.getIn(['form', 'pages'], List());
97
+ var values = traverseElement(pages, function (element, values) {
98
+ var name = element.get('name');
99
+ var type = convertRenderType(element);
100
+ var initialValue = getInitialValue(submission, element, type);
101
+ var isAttachment = element.get('renderType') === 'attachment';
102
+ return element.get('type') === 'field' ? values.push({
103
+ name: name,
104
+ label: name,
105
+ type: type,
106
+ options: getChoices(element, initialValue),
107
+ initialValue: initialValue,
108
+ enabled: !isAttachment,
109
+ "transient": isAttachment,
110
+ serialize: serializer(element, type)
111
+ }) : values;
112
+ }, List());
113
+ return values.toJS();
114
+ }
115
+ };
116
+ };
117
+
118
+ export var SubmissionForm = generateForm({
119
+ formOptions: ['submissionId'],
120
+ dataSources: dataSources,
121
+ fields: fields,
122
+ handleSubmit: handleSubmit
123
+ });
124
+ SubmissionForm.displayName = 'SubmissionForm';
@@ -4,7 +4,7 @@ import _regeneratorRuntime from "@babel/runtime/regenerator";
4
4
  import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
5
5
  import { generateForm } from '../../form/Form';
6
6
  import { get, Map } from 'immutable';
7
- import { fetchWebApi, createWebApi, updateWebApi, fetchSecurityPolicyDefinitions, fetchSpace, fetchTree, createTree, updateTree } from '../../../apis';
7
+ import { createWebApi, updateWebApi, fetchSecurityPolicyDefinitions, createTree, updateTree, fetchSpace } from '../../../apis';
8
8
  export var WEB_API_METHODS = ['GET', 'POST', 'PUT', 'DELETE'];
9
9
  var securityEndpoints = {
10
10
  webApiExecution: {
@@ -15,136 +15,116 @@ var securityEndpoints = {
15
15
  };
16
16
 
17
17
  var dataSources = function dataSources(_ref) {
18
- var slug = _ref.slug,
19
- kappSlug = _ref.kappSlug;
18
+ var kappSlug = _ref.kappSlug,
19
+ webApi = _ref.webApi;
20
20
  return {
21
- webApi: {
22
- fn: fetchWebApi,
23
- params: slug && [{
24
- slug: slug,
25
- kappSlug: kappSlug,
26
- include: 'details,securityPolicies'
27
- }],
28
- transform: function transform(result) {
29
- return result.webApi;
30
- }
31
- },
32
21
  securityPolicyDefinitions: {
33
22
  fn: fetchSecurityPolicyDefinitions,
34
- params: kappSlug ? [{
35
- kappSlug: kappSlug
23
+ params: kappSlug || webApi && webApi.get('kappSlug') ? [{
24
+ kappSlug: kappSlug || webApi && webApi.get('kappSlug')
36
25
  }] : [],
37
26
  transform: function transform(result) {
38
27
  return result.securityPolicyDefinitions;
39
28
  }
40
- },
41
- sourceName: {
42
- fn: fetchSpace,
43
- params: [{
44
- include: 'platformComponents'
45
- }],
46
- transform: function transform(result) {
47
- return result.space.platformComponents.task.config.platformSourceName;
48
- }
49
- },
50
- sourceGroup: {
51
- fn: function fn() {
52
- return kappSlug ? "WebApis > ".concat(kappSlug) : 'WebApis';
53
- },
54
- params: []
55
- },
56
- tree: {
57
- fn: fetchTree,
58
- params: function params(_ref2) {
59
- var sourceName = _ref2.sourceName,
60
- sourceGroup = _ref2.sourceGroup,
61
- webApi = _ref2.webApi;
62
- return webApi && sourceName && [{
63
- sourceName: sourceName,
64
- sourceGroup: sourceGroup,
65
- name: webApi.get('slug')
66
- }];
67
- },
68
- transform: function transform(result) {
69
- return result.error && result.error.notFound ? {} : result.tree;
70
- }
71
29
  }
72
30
  };
73
31
  };
74
32
 
75
- var handleSubmit = function handleSubmit(_ref3) {
76
- var slug = _ref3.slug,
77
- kappSlug = _ref3.kappSlug;
33
+ var handleSubmit = function handleSubmit(_ref2) {
34
+ var slug = _ref2.slug,
35
+ kappSlug = _ref2.kappSlug,
36
+ webApi = _ref2.webApi;
78
37
  return /*#__PURE__*/function () {
79
- var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(values, bindings) {
80
- var sourceGroup, sourceName, tree, _yield, webApi, error, _yield$createTree, createTreeError, _yield$updateTree, updateTreeError;
38
+ var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(values) {
39
+ var _yield$fetchSpace, space, sourceName, sourceGroup, _ref4, _webApi, error1, _ref5, tree, error2;
81
40
 
82
41
  return _regeneratorRuntime.wrap(function _callee$(_context) {
83
42
  while (1) {
84
43
  switch (_context.prev = _context.next) {
85
44
  case 0:
86
- sourceGroup = bindings.sourceGroup, sourceName = bindings.sourceName, tree = bindings.tree;
45
+ if (webApi) {
46
+ _context.next = 38;
47
+ break;
48
+ }
49
+
87
50
  _context.next = 3;
88
- return (slug ? updateWebApi : createWebApi)({
89
- kappSlug: kappSlug,
90
- slug: slug,
91
- webApi: values.toJS(),
92
- include: 'securityPolicies'
51
+ return fetchSpace({
52
+ include: 'platformComponents'
93
53
  });
94
54
 
95
55
  case 3:
96
- _yield = _context.sent;
97
- webApi = _yield.webApi;
98
- error = _yield.error;
56
+ _yield$fetchSpace = _context.sent;
57
+ space = _yield$fetchSpace.space;
58
+ sourceName = space.platformComponents.task.config.platformSourceName;
59
+ sourceGroup = kappSlug ? "WebApis > ".concat(kappSlug) : 'WebApis';
99
60
 
100
- if (!error) {
101
- _context.next = 8;
61
+ if (!slug) {
62
+ _context.next = 13;
102
63
  break;
103
64
  }
104
65
 
105
- throw error.statusCode === 400 && error.message || 'There was an error saving the WebAPI';
66
+ _context.next = 10;
67
+ return updateWebApi({
68
+ kappSlug: kappSlug,
69
+ slug: slug,
70
+ webApi: values.toJS(),
71
+ include: 'securityPolicies'
72
+ });
106
73
 
107
- case 8:
108
- if (slug) {
109
- _context.next = 17;
110
- break;
111
- }
74
+ case 10:
75
+ _context.t0 = _context.sent;
76
+ _context.next = 16;
77
+ break;
112
78
 
113
- _context.next = 11;
114
- return createTree({
115
- tree: {
116
- sourceGroup: sourceGroup,
117
- sourceName: sourceName,
118
- name: values.get('slug')
119
- }
79
+ case 13:
80
+ _context.next = 15;
81
+ return createWebApi({
82
+ kappSlug: kappSlug,
83
+ webApi: values.toJS(),
84
+ include: 'securityPolicies'
120
85
  });
121
86
 
122
- case 11:
123
- _yield$createTree = _context.sent;
124
- createTreeError = _yield$createTree.error;
87
+ case 15:
88
+ _context.t0 = _context.sent;
89
+
90
+ case 16:
91
+ _ref4 = _context.t0;
92
+ _webApi = _ref4.webApi;
93
+ error1 = _ref4.error;
125
94
 
126
- if (!createTreeError) {
127
- _context.next = 15;
95
+ if (!error1) {
96
+ _context.next = 21;
128
97
  break;
129
98
  }
130
99
 
131
- throw createTreeError.statusCode === 400 && createTreeError.message || 'There was an error creating the WebAPI tree';
132
-
133
- case 15:
134
- _context.next = 24;
135
- break;
100
+ throw error1.statusCode === 400 && error1.message || 'There was an error saving the WebAPI';
136
101
 
137
- case 17:
138
- if (!(!tree.isEmpty() && slug !== values.get('slug'))) {
139
- _context.next = 24;
102
+ case 21:
103
+ if (!slug) {
104
+ _context.next = 27;
140
105
  break;
141
106
  }
142
107
 
143
- _context.next = 20;
108
+ _context.next = 24;
144
109
  return updateTree({
145
110
  sourceName: sourceName,
146
111
  sourceGroup: sourceGroup,
147
112
  name: slug,
113
+ tree: {
114
+ sourceName: sourceName,
115
+ sourceGroup: sourceGroup,
116
+ name: values.get('slug')
117
+ }
118
+ });
119
+
120
+ case 24:
121
+ _context.t1 = _context.sent;
122
+ _context.next = 30;
123
+ break;
124
+
125
+ case 27:
126
+ _context.next = 29;
127
+ return createTree({
148
128
  tree: {
149
129
  sourceGroup: sourceGroup,
150
130
  sourceName: sourceName,
@@ -152,21 +132,31 @@ var handleSubmit = function handleSubmit(_ref3) {
152
132
  }
153
133
  });
154
134
 
155
- case 20:
156
- _yield$updateTree = _context.sent;
157
- updateTreeError = _yield$updateTree.error;
135
+ case 29:
136
+ _context.t1 = _context.sent;
137
+
138
+ case 30:
139
+ _ref5 = _context.t1;
140
+ tree = _ref5.tree;
141
+ error2 = _ref5.error;
158
142
 
159
- if (!updateTreeError) {
160
- _context.next = 24;
143
+ if (!error2) {
144
+ _context.next = 35;
161
145
  break;
162
146
  }
163
147
 
164
- throw updateTreeError.statusCode === 400 && updateTreeError.message || 'There was an error updating the WebAPI tree';
148
+ throw error2.statusCode === 400 && error2.message || 'There was an error saving the WebAPI tree';
165
149
 
166
- case 24:
167
- return _context.abrupt("return", webApi);
150
+ case 35:
151
+ return _context.abrupt("return", {
152
+ tree: tree,
153
+ webApi: _webApi
154
+ });
155
+
156
+ case 38:
157
+ return _context.abrupt("return", values.toObject());
168
158
 
169
- case 25:
159
+ case 39:
170
160
  case "end":
171
161
  return _context.stop();
172
162
  }
@@ -174,18 +164,17 @@ var handleSubmit = function handleSubmit(_ref3) {
174
164
  }, _callee);
175
165
  }));
176
166
 
177
- return function (_x, _x2) {
178
- return _ref4.apply(this, arguments);
167
+ return function (_x) {
168
+ return _ref3.apply(this, arguments);
179
169
  };
180
170
  }();
181
171
  };
182
172
 
183
- var fields = function fields(_ref5) {
184
- var slug = _ref5.slug;
185
- return function (_ref6) {
186
- var tree = _ref6.tree,
187
- webApi = _ref6.webApi;
188
- return (!slug || webApi && tree) && [{
173
+ var fields = function fields(_ref6) {
174
+ var webApi = _ref6.webApi;
175
+ return function (_ref7) {
176
+ var securityPolicyDefinitions = _ref7.securityPolicyDefinitions;
177
+ return securityPolicyDefinitions && [{
189
178
  name: 'slug',
190
179
  label: 'Slug',
191
180
  type: 'text',
@@ -203,17 +192,17 @@ var fields = function fields(_ref5) {
203
192
  };
204
193
  }),
205
194
  initialValue: get(webApi, 'method') || ''
206
- }].concat(_toConsumableArray(Object.entries(securityEndpoints).map(function (_ref7) {
207
- var _ref8 = _slicedToArray(_ref7, 2),
208
- endpointFieldName = _ref8[0],
209
- endpoint = _ref8[1];
195
+ }].concat(_toConsumableArray(Object.entries(securityEndpoints).map(function (_ref8) {
196
+ var _ref9 = _slicedToArray(_ref8, 2),
197
+ endpointFieldName = _ref9[0],
198
+ endpoint = _ref9[1];
210
199
 
211
200
  return {
212
201
  name: endpointFieldName,
213
202
  label: endpoint.label,
214
203
  type: 'select',
215
- options: function options(_ref9) {
216
- var securityPolicyDefinitions = _ref9.securityPolicyDefinitions;
204
+ options: function options(_ref10) {
205
+ var securityPolicyDefinitions = _ref10.securityPolicyDefinitions;
217
206
  return securityPolicyDefinitions ? securityPolicyDefinitions.filter(function (definition) {
218
207
  return endpoint.types.includes(definition.get('type'));
219
208
  }).map(function (definition) {
@@ -233,20 +222,16 @@ var fields = function fields(_ref5) {
233
222
  label: 'Security Policies',
234
223
  type: null,
235
224
  visible: false,
236
- serialize: function serialize(_ref10) {
237
- var values = _ref10.values;
238
- return Object.entries(securityEndpoints).map(function (_ref11) {
239
- var _ref12 = _slicedToArray(_ref11, 2),
240
- endpointFieldName = _ref12[0],
241
- policy = _ref12[1];
242
-
243
- return {
225
+ serialize: function serialize(_ref11) {
226
+ var values = _ref11.values;
227
+ return Map(securityEndpoints).map(function (policy, endpointFieldName) {
228
+ return Map({
244
229
  endpoint: policy.endpoint,
245
230
  name: values.get(endpointFieldName)
246
- };
247
- }).filter(function (endpoint) {
248
- return endpoint.name !== '';
249
- });
231
+ });
232
+ }).valueSeq().filter(function (policy) {
233
+ return policy.get('name') !== '';
234
+ }).toList();
250
235
  },
251
236
  initialValue: get(webApi, 'securityPolicies')
252
237
  }]);
@@ -254,7 +239,7 @@ var fields = function fields(_ref5) {
254
239
  };
255
240
 
256
241
  export var WebApiForm = generateForm({
257
- formOptions: ['slug', 'kappSlug'],
242
+ formOptions: ['kappSlug', 'slug', 'webApi'],
258
243
  dataSources: dataSources,
259
244
  fields: fields,
260
245
  handleSubmit: handleSubmit
@@ -257,7 +257,7 @@ export var getFieldComponentProps = function getFieldComponentProps(field, readO
257
257
  onBlur: field.eventHandlers.get('onBlur'),
258
258
  onChange: field.eventHandlers.get('onChange'),
259
259
  onFocus: field.eventHandlers.get('onFocus'),
260
- options: ['attributes', 'code', 'form', 'form-multi', 'map', 'radio', 'select', 'select-multi', 'table', 'text', 'text-multi'].includes(field.type) ? field.options : undefined,
260
+ options: ['attributes', 'checkbox-multi', 'code', 'form', 'form-multi', 'map', 'radio', 'select', 'select-multi', 'table', 'text', 'text-multi'].includes(field.type) ? field.options : undefined,
261
261
  placeholder: field.placeholder,
262
262
  renderAttributes: field.renderAttributes,
263
263
  required: field.required,