1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
import { Doc, DocListCast, Field, Opt } from '../../fields/Doc';
import { Id } from '../../fields/FieldSymbols';
import { StrCast } from '../../fields/Types';
import { DocumentType } from '../documents/DocumentTypes';
export namespace SearchUtil {
export type HighlightingResult = { [id: string]: { [key: string]: string[] } };
export function SearchCollection(collectionDoc: Opt<Doc>, query: string) {
const blockedTypes = [DocumentType.PRESELEMENT, DocumentType.CONFIG, DocumentType.KVP, DocumentType.FONTICON, DocumentType.BUTTON, DocumentType.SCRIPTING];
const blockedKeys = [
'x',
'y',
'proto',
'width',
'layout_autoHeight',
'acl-Override',
'acl-Guest',
'embedContainer',
'zIndex',
'height',
'text_scrollHeight',
'text_height',
'cloneFieldFilter',
'isDataDoc',
'text_annotations',
'dragFactory_count',
'text_noTemplate',
'proto_embeddings',
'isSystem',
'layout_fieldKey',
'isBaseProto',
'xMargin',
'yMargin',
'links',
'layout',
'layout_keyValue',
'layout_fitWidth',
'type_collection',
'title_custom',
'freeform_panX',
'freeform_panY',
'freeform_scale',
];
query = query.toLowerCase();
const results = new Map<Doc, string[]>();
if (collectionDoc) {
const docs = DocListCast(collectionDoc[Doc.LayoutFieldKey(collectionDoc)]);
const docIDs: String[] = [];
SearchUtil.foreachRecursiveDoc(docs, (depth: number, doc: Doc) => {
const dtype = StrCast(doc.type) as DocumentType;
if (dtype && !blockedTypes.includes(dtype) && !docIDs.includes(doc[Id]) && depth >= 0) {
const hlights = new Set<string>();
SearchUtil.documentKeys(doc).forEach(
key =>
(Field.toString(doc[key] as Field) + Field.toScriptString(doc[key] as Field))
.toLowerCase() //
.includes(query) && hlights.add(key)
);
blockedKeys.forEach(key => hlights.delete(key));
if (Array.from(hlights.keys()).length > 0) {
results.set(doc, Array.from(hlights.keys()));
}
}
docIDs.push(doc[Id]);
});
}
return results;
}
/**
* @param {Doc} doc - doc for which keys are returned
*
* This method returns a list of a document doc's keys.
*/
export function documentKeys(doc: Doc) {
const keys: { [key: string]: boolean } = {};
Doc.GetAllPrototypes(doc).map(proto => Object.keys(proto).forEach(key => (keys[key] = false)));
return Array.from(Object.keys(keys));
}
/**
* @param {Doc[]} docs - docs to be searched through recursively
* @param {number, Doc => void} func - function to be called on each doc
*
* This method iterates through an array of docs and all docs within those docs, calling
* the function func on each doc.
*/
export function foreachRecursiveDoc(docs: Doc[], func: (depth: number, doc: Doc) => void) {
let newarray: Doc[] = [];
var depth = 0;
const visited: Doc[] = [];
while (docs.length > 0) {
newarray = [];
docs.filter(d => d && !visited.includes(d)).forEach(d => {
visited.push(d);
const fieldKey = Doc.LayoutFieldKey(d);
const annos = !Field.toString(Doc.LayoutField(d) as Field).includes('CollectionView');
const data = d[annos ? fieldKey + '_annotations' : fieldKey];
data && newarray.push(...DocListCast(data));
const sidebar = d[fieldKey + '_sidebar'];
sidebar && newarray.push(...DocListCast(sidebar));
func(depth, d);
});
docs = newarray;
depth++;
}
}
}
|