@pnp/sp
Version:
pnp - provides a fluent api for working with SharePoint REST
169 lines • 8.27 kB
JavaScript
import { addProp, body, TextParse } from "@pnp/queryable";
import { _List, List } from "../lists/types.js";
import { Folder } from "../folders/types.js";
import { combine, isArray } from "@pnp/core";
import { escapeQueryStrValue } from "../utils/escape-query-str.js";
import { spPost } from "../operations.js";
import { SPCollection } from "../presets/all.js";
addProp(_List, "rootFolder", Folder);
_List.prototype.getDefaultColumnValues = async function () {
const pathPart = await this.rootFolder.select("ServerRelativePath")();
const webUrl = await this.select("ParentWeb/Url").expand("ParentWeb")();
const path = combine("/", pathPart.ServerRelativePath.DecodedUrl, "Forms/client_LocationBasedDefaults.html");
const baseFilePath = combine(webUrl.ParentWeb.Url, `_api/web/getFileByServerRelativePath(decodedUrl='${escapeQueryStrValue(path)}')`);
let xml = "";
try {
// we are reading the contents of the file
xml = await Folder([this, baseFilePath], "$value").using(TextParse())();
}
catch (e) {
// if this call fails we assume it is because the file is 404
if (e && e.status && e.status === 404) {
// return an empty array
return [];
}
throw e;
}
// get all the tags from the xml
const matches = xml.match(/<a.*?<\/a>/ig);
const tags = matches === null ? [] : matches.map(t => t.trim());
// now we need to turn these tags of form into objects
// <a href="/sites/dev/My%20Title"><DefaultValue FieldName="TextField">Test</DefaultValue></a>
return tags.reduce((defVals, t) => {
const m = /<a href="(.*?)">/ig.exec(t);
// if things worked out captures are:
// 0: whole string
// 1: ENCODED server relative path
if (m.length < 1) {
// this indicates an error somewhere, but we have no way to meaningfully recover
// perhaps the way the tags are stored has changed on the server? Check that first.
this.log(`Could not parse default column value from '${t}'`, 2);
return null;
}
// return the parsed out values
const subMatches = t.match(/<DefaultValue.*?<\/DefaultValue>/ig);
const subTags = subMatches === null ? [] : subMatches.map(st => st.trim());
subTags.map(st => {
const sm = /<DefaultValue FieldName="(.*?)">(.*?)<\/DefaultValue>/ig.exec(st);
// if things worked out captures are:
// 0: whole string
// 1: Field internal name
// 2: Default value as string
if (sm.length < 1) {
this.log(`Could not parse default column value from '${st}'`, 2);
}
else {
defVals.push({
name: sm[1],
path: decodeURIComponent(m[1]),
value: sm[2],
});
}
});
return defVals;
}, []).filter(v => v !== null);
};
_List.prototype.setDefaultColumnValues = async function (defaults) {
// we need the field types from the list to map the values
// eslint-disable-next-line max-len
const fieldDefs = await SPCollection(this, "fields").select("InternalName", "TypeAsString").filter("Hidden ne true")();
// group field defaults by path
const defaultsByPath = {};
for (let i = 0; i < defaults.length; i++) {
if (defaultsByPath[defaults[i].path] == null) {
defaultsByPath[defaults[i].path] = [defaults[i]];
}
else {
defaultsByPath[defaults[i].path].push(defaults[i]);
}
}
const paths = Object.getOwnPropertyNames(defaultsByPath);
const pathDefaults = [];
// For each path, group field defaults
for (let j = 0; j < paths.length; j++) {
// map the values into the right format and produce our xml elements
const pathFields = defaultsByPath[paths[j]];
const tags = pathFields.map(fieldDefault => {
const index = fieldDefs.findIndex(fd => fd.InternalName === fieldDefault.name);
if (index < 0) {
throw Error(`Field '${fieldDefault.name}' does not exist in the list. Please check the internal field name. Failed to set defaults.`);
}
const fieldDef = fieldDefs[index];
let value = "";
switch (fieldDef.TypeAsString) {
case "Boolean":
case "Currency":
case "Text":
case "DateTime":
case "Number":
case "Choice":
case "User":
if (isArray(fieldDefault.value)) {
throw Error(`The type '${fieldDef.TypeAsString}' does not support multiple values.`);
}
value = `${fieldDefault.value}`;
break;
case "MultiChoice":
if (isArray(fieldDefault.value)) {
value = fieldDefault.value.map(v => `${v}`).join(";");
}
else {
value = `${fieldDefault.value}`;
}
break;
case "UserMulti":
if (isArray(fieldDefault.value)) {
value = fieldDefault.value.map(v => `${v}`).join(";#");
}
else {
value = `${fieldDefault.value}`;
}
break;
case "Taxonomy":
case "TaxonomyFieldType":
if (isArray(fieldDefault.value)) {
throw Error(`The type '${fieldDef.TypeAsString}' does not support multiple values.`);
}
else {
value = `${fieldDefault.value.wssId};#${fieldDefault.value.termName}|${fieldDefault.value.termId}`;
}
break;
case "TaxonomyMulti":
case "TaxonomyFieldTypeMulti":
if (isArray(fieldDefault.value)) {
value = fieldDefault.value.map(v => `${v.wssId};#${v.termName}|${v.termId}`).join(";#");
}
else {
value = [fieldDefault.value].map(v => `${v.wssId};#${v.termName}|${v.termId}`).join(";#");
}
break;
}
return `<DefaultValue FieldName="${fieldDefault.name}">${value}</DefaultValue>`;
});
const href = pathFields[0].path.replace(/ /gi, "%20");
const pathDefault = `<a href="${href}">${tags.join("")}</a>`;
pathDefaults.push(pathDefault);
}
// builds update to defaults
const xml = `<MetadataDefaults>${pathDefaults.join("")}</MetadataDefaults>`;
const pathPart = await this.rootFolder.select("ServerRelativePath")();
const webUrl = await this.select("ParentWeb/Url").expand("ParentWeb")();
const path = combine("/", pathPart.ServerRelativePath.DecodedUrl, "Forms");
const baseFilePath = combine(webUrl.ParentWeb.Url, "_api/web", `getFolderByServerRelativePath(decodedUrl='${escapeQueryStrValue(path)}')`, "files");
await spPost(Folder([this, baseFilePath], "add(overwrite=true,url='client_LocationBasedDefaults.html')"), { body: xml });
// finally we need to ensure this list has the right event receiver added
const existingReceivers = await this.eventReceivers.filter("ReceiverName eq 'LocationBasedMetadataDefaultsReceiver ItemAdded'").select("ReceiverId")();
if (existingReceivers.length < 1) {
await spPost(List(this.eventReceivers, "add"), body({
eventReceiverCreationInformation: {
EventType: 10001,
ReceiverAssembly: "Microsoft.Office.DocumentManagement, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c",
ReceiverClass: "Microsoft.Office.DocumentManagement.LocationBasedMetadataDefaultsReceiver",
ReceiverName: "LocationBasedMetadataDefaultsReceiver ItemAdded",
SequenceNumber: 1000,
Synchronization: 1,
},
}));
}
};
//# sourceMappingURL=list.js.map