@pnp/spfx-controls-react 3.17.0-beta.7003036 → 3.17.0-beta.7072516

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 (57) hide show
  1. package/CHANGELOG.json +4 -2
  2. package/CHANGELOG.md +2 -1
  3. package/lib/common/SPEntities.d.ts +5 -0
  4. package/lib/common/SPEntities.d.ts.map +1 -1
  5. package/lib/common/telemetry/version.js +1 -1
  6. package/lib/common/utilities/CustomFormatting.d.ts +31 -0
  7. package/lib/common/utilities/CustomFormatting.d.ts.map +1 -0
  8. package/lib/common/utilities/CustomFormatting.js +160 -0
  9. package/lib/common/utilities/CustomFormatting.js.map +1 -0
  10. package/lib/common/utilities/FormulaEvaluation.d.ts +21 -0
  11. package/lib/common/utilities/FormulaEvaluation.d.ts.map +1 -0
  12. package/lib/common/utilities/FormulaEvaluation.js +612 -0
  13. package/lib/common/utilities/FormulaEvaluation.js.map +1 -0
  14. package/lib/common/utilities/FormulaEvaluation.types.d.ts +23 -0
  15. package/lib/common/utilities/FormulaEvaluation.types.d.ts.map +1 -0
  16. package/lib/common/utilities/FormulaEvaluation.types.js +80 -0
  17. package/lib/common/utilities/FormulaEvaluation.types.js.map +1 -0
  18. package/lib/common/utilities/ICustomFormatting.d.ts +27 -0
  19. package/lib/common/utilities/ICustomFormatting.d.ts.map +1 -0
  20. package/lib/common/utilities/ICustomFormatting.js +2 -0
  21. package/lib/common/utilities/ICustomFormatting.js.map +1 -0
  22. package/lib/controls/dynamicForm/DynamicForm.d.ts +53 -5
  23. package/lib/controls/dynamicForm/DynamicForm.d.ts.map +1 -1
  24. package/lib/controls/dynamicForm/DynamicForm.js +828 -536
  25. package/lib/controls/dynamicForm/DynamicForm.js.map +1 -1
  26. package/lib/controls/dynamicForm/DynamicForm.module.css +2 -2
  27. package/lib/controls/dynamicForm/DynamicForm.module.scss.d.ts +4 -0
  28. package/lib/controls/dynamicForm/DynamicForm.module.scss.d.ts.map +1 -1
  29. package/lib/controls/dynamicForm/DynamicForm.module.scss.js +25 -21
  30. package/lib/controls/dynamicForm/DynamicForm.module.scss.js.map +1 -1
  31. package/lib/controls/dynamicForm/IDynamicFormProps.d.ts +12 -0
  32. package/lib/controls/dynamicForm/IDynamicFormProps.d.ts.map +1 -1
  33. package/lib/controls/dynamicForm/IDynamicFormState.d.ts +25 -0
  34. package/lib/controls/dynamicForm/IDynamicFormState.d.ts.map +1 -1
  35. package/lib/controls/dynamicForm/dynamicField/DynamicField.d.ts.map +1 -1
  36. package/lib/controls/dynamicForm/dynamicField/DynamicField.js +57 -42
  37. package/lib/controls/dynamicForm/dynamicField/DynamicField.js.map +1 -1
  38. package/lib/controls/dynamicForm/dynamicField/IDynamicFieldProps.d.ts +32 -11
  39. package/lib/controls/dynamicForm/dynamicField/IDynamicFieldProps.d.ts.map +1 -1
  40. package/lib/controls/fieldCollectionData/collectionDataItem/CollectionDataItem.js.map +1 -1
  41. package/lib/controls/webPartTitle/WebPartTitle.js +1 -1
  42. package/lib/controls/webPartTitle/WebPartTitle.js.map +1 -1
  43. package/lib/services/ISPService.d.ts +194 -0
  44. package/lib/services/ISPService.d.ts.map +1 -1
  45. package/lib/services/ISPService.js +13 -0
  46. package/lib/services/ISPService.js.map +1 -1
  47. package/lib/services/SPService.d.ts +10 -1
  48. package/lib/services/SPService.d.ts.map +1 -1
  49. package/lib/services/SPService.js +69 -0
  50. package/lib/services/SPService.js.map +1 -1
  51. package/lib/services/SPServiceMock.d.ts +3 -1
  52. package/lib/services/SPServiceMock.d.ts.map +1 -1
  53. package/lib/services/SPServiceMock.js +6 -0
  54. package/lib/services/SPServiceMock.js.map +1 -1
  55. package/package.json +1 -1
  56. package/release/manifests/45165954-80f9-44c1-9967-cd38ae92a33b.manifest.json +58 -3
  57. package/tests/utils/formulaevaluation.test.ts +248 -0
@@ -61,23 +61,28 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
61
61
  }
62
62
  };
63
63
  /* eslint-disable @microsoft/spfx/no-async-await */
64
- import { SPHttpClient } from "@microsoft/sp-http";
65
- import { sp } from "@pnp/sp/presets/all";
64
+ import * as React from "react";
66
65
  import * as strings from "ControlStrings";
66
+ import styles from "./DynamicForm.module.scss";
67
+ // Controls
67
68
  import { DefaultButton, PrimaryButton, } from "@fluentui/react/lib/Button";
69
+ import { Dialog, DialogFooter, DialogType, } from "@fluentui/react/lib/Dialog";
70
+ import { MessageBar, MessageBarType } from "@fluentui/react/lib/MessageBar";
68
71
  import { ProgressIndicator } from "@fluentui/react/lib/ProgressIndicator";
69
72
  import { Stack } from "@fluentui/react/lib/Stack";
70
73
  import { Icon } from "@fluentui/react/lib/components/Icon/Icon";
71
- import * as React from "react";
72
- import SPservice from "../../services/SPService";
73
- import { FilePicker } from "../filePicker";
74
74
  import { DynamicField } from "./dynamicField";
75
- import styles from "./DynamicForm.module.scss";
76
- import { Dialog, DialogFooter, DialogType, } from "@fluentui/react/lib/Dialog";
75
+ import { FilePicker } from "../filePicker";
76
+ // pnp/sp, helpers / utils
77
+ import { sp } from "@pnp/sp";
77
78
  import "@pnp/sp/lists";
78
79
  import "@pnp/sp/content-types";
79
80
  import "@pnp/sp/folders";
80
81
  import "@pnp/sp/items";
82
+ import { cloneDeep, isEqual } from "lodash";
83
+ import SPservice from "../../services/SPService";
84
+ import { FormulaEvaluation } from "../../common/utilities/FormulaEvaluation";
85
+ import CustomFormattingHelper from "../../common/utilities/CustomFormatting";
81
86
  var stackTokens = { childrenGap: 20 };
82
87
  /**
83
88
  * DynamicForm Class Control
@@ -89,54 +94,87 @@ var DynamicForm = /** @class */ (function (_super) {
89
94
  _this.webURL = _this.props.webAbsoluteUrl
90
95
  ? _this.props.webAbsoluteUrl
91
96
  : _this.props.context.pageContext.web.absoluteUrl;
92
- //trigger when the user submits the form.
97
+ _this.renderField = function (field) {
98
+ var fieldOverrides = _this.props.fieldOverrides;
99
+ var _a = _this.state, hiddenByFormula = _a.hiddenByFormula, isSaving = _a.isSaving, validationErrors = _a.validationErrors;
100
+ // If the field is hidden by a formula, don't render it
101
+ if (hiddenByFormula.find(function (h) { return h === field.columnInternalName; })) {
102
+ return null;
103
+ }
104
+ // If validation error, show error message
105
+ var validationErrorMessage = "";
106
+ if (validationErrors[field.columnInternalName]) {
107
+ validationErrorMessage = validationErrors[field.columnInternalName];
108
+ }
109
+ // If field override is provided, use it instead of the DynamicField component
110
+ if (fieldOverrides &&
111
+ Object.prototype.hasOwnProperty.call(fieldOverrides, field.columnInternalName)) {
112
+ field.disabled = field.disabled || isSaving;
113
+ return fieldOverrides[field.columnInternalName](field);
114
+ }
115
+ // Default render
116
+ return (React.createElement(DynamicField, __assign({ key: field.columnInternalName }, field, { disabled: field.disabled || isSaving, validationErrorMessage: validationErrorMessage })));
117
+ };
118
+ /** Triggered when the user submits the form. */
93
119
  _this.onSubmitClick = function () { return __awaiter(_this, void 0, void 0, function () {
94
- var _a, listId, listItemId, contentTypeId, onSubmitted, onBeforeSubmit, onSubmitError, enableFileSelection, validationErrorDialogProps, returnListItemInstanceOnSubmit, shouldBeReturnBack_1, fields, objects, _loop_1, this_1, i, len, isCancelled, newETag, iur, error_1, contentTypeIdField, iar, error_2, idField, titleField, contentTypeIdField, library, folderTitle, newFolder, fields_1, folderId, iur, error_3, error_4;
95
- var _this = this;
120
+ var _a, listId, listItemId, onSubmitted, onBeforeSubmit, onSubmitError, enableFileSelection, validationErrorDialogProps, returnListItemInstanceOnSubmit, contentTypeId, fileSelectRendered, shouldBeReturnBack_1, fields, validationDisabled, validationErrors, objects, _loop_1, this_1, i, len, isCancelled, apiError, newETag, iur, error_1, contentTypeIdField, iar, error_2, idField, titleField, contentTypeIdField, library, folderTitle, newFolder, fields_1, folderId, iur, error_3, error_4;
96
121
  var _b, _c, _d, _e;
97
122
  return __generator(this, function (_f) {
98
123
  switch (_f.label) {
99
124
  case 0:
100
- _a = this.props, listId = _a.listId, listItemId = _a.listItemId, contentTypeId = _a.contentTypeId, onSubmitted = _a.onSubmitted, onBeforeSubmit = _a.onBeforeSubmit, onSubmitError = _a.onSubmitError, enableFileSelection = _a.enableFileSelection, validationErrorDialogProps = _a.validationErrorDialogProps, returnListItemInstanceOnSubmit = _a.returnListItemInstanceOnSubmit;
125
+ _a = this.props, listId = _a.listId, listItemId = _a.listItemId, onSubmitted = _a.onSubmitted, onBeforeSubmit = _a.onBeforeSubmit, onSubmitError = _a.onSubmitError, enableFileSelection = _a.enableFileSelection, validationErrorDialogProps = _a.validationErrorDialogProps, returnListItemInstanceOnSubmit = _a.returnListItemInstanceOnSubmit;
126
+ contentTypeId = this.props.contentTypeId;
127
+ if (this.state.contentTypeId !== undefined)
128
+ contentTypeId = this.state.contentTypeId;
129
+ fileSelectRendered = !listItemId && contentTypeId.startsWith("0x0101") && enableFileSelection === true;
101
130
  _f.label = 1;
102
131
  case 1:
103
- _f.trys.push([1, 31, , 32]);
132
+ _f.trys.push([1, 30, , 31]);
104
133
  shouldBeReturnBack_1 = false;
105
134
  fields = (this.state.fieldCollection || []).slice();
106
- fields.forEach(function (val) {
107
- if (val.required) {
108
- if (val.newValue === null) {
109
- if (val.fieldDefaultValue === null ||
110
- val.fieldDefaultValue === "" ||
111
- val.fieldDefaultValue.length === 0 ||
112
- val.fieldDefaultValue === undefined) {
113
- if (val.fieldType === "DateTime")
114
- val.fieldDefaultValue = null;
135
+ fields.forEach(function (field) {
136
+ // When a field is required and has no value
137
+ if (field.required) {
138
+ if (field.newValue === null) {
139
+ if (field.defaultValue === null ||
140
+ field.defaultValue === "" ||
141
+ field.defaultValue.length === 0 ||
142
+ field.defaultValue === undefined) {
143
+ if (field.fieldType === "DateTime")
144
+ field.defaultValue = null;
115
145
  else
116
- val.fieldDefaultValue = "";
146
+ field.defaultValue = "";
117
147
  shouldBeReturnBack_1 = true;
118
148
  }
119
149
  }
120
- else if (val.newValue === "") {
121
- val.fieldDefaultValue = "";
150
+ else if (field.newValue === "") {
151
+ field.defaultValue = "";
122
152
  shouldBeReturnBack_1 = true;
123
153
  }
124
- else if (Array.isArray(val.newValue) && val.newValue.length === 0) {
125
- val.fieldDefaultValue = null;
154
+ else if (Array.isArray(field.newValue) && field.newValue.length === 0) {
155
+ field.defaultValue = null;
126
156
  shouldBeReturnBack_1 = true;
127
157
  }
128
158
  }
129
- if (val.fieldType === "Number") {
130
- if (val.showAsPercentage)
131
- val.newValue /= 100;
132
- if (_this.isEmptyNumOrString(val.newValue) && (val.minimumValue !== null || val.maximumValue !== null)) {
133
- val.newValue = val.fieldDefaultValue = null;
134
- }
135
- if (!_this.isEmptyNumOrString(val.newValue) && (isNaN(Number(val.newValue)) || (val.newValue < val.minimumValue) || (val.newValue > val.maximumValue))) {
159
+ // Check min and max values for number fields
160
+ if (field.fieldType === "Number" && field.newValue !== undefined && field.newValue.trim() !== "") {
161
+ if ((field.newValue < field.minimumValue) || (field.newValue > field.maximumValue)) {
136
162
  shouldBeReturnBack_1 = true;
137
163
  }
138
164
  }
139
165
  });
166
+ validationDisabled = this.props.useFieldValidation === false;
167
+ validationErrors = {};
168
+ if (!!validationDisabled) return [3 /*break*/, 3];
169
+ return [4 /*yield*/, this.evaluateFormulas(this.state.validationFormulas, true, true, this.state.hiddenByFormula)];
170
+ case 2:
171
+ validationErrors = (_f.sent());
172
+ if (Object.keys(validationErrors).length > 0) {
173
+ shouldBeReturnBack_1 = true;
174
+ }
175
+ _f.label = 3;
176
+ case 3:
177
+ // If validation failed, return without saving
140
178
  if (shouldBeReturnBack_1) {
141
179
  this.setState({
142
180
  fieldCollection: fields,
@@ -144,10 +182,11 @@ var DynamicForm = /** @class */ (function (_super) {
144
182
  });
145
183
  return [2 /*return*/];
146
184
  }
147
- if (enableFileSelection === true && this.state.selectedFile === undefined && this.props.listItemId === undefined) {
185
+ if (fileSelectRendered === true && this.state.selectedFile === undefined && this.props.listItemId === undefined) {
148
186
  this.setState({
149
187
  missingSelectedFile: true,
150
188
  isValidationErrorDialogOpen: (validationErrorDialogProps === null || validationErrorDialogProps === void 0 ? void 0 : validationErrorDialogProps.showDialogOnValidationError) === true,
189
+ validationErrors: validationErrors
151
190
  });
152
191
  return [2 /*return*/];
153
192
  }
@@ -156,74 +195,73 @@ var DynamicForm = /** @class */ (function (_super) {
156
195
  });
157
196
  objects = {};
158
197
  _loop_1 = function (i, len) {
159
- var val, fieldType, additionalData, columnInternalName, hiddenFieldName, value_1, uploadedImage;
198
+ var field, fieldType, additionalData, columnInternalName, hiddenFieldName, value_1, uploadedImage;
160
199
  return __generator(this, function (_g) {
161
200
  switch (_g.label) {
162
201
  case 0:
163
- val = fields[i];
164
- fieldType = val.fieldType, additionalData = val.additionalData, columnInternalName = val.columnInternalName, hiddenFieldName = val.hiddenFieldName;
165
- if (!(val.newValue !== null && val.newValue !== undefined)) return [3 /*break*/, 14];
166
- value_1 = val.newValue;
167
- if (!(fieldType === "Lookup")) return [3 /*break*/, 1];
168
- if (value_1 && value_1.length > 0) {
169
- objects["".concat(columnInternalName, "Id")] = value_1[0].key;
202
+ field = fields[i];
203
+ fieldType = field.fieldType, additionalData = field.additionalData, columnInternalName = field.columnInternalName, hiddenFieldName = field.hiddenFieldName;
204
+ if (!(field.newValue !== null && field.newValue !== undefined)) return [3 /*break*/, 3];
205
+ value_1 = field.newValue;
206
+ if (["Lookup", "LookupMulti", "User", "UserMulti"].indexOf(fieldType) < 0) {
207
+ objects[columnInternalName] = value_1;
170
208
  }
171
- else {
172
- objects["".concat(columnInternalName, "Id")] = null;
209
+ // Choice fields
210
+ if (fieldType === "Choice") {
211
+ objects[columnInternalName] = field.newValue.key;
173
212
  }
174
- return [3 /*break*/, 14];
175
- case 1:
176
- if (!(fieldType === "LookupMulti")) return [3 /*break*/, 2];
177
- value_1 = [];
178
- val.newValue.forEach(function (element) {
179
- value_1.push(element.key);
180
- });
181
- objects["".concat(columnInternalName, "Id")] = {
182
- results: value_1.length === 0 ? null : value_1,
183
- };
184
- return [3 /*break*/, 14];
185
- case 2:
186
- if (!(fieldType === "TaxonomyFieldType")) return [3 /*break*/, 3];
187
- objects[columnInternalName] = {
188
- __metadata: { type: "SP.Taxonomy.TaxonomyFieldValue" },
189
- Label: (_c = (_b = value_1[0]) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : "",
190
- TermGuid: (_e = (_d = value_1[0]) === null || _d === void 0 ? void 0 : _d.key) !== null && _e !== void 0 ? _e : "11111111-1111-1111-1111-111111111111",
191
- WssId: "-1",
192
- };
193
- return [3 /*break*/, 14];
194
- case 3:
195
- if (!(fieldType === "TaxonomyFieldTypeMulti")) return [3 /*break*/, 4];
196
- objects[hiddenFieldName] = val.newValue
197
- .map(function (term) { return "-1#;".concat(term.name, "|").concat(term.key, ";"); })
198
- .join("#");
199
- return [3 /*break*/, 14];
200
- case 4:
201
- if (!(fieldType === "User")) return [3 /*break*/, 5];
202
- objects["".concat(columnInternalName, "Id")] = val.newValue.length === 0 ? null : val.newValue;
203
- return [3 /*break*/, 14];
204
- case 5:
205
- if (!(fieldType === "Choice")) return [3 /*break*/, 6];
206
- objects[columnInternalName] = val.newValue.key;
207
- return [3 /*break*/, 14];
208
- case 6:
209
- if (!(fieldType === "MultiChoice")) return [3 /*break*/, 7];
210
- objects[columnInternalName] = { results: val.newValue };
211
- return [3 /*break*/, 14];
212
- case 7:
213
- if (!(fieldType === "Location")) return [3 /*break*/, 8];
214
- objects[columnInternalName] = JSON.stringify(val.newValue);
215
- return [3 /*break*/, 14];
216
- case 8:
217
- if (!(fieldType === "UserMulti")) return [3 /*break*/, 9];
218
- objects["".concat(columnInternalName, "Id")] = {
219
- results: val.newValue.length === 0 ? null : val.newValue,
220
- };
221
- return [3 /*break*/, 14];
222
- case 9:
223
- if (!(fieldType === "Thumbnail")) return [3 /*break*/, 13];
224
- if (!additionalData) return [3 /*break*/, 11];
213
+ if (fieldType === "MultiChoice") {
214
+ objects[columnInternalName] = { results: field.newValue };
215
+ }
216
+ // Lookup fields
217
+ if (fieldType === "Lookup") {
218
+ if (value_1 && value_1.length > 0) {
219
+ objects["".concat(columnInternalName, "Id")] = value_1[0].key;
220
+ }
221
+ else {
222
+ objects["".concat(columnInternalName, "Id")] = null;
223
+ }
224
+ }
225
+ if (fieldType === "LookupMulti") {
226
+ value_1 = [];
227
+ field.newValue.forEach(function (element) {
228
+ value_1.push(element.key);
229
+ });
230
+ objects["".concat(columnInternalName, "Id")] = {
231
+ results: value_1.length === 0 ? null : value_1,
232
+ };
233
+ }
234
+ // User fields
235
+ if (fieldType === "User") {
236
+ objects["".concat(columnInternalName, "Id")] = field.newValue.length === 0 ? null : field.newValue;
237
+ }
238
+ if (fieldType === "UserMulti") {
239
+ objects["".concat(columnInternalName, "Id")] = {
240
+ results: field.newValue.length === 0 ? null : field.newValue,
241
+ };
242
+ }
243
+ // Taxonomy / Managed Metadata fields
244
+ if (fieldType === "TaxonomyFieldType") {
245
+ objects[columnInternalName] = {
246
+ __metadata: { type: "SP.Taxonomy.TaxonomyFieldValue" },
247
+ Label: (_c = (_b = value_1[0]) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : "",
248
+ TermGuid: (_e = (_d = value_1[0]) === null || _d === void 0 ? void 0 : _d.key) !== null && _e !== void 0 ? _e : "11111111-1111-1111-1111-111111111111",
249
+ WssId: "-1",
250
+ };
251
+ }
252
+ if (fieldType === "TaxonomyFieldTypeMulti") {
253
+ objects[hiddenFieldName] = field.newValue
254
+ .map(function (term) { return "-1#;".concat(term.name, "|").concat(term.key, ";"); })
255
+ .join("#");
256
+ }
257
+ // Other fields
258
+ if (fieldType === "Location") {
259
+ objects[columnInternalName] = JSON.stringify(field.newValue);
260
+ }
261
+ if (!(fieldType === "Thumbnail")) return [3 /*break*/, 3];
262
+ if (!additionalData) return [3 /*break*/, 2];
225
263
  return [4 /*yield*/, this_1.uploadImage(additionalData)];
226
- case 10:
264
+ case 1:
227
265
  uploadedImage = _g.sent();
228
266
  objects[columnInternalName] = JSON.stringify({
229
267
  type: "thumbnail",
@@ -231,34 +269,30 @@ var DynamicForm = /** @class */ (function (_super) {
231
269
  serverRelativeUrl: uploadedImage.ServerRelativeUrl,
232
270
  id: uploadedImage.UniqueId,
233
271
  });
234
- return [3 /*break*/, 12];
235
- case 11:
272
+ return [3 /*break*/, 3];
273
+ case 2:
236
274
  objects[columnInternalName] = null;
237
- _g.label = 12;
238
- case 12: return [3 /*break*/, 14];
239
- case 13:
240
- objects[columnInternalName] = val.newValue;
241
- _g.label = 14;
242
- case 14: return [2 /*return*/];
275
+ _g.label = 3;
276
+ case 3: return [2 /*return*/];
243
277
  }
244
278
  });
245
279
  };
246
280
  this_1 = this;
247
281
  i = 0, len = fields.length;
248
- _f.label = 2;
249
- case 2:
250
- if (!(i < len)) return [3 /*break*/, 5];
251
- return [5 /*yield**/, _loop_1(i, len)];
252
- case 3:
253
- _f.sent();
254
282
  _f.label = 4;
255
283
  case 4:
256
- i++;
257
- return [3 /*break*/, 2];
284
+ if (!(i < len)) return [3 /*break*/, 7];
285
+ return [5 /*yield**/, _loop_1(i, len)];
258
286
  case 5:
259
- if (!onBeforeSubmit) return [3 /*break*/, 7];
260
- return [4 /*yield*/, onBeforeSubmit(objects)];
287
+ _f.sent();
288
+ _f.label = 6;
261
289
  case 6:
290
+ i++;
291
+ return [3 /*break*/, 4];
292
+ case 7:
293
+ if (!onBeforeSubmit) return [3 /*break*/, 9];
294
+ return [4 /*yield*/, onBeforeSubmit(objects)];
295
+ case 8:
262
296
  isCancelled = _f.sent();
263
297
  if (isCancelled) {
264
298
  this.setState({
@@ -266,18 +300,19 @@ var DynamicForm = /** @class */ (function (_super) {
266
300
  });
267
301
  return [2 /*return*/];
268
302
  }
269
- _f.label = 7;
270
- case 7:
303
+ _f.label = 9;
304
+ case 9:
305
+ apiError = void 0;
271
306
  newETag = undefined;
272
- if (!listItemId) return [3 /*break*/, 12];
273
- _f.label = 8;
274
- case 8:
275
- _f.trys.push([8, 10, , 11]);
307
+ if (!listItemId) return [3 /*break*/, 14];
308
+ _f.label = 10;
309
+ case 10:
310
+ _f.trys.push([10, 12, , 13]);
276
311
  return [4 /*yield*/, sp.web.lists
277
312
  .getById(listId)
278
313
  .items.getById(listItemId)
279
314
  .update(objects, this.state.etag)];
280
- case 9:
315
+ case 11:
281
316
  iur = _f.sent();
282
317
  newETag = iur.data["odata.etag"];
283
318
  if (onSubmitted) {
@@ -285,116 +320,114 @@ var DynamicForm = /** @class */ (function (_super) {
285
320
  ? iur.item
286
321
  : undefined);
287
322
  }
288
- return [3 /*break*/, 11];
289
- case 10:
323
+ return [3 /*break*/, 13];
324
+ case 12:
290
325
  error_1 = _f.sent();
326
+ apiError = error_1.message;
291
327
  if (onSubmitError) {
292
328
  onSubmitError(objects, error_1);
293
329
  }
294
330
  console.log("Error", error_1);
295
- return [3 /*break*/, 11];
296
- case 11: return [3 /*break*/, 30];
297
- case 12:
331
+ return [3 /*break*/, 13];
332
+ case 13: return [3 /*break*/, 29];
333
+ case 14:
298
334
  if (!(contentTypeId === undefined ||
299
335
  contentTypeId === "" ||
300
336
  (!contentTypeId.startsWith("0x0120") &&
301
- contentTypeId.startsWith("0x01")))) return [3 /*break*/, 18];
302
- if (!(contentTypeId === undefined || enableFileSelection === true)) return [3 /*break*/, 14];
337
+ contentTypeId.startsWith("0x01")))) return [3 /*break*/, 20];
338
+ if (!(fileSelectRendered === true)) return [3 /*break*/, 16];
303
339
  return [4 /*yield*/, this.addFileToLibrary(objects)];
304
- case 13:
340
+ case 15:
305
341
  _f.sent();
306
- return [3 /*break*/, 17];
307
- case 14:
308
- _f.trys.push([14, 16, , 17]);
342
+ return [3 /*break*/, 19];
343
+ case 16:
344
+ _f.trys.push([16, 18, , 19]);
309
345
  contentTypeIdField = "ContentTypeId";
310
- //check if item contenttype is passed, then update the object with content type id, else, pass the object
346
+ // check if item contenttype is passed, then update the object with content type id, else, pass the object
311
347
  if (contentTypeId !== undefined && contentTypeId.startsWith("0x01"))
312
348
  objects[contentTypeIdField] = contentTypeId;
313
349
  return [4 /*yield*/, sp.web.lists.getById(listId).items.add(objects)];
314
- case 15:
350
+ case 17:
315
351
  iar = _f.sent();
316
352
  if (onSubmitted) {
317
353
  onSubmitted(iar.data, this.props.returnListItemInstanceOnSubmit !== false
318
354
  ? iar.item
319
355
  : undefined);
320
356
  }
321
- return [3 /*break*/, 17];
322
- case 16:
357
+ return [3 /*break*/, 19];
358
+ case 18:
323
359
  error_2 = _f.sent();
360
+ apiError = error_2.message;
324
361
  if (onSubmitError) {
325
362
  onSubmitError(objects, error_2);
326
363
  }
327
364
  console.log("Error", error_2);
328
- return [3 /*break*/, 17];
329
- case 17: return [3 /*break*/, 30];
330
- case 18:
331
- if (!contentTypeId.startsWith("0x0120")) return [3 /*break*/, 28];
332
- _f.label = 19;
333
- case 19:
334
- _f.trys.push([19, 26, , 27]);
365
+ return [3 /*break*/, 19];
366
+ case 19: return [3 /*break*/, 29];
367
+ case 20:
368
+ if (!contentTypeId.startsWith("0x0120")) return [3 /*break*/, 29];
369
+ _f.label = 21;
370
+ case 21:
371
+ _f.trys.push([21, 28, , 29]);
335
372
  idField = "ID";
336
373
  titleField = "Title";
337
374
  contentTypeIdField = "ContentTypeId";
338
375
  return [4 /*yield*/, sp.web.lists.getById(listId)];
339
- case 20:
376
+ case 22:
340
377
  library = _f.sent();
341
378
  folderTitle = objects[titleField] !== undefined && objects[titleField] !== ""
342
379
  ? objects[titleField].replace(/["|*|:|<|>|?|/|\\||]/g, "_") // Replace not allowed chars in folder name
343
380
  : "";
344
381
  return [4 /*yield*/, library.rootFolder.addSubFolderUsingPath(folderTitle)];
345
- case 21:
382
+ case 23:
346
383
  newFolder = _f.sent();
347
384
  return [4 /*yield*/, newFolder.listItemAllFields()];
348
- case 22:
385
+ case 24:
349
386
  fields_1 = _f.sent();
350
- if (!fields_1[idField]) return [3 /*break*/, 24];
387
+ if (!fields_1[idField]) return [3 /*break*/, 26];
351
388
  folderId = fields_1[idField];
352
389
  // Set the content type ID for the target item
353
390
  objects[contentTypeIdField] = contentTypeId;
354
391
  return [4 /*yield*/, library.items.getById(folderId).update(objects)];
355
- case 23:
392
+ case 25:
356
393
  iur = _f.sent();
357
394
  if (onSubmitted) {
358
395
  onSubmitted(iur.data, this.props.returnListItemInstanceOnSubmit !== false
359
396
  ? iur.item
360
397
  : undefined);
361
398
  }
362
- return [3 /*break*/, 25];
363
- case 24: throw new Error("Unable to read the ID of the just created folder or Document Set");
364
- case 25: return [3 /*break*/, 27];
365
- case 26:
399
+ return [3 /*break*/, 27];
400
+ case 26: throw new Error("Unable to read the ID of the just created folder or Document Set");
401
+ case 27: return [3 /*break*/, 29];
402
+ case 28:
366
403
  error_3 = _f.sent();
404
+ apiError = error_3.message;
367
405
  if (onSubmitError) {
368
406
  onSubmitError(objects, error_3);
369
407
  }
370
408
  console.log("Error", error_3);
371
- return [3 /*break*/, 27];
372
- case 27: return [3 /*break*/, 30];
373
- case 28:
374
- if (!(contentTypeId.startsWith("0x01") && enableFileSelection === true)) return [3 /*break*/, 30];
375
- // We are adding a folder or a Document Set
376
- return [4 /*yield*/, this.addFileToLibrary(objects)];
409
+ return [3 /*break*/, 29];
377
410
  case 29:
378
- // We are adding a folder or a Document Set
379
- _f.sent();
380
- _f.label = 30;
381
- case 30:
382
411
  this.setState({
383
412
  isSaving: false,
384
413
  etag: newETag,
414
+ infoErrorMessages: apiError ? [{ type: MessageBarType.error, message: apiError }] : [],
385
415
  });
386
- return [3 /*break*/, 32];
387
- case 31:
416
+ return [3 /*break*/, 31];
417
+ case 30:
388
418
  error_4 = _f.sent();
389
419
  if (onSubmitError) {
390
420
  onSubmitError(null, error_4);
391
421
  }
392
422
  console.log("Error onSubmit", error_4);
393
- return [3 /*break*/, 32];
394
- case 32: return [2 /*return*/];
423
+ return [3 /*break*/, 31];
424
+ case 31: return [2 /*return*/];
395
425
  }
396
426
  });
397
427
  }); };
428
+ /**
429
+ * Adds selected file to the library
430
+ */
398
431
  _this.addFileToLibrary = function (objects) { return __awaiter(_this, void 0, void 0, function () {
399
432
  var selectedFile, _a, listId, contentTypeId, onSubmitted, onSubmitError, returnListItemInstanceOnSubmit, idField, contentTypeIdField, library, itemTitle, fileCreatedResult, _b, _c, _d, fields, folderId, iur, error_5;
400
433
  return __generator(this, function (_e) {
@@ -402,6 +435,7 @@ var DynamicForm = /** @class */ (function (_super) {
402
435
  case 0:
403
436
  selectedFile = this.state.selectedFile;
404
437
  _a = this.props, listId = _a.listId, contentTypeId = _a.contentTypeId, onSubmitted = _a.onSubmitted, onSubmitError = _a.onSubmitError, returnListItemInstanceOnSubmit = _a.returnListItemInstanceOnSubmit;
438
+ if (!(selectedFile !== undefined)) return [3 /*break*/, 10];
405
439
  _e.label = 1;
406
440
  case 1:
407
441
  _e.trys.push([1, 9, , 10]);
@@ -448,21 +482,40 @@ var DynamicForm = /** @class */ (function (_super) {
448
482
  }
449
483
  });
450
484
  }); };
451
- // trigger when the user change any value in the form
485
+ /**
486
+ * Triggered when the user makes any field value change in the form
487
+ */
452
488
  _this.onChange = function (internalName,
453
489
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
454
- newValue, additionalData) { return __awaiter(_this, void 0, void 0, function () {
455
- var fieldCol, field, user, result, index, element, user, result;
490
+ newValue, validate, additionalData) { return __awaiter(_this, void 0, void 0, function () {
491
+ var fieldCol, field, user, result, emails, index, element, user, result, validationErrors;
492
+ var _this = this;
456
493
  return __generator(this, function (_a) {
457
494
  switch (_a.label) {
458
495
  case 0:
459
- fieldCol = (this.state.fieldCollection || []).slice();
496
+ fieldCol = cloneDeep(this.state.fieldCollection || []);
460
497
  field = fieldCol.filter(function (element, i) {
461
498
  return element.columnInternalName === internalName;
462
499
  })[0];
500
+ // Init new value(s)
463
501
  field.newValue = newValue;
502
+ field.stringValue = newValue.toString();
464
503
  field.additionalData = additionalData;
465
- if (!(field.fieldType === "User" && newValue.length !== 0)) return [3 /*break*/, 4];
504
+ field.subPropertyValues = {};
505
+ // Store string values for various field types
506
+ if (field.fieldType === "Choice") {
507
+ field.stringValue = newValue.text;
508
+ }
509
+ if (field.fieldType === "MultiChoice") {
510
+ field.stringValue = newValue.join(';#');
511
+ }
512
+ if (field.fieldType === "Lookup" || field.fieldType === "LookupMulti") {
513
+ field.stringValue = newValue.map(function (nv) { return nv.key + ';#' + nv.name; }).join(';#');
514
+ }
515
+ if (field.fieldType === "TaxonomyFieldType" || field.fieldType === "TaxonomyFieldTypeMulti") {
516
+ field.stringValue = newValue.map(function (nv) { return nv.name; }).join(';');
517
+ }
518
+ if (!(field.fieldType === "User" && newValue.length !== 0)) return [3 /*break*/, 3];
466
519
  if (!(newValue[0].id === undefined ||
467
520
  parseInt(newValue[0].id, 10).toString() === "NaN")) return [3 /*break*/, 2];
468
521
  user = newValue[0].secondaryText;
@@ -473,47 +526,187 @@ var DynamicForm = /** @class */ (function (_super) {
473
526
  case 1:
474
527
  result = _a.sent();
475
528
  field.newValue = result.data.Id; // eslint-disable-line require-atomic-updates
529
+ field.stringValue = user;
530
+ field.subPropertyValues = {
531
+ id: result.data.Id,
532
+ title: result.data.Title,
533
+ email: result.data.Email,
534
+ };
476
535
  return [3 /*break*/, 3];
477
536
  case 2:
478
537
  field.newValue = newValue[0].id;
479
538
  _a.label = 3;
480
- case 3: return [3 /*break*/, 9];
481
- case 4:
539
+ case 3:
482
540
  if (!(field.fieldType === "UserMulti" && newValue.length !== 0)) return [3 /*break*/, 9];
483
541
  field.newValue = [];
542
+ emails = [];
484
543
  index = 0;
485
- _a.label = 5;
486
- case 5:
487
- if (!(index < newValue.length)) return [3 /*break*/, 9];
544
+ _a.label = 4;
545
+ case 4:
546
+ if (!(index < newValue.length)) return [3 /*break*/, 8];
488
547
  element = newValue[index];
489
548
  if (!(element.id === undefined ||
490
- parseInt(element.id, 10).toString() === "NaN")) return [3 /*break*/, 7];
549
+ parseInt(element.id, 10).toString() === "NaN")) return [3 /*break*/, 6];
491
550
  user = element.secondaryText;
492
551
  if (user.indexOf("@") === -1) {
493
552
  user = element.loginName;
494
553
  }
495
554
  return [4 /*yield*/, sp.web.ensureUser(user)];
496
- case 6:
555
+ case 5:
497
556
  result = _a.sent();
498
557
  field.newValue.push(result.data.Id);
499
- return [3 /*break*/, 8];
500
- case 7:
558
+ emails.push(user);
559
+ return [3 /*break*/, 7];
560
+ case 6:
501
561
  field.newValue.push(element.id);
502
- _a.label = 8;
503
- case 8:
562
+ _a.label = 7;
563
+ case 7:
504
564
  index++;
505
- return [3 /*break*/, 5];
565
+ return [3 /*break*/, 4];
566
+ case 8:
567
+ field.stringValue = emails.join(";");
568
+ _a.label = 9;
506
569
  case 9:
570
+ validationErrors = __assign({}, this.state.validationErrors);
571
+ if (validationErrors[field.columnInternalName])
572
+ delete validationErrors[field.columnInternalName];
507
573
  this.setState({
508
574
  fieldCollection: fieldCol,
575
+ validationErrors: validationErrors
576
+ }, function () {
577
+ if (validate)
578
+ _this.performValidation();
509
579
  });
510
580
  return [2 /*return*/];
511
581
  }
512
582
  });
513
583
  }); };
514
- //getting all the fields information as part of get ready process
515
- _this.getFieldInformations = function () { return __awaiter(_this, void 0, void 0, function () {
516
- var _a, listId, listItemId, disabledFields, respectETag, onListItemLoaded, contentTypeId, spList, item, etag, defaultContentType, listFields, tempFields, order, responseValue, hiddenFields, defaultDayOfWeek, _loop_2, this_2, i, len, installedLanguages, error_6;
584
+ /** Validation callback, used when form first loads (getListInformation) and following onChange */
585
+ _this.performValidation = function (skipFieldValueValidation) {
586
+ var _a = _this.props, useClientSideValidation = _a.useClientSideValidation, useFieldValidation = _a.useFieldValidation;
587
+ var _b = _this.state, clientValidationFormulas = _b.clientValidationFormulas, validationFormulas = _b.validationFormulas;
588
+ if (Object.keys(clientValidationFormulas).length || Object.keys(validationFormulas).length) {
589
+ _this.setState({
590
+ isSaving: true, // Disable save btn and fields while validation in progress
591
+ }, function () {
592
+ var clientSideValidationDisabled = useClientSideValidation === false;
593
+ var fieldValidationDisabled = useFieldValidation === false;
594
+ var hiddenByFormula = !clientSideValidationDisabled ? _this.evaluateColumnVisibilityFormulas() : [];
595
+ var validationErrors = __assign({}, _this.state.validationErrors);
596
+ if (!skipFieldValueValidation && !fieldValidationDisabled)
597
+ validationErrors = _this.evaluateFieldValueFormulas(hiddenByFormula);
598
+ _this.setState({ hiddenByFormula: hiddenByFormula, isSaving: false, validationErrors: validationErrors });
599
+ });
600
+ }
601
+ };
602
+ /** Determines visibility of fields that have show/hide formulas set in Edit Form > Edit Columns > Edit Conditional Formula */
603
+ _this.evaluateColumnVisibilityFormulas = function () {
604
+ return _this.evaluateFormulas(_this.state.clientValidationFormulas, false);
605
+ };
606
+ /** Evaluates field validation formulas set in column settings and returns a Record of error messages */
607
+ _this.evaluateFieldValueFormulas = function (hiddenFields) {
608
+ return _this.evaluateFormulas(_this.state.validationFormulas, true, true, hiddenFields);
609
+ };
610
+ /**
611
+ * Evaluates formulas and returns a Record of error messages or an array of column names that have failed validation
612
+ * @param formulas A Record / dictionary-like object, where key is internal column name and value is an object with ValidationFormula and ValidationMessage properties
613
+ * @param returnMessages Determines whether a Record of error messages is returned or an array of column names that have failed validation
614
+ * @param requireValue Set to true if the formula should only be evaluated when the field has a value
615
+ * @returns
616
+ */
617
+ _this.evaluateFormulas = function (formulas, returnMessages, requireValue, ignoreFields) {
618
+ if (returnMessages === void 0) { returnMessages = true; }
619
+ if (requireValue === void 0) { requireValue = false; }
620
+ if (ignoreFields === void 0) { ignoreFields = []; }
621
+ var fieldCollection = _this.state.fieldCollection;
622
+ var results = {};
623
+ var _loop_2 = function (i) {
624
+ var fieldName = Object.keys(formulas)[i];
625
+ if (formulas[fieldName]) {
626
+ var field = fieldCollection.find(function (f) { return f.columnInternalName === fieldName; });
627
+ if (!field)
628
+ return "continue";
629
+ if (ignoreFields.indexOf(fieldName) > -1)
630
+ return "continue"; // Skip fields that are being ignored (e.g. hidden by formula)
631
+ var formula = formulas[fieldName].ValidationFormula;
632
+ var message = formulas[fieldName].ValidationMessage;
633
+ if (!formula)
634
+ return "continue";
635
+ var context = _this.getFormValuesForValidation();
636
+ if (requireValue && !context[fieldName])
637
+ return "continue";
638
+ var result = _this._formulaEvaluation.evaluate(formula, context);
639
+ if (Boolean(result) !== true) {
640
+ results[fieldName] = message;
641
+ }
642
+ }
643
+ };
644
+ for (var i = 0; i < Object.keys(formulas).length; i++) {
645
+ _loop_2(i);
646
+ }
647
+ if (!returnMessages) {
648
+ return Object.keys(results);
649
+ }
650
+ return results;
651
+ };
652
+ /**
653
+ * Used for validation. Returns a Record of field values, where key is internal column name and value is the field value.
654
+ * Expands certain properties and stores many of them as primitives (strings, numbers or bools) so the expression evaluator
655
+ * can process them. For example: a User column named Person will have values stored as Person, Person.email, Person.title etc.
656
+ * This is so the expression evaluator can process expressions like '=[$Person.title] == "Contoso Employee 1138"'
657
+ * @param fieldCollection Optional. Could be used to compare field values in state with previous state.
658
+ * @returns
659
+ */
660
+ _this.getFormValuesForValidation = function (fieldCollection) {
661
+ var fieldColFromState = _this.state.fieldCollection;
662
+ if (!fieldCollection)
663
+ fieldCollection = fieldColFromState;
664
+ return fieldCollection.reduce(function (prev, cur) {
665
+ var value = cur.value;
666
+ switch (cur.fieldType) {
667
+ case "Lookup":
668
+ case "Choice":
669
+ case "TaxonomyFieldType":
670
+ case "LookupMulti":
671
+ case "MultiChoice":
672
+ case "TaxonomyFieldTypeMulti":
673
+ case "User":
674
+ case "UserMulti":
675
+ value = cur.stringValue;
676
+ break;
677
+ case "Currency":
678
+ case "Number":
679
+ if (cur.value !== undefined && cur.value !== null)
680
+ value = Number(cur.value);
681
+ if (cur.newValue !== undefined && cur.newValue !== null)
682
+ value = Number(cur.newValue);
683
+ break;
684
+ case "URL":
685
+ if (cur.value !== undefined && cur.value !== null)
686
+ value = cur.value.Url;
687
+ if (cur.newValue !== undefined && cur.newValue !== null)
688
+ value = cur.newValue.Url;
689
+ value = cur.newValue ? cur.newValue.Url : null;
690
+ break;
691
+ default:
692
+ value = cur.newValue || cur.value;
693
+ break;
694
+ }
695
+ prev[cur.columnInternalName] = value;
696
+ if (cur.subPropertyValues) {
697
+ Object.keys(cur.subPropertyValues).forEach(function (key) {
698
+ prev["".concat(cur.columnInternalName, ".").concat(key)] = cur.subPropertyValues[key];
699
+ });
700
+ }
701
+ return prev;
702
+ }, {});
703
+ };
704
+ /**
705
+ * Invoked when component first mounts, loads information about the SharePoint list, fields and list item
706
+ */
707
+ _this.getListInformation = function () { return __awaiter(_this, void 0, void 0, function () {
708
+ var _a, listId, listItemId, disabledFields, respectETag, onListItemLoaded, contentTypeId, listInfo, additionalInfo, numberFields, validationFormulas, contentTypeName, clientValidationFormulas, headerJSON, footerJSON, bodySections, customFormatInfo, spList, item, etag, tempFields, installedLanguages, error_6;
709
+ var _this = this;
517
710
  return __generator(this, function (_b) {
518
711
  switch (_b.label) {
519
712
  case 0:
@@ -521,311 +714,92 @@ var DynamicForm = /** @class */ (function (_super) {
521
714
  contentTypeId = this.props.contentTypeId;
522
715
  _b.label = 1;
523
716
  case 1:
524
- _b.trys.push([1, 16, , 17]);
525
- return [4 /*yield*/, sp.web.lists.getById(listId)];
717
+ _b.trys.push([1, 11, , 12]);
718
+ return [4 /*yield*/, this._spService.getListFormRenderInfo(listId)];
526
719
  case 2:
527
- spList = _b.sent();
720
+ listInfo = _b.sent();
721
+ return [4 /*yield*/, this._spService.getAdditionalListFormFieldInfo(listId)];
722
+ case 3:
723
+ additionalInfo = _b.sent();
724
+ numberFields = additionalInfo.filter(function (f) { return f.TypeAsString === "Number" || f.TypeAsString === "Currency"; });
725
+ validationFormulas = additionalInfo.reduce(function (prev, cur) {
726
+ if (!prev[cur.InternalName] && cur.ValidationFormula) {
727
+ prev[cur.InternalName] = {
728
+ ValidationFormula: cur.ValidationFormula,
729
+ ValidationMessage: cur.ValidationMessage,
730
+ };
731
+ }
732
+ return prev;
733
+ }, {});
734
+ // If no content type ID is provided, use the default (first one in the list)
735
+ if (contentTypeId === undefined || contentTypeId === "") {
736
+ contentTypeId = Object.keys(listInfo.ContentTypeIdToNameMap)[0];
737
+ }
738
+ contentTypeName = listInfo.ContentTypeIdToNameMap[contentTypeId];
739
+ clientValidationFormulas = listInfo.ClientForms.Edit[contentTypeName].reduce(function (prev, cur) {
740
+ if (cur.ClientValidationFormula) {
741
+ prev[cur.InternalName] = {
742
+ ValidationFormula: cur.ClientValidationFormula,
743
+ ValidationMessage: cur.ClientValidationMessage,
744
+ };
745
+ }
746
+ return prev;
747
+ }, {});
748
+ headerJSON = void 0, footerJSON = void 0;
749
+ bodySections = void 0;
750
+ if (listInfo.ClientFormCustomFormatter && listInfo.ClientFormCustomFormatter[contentTypeId]) {
751
+ customFormatInfo = JSON.parse(listInfo.ClientFormCustomFormatter[contentTypeId]);
752
+ bodySections = customFormatInfo.bodyJSONFormatter.sections;
753
+ headerJSON = customFormatInfo.headerJSONFormatter;
754
+ footerJSON = customFormatInfo.footerJSONFormatter;
755
+ }
756
+ spList = sp.web.lists.getById(listId);
528
757
  item = null;
529
758
  etag = undefined;
530
- if (!(listItemId !== undefined && listItemId !== null && listItemId !== 0)) return [3 /*break*/, 6];
531
- return [4 /*yield*/, spList.items.getById(listItemId).get()];
532
- case 3:
759
+ if (!(listItemId !== undefined && listItemId !== null && listItemId !== 0)) return [3 /*break*/, 7];
760
+ return [4 /*yield*/, spList.items.getById(listItemId).get().catch(function (err) { return _this.updateFormMessages(MessageBarType.error, err.message); })];
761
+ case 4:
533
762
  item = _b.sent();
534
- if (!onListItemLoaded) return [3 /*break*/, 5];
763
+ if (!onListItemLoaded) return [3 /*break*/, 6];
535
764
  return [4 /*yield*/, onListItemLoaded(item)];
536
- case 4:
537
- _b.sent();
538
- _b.label = 5;
539
765
  case 5:
766
+ _b.sent();
767
+ _b.label = 6;
768
+ case 6:
540
769
  if (respectETag !== false) {
541
770
  etag = item["odata.etag"];
542
771
  }
543
- _b.label = 6;
544
- case 6:
545
- if (!(contentTypeId === undefined || contentTypeId === "")) return [3 /*break*/, 8];
546
- return [4 /*yield*/, spList.contentTypes
547
- .select("Id", "Name")
548
- .get()];
549
- case 7:
550
- defaultContentType = _b.sent();
551
- contentTypeId = defaultContentType[0].Id.StringValue;
552
- _b.label = 8;
553
- case 8: return [4 /*yield*/, this.getFormFields(listId, contentTypeId, this.webURL)];
772
+ _b.label = 7;
773
+ case 7: return [4 /*yield*/, this.buildFieldCollection(listInfo, contentTypeName, item, numberFields, listId, listItemId, disabledFields)];
774
+ case 8:
775
+ tempFields = _b.sent();
776
+ installedLanguages = void 0;
777
+ if (!(tempFields.filter(function (f) { return f.fieldType === "Currency"; }).length > 0)) return [3 /*break*/, 10];
778
+ return [4 /*yield*/, sp.web.regionalSettings.getInstalledLanguages()];
554
779
  case 9:
555
- listFields = _b.sent();
556
- tempFields = [];
557
- order = 0;
558
- responseValue = listFields.value;
559
- hiddenFields = this.props.hiddenFields !== undefined ? this.props.hiddenFields : [];
560
- defaultDayOfWeek = 0;
561
- _loop_2 = function (i, len) {
562
- var field, fieldType, cultureName, hiddenName, termSetId, anchorId, lookupListId, lookupField, choices_1, defaultValue, selectedTags_1, richText, dateFormat, principalType, minValue, maxValue, showAsPercentage, response, response, schemaXml, dateFormatRegEx, userEmails, _c, _d;
563
- return __generator(this, function (_e) {
564
- switch (_e.label) {
565
- case 0:
566
- field = responseValue[i];
567
- if (!(hiddenFields.indexOf(field.EntityPropertyName) < 0)) return [3 /*break*/, 30];
568
- order++;
569
- fieldType = field.TypeAsString;
570
- field.order = order;
571
- cultureName = void 0;
572
- hiddenName = "";
573
- termSetId = "";
574
- anchorId = "";
575
- lookupListId = "";
576
- lookupField = "";
577
- choices_1 = [];
578
- defaultValue = null;
579
- selectedTags_1 = [];
580
- richText = false;
581
- dateFormat = void 0;
582
- principalType = "";
583
- minValue = void 0;
584
- maxValue = void 0;
585
- showAsPercentage = void 0;
586
- if (item !== null) {
587
- defaultValue = item[field.EntityPropertyName];
588
- }
589
- else {
590
- defaultValue = field.DefaultValue;
591
- }
592
- if (!(fieldType === "Choice" || fieldType === "MultiChoice")) return [3 /*break*/, 1];
593
- field.Choices.forEach(function (element) {
594
- choices_1.push({ key: element, text: element });
595
- });
596
- return [3 /*break*/, 29];
597
- case 1:
598
- if (!(fieldType === "Note")) return [3 /*break*/, 2];
599
- richText = field.RichText;
600
- return [3 /*break*/, 29];
601
- case 2:
602
- if (!(fieldType === "Number" || fieldType === "Currency")) return [3 /*break*/, 3];
603
- minValue = field.MinimumValue;
604
- maxValue = field.MaximumValue;
605
- if (fieldType === "Number") {
606
- showAsPercentage = field.ShowAsPercentage;
607
- }
608
- else {
609
- cultureName = this_2.cultureNameLookup(field.CurrencyLocaleId);
610
- }
611
- return [3 /*break*/, 29];
612
- case 3:
613
- if (!(fieldType === "Lookup")) return [3 /*break*/, 7];
614
- lookupListId = field.LookupList;
615
- lookupField = field.LookupField;
616
- if (!(item !== null)) return [3 /*break*/, 5];
617
- return [4 /*yield*/, this_2._spService.getLookupValue(listId, listItemId, field.EntityPropertyName, lookupField, this_2.webURL)];
618
- case 4:
619
- defaultValue = _e.sent();
620
- return [3 /*break*/, 6];
621
- case 5:
622
- defaultValue = [];
623
- _e.label = 6;
624
- case 6: return [3 /*break*/, 29];
625
- case 7:
626
- if (!(fieldType === "LookupMulti")) return [3 /*break*/, 11];
627
- lookupListId = field.LookupList;
628
- lookupField = field.LookupField;
629
- if (!(item !== null)) return [3 /*break*/, 9];
630
- return [4 /*yield*/, this_2._spService.getLookupValues(listId, listItemId, field.EntityPropertyName, lookupField, this_2.webURL)];
631
- case 8:
632
- defaultValue = _e.sent();
633
- return [3 /*break*/, 10];
634
- case 9:
635
- defaultValue = [];
636
- _e.label = 10;
637
- case 10: return [3 /*break*/, 29];
638
- case 11:
639
- if (!(fieldType === "TaxonomyFieldTypeMulti")) return [3 /*break*/, 13];
640
- return [4 /*yield*/, this_2._spService.getTaxonomyFieldInternalName(this_2.props.listId, field.TextField, this_2.webURL)];
641
- case 12:
642
- response = _e.sent();
643
- hiddenName = response.value;
644
- termSetId = field.TermSetId;
645
- anchorId = field.AnchorId;
646
- if (item !== null && item[field.InternalName] !== null && item[field.InternalName].results !== null) {
647
- item[field.InternalName].results.forEach(function (element) {
648
- selectedTags_1.push({
649
- key: element.TermGuid,
650
- name: element.Label,
651
- });
652
- });
653
- defaultValue = selectedTags_1;
654
- }
655
- else {
656
- if (defaultValue !== null && defaultValue !== "") {
657
- defaultValue.split(/#|;/).forEach(function (element) {
658
- if (element.indexOf("|") !== -1)
659
- selectedTags_1.push({
660
- key: element.split("|")[1],
661
- name: element.split("|")[0],
662
- });
663
- });
664
- defaultValue = selectedTags_1;
665
- }
666
- }
667
- if (defaultValue === "")
668
- defaultValue = null;
669
- return [3 /*break*/, 29];
670
- case 13:
671
- if (!(fieldType === "TaxonomyFieldType")) return [3 /*break*/, 17];
672
- termSetId = field.TermSetId;
673
- anchorId = field.AnchorId;
674
- if (!(item !== null)) return [3 /*break*/, 15];
675
- return [4 /*yield*/, this_2._spService.getSingleManagedMetadataLabel(listId, listItemId, field.InternalName)];
676
- case 14:
677
- response = _e.sent();
678
- if (response) {
679
- selectedTags_1.push({
680
- key: response.TermID,
681
- name: response.Label,
682
- });
683
- defaultValue = selectedTags_1;
684
- }
685
- return [3 /*break*/, 16];
686
- case 15:
687
- if (defaultValue !== "") {
688
- selectedTags_1.push({
689
- key: defaultValue.split("|")[1],
690
- name: defaultValue.split("|")[0].split("#")[1],
691
- });
692
- defaultValue = selectedTags_1;
693
- }
694
- _e.label = 16;
695
- case 16:
696
- if (defaultValue === "")
697
- defaultValue = null;
698
- return [3 /*break*/, 29];
699
- case 17:
700
- if (!(fieldType === "DateTime")) return [3 /*break*/, 19];
701
- if (item !== null && item[field.InternalName])
702
- defaultValue = new Date(item[field.InternalName]);
703
- else if (defaultValue === "[today]") {
704
- defaultValue = new Date();
705
- }
706
- schemaXml = field.SchemaXml;
707
- dateFormatRegEx = /\s+Format="([^"]+)"/gim.exec(schemaXml);
708
- dateFormat =
709
- dateFormatRegEx && dateFormatRegEx.length
710
- ? dateFormatRegEx[1]
711
- : "DateOnly";
712
- return [4 /*yield*/, this_2._spService.getRegionalWebSettings()];
713
- case 18:
714
- defaultDayOfWeek = (_e.sent())
715
- .FirstDayOfWeek;
716
- return [3 /*break*/, 29];
717
- case 19:
718
- if (!(fieldType === "UserMulti")) return [3 /*break*/, 23];
719
- if (!(item !== null)) return [3 /*break*/, 21];
720
- return [4 /*yield*/, this_2._spService.getUsersUPNFromFieldValue(listId, listItemId, field.InternalName, this_2.webURL)];
721
- case 20:
722
- defaultValue = _e.sent();
723
- return [3 /*break*/, 22];
724
- case 21:
725
- defaultValue = [];
726
- _e.label = 22;
727
- case 22:
728
- principalType = field.SchemaXml.split('UserSelectionMode="')[1];
729
- principalType = principalType.substring(0, principalType.indexOf('"'));
730
- return [3 /*break*/, 29];
731
- case 23:
732
- if (!(fieldType === "Thumbnail")) return [3 /*break*/, 24];
733
- if (defaultValue) {
734
- defaultValue = JSON.parse(defaultValue).serverRelativeUrl;
735
- }
736
- return [3 /*break*/, 29];
737
- case 24:
738
- if (!(fieldType === "User")) return [3 /*break*/, 28];
739
- if (!(item !== null)) return [3 /*break*/, 26];
740
- userEmails = [];
741
- _d = (_c = userEmails).push;
742
- return [4 /*yield*/, this_2._spService.getUserUPNFromFieldValue(listId, listItemId, field.InternalName, this_2.webURL)];
743
- case 25:
744
- _d.apply(_c, [(_e.sent()) + ""]);
745
- defaultValue = userEmails;
746
- return [3 /*break*/, 27];
747
- case 26:
748
- defaultValue = [];
749
- _e.label = 27;
750
- case 27:
751
- principalType = field.SchemaXml.split('UserSelectionMode="')[1];
752
- principalType = principalType.substring(0, principalType.indexOf('"'));
753
- return [3 /*break*/, 29];
754
- case 28:
755
- if (fieldType === "Location") {
756
- defaultValue = JSON.parse(defaultValue);
757
- }
758
- else if (fieldType === "Boolean") {
759
- defaultValue = Boolean(Number(defaultValue));
760
- }
761
- _e.label = 29;
762
- case 29:
763
- tempFields.push({
764
- newValue: null,
765
- fieldTermSetId: termSetId,
766
- fieldAnchorId: anchorId,
767
- options: choices_1,
768
- lookupListID: lookupListId,
769
- lookupField: lookupField,
770
- cultureName: cultureName,
771
- changedValue: defaultValue,
772
- fieldType: field.TypeAsString,
773
- fieldTitle: field.Title,
774
- fieldDefaultValue: defaultValue,
775
- context: this_2.props.context,
776
- disabled: this_2.props.disabled ||
777
- (disabledFields &&
778
- disabledFields.indexOf(field.InternalName) > -1),
779
- listId: this_2.props.listId,
780
- columnInternalName: field.EntityPropertyName,
781
- label: field.Title,
782
- onChanged: this_2.onChange,
783
- required: field.Required,
784
- hiddenFieldName: hiddenName,
785
- Order: field.order,
786
- isRichText: richText,
787
- dateFormat: dateFormat,
788
- firstDayOfWeek: defaultDayOfWeek,
789
- listItemId: listItemId,
790
- principalType: principalType,
791
- description: field.Description,
792
- minimumValue: minValue,
793
- maximumValue: maxValue,
794
- showAsPercentage: showAsPercentage
795
- });
796
- tempFields.sort(function (a, b) { return a.Order - b.Order; });
797
- _e.label = 30;
798
- case 30: return [2 /*return*/];
799
- }
800
- });
801
- };
802
- this_2 = this;
803
- i = 0, len = responseValue.length;
780
+ installedLanguages = _b.sent();
804
781
  _b.label = 10;
805
782
  case 10:
806
- if (!(i < len)) return [3 /*break*/, 13];
807
- return [5 /*yield**/, _loop_2(i, len)];
783
+ this.setState({
784
+ contentTypeId: contentTypeId,
785
+ clientValidationFormulas: clientValidationFormulas,
786
+ customFormatting: {
787
+ header: headerJSON,
788
+ body: bodySections,
789
+ footer: footerJSON
790
+ },
791
+ etag: etag,
792
+ fieldCollection: tempFields,
793
+ installedLanguages: installedLanguages,
794
+ validationFormulas: validationFormulas
795
+ }, function () { return _this.performValidation(true); });
796
+ return [3 /*break*/, 12];
808
797
  case 11:
809
- _b.sent();
810
- _b.label = 12;
811
- case 12:
812
- i++;
813
- return [3 /*break*/, 10];
814
- case 13:
815
- installedLanguages = void 0;
816
- if (!(tempFields.filter(function (f) { return f.fieldType === "Currency"; }).length > 0)) return [3 /*break*/, 15];
817
- return [4 /*yield*/, sp.web.regionalSettings.getInstalledLanguages()];
818
- case 14:
819
- installedLanguages = _b.sent();
820
- _b.label = 15;
821
- case 15:
822
- this.setState({ fieldCollection: tempFields, installedLanguages: installedLanguages, etag: etag });
823
- return [3 /*break*/, 17];
824
- case 16:
825
798
  error_6 = _b.sent();
826
- console.log("Error get field informations", error_6);
799
+ this.updateFormMessages(MessageBarType.error, 'An error occurred while loading: ' + error_6.message);
800
+ console.error("An error occurred while loading DynamicForm", error_6);
827
801
  return [2 /*return*/, null];
828
- case 17: return [2 /*return*/];
802
+ case 12: return [2 /*return*/];
829
803
  }
830
804
  });
831
805
  }); };
@@ -861,48 +835,6 @@ var DynamicForm = /** @class */ (function (_super) {
861
835
  };
862
836
  });
863
837
  };
864
- _this.getFormFields = function (listId, contentTypeId, webUrl
865
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
866
- ) { return __awaiter(_this, void 0, void 0, function () {
867
- var context, webAbsoluteUrl, apiUrl, data, results, error_7;
868
- return __generator(this, function (_a) {
869
- switch (_a.label) {
870
- case 0:
871
- _a.trys.push([0, 4, , 5]);
872
- context = this.props.context;
873
- webAbsoluteUrl = !webUrl ? this.webURL : webUrl;
874
- apiUrl = "";
875
- if (contentTypeId !== undefined && contentTypeId !== "") {
876
- if (contentTypeId.startsWith("0x0120")) {
877
- apiUrl = "".concat(webAbsoluteUrl, "/_api/web/lists(@listId)/contenttypes('").concat(contentTypeId, "')/fields?@listId=guid'").concat(encodeURIComponent(listId), "'&$filter=ReadOnlyField eq false and (Hidden eq false or StaticName eq 'Title') and (FromBaseType eq false or StaticName eq 'Title')");
878
- }
879
- else {
880
- apiUrl = "".concat(webAbsoluteUrl, "/_api/web/lists(@listId)/contenttypes('").concat(contentTypeId, "')/fields?@listId=guid'").concat(encodeURIComponent(listId), "'&$filter=ReadOnlyField eq false and Hidden eq false and (FromBaseType eq false or StaticName eq 'Title')");
881
- }
882
- }
883
- else {
884
- apiUrl = "".concat(webAbsoluteUrl, "/_api/web/lists(@listId)/fields?@listId=guid'").concat(encodeURIComponent(listId), "'&$filter=ReadOnlyField eq false and Hidden eq false and (FromBaseType eq false or StaticName eq 'Title')");
885
- }
886
- return [4 /*yield*/, context.spHttpClient.get(apiUrl, SPHttpClient.configurations.v1)];
887
- case 1:
888
- data = _a.sent();
889
- if (!data.ok) return [3 /*break*/, 3];
890
- return [4 /*yield*/, data.json()];
891
- case 2:
892
- results = _a.sent();
893
- if (results) {
894
- return [2 /*return*/, results];
895
- }
896
- _a.label = 3;
897
- case 3: return [2 /*return*/, null];
898
- case 4:
899
- error_7 = _a.sent();
900
- console.dir(error_7);
901
- return [2 /*return*/, Promise.reject(error_7)];
902
- case 5: return [2 /*return*/];
903
- }
904
- });
905
- }); };
906
838
  _this.closeValidationErrorDialog = function () {
907
839
  _this.setState({
908
840
  isValidationErrorDialogOpen: false,
@@ -991,50 +923,115 @@ var DynamicForm = /** @class */ (function (_super) {
991
923
  }
992
924
  // Initialize state
993
925
  _this.state = {
926
+ infoErrorMessages: [],
994
927
  fieldCollection: [],
928
+ validationFormulas: {},
929
+ clientValidationFormulas: {},
930
+ validationErrors: {},
931
+ hiddenByFormula: [],
995
932
  isValidationErrorDialogOpen: false,
996
933
  };
997
934
  // Get SPService Factory
998
935
  _this._spService = _this.props.webAbsoluteUrl
999
936
  ? new SPservice(_this.props.context, _this.props.webAbsoluteUrl)
1000
937
  : new SPservice(_this.props.context);
938
+ // Setup Formula Validation utils
939
+ _this._formulaEvaluation = new FormulaEvaluation(_this.props.context, _this.props.webAbsoluteUrl);
940
+ // Setup Custom Formatting utils
941
+ _this._customFormatter = new CustomFormattingHelper(_this._formulaEvaluation);
1001
942
  return _this;
1002
943
  }
1003
944
  /**
1004
945
  * Lifecycle hook when component is mounted
1005
946
  */
1006
947
  DynamicForm.prototype.componentDidMount = function () {
1007
- this.getFieldInformations()
948
+ this.getListInformation()
1008
949
  .then(function () {
1009
950
  /* no-op; */
1010
951
  })
1011
- .catch(function () {
952
+ .catch(function (err) {
1012
953
  /* no-op; */
954
+ console.error(err);
1013
955
  });
1014
956
  };
957
+ DynamicForm.prototype.componentDidUpdate = function (prevProps, prevState) {
958
+ var _this = this;
959
+ if (!isEqual(prevProps, this.props)) {
960
+ // Props have changed due to parent component or workbench config, reset state
961
+ this.setState({
962
+ infoErrorMessages: [],
963
+ validationErrors: {} // Reset validation errors
964
+ }, function () {
965
+ // If listId or listItemId have changed, reload list information
966
+ if (prevProps.listId !== _this.props.listId || prevProps.listItemId !== _this.props.listItemId) {
967
+ _this.getListInformation()
968
+ .then(function () {
969
+ /* no-op; */
970
+ })
971
+ .catch(function (err) {
972
+ /* no-op; */
973
+ console.error(err);
974
+ });
975
+ }
976
+ else {
977
+ _this.performValidation();
978
+ }
979
+ });
980
+ }
981
+ };
1015
982
  /**
1016
983
  * Default React component render method
1017
984
  */
1018
985
  DynamicForm.prototype.render = function () {
986
+ var _a;
1019
987
  var _this = this;
1020
- var _a = this.state, fieldCollection = _a.fieldCollection, isSaving = _a.isSaving;
1021
- var fieldOverrides = this.props.fieldOverrides;
988
+ var _b = this.state, customFormatting = _b.customFormatting, fieldCollection = _b.fieldCollection, hiddenByFormula = _b.hiddenByFormula, infoErrorMessages = _b.infoErrorMessages, isSaving = _b.isSaving;
989
+ var customFormattingDisabled = this.props.useCustomFormatting === false;
990
+ // Custom Formatting - Header
991
+ var headerContent;
992
+ if (!customFormattingDisabled && (customFormatting === null || customFormatting === void 0 ? void 0 : customFormatting.header)) {
993
+ headerContent = this._customFormatter.renderCustomFormatContent(customFormatting.header, this.getFormValuesForValidation(), true);
994
+ }
995
+ // Custom Formatting - Body
996
+ var bodySections = [];
997
+ if (!customFormattingDisabled && (customFormatting === null || customFormatting === void 0 ? void 0 : customFormatting.body)) {
998
+ bodySections.push.apply(bodySections, customFormatting.body.slice());
999
+ if (bodySections.length > 0) {
1000
+ var specifiedFields_1 = bodySections.reduce(function (prev, cur) {
1001
+ prev.push.apply(prev, cur.fields);
1002
+ return prev;
1003
+ }, []);
1004
+ var omittedFields = fieldCollection.filter(function (f) { return !specifiedFields_1.includes(f.label); }).map(function (f) { return f.label; });
1005
+ (_a = bodySections[bodySections.length - 1].fields).push.apply(_a, omittedFields);
1006
+ }
1007
+ }
1008
+ // Custom Formatting - Footer
1009
+ var footerContent;
1010
+ if (!customFormattingDisabled && (customFormatting === null || customFormatting === void 0 ? void 0 : customFormatting.footer)) {
1011
+ footerContent = this._customFormatter.renderCustomFormatContent(customFormatting.footer, this.getFormValuesForValidation(), true);
1012
+ }
1013
+ // Content Type
1014
+ var contentTypeId = this.props.contentTypeId;
1015
+ if (this.state.contentTypeId !== undefined)
1016
+ contentTypeId = this.state.contentTypeId;
1022
1017
  return (React.createElement("div", null,
1018
+ infoErrorMessages.map(function (ie, i) { return (React.createElement(MessageBar, { key: i, messageBarType: ie.type }, ie.message)); }),
1023
1019
  fieldCollection.length === 0 ? (React.createElement("div", null,
1024
1020
  React.createElement(ProgressIndicator, { label: strings.DynamicFormLoading, description: strings.DynamicFormPleaseWait }))) : (React.createElement("div", null,
1021
+ headerContent,
1025
1022
  this.props.enableFileSelection === true &&
1026
1023
  this.props.listItemId === undefined &&
1027
- this.props.contentTypeId !== undefined &&
1028
- this.props.contentTypeId.startsWith("0x0101") &&
1024
+ contentTypeId !== undefined &&
1025
+ contentTypeId.startsWith("0x0101") &&
1029
1026
  this.renderFileSelectionControl(),
1030
- fieldCollection.map(function (v, i) {
1031
- if (fieldOverrides &&
1032
- Object.prototype.hasOwnProperty.call(fieldOverrides, v.columnInternalName)) {
1033
- v.disabled = v.disabled || isSaving;
1034
- return fieldOverrides[v.columnInternalName](v);
1035
- }
1036
- return (React.createElement(DynamicField, __assign({ key: v.columnInternalName }, v, { disabled: v.disabled || isSaving })));
1037
- }),
1027
+ (bodySections.length > 0 && !customFormattingDisabled) && bodySections
1028
+ .filter(function (bs) { return bs.fields.filter(function (bsf) { return hiddenByFormula.indexOf(bsf) < 0; }).length > 0; })
1029
+ .map(function (section, i) { return (React.createElement(React.Fragment, null,
1030
+ React.createElement("h2", { className: styles.sectionTitle }, section.displayname),
1031
+ React.createElement("div", { className: styles.sectionFormFields }, section.fields.map(function (f, i) { return (React.createElement("div", { key: f, className: styles.sectionFormField }, _this.renderField(fieldCollection.find(function (fc) { return fc.label === f; })))); })),
1032
+ i < bodySections.length - 1 && React.createElement("hr", { className: styles.sectionLine, "aria-hidden": true }))); }),
1033
+ (bodySections.length === 0 || customFormattingDisabled) && fieldCollection.map(function (f, i) { return _this.renderField(f); }),
1034
+ footerContent,
1038
1035
  !this.props.disabled && (React.createElement(Stack, { className: styles.buttons, horizontal: true, tokens: stackTokens },
1039
1036
  React.createElement(PrimaryButton, { disabled: isSaving, text: strings.Save, onClick: function () { return _this.onSubmitClick(); } }),
1040
1037
  React.createElement(DefaultButton, { disabled: isSaving, text: strings.Cancel, onClick: this.props.onCancelled }))))),
@@ -1052,6 +1049,305 @@ var DynamicForm = /** @class */ (function (_super) {
1052
1049
  React.createElement("div", { className: "ms-Dialog-actionsRight ".concat(styles.actionsRight) },
1053
1050
  React.createElement(DefaultButton, { className: styles.action, onClick: this.closeValidationErrorDialog, text: strings.CloseButton }))))));
1054
1051
  };
1052
+ DynamicForm.prototype.updateFormMessages = function (type, message) {
1053
+ var infoErrorMessages = this.state.infoErrorMessages;
1054
+ var newMessages = infoErrorMessages.slice();
1055
+ newMessages.push({ type: type, message: message });
1056
+ this.setState({ infoErrorMessages: newMessages });
1057
+ };
1058
+ /**
1059
+ * Builds a collection of fields to be rendered in the form
1060
+ * @param listInfo Data returned by RenderListDataAsStream with RenderOptions = 64 (ClientFormSchema)
1061
+ * @param contentTypeName SharePoint List Content Type
1062
+ * @param item SharePoint List Item
1063
+ * @param numberFields Additional information about Number fields (min and max values)
1064
+ * @param listId SharePoint List ID
1065
+ * @param listItemId SharePoint List Item ID
1066
+ * @param disabledFields Fields that should be disabled due to configuration
1067
+ * @returns
1068
+ */
1069
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1070
+ DynamicForm.prototype.buildFieldCollection = function (listInfo, contentTypeName, item, numberFields, listId, listItemId, disabledFields) {
1071
+ return __awaiter(this, void 0, void 0, function () {
1072
+ var tempFields, order, hiddenFields, defaultDayOfWeek, _loop_3, this_2, i, len;
1073
+ return __generator(this, function (_a) {
1074
+ switch (_a.label) {
1075
+ case 0:
1076
+ tempFields = [];
1077
+ order = 0;
1078
+ hiddenFields = this.props.hiddenFields !== undefined ? this.props.hiddenFields : [];
1079
+ defaultDayOfWeek = 0;
1080
+ _loop_3 = function (i, len) {
1081
+ var field, hiddenName, termSetId, anchorId, lookupListId, lookupField, choices_1, defaultValue, value, stringValue, subPropertyValues, richText, dateFormat, principalType, cultureName, minValue, maxValue, showAsPercentage, selectedTags_1, numberField, userEmails, _b, _c, response;
1082
+ return __generator(this, function (_d) {
1083
+ switch (_d.label) {
1084
+ case 0:
1085
+ field = listInfo.ClientForms.Edit[contentTypeName][i];
1086
+ if (!(hiddenFields.indexOf(field.InternalName) < 0)) return [3 /*break*/, 18];
1087
+ order++;
1088
+ hiddenName = "";
1089
+ termSetId = "";
1090
+ anchorId = "";
1091
+ lookupListId = "";
1092
+ lookupField = "";
1093
+ choices_1 = [];
1094
+ defaultValue = null;
1095
+ value = undefined;
1096
+ stringValue = null;
1097
+ subPropertyValues = {};
1098
+ richText = false;
1099
+ dateFormat = void 0;
1100
+ principalType = "";
1101
+ cultureName = void 0;
1102
+ minValue = void 0;
1103
+ maxValue = void 0;
1104
+ showAsPercentage = void 0;
1105
+ selectedTags_1 = [];
1106
+ // If a SharePoint Item was loaded, get the field value from it
1107
+ if (item !== null && item[field.InternalName]) {
1108
+ value = item[field.InternalName];
1109
+ stringValue = value.toString();
1110
+ }
1111
+ else {
1112
+ defaultValue = field.DefaultValue;
1113
+ }
1114
+ // Store choices for Choice fields
1115
+ if (field.FieldType === "Choice") {
1116
+ field.Choices.forEach(function (element) {
1117
+ choices_1.push({ key: element, text: element });
1118
+ });
1119
+ }
1120
+ if (field.FieldType === "MultiChoice") {
1121
+ field.MultiChoices.forEach(function (element) {
1122
+ choices_1.push({ key: element, text: element });
1123
+ });
1124
+ }
1125
+ // Setup Note, Number and Currency fields
1126
+ if (field.FieldType === "Note") {
1127
+ richText = field.RichText;
1128
+ }
1129
+ if (field.FieldType === "Number" || field.FieldType === "Currency") {
1130
+ numberField = numberFields.find(function (f) { return f.InternalName === field.InternalName; });
1131
+ if (numberField) {
1132
+ minValue = numberField.MinimumValue;
1133
+ maxValue = numberField.MaximumValue;
1134
+ }
1135
+ showAsPercentage = field.ShowAsPercentage;
1136
+ if (field.FieldType === "Currency") {
1137
+ cultureName = this_2.cultureNameLookup(numberField.CurrencyLocaleId);
1138
+ }
1139
+ }
1140
+ if (!(field.FieldType === "Lookup" || field.FieldType === "LookupMulti")) return [3 /*break*/, 3];
1141
+ lookupListId = field.LookupListId;
1142
+ lookupField = field.LookupFieldName;
1143
+ if (!(item !== null)) return [3 /*break*/, 2];
1144
+ return [4 /*yield*/, this_2._spService.getLookupValues(listId, listItemId, field.InternalName, lookupField, this_2.webURL)];
1145
+ case 1:
1146
+ value = _d.sent();
1147
+ stringValue = value === null || value === void 0 ? void 0 : value.map(function (dv) { return dv.key + ';#' + dv.name; }).join(';#');
1148
+ if (item[field.InternalName + "Id"]) {
1149
+ subPropertyValues.id = item[field.InternalName + "Id"];
1150
+ subPropertyValues.lookupId = subPropertyValues.id;
1151
+ }
1152
+ subPropertyValues.lookupValue = value === null || value === void 0 ? void 0 : value.map(function (dv) { return dv.name; });
1153
+ return [3 /*break*/, 3];
1154
+ case 2:
1155
+ value = [];
1156
+ _d.label = 3;
1157
+ case 3:
1158
+ if (!(field.FieldType === "User")) return [3 /*break*/, 7];
1159
+ if (!(item !== null)) return [3 /*break*/, 5];
1160
+ userEmails = [];
1161
+ _c = (_b = userEmails).push;
1162
+ return [4 /*yield*/, this_2._spService.getUserUPNFromFieldValue(listId, listItemId, field.InternalName, this_2.webURL)];
1163
+ case 4:
1164
+ _c.apply(_b, [(_d.sent()) + ""]);
1165
+ value = userEmails;
1166
+ stringValue = userEmails === null || userEmails === void 0 ? void 0 : userEmails.map(function (dv) { return dv.split('/').shift(); }).join(';');
1167
+ if (item[field.InternalName + "Id"]) {
1168
+ subPropertyValues.id = item[field.InternalName + "Id"];
1169
+ }
1170
+ subPropertyValues.title = userEmails === null || userEmails === void 0 ? void 0 : userEmails.map(function (dv) { return dv.split('/').pop(); })[0];
1171
+ subPropertyValues.email = userEmails[0];
1172
+ return [3 /*break*/, 6];
1173
+ case 5:
1174
+ value = [];
1175
+ _d.label = 6;
1176
+ case 6:
1177
+ principalType = field.PrincipalAccountType;
1178
+ _d.label = 7;
1179
+ case 7:
1180
+ if (!(field.FieldType === "UserMulti")) return [3 /*break*/, 11];
1181
+ if (!(item !== null)) return [3 /*break*/, 9];
1182
+ return [4 /*yield*/, this_2._spService.getUsersUPNFromFieldValue(listId, listItemId, field.InternalName, this_2.webURL)];
1183
+ case 8:
1184
+ value = _d.sent();
1185
+ stringValue = value === null || value === void 0 ? void 0 : value.map(function (dv) { return dv.split('/').pop(); }).join(';');
1186
+ return [3 /*break*/, 10];
1187
+ case 9:
1188
+ value = [];
1189
+ _d.label = 10;
1190
+ case 10:
1191
+ principalType = field.PrincipalAccountType;
1192
+ _d.label = 11;
1193
+ case 11:
1194
+ if (!(field.FieldType === "TaxonomyFieldType")) return [3 /*break*/, 15];
1195
+ termSetId = field.TermSetId;
1196
+ anchorId = field.AnchorId;
1197
+ if (!(item !== null)) return [3 /*break*/, 13];
1198
+ return [4 /*yield*/, this_2._spService.getSingleManagedMetadataLabel(listId, listItemId, field.InternalName)];
1199
+ case 12:
1200
+ response = _d.sent();
1201
+ if (response) {
1202
+ selectedTags_1.push({
1203
+ key: response.TermID,
1204
+ name: response.Label,
1205
+ });
1206
+ value = selectedTags_1;
1207
+ stringValue = selectedTags_1 === null || selectedTags_1 === void 0 ? void 0 : selectedTags_1.map(function (dv) { return dv.key + ';#' + dv.name; }).join(';#');
1208
+ }
1209
+ return [3 /*break*/, 14];
1210
+ case 13:
1211
+ if (defaultValue !== "") {
1212
+ selectedTags_1.push({
1213
+ key: defaultValue.split("|")[1],
1214
+ name: defaultValue.split("|")[0].split("#")[1],
1215
+ });
1216
+ value = selectedTags_1;
1217
+ }
1218
+ _d.label = 14;
1219
+ case 14:
1220
+ if (defaultValue === "")
1221
+ defaultValue = null;
1222
+ _d.label = 15;
1223
+ case 15:
1224
+ if (field.FieldType === "TaxonomyFieldTypeMulti") {
1225
+ hiddenName = field.HiddenListInternalName;
1226
+ termSetId = field.TermSetId;
1227
+ anchorId = field.AnchorId;
1228
+ if (item !== null) {
1229
+ item[field.InternalName].forEach(function (element) {
1230
+ selectedTags_1.push({
1231
+ key: element.TermGuid,
1232
+ name: element.Label,
1233
+ });
1234
+ });
1235
+ defaultValue = selectedTags_1;
1236
+ }
1237
+ else {
1238
+ if (defaultValue !== null && defaultValue !== "") {
1239
+ defaultValue.split(/#|;/).forEach(function (element) {
1240
+ if (element.indexOf("|") !== -1)
1241
+ selectedTags_1.push({
1242
+ key: element.split("|")[1],
1243
+ name: element.split("|")[0],
1244
+ });
1245
+ });
1246
+ value = selectedTags_1;
1247
+ stringValue = selectedTags_1 === null || selectedTags_1 === void 0 ? void 0 : selectedTags_1.map(function (dv) { return dv.key + ';#' + dv.name; }).join(';#');
1248
+ }
1249
+ }
1250
+ if (defaultValue === "")
1251
+ defaultValue = null;
1252
+ }
1253
+ if (!(field.FieldType === "DateTime")) return [3 /*break*/, 17];
1254
+ if (item !== null && item[field.InternalName]) {
1255
+ value = new Date(item[field.InternalName]);
1256
+ stringValue = value.toISOString();
1257
+ }
1258
+ else if (defaultValue === "[today]") {
1259
+ defaultValue = new Date();
1260
+ }
1261
+ else if (defaultValue) {
1262
+ defaultValue = new Date(defaultValue);
1263
+ }
1264
+ dateFormat = field.DateFormat || "DateOnly";
1265
+ return [4 /*yield*/, this_2._spService.getRegionalWebSettings()];
1266
+ case 16:
1267
+ defaultDayOfWeek = (_d.sent()).FirstDayOfWeek;
1268
+ _d.label = 17;
1269
+ case 17:
1270
+ // Setup Thumbnail, Location and Boolean fields
1271
+ if (field.FieldType === "Thumbnail") {
1272
+ if (defaultValue) {
1273
+ defaultValue = JSON.parse(defaultValue).serverRelativeUrl;
1274
+ }
1275
+ if (value) {
1276
+ value = JSON.parse(value).serverRelativeUrl;
1277
+ }
1278
+ }
1279
+ if (field.FieldType === "Location") {
1280
+ if (defaultValue)
1281
+ defaultValue = JSON.parse(defaultValue);
1282
+ if (value)
1283
+ value = JSON.parse(value);
1284
+ }
1285
+ if (field.FieldType === "Boolean") {
1286
+ if (defaultValue !== undefined && defaultValue !== null)
1287
+ defaultValue = Boolean(Number(defaultValue));
1288
+ if (value !== undefined && value !== null)
1289
+ value = Boolean(Number(value));
1290
+ }
1291
+ tempFields.push({
1292
+ value: value,
1293
+ newValue: undefined,
1294
+ stringValue: stringValue,
1295
+ subPropertyValues: subPropertyValues,
1296
+ cultureName: cultureName,
1297
+ fieldTermSetId: termSetId,
1298
+ fieldAnchorId: anchorId,
1299
+ options: choices_1,
1300
+ lookupListID: lookupListId,
1301
+ lookupField: lookupField,
1302
+ // changedValue: defaultValue,
1303
+ fieldType: field.FieldType,
1304
+ // fieldTitle: field.Title,
1305
+ defaultValue: defaultValue,
1306
+ context: this_2.props.context,
1307
+ disabled: this_2.props.disabled ||
1308
+ (disabledFields &&
1309
+ disabledFields.indexOf(field.InternalName) > -1),
1310
+ // listId: this.props.listId,
1311
+ columnInternalName: field.InternalName,
1312
+ label: field.Title,
1313
+ onChanged: this_2.onChange,
1314
+ required: field.Required,
1315
+ hiddenFieldName: hiddenName,
1316
+ Order: order,
1317
+ isRichText: richText,
1318
+ dateFormat: dateFormat,
1319
+ firstDayOfWeek: defaultDayOfWeek,
1320
+ listItemId: listItemId,
1321
+ principalType: principalType,
1322
+ description: field.Description,
1323
+ minimumValue: minValue,
1324
+ maximumValue: maxValue,
1325
+ showAsPercentage: showAsPercentage,
1326
+ });
1327
+ // This may not be necessary now using RenderListDataAsStream
1328
+ tempFields.sort(function (a, b) { return a.Order - b.Order; });
1329
+ _d.label = 18;
1330
+ case 18: return [2 /*return*/];
1331
+ }
1332
+ });
1333
+ };
1334
+ this_2 = this;
1335
+ i = 0, len = listInfo.ClientForms.Edit[contentTypeName].length;
1336
+ _a.label = 1;
1337
+ case 1:
1338
+ if (!(i < len)) return [3 /*break*/, 4];
1339
+ return [5 /*yield**/, _loop_3(i, len)];
1340
+ case 2:
1341
+ _a.sent();
1342
+ _a.label = 3;
1343
+ case 3:
1344
+ i++;
1345
+ return [3 /*break*/, 1];
1346
+ case 4: return [2 /*return*/, tempFields];
1347
+ }
1348
+ });
1349
+ });
1350
+ };
1055
1351
  DynamicForm.prototype.cultureNameLookup = function (lcid) {
1056
1352
  var _a, _b;
1057
1353
  var pageCulture = this.props.context.pageContext.cultureInfo.currentCultureName;
@@ -1059,10 +1355,6 @@ var DynamicForm = /** @class */ (function (_super) {
1059
1355
  return pageCulture;
1060
1356
  return (_b = (_a = this.state.installedLanguages) === null || _a === void 0 ? void 0 : _a.find(function (lang) { return lang.Lcid === lcid; }).DisplayName) !== null && _b !== void 0 ? _b : pageCulture;
1061
1357
  };
1062
- DynamicForm.prototype.isEmptyNumOrString = function (value) {
1063
- if (((value === null || value === void 0 ? void 0 : value.toString().trim().length) || 0) === 0)
1064
- return true;
1065
- };
1066
1358
  return DynamicForm;
1067
1359
  }(React.Component));
1068
1360
  export { DynamicForm };