Skip to content

Commit bbb4b31

Browse files
author
Alex Terentiev
committed
wip
1 parent 378452f commit bbb4b31

File tree

1 file changed

+69
-6
lines changed

1 file changed

+69
-6
lines changed

src/services/SPService.ts

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,16 @@ import { urlCombine } from "../common/utilities";
66
import filter from 'lodash/filter';
77
import find from 'lodash/find';
88

9+
interface ICachedListItems {
10+
items: any[];
11+
expiration: number;
12+
}
13+
914
export default class SPService implements ISPService {
1015

1116
private _webAbsoluteUrl: string;
17+
private _cachedListItems: Map<string, ICachedListItems> = new Map<string, ICachedListItems>();
18+
1219

1320
constructor(private _context: BaseComponentContext, webAbsoluteUrl?: string) {
1421
this._webAbsoluteUrl = webAbsoluteUrl ? webAbsoluteUrl : this._context.pageContext.web.absoluteUrl;
@@ -146,13 +153,24 @@ export default class SPService implements ISPService {
146153
/**
147154
* Get List Items
148155
*/
149-
public async getListItems(filterText: string, listId: string, internalColumnName: string, field: ISPField | undefined, keyInternalColumnName?: string, webUrl?: string, filterString?: string, substringSearch: boolean = false, orderBy?: string): Promise<any[]> {
156+
public async getListItems(
157+
filterText: string,
158+
listId: string,
159+
internalColumnName: string,
160+
field: ISPField | undefined,
161+
keyInternalColumnName?: string,
162+
webUrl?: string,
163+
filterString?: string,
164+
substringSearch: boolean = false,
165+
orderBy?: string,
166+
cacheInterval: number = 1): Promise<any[]> {
150167
let returnItems: any[];
151168
const webAbsoluteUrl = !webUrl ? this._webAbsoluteUrl : webUrl;
152169
let apiUrl = '';
153170
let isPost = false;
171+
let processItems: ((items: any[]) => any[]) | undefined;
154172

155-
if (field && field.TypeAsString === 'Calculated') { // for calculated fields we need to use CAML query
173+
if (field && field.TypeAsString === 'Calculated' && this._isTextFieldType(field.ResultType)) { // for calculated fields we need to use CAML query
156174
let orderByStr = '';
157175

158176
if (orderBy) {
@@ -169,19 +187,40 @@ export default class SPService implements ISPService {
169187
apiUrl = `${webAbsoluteUrl}/_api/web/lists('${listId}')/GetItems(query=@v1)?$select=${keyInternalColumnName || 'Id'},${internalColumnName}&@v1=${JSON.stringify({ ViewXml: camlQuery })}`;
170188
isPost = true;
171189
}
172-
else {
190+
else if (this._isTextFieldType(field.TypeAsString)) {
173191
const filterStr = substringSearch ? // JJ - 20200613 - find by substring as an option
174192
`${filterText ? `substringof('${encodeURIComponent(filterText.replace("'", "''"))}',${internalColumnName})` : ''}${filterString ? (filterText ? ' and ' : '') + filterString : ''}`
175193
: `${filterText ? `startswith(${internalColumnName},'${encodeURIComponent(filterText.replace("'", "''"))}')` : ''}${filterString ? (filterText ? ' and ' : '') + filterString : ''}`; //string = filterList ? `and ${filterList}` : '';
176194
apiUrl = `${webAbsoluteUrl}/_api/web/lists('${listId}')/items?$select=${keyInternalColumnName || 'Id'},${internalColumnName}&$filter=${filterStr}&$orderby=${orderBy}`;
177195
}
196+
else { // we need to get FieldValuesAsText and cache them
197+
const mapKey = `${webAbsoluteUrl}##${listId}##${internalColumnName}##${keyInternalColumnName || 'Id'}`;
198+
const cachedItems = this._cachedListItems.get(mapKey);
199+
200+
if (cachedItems && cachedItems.expiration < Date.now()) {
201+
return this._filterListItemsFieldValuesAsText(cachedItems.items, internalColumnName, filterText, substringSearch);
202+
}
203+
204+
apiUrl = `${webAbsoluteUrl}/_api/web/lists('${listId}')/GetItems?$select=${keyInternalColumnName || 'Id'},FieldValuesAsText/${internalColumnName}&$expand=FieldValuesAsText&$orderby=${orderBy}${filterString ? '&$filter=' + filterString : ''}`;
205+
isPost = true;
206+
207+
processItems = (items: any[]) => {
208+
209+
this._cachedListItems.set(mapKey, {
210+
items,
211+
expiration: Date.now() + cacheInterval * 60 * 1000
212+
});
213+
214+
return this._filterListItemsFieldValuesAsText(items, internalColumnName, filterText, substringSearch);
215+
};
216+
}
178217

179218
try {
180219
const data = isPost ? await this._context.spHttpClient.post(apiUrl, SPHttpClient.configurations.v1, {}) : await this._context.spHttpClient.get(apiUrl, SPHttpClient.configurations.v1);
181220
if (data.ok) {
182221
const results = await data.json();
183222
if (results && results.value && results.value.length > 0) {
184-
return results.value;
223+
return processItems ? processItems(results.value) : results.value;
185224
}
186225
}
187226

@@ -191,8 +230,6 @@ export default class SPService implements ISPService {
191230
}
192231
}
193232

194-
195-
196233
/**
197234
* Gets list items for list item picker
198235
* @param filterText
@@ -600,4 +637,30 @@ export default class SPService implements ISPService {
600637

601638
return result;
602639
}
640+
641+
private _isTextFieldType(fieldType?: string): boolean {
642+
if (!fieldType) {
643+
return true;
644+
}
645+
const lowercasedFieldType = fieldType.toLowerCase();
646+
return lowercasedFieldType === 'text' || lowercasedFieldType === 'note';
647+
}
648+
649+
private _filterListItemsFieldValuesAsText(items: any[], internalColumnName: string, filterText: string | undefined, substringSearch: boolean): any[] {
650+
const lowercasedFilterText = filterText.toLowerCase();
651+
652+
return items.filter(i => {
653+
let fieldValue = i.FieldValuesAsText[internalColumnName];
654+
if (!fieldValue) {
655+
return false;
656+
}
657+
fieldValue = fieldValue.toLowerCase();
658+
659+
if (!filterText) {
660+
return true;
661+
}
662+
663+
return substringSearch ? fieldValue.indexOf(lowercasedFilterText) > -1 : fieldValue.startsWith(lowercasedFilterText);
664+
});
665+
}
603666
}

0 commit comments

Comments
 (0)