@pnp/spfx-controls-react
Version:
Reusable React controls for SharePoint Framework solutions
815 lines • 109 kB
JavaScript
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
/* eslint-disable @microsoft/spfx/no-async-await */
import * as React from "react";
import * as strings from "ControlStrings";
// Controls
import { DefaultButton, PrimaryButton, } from "@fluentui/react/lib/Button";
import { Dialog, DialogFooter, DialogType, } from "@fluentui/react/lib/Dialog";
import { MessageBar, MessageBarType } from "@fluentui/react/lib/MessageBar";
import { ProgressIndicator } from "@fluentui/react/lib/ProgressIndicator";
import { Stack } from "@fluentui/react/lib/Stack";
import { DynamicField } from "./dynamicField";
import { FilePicker } from "../filePicker";
import { Guid } from '@microsoft/sp-core-library';
// pnp/sp, helpers / utils
import { sp } from "@pnp/sp";
import "@pnp/sp/lists";
import "@pnp/sp/content-types";
import "@pnp/sp/folders";
import "@pnp/sp/items";
import { ChoiceFieldFormatType } from "@pnp/sp/presets/all";
import { cloneDeep, isEqual } from "lodash";
import SPservice from "../../services/SPService";
import { FormulaEvaluation } from "../../common/utilities/FormulaEvaluation";
import CustomFormattingHelper from "../../common/utilities/CustomFormatting";
import { SPTaxonomyService } from '../../services/SPTaxonomyService';
import { getStyles } from "./DynamicForm.styles";
import { getFluentUIThemeOrDefault } from "../../common/utilities/ThemeUtility";
import { classNamesFunction, styled } from "@fluentui/react";
import { Icon } from "@fluentui/react/lib/Icon";
var stackTokens = { childrenGap: 20 };
var getstyles = classNamesFunction();
var getFieldstyles = classNamesFunction();
var theme = getFluentUIThemeOrDefault();
var timeout = function (ms) {
return new Promise(function (resolve) { return setTimeout(resolve, ms); });
};
/**
* DynamicForm Class Control
*/
var DynamicFormBase = /** @class */ (function (_super) {
__extends(DynamicFormBase, _super);
function DynamicFormBase(props) {
var _this = _super.call(this, props) || this;
_this.webURL = _this.props.webAbsoluteUrl
? _this.props.webAbsoluteUrl
: _this.props.context.pageContext.web.absoluteUrl;
_this.sortFields = function (fields, customSort) {
var fMap = new Map();
for (var _i = 0, fields_1 = fields; _i < fields_1.length; _i++) {
var field = fields_1[_i];
fMap.set(field.columnInternalName.toLowerCase(), field);
}
var sortedFields = customSort
.map(function (sortColumn) { return sortColumn.toLowerCase(); })
.filter(function (normalizedSortColumn) { return fMap.has(normalizedSortColumn); })
.map(function (normalizedSortColumn) { return fMap.get(normalizedSortColumn); })
.filter(function (field) { return field !== undefined; });
var remainingFields = fields.filter(function (field) { return !sortedFields.includes(field); });
var uniqueRemainingFields = Array.from(new Set(remainingFields));
return __spreadArray(__spreadArray([], sortedFields, true), uniqueRemainingFields, true);
};
_this.renderField = function (field) {
var fieldOverrides = _this.props.fieldOverrides;
var _a = _this.state, hiddenByFormula = _a.hiddenByFormula, isSaving = _a.isSaving, validationErrors = _a.validationErrors;
var styles = getFieldstyles(_this._classNames.subComponentStyles.fieldStyles(), { theme: theme });
// If the field is hidden by a formula or field doesn't exist (usually occurs in custom formatting section layout when field display name changed), don't render it
if (!field || hiddenByFormula.find(function (h) { return h === field.columnInternalName; })) {
return null;
}
// If validation error, show error message
var validationErrorMessage = "";
if (validationErrors[field.columnInternalName]) {
validationErrorMessage = validationErrors[field.columnInternalName];
}
// If field override is provided, use it instead of the DynamicField component
if (fieldOverrides &&
Object.prototype.hasOwnProperty.call(fieldOverrides, field.columnInternalName)) {
return fieldOverrides[field.columnInternalName](__assign(__assign({}, field), { disabled: field.disabled || isSaving }));
}
// Default render
return (React.createElement(DynamicField, __assign({ key: field.columnInternalName, styles: styles }, field, { disabled: field.disabled || isSaving, validationErrorMessage: validationErrorMessage })));
};
/** Triggered when the user submits the form. */
_this.onSubmitClick = function () { return __awaiter(_this, void 0, void 0, function () {
var _a, listId, listItemId, onSubmitted, onBeforeSubmit, onSubmitError, enableFileSelection, validationErrorDialogProps, returnListItemInstanceOnSubmit, useModernTaxonomyPicker, 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, contentTypeIdField, library, folderFileName, folder, _b, newFolder, fields_2, folderId, iur, error_3, error_4;
var _c, _d, _e, _f, _g, _h, _j, _k, _l;
return __generator(this, function (_m) {
switch (_m.label) {
case 0:
_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, useModernTaxonomyPicker = _a.useModernTaxonomyPicker;
contentTypeId = this.props.contentTypeId;
if (this.state.contentTypeId !== undefined)
contentTypeId = this.state.contentTypeId;
fileSelectRendered = !listItemId && contentTypeId.startsWith("0x0101") && enableFileSelection === true;
_m.label = 1;
case 1:
_m.trys.push([1, 33, , 34]);
shouldBeReturnBack_1 = false;
fields = (this.state.fieldCollection || []).slice();
fields.forEach(function (field) {
// When a field is required and has no value
if (field.required) {
if ((field.newValue === undefined || field.newValue.length === 0) && (field.value === undefined || field.value.length === 0)) {
if (field.defaultValue === null ||
field.defaultValue === "" ||
field.defaultValue.length === 0 ||
field.defaultValue === undefined) {
if (field.fieldType === "DateTime")
field.defaultValue = null;
else
field.defaultValue = "";
shouldBeReturnBack_1 = true;
}
}
else if (field.newValue === "") {
field.defaultValue = "";
shouldBeReturnBack_1 = true;
}
else if (Array.isArray(field.newValue) && field.newValue.length === 0) {
field.defaultValue = null;
shouldBeReturnBack_1 = true;
}
}
// Check min and max values for number fields
if (field.fieldType === "Number" && field.newValue !== undefined && field.newValue.trim() !== "") {
if ((field.newValue < field.minimumValue) || (field.newValue > field.maximumValue)) {
shouldBeReturnBack_1 = true;
}
}
});
validationDisabled = this.props.useFieldValidation === false;
validationErrors = {};
if (!!validationDisabled) return [3 /*break*/, 3];
return [4 /*yield*/, this.evaluateFormulas(this.state.validationFormulas, true, true, this.state.hiddenByFormula)];
case 2:
validationErrors = (_m.sent());
if (Object.keys(validationErrors).length > 0) {
shouldBeReturnBack_1 = true;
}
_m.label = 3;
case 3:
// If validation failed, return without saving
if (shouldBeReturnBack_1) {
this.setState({
fieldCollection: fields,
isValidationErrorDialogOpen: (validationErrorDialogProps === null || validationErrorDialogProps === void 0 ? void 0 : validationErrorDialogProps.showDialogOnValidationError) === true,
});
return [2 /*return*/];
}
if (fileSelectRendered === true && this.state.selectedFile === undefined && this.props.listItemId === undefined) {
this.setState({
missingSelectedFile: true,
isValidationErrorDialogOpen: (validationErrorDialogProps === null || validationErrorDialogProps === void 0 ? void 0 : validationErrorDialogProps.showDialogOnValidationError) === true,
validationErrors: validationErrors
});
return [2 /*return*/];
}
this.setState({
isSaving: true,
});
objects = {};
_loop_1 = function (i, len) {
var field, fieldType, additionalData, columnInternalName, hiddenFieldName, fieldcolumnInternalName, value_1, uploadedImage;
return __generator(this, function (_o) {
switch (_o.label) {
case 0:
field = fields[i];
fieldType = field.fieldType, additionalData = field.additionalData, columnInternalName = field.columnInternalName, hiddenFieldName = field.hiddenFieldName;
fieldcolumnInternalName = columnInternalName;
if (fieldcolumnInternalName.startsWith('_x') || fieldcolumnInternalName.startsWith('_')) {
fieldcolumnInternalName = "OData_".concat(fieldcolumnInternalName);
}
if (!(field.newValue !== undefined)) return [3 /*break*/, 3];
value_1 = field.newValue;
if (["Lookup", "LookupMulti", "User", "UserMulti", "TaxonomyFieldTypeMulti"].indexOf(fieldType) < 0) {
objects[columnInternalName] = value_1;
}
// Choice fields
if (fieldType === "Choice") {
objects[fieldcolumnInternalName] = field.newValue.key;
}
if (fieldType === "MultiChoice") {
objects[fieldcolumnInternalName] = { results: field.newValue };
}
// Lookup fields
if (fieldType === "Lookup") {
if (value_1 && value_1.length > 0) {
objects["".concat(fieldcolumnInternalName, "Id")] = value_1[0].key;
}
else {
objects["".concat(fieldcolumnInternalName, "Id")] = null;
}
}
if (fieldType === "LookupMulti") {
value_1 = [];
field.newValue.forEach(function (element) {
value_1.push(element.key);
});
objects["".concat(fieldcolumnInternalName, "Id")] = {
results: value_1.length === 0 ? [] : value_1,
};
}
// User fields
if (fieldType === "User") {
objects["".concat(fieldcolumnInternalName, "Id")] = field.newValue.length === 0 ? null : field.newValue;
}
if (fieldType === "UserMulti") {
objects["".concat(fieldcolumnInternalName, "Id")] = {
results: field.newValue.length === 0 ? null : field.newValue,
};
}
// Taxonomy / Managed Metadata fields
if (useModernTaxonomyPicker) {
//Use ITermInfo[] for modern taxonomy picker
if (fieldType === "TaxonomyFieldType") {
objects[fieldcolumnInternalName] = {
__metadata: { type: "SP.Taxonomy.TaxonomyFieldValue" },
Label: (_e = (_d = (_c = value_1[0]) === null || _c === void 0 ? void 0 : _c.labels[0]) === null || _d === void 0 ? void 0 : _d.name) !== null && _e !== void 0 ? _e : "",
TermGuid: (_g = (_f = value_1[0]) === null || _f === void 0 ? void 0 : _f.id) !== null && _g !== void 0 ? _g : "11111111-1111-1111-1111-111111111111",
WssId: "-1",
};
}
if (fieldType === "TaxonomyFieldTypeMulti") {
objects[hiddenFieldName] = field.newValue
.map(function (term) { var _a; return "-1#;".concat(((_a = term.labels[0]) === null || _a === void 0 ? void 0 : _a.name) || "", "|").concat(term.id, ";"); })
.join("#");
}
}
else {
//Use IPickerTerms
if (fieldType === "TaxonomyFieldType") {
objects[fieldcolumnInternalName] = {
__metadata: { type: "SP.Taxonomy.TaxonomyFieldValue" },
Label: (_j = (_h = value_1[0]) === null || _h === void 0 ? void 0 : _h.name) !== null && _j !== void 0 ? _j : "",
TermGuid: (_l = (_k = value_1[0]) === null || _k === void 0 ? void 0 : _k.key) !== null && _l !== void 0 ? _l : "11111111-1111-1111-1111-111111111111",
WssId: "-1",
};
}
if (fieldType === "TaxonomyFieldTypeMulti") {
objects[hiddenFieldName] = field.newValue
.map(function (term) { return "-1#;".concat(term.name, "|").concat(term.key, ";"); })
.join("#");
}
}
// Other fields
if (fieldType === "Location") {
objects[fieldcolumnInternalName] = JSON.stringify(field.newValue);
}
if (!(fieldType === "Thumbnail")) return [3 /*break*/, 3];
if (!additionalData) return [3 /*break*/, 2];
return [4 /*yield*/, this_1.uploadImage(additionalData)];
case 1:
uploadedImage = _o.sent();
objects[fieldcolumnInternalName] = JSON.stringify({
type: "thumbnail",
fileName: uploadedImage.Name,
serverRelativeUrl: uploadedImage.ServerRelativeUrl,
id: uploadedImage.UniqueId,
});
return [3 /*break*/, 3];
case 2:
objects[fieldcolumnInternalName] = null;
_o.label = 3;
case 3: return [2 /*return*/];
}
});
};
this_1 = this;
i = 0, len = fields.length;
_m.label = 4;
case 4:
if (!(i < len)) return [3 /*break*/, 7];
return [5 /*yield**/, _loop_1(i, len)];
case 5:
_m.sent();
_m.label = 6;
case 6:
i++;
return [3 /*break*/, 4];
case 7:
if (!onBeforeSubmit) return [3 /*break*/, 9];
return [4 /*yield*/, onBeforeSubmit(objects)];
case 8:
isCancelled = _m.sent();
if (isCancelled) {
this.setState({
isSaving: false,
});
return [2 /*return*/];
}
_m.label = 9;
case 9:
apiError = void 0;
newETag = undefined;
if (!listItemId) return [3 /*break*/, 14];
_m.label = 10;
case 10:
_m.trys.push([10, 12, , 13]);
return [4 /*yield*/, sp.web.lists
.getById(listId)
.items.getById(listItemId)
.update(objects, this.state.etag)];
case 11:
iur = _m.sent();
newETag = iur.data["odata.etag"];
if (onSubmitted) {
onSubmitted(iur.data, returnListItemInstanceOnSubmit !== false
? iur.item
: undefined);
}
return [3 /*break*/, 13];
case 12:
error_1 = _m.sent();
apiError = error_1.message;
if (onSubmitError) {
onSubmitError(objects, error_1);
}
console.log("Error", error_1);
return [3 /*break*/, 13];
case 13: return [3 /*break*/, 32];
case 14:
if (!(contentTypeId === undefined ||
contentTypeId === "" ||
(!contentTypeId.startsWith("0x0120") &&
contentTypeId.startsWith("0x01")))) return [3 /*break*/, 20];
if (!(fileSelectRendered === true)) return [3 /*break*/, 16];
return [4 /*yield*/, this.addFileToLibrary(objects)];
case 15:
_m.sent();
return [3 /*break*/, 19];
case 16:
_m.trys.push([16, 18, , 19]);
contentTypeIdField = "ContentTypeId";
// check if item contenttype is passed, then update the object with content type id, else, pass the object
if (contentTypeId !== undefined && contentTypeId.startsWith("0x01"))
objects[contentTypeIdField] = contentTypeId;
return [4 /*yield*/, sp.web.lists.getById(listId).items.add(objects)];
case 17:
iar = _m.sent();
if (onSubmitted) {
onSubmitted(iar.data, this.props.returnListItemInstanceOnSubmit !== false
? iar.item
: undefined);
}
return [3 /*break*/, 19];
case 18:
error_2 = _m.sent();
apiError = error_2.message;
if (onSubmitError) {
onSubmitError(objects, error_2);
}
console.log("Error", error_2);
return [3 /*break*/, 19];
case 19: return [3 /*break*/, 32];
case 20:
if (!contentTypeId.startsWith("0x0120")) return [3 /*break*/, 32];
_m.label = 21;
case 21:
_m.trys.push([21, 31, , 32]);
idField = "ID";
contentTypeIdField = "ContentTypeId";
return [4 /*yield*/, sp.web.lists.getById(listId)];
case 22:
library = _m.sent();
folderFileName = this.getFolderName(objects);
if (!!this.props.folderPath) return [3 /*break*/, 23];
_b = library.rootFolder;
return [3 /*break*/, 25];
case 23: return [4 /*yield*/, this.getFolderByPath(this.props.folderPath, library.rootFolder)];
case 24:
_b = _m.sent();
_m.label = 25;
case 25:
folder = _b;
return [4 /*yield*/, folder.addSubFolderUsingPath(folderFileName)];
case 26:
newFolder = _m.sent();
return [4 /*yield*/, newFolder.listItemAllFields()];
case 27:
fields_2 = _m.sent();
if (!fields_2[idField]) return [3 /*break*/, 29];
folderId = fields_2[idField];
// Set the content type ID for the target item
objects[contentTypeIdField] = contentTypeId;
return [4 /*yield*/, this.updateListItemRetry(library, folderId, objects)];
case 28:
iur = _m.sent();
if (onSubmitted) {
onSubmitted(iur.data, this.props.returnListItemInstanceOnSubmit !== false
? iur.item
: undefined);
}
return [3 /*break*/, 30];
case 29: throw new Error("Unable to read the ID of the just created folder or Document Set");
case 30: return [3 /*break*/, 32];
case 31:
error_3 = _m.sent();
apiError = error_3.message;
if (onSubmitError) {
onSubmitError(objects, error_3);
}
console.log("Error", error_3);
return [3 /*break*/, 32];
case 32:
this.setState({
isSaving: false,
etag: newETag,
infoErrorMessages: apiError ? [{ type: MessageBarType.error, message: apiError }] : [],
});
return [3 /*break*/, 34];
case 33:
error_4 = _m.sent();
if (onSubmitError) {
onSubmitError(null, error_4);
}
console.log("Error onSubmit", error_4);
return [3 /*break*/, 34];
case 34: return [2 /*return*/];
}
});
}); };
/**
* Adds selected file to the library
*/
_this.addFileToLibrary = function (objects) { return __awaiter(_this, void 0, void 0, function () {
var selectedFile, _a, listId, contentTypeId, onSubmitted, onSubmitError, returnListItemInstanceOnSubmit, idField, contentTypeIdField, library, itemTitle, folder, _b, fileCreatedResult, _c, _d, _e, fields, fileId, iur, error_5;
return __generator(this, function (_f) {
switch (_f.label) {
case 0:
selectedFile = this.state.selectedFile;
_a = this.props, listId = _a.listId, contentTypeId = _a.contentTypeId, onSubmitted = _a.onSubmitted, onSubmitError = _a.onSubmitError, returnListItemInstanceOnSubmit = _a.returnListItemInstanceOnSubmit;
if (!(selectedFile !== undefined)) return [3 /*break*/, 13];
_f.label = 1;
case 1:
_f.trys.push([1, 12, , 13]);
idField = "ID";
contentTypeIdField = "ContentTypeId";
return [4 /*yield*/, sp.web.lists.getById(listId)];
case 2:
library = _f.sent();
itemTitle = selectedFile !== undefined && selectedFile.fileName !== undefined && selectedFile.fileName !== ""
? selectedFile.fileName.replace(/["|*|:|<|>|?|/|\\||]/g, "_").trim() // Replace not allowed chars in folder name and trim empty spaces at the start or end.
: "";
if (!!this.props.folderPath) return [3 /*break*/, 3];
_b = library.rootFolder;
return [3 /*break*/, 5];
case 3: return [4 /*yield*/, this.getFolderByPath(this.props.folderPath, library.rootFolder)];
case 4:
_b = _f.sent();
_f.label = 5;
case 5:
folder = _b;
_d = (_c = folder.files).addChunked;
_e = [encodeURI(itemTitle)];
return [4 /*yield*/, selectedFile.downloadFileContent()];
case 6: return [4 /*yield*/, _d.apply(_c, _e.concat([_f.sent()]))];
case 7:
fileCreatedResult = _f.sent();
return [4 /*yield*/, fileCreatedResult.file.listItemAllFields()];
case 8:
fields = _f.sent();
if (!fields[idField]) return [3 /*break*/, 10];
fileId = fields[idField];
// Set the content type ID for the target item
objects[contentTypeIdField] = contentTypeId;
return [4 /*yield*/, this.updateListItemRetry(library, fileId, objects)];
case 9:
iur = _f.sent();
if (onSubmitted) {
onSubmitted(iur.data, returnListItemInstanceOnSubmit !== false
? iur.item
: undefined);
}
return [3 /*break*/, 11];
case 10: throw new Error("Unable to read the ID of the just created file");
case 11: return [3 /*break*/, 13];
case 12:
error_5 = _f.sent();
if (onSubmitError) {
onSubmitError(objects, error_5);
}
console.log("Error", error_5);
return [3 /*break*/, 13];
case 13: return [2 /*return*/];
}
});
}); };
/**
* Triggered when the user makes any field value change in the form
*/
_this.onChange = function (internalName,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
newValue, validate, additionalData) { return __awaiter(_this, void 0, void 0, function () {
var fieldCol, field, useModernTaxonomyPicker, user, result, emails, index, element, user, result, validationErrors;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
fieldCol = cloneDeep(this.state.fieldCollection || []);
field = fieldCol.filter(function (element, i) {
return element.columnInternalName === internalName;
})[0];
useModernTaxonomyPicker = this.props.useModernTaxonomyPicker;
// Init new value(s)
field.newValue = newValue;
field.stringValue = newValue ? newValue.toString() : '';
field.additionalData = additionalData;
field.subPropertyValues = {};
// Store string values for various field types
if (field.fieldType === "Choice") {
field.stringValue = newValue.text;
}
if (field.fieldType === "MultiChoice") {
field.stringValue = newValue.join(';#');
}
if (field.fieldType === "Lookup" || field.fieldType === "LookupMulti") {
field.stringValue = newValue.map(function (nv) { return nv.key + ';#' + nv.name; }).join(';#');
}
if (useModernTaxonomyPicker) {
if (field.fieldType === "TaxonomyFieldType" || field.fieldType === "TaxonomyFieldTypeMulti") {
if (Array.isArray(newValue) && newValue.length > 0) {
field.stringValue = newValue.map(function (nv) { return nv.labels.map(function (label) { return label.name; }).join(';'); }).join(';');
}
else {
field.stringValue = "";
}
}
}
else {
if (field.fieldType === "TaxonomyFieldType" || field.fieldType === "TaxonomyFieldTypeMulti") {
field.stringValue = newValue.map(function (nv) { return nv.name; }).join(';');
}
}
if (!(field.fieldType === "User" && newValue.length !== 0)) return [3 /*break*/, 3];
if (!(newValue[0].id === undefined ||
parseInt(newValue[0].id, 10).toString() === "NaN")) return [3 /*break*/, 2];
user = newValue[0].secondaryText;
if (user.indexOf("@") === -1) {
user = newValue[0].loginName;
}
return [4 /*yield*/, sp.web.ensureUser(user)];
case 1:
result = _a.sent();
field.newValue = result.data.Id; // eslint-disable-line require-atomic-updates
field.stringValue = user;
field.subPropertyValues = {
id: result.data.Id,
title: result.data.Title,
email: result.data.Email,
};
return [3 /*break*/, 3];
case 2:
field.newValue = newValue[0].id;
_a.label = 3;
case 3:
if (!(field.fieldType === "UserMulti" && newValue.length !== 0)) return [3 /*break*/, 9];
field.newValue = [];
emails = [];
index = 0;
_a.label = 4;
case 4:
if (!(index < newValue.length)) return [3 /*break*/, 8];
element = newValue[index];
if (!(element.id === undefined ||
parseInt(element.id, 10).toString() === "NaN")) return [3 /*break*/, 6];
user = element.secondaryText;
if (user.indexOf("@") === -1) {
user = element.loginName;
}
return [4 /*yield*/, sp.web.ensureUser(user)];
case 5:
result = _a.sent();
field.newValue.push(result.data.Id);
emails.push(user);
return [3 /*break*/, 7];
case 6:
field.newValue.push(element.id);
_a.label = 7;
case 7:
index++;
return [3 /*break*/, 4];
case 8:
field.stringValue = emails.join(";");
_a.label = 9;
case 9:
validationErrors = __assign({}, this.state.validationErrors);
if (validationErrors[field.columnInternalName])
delete validationErrors[field.columnInternalName];
this.setState({
fieldCollection: fieldCol,
validationErrors: validationErrors
}, function () {
if (validate)
_this.performValidation();
});
return [2 /*return*/];
}
});
}); };
/** Validation callback, used when form first loads (getListInformation) and following onChange */
_this.performValidation = function (skipFieldValueValidation) {
var _a = _this.props, useClientSideValidation = _a.useClientSideValidation, useFieldValidation = _a.useFieldValidation;
var _b = _this.state, clientValidationFormulas = _b.clientValidationFormulas, validationFormulas = _b.validationFormulas;
if (Object.keys(clientValidationFormulas).length || Object.keys(validationFormulas).length) {
_this.setState({
isSaving: true, // Disable save btn and fields while validation in progress
}, function () {
var clientSideValidationDisabled = useClientSideValidation === false;
var fieldValidationDisabled = useFieldValidation === false;
var hiddenByFormula = !clientSideValidationDisabled ? _this.evaluateColumnVisibilityFormulas() : [];
var validationErrors = __assign({}, _this.state.validationErrors);
if (!skipFieldValueValidation && !fieldValidationDisabled)
validationErrors = _this.evaluateFieldValueFormulas(hiddenByFormula);
_this.setState({ hiddenByFormula: hiddenByFormula, isSaving: false, validationErrors: validationErrors });
});
}
};
/** Determines visibility of fields that have show/hide formulas set in Edit Form > Edit Columns > Edit Conditional Formula */
_this.evaluateColumnVisibilityFormulas = function () {
return _this.evaluateFormulas(_this.state.clientValidationFormulas, false);
};
/** Evaluates field validation formulas set in column settings and returns a Record of error messages */
_this.evaluateFieldValueFormulas = function (hiddenFields) {
return _this.evaluateFormulas(_this.state.validationFormulas, true, true, hiddenFields);
};
/**
* Evaluates formulas and returns a Record of error messages or an array of column names that have failed validation
* @param formulas A Record / dictionary-like object, where key is internal column name and value is an object with ValidationFormula and ValidationMessage properties
* @param returnMessages Determines whether a Record of error messages is returned or an array of column names that have failed validation
* @param requireValue Set to true if the formula should only be evaluated when the field has a value
* @returns
*/
_this.evaluateFormulas = function (formulas, returnMessages, requireValue, ignoreFields) {
if (returnMessages === void 0) { returnMessages = true; }
if (requireValue === void 0) { requireValue = false; }
if (ignoreFields === void 0) { ignoreFields = []; }
var fieldCollection = _this.state.fieldCollection;
var results = {};
var _loop_2 = function (i) {
var fieldName = Object.keys(formulas)[i];
if (formulas[fieldName]) {
var field = fieldCollection.find(function (f) { return f.columnInternalName === fieldName; });
if (!field)
return "continue";
if (ignoreFields.indexOf(fieldName) > -1)
return "continue"; // Skip fields that are being ignored (e.g. hidden by formula)
var formula = formulas[fieldName].ValidationFormula;
var message = formulas[fieldName].ValidationMessage;
if (!formula)
return "continue";
var context = _this.getFormValuesForValidation();
if (requireValue && !context[fieldName])
return "continue";
var result = _this._formulaEvaluation.evaluate(formula, context);
if (Boolean(result) !== true) {
results[fieldName] = message;
}
}
};
for (var i = 0; i < Object.keys(formulas).length; i++) {
_loop_2(i);
}
if (!returnMessages) {
return Object.keys(results);
}
return results;
};
/**
* Used for validation. Returns a Record of field values, where key is internal column name and value is the field value.
* Expands certain properties and stores many of them as primitives (strings, numbers or bools) so the expression evaluator
* can process them. For example: a User column named Person will have values stored as Person, Person.email, Person.title etc.
* This is so the expression evaluator can process expressions like '=[$Person.title] == "Contoso Employee 1138"'
* @param fieldCollection Optional. Could be used to compare field values in state with previous state.
* @returns
*/
_this.getFormValuesForValidation = function (fieldCollection) {
var fieldColFromState = _this.state.fieldCollection;
if (!fieldCollection)
fieldCollection = fieldColFromState;
return fieldCollection.reduce(function (prev, cur) {
var value = cur.value;
switch (cur.fieldType) {
case "Lookup":
case "Choice":
case "TaxonomyFieldType":
case "LookupMulti":
case "MultiChoice":
case "TaxonomyFieldTypeMulti":
case "User":
case "UserMulti":
value = cur.stringValue;
break;
case "Currency":
case "Number":
if (cur.value !== undefined && cur.value !== null)
value = Number(cur.value);
if (cur.newValue !== undefined && cur.newValue !== null)
value = Number(cur.newValue);
break;
case "URL":
if (cur.value !== undefined && cur.value !== null)
value = cur.value.Url;
if (cur.newValue !== undefined && cur.newValue !== null)
value = cur.newValue.Url;
value = cur.newValue ? cur.newValue.Url : null;
break;
default:
value = cur.newValue || cur.value;
break;
}
prev[cur.columnInternalName] = value;
if (cur.subPropertyValues) {
Object.keys(cur.subPropertyValues).forEach(function (key) {
prev["".concat(cur.columnInternalName, ".").concat(key)] = cur.subPropertyValues[key];
});
}
return prev;
}, {});
};
/**
* Invoked when component first mounts, loads information about the SharePoint list, fields and list item
*/
_this.getListInformation = function () { return __awaiter(_this, void 0, void 0, function () {
var _a, listId, listItemId, disabledFields, respectETag, customIcons, onListItemLoaded, contentTypeId, listInfo, additionalInfo, numberFields, validationFormulas, contentTypeName, clientValidationFormulas, headerJSON, footerJSON, bodySections, customFormatInfo, spList, item, isEditingItem, etag, spListItem, tempFields, sortedFields, installedLanguages, error_6;
var _this = this;
var _b, _c;
return __generator(this, function (_d) {
switch (_d.label) {
case 0:
_a = this.props, listId = _a.listId, listItemId = _a.listItemId, disabledFields = _a.disabledFields, respectETag = _a.respectETag, customIcons = _a.customIcons, onListItemLoaded = _a.onListItemLoaded;
contentTypeId = this.props.contentTypeId;
_d.label = 1;
case 1:
_d.trys.push([1, 11, , 12]);
return [4 /*yield*/, this._spService.getListFormRenderInfo(listId, this.webURL)];
case 2:
listInfo = _d.sent();
return [4 /*yield*/, this._spService.getAdditionalListFormFieldInfo(listId, this.webURL)];
case 3:
additionalInfo = _d.sent();
numberFields = additionalInfo === null || additionalInfo === void 0 ? void 0 : additionalInfo.filter(function (f) { return f.TypeAsString === "Number" || f.TypeAsString === "Currency"; });
validationFormulas = additionalInfo.reduce(function (prev, cur) {
if (!prev[cur.InternalName] && cur.ValidationFormula) {
prev[cur.InternalName] = {
ValidationFormula: cur.Valida