UNPKG

8.27 kBJavaScriptView Raw
1import { addProp, body, TextParse } from "@pnp/queryable";
2import { _List, List } from "../lists/types.js";
3import { Folder } from "../folders/types.js";
4import { combine, isArray } from "@pnp/core";
5import { escapeQueryStrValue } from "../utils/escape-query-str.js";
6import { spPost } from "../operations.js";
7import { SPCollection } from "../presets/all.js";
8addProp(_List, "rootFolder", Folder);
9_List.prototype.getDefaultColumnValues = async function () {
10 const pathPart = await this.rootFolder.select("ServerRelativePath")();
11 const webUrl = await this.select("ParentWeb/Url").expand("ParentWeb")();
12 const path = combine("/", pathPart.ServerRelativePath.DecodedUrl, "Forms/client_LocationBasedDefaults.html");
13 const baseFilePath = combine(webUrl.ParentWeb.Url, `_api/web/getFileByServerRelativePath(decodedUrl='${escapeQueryStrValue(path)}')`);
14 let xml = "";
15 try {
16 // we are reading the contents of the file
17 xml = await Folder([this, baseFilePath], "$value").using(TextParse())();
18 }
19 catch (e) {
20 // if this call fails we assume it is because the file is 404
21 if (e && e.status && e.status === 404) {
22 // return an empty array
23 return [];
24 }
25 throw e;
26 }
27 // get all the tags from the xml
28 const matches = xml.match(/<a.*?<\/a>/ig);
29 const tags = matches === null ? [] : matches.map(t => t.trim());
30 // now we need to turn these tags of form into objects
31 // <a href="/sites/dev/My%20Title"><DefaultValue FieldName="TextField">Test</DefaultValue></a>
32 return tags.reduce((defVals, t) => {
33 const m = /<a href="(.*?)">/ig.exec(t);
34 // if things worked out captures are:
35 // 0: whole string
36 // 1: ENCODED server relative path
37 if (m.length < 1) {
38 // this indicates an error somewhere, but we have no way to meaningfully recover
39 // perhaps the way the tags are stored has changed on the server? Check that first.
40 this.log(`Could not parse default column value from '${t}'`, 2);
41 return null;
42 }
43 // return the parsed out values
44 const subMatches = t.match(/<DefaultValue.*?<\/DefaultValue>/ig);
45 const subTags = subMatches === null ? [] : subMatches.map(st => st.trim());
46 subTags.map(st => {
47 const sm = /<DefaultValue FieldName="(.*?)">(.*?)<\/DefaultValue>/ig.exec(st);
48 // if things worked out captures are:
49 // 0: whole string
50 // 1: Field internal name
51 // 2: Default value as string
52 if (sm.length < 1) {
53 this.log(`Could not parse default column value from '${st}'`, 2);
54 }
55 else {
56 defVals.push({
57 name: sm[1],
58 path: decodeURIComponent(m[1]),
59 value: sm[2],
60 });
61 }
62 });
63 return defVals;
64 }, []).filter(v => v !== null);
65};
66_List.prototype.setDefaultColumnValues = async function (defaults) {
67 // we need the field types from the list to map the values
68 // eslint-disable-next-line max-len
69 const fieldDefs = await SPCollection(this, "fields").select("InternalName", "TypeAsString").filter("Hidden ne true")();
70 // group field defaults by path
71 const defaultsByPath = {};
72 for (let i = 0; i < defaults.length; i++) {
73 if (defaultsByPath[defaults[i].path] == null) {
74 defaultsByPath[defaults[i].path] = [defaults[i]];
75 }
76 else {
77 defaultsByPath[defaults[i].path].push(defaults[i]);
78 }
79 }
80 const paths = Object.getOwnPropertyNames(defaultsByPath);
81 const pathDefaults = [];
82 // For each path, group field defaults
83 for (let j = 0; j < paths.length; j++) {
84 // map the values into the right format and produce our xml elements
85 const pathFields = defaultsByPath[paths[j]];
86 const tags = pathFields.map(fieldDefault => {
87 const index = fieldDefs.findIndex(fd => fd.InternalName === fieldDefault.name);
88 if (index < 0) {
89 throw Error(`Field '${fieldDefault.name}' does not exist in the list. Please check the internal field name. Failed to set defaults.`);
90 }
91 const fieldDef = fieldDefs[index];
92 let value = "";
93 switch (fieldDef.TypeAsString) {
94 case "Boolean":
95 case "Currency":
96 case "Text":
97 case "DateTime":
98 case "Number":
99 case "Choice":
100 case "User":
101 if (isArray(fieldDefault.value)) {
102 throw Error(`The type '${fieldDef.TypeAsString}' does not support multiple values.`);
103 }
104 value = `${fieldDefault.value}`;
105 break;
106 case "MultiChoice":
107 if (isArray(fieldDefault.value)) {
108 value = fieldDefault.value.map(v => `${v}`).join(";");
109 }
110 else {
111 value = `${fieldDefault.value}`;
112 }
113 break;
114 case "UserMulti":
115 if (isArray(fieldDefault.value)) {
116 value = fieldDefault.value.map(v => `${v}`).join(";#");
117 }
118 else {
119 value = `${fieldDefault.value}`;
120 }
121 break;
122 case "Taxonomy":
123 case "TaxonomyFieldType":
124 if (isArray(fieldDefault.value)) {
125 throw Error(`The type '${fieldDef.TypeAsString}' does not support multiple values.`);
126 }
127 else {
128 value = `${fieldDefault.value.wssId};#${fieldDefault.value.termName}|${fieldDefault.value.termId}`;
129 }
130 break;
131 case "TaxonomyMulti":
132 case "TaxonomyFieldTypeMulti":
133 if (isArray(fieldDefault.value)) {
134 value = fieldDefault.value.map(v => `${v.wssId};#${v.termName}|${v.termId}`).join(";#");
135 }
136 else {
137 value = [fieldDefault.value].map(v => `${v.wssId};#${v.termName}|${v.termId}`).join(";#");
138 }
139 break;
140 }
141 return `<DefaultValue FieldName="${fieldDefault.name}">${value}</DefaultValue>`;
142 });
143 const href = pathFields[0].path.replace(/ /gi, "%20");
144 const pathDefault = `<a href="${href}">${tags.join("")}</a>`;
145 pathDefaults.push(pathDefault);
146 }
147 // builds update to defaults
148 const xml = `<MetadataDefaults>${pathDefaults.join("")}</MetadataDefaults>`;
149 const pathPart = await this.rootFolder.select("ServerRelativePath")();
150 const webUrl = await this.select("ParentWeb/Url").expand("ParentWeb")();
151 const path = combine("/", pathPart.ServerRelativePath.DecodedUrl, "Forms");
152 const baseFilePath = combine(webUrl.ParentWeb.Url, "_api/web", `getFolderByServerRelativePath(decodedUrl='${escapeQueryStrValue(path)}')`, "files");
153 await spPost(Folder([this, baseFilePath], "add(overwrite=true,url='client_LocationBasedDefaults.html')"), { body: xml });
154 // finally we need to ensure this list has the right event receiver added
155 const existingReceivers = await this.eventReceivers.filter("ReceiverName eq 'LocationBasedMetadataDefaultsReceiver ItemAdded'").select("ReceiverId")();
156 if (existingReceivers.length < 1) {
157 await spPost(List(this.eventReceivers, "add"), body({
158 eventReceiverCreationInformation: {
159 EventType: 10001,
160 ReceiverAssembly: "Microsoft.Office.DocumentManagement, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c",
161 ReceiverClass: "Microsoft.Office.DocumentManagement.LocationBasedMetadataDefaultsReceiver",
162 ReceiverName: "LocationBasedMetadataDefaultsReceiver ItemAdded",
163 SequenceNumber: 1000,
164 Synchronization: 1,
165 },
166 }));
167 }
168};
169//# sourceMappingURL=list.js.map
\No newline at end of file