diff options
Diffstat (limited to 'src/client/util/SearchUtil.ts')
| -rw-r--r-- | src/client/util/SearchUtil.ts | 47 |
1 files changed, 27 insertions, 20 deletions
diff --git a/src/client/util/SearchUtil.ts b/src/client/util/SearchUtil.ts index 733eae5f4..2f23d07dc 100644 --- a/src/client/util/SearchUtil.ts +++ b/src/client/util/SearchUtil.ts @@ -8,12 +8,19 @@ import { DocOptions, FInfo } from '../documents/Documents'; export namespace SearchUtil { export type HighlightingResult = { [id: string]: { [key: string]: string[] } }; + /** + * Recursively search all Docs within the collection for the query string. + * @param {Doc} collectionDoc - The collection document to search within. + * @param {string} queryIn - The query string to search for. + * @param {boolean} matchKeyNames - Whether to match metadata field names in addition to field values + * @param {string[]} onlyKeys - Optional: restrict search to only look in the specified array of field names. + */ export function SearchCollection(collectionDoc: Opt<Doc>, queryIn: string, matchKeyNames: boolean, onlyKeys?: string[]) { - const blockedTypes = [DocumentType.PRESELEMENT, DocumentType.CONFIG, DocumentType.KVP, DocumentType.FONTICON, DocumentType.BUTTON, DocumentType.SCRIPTING]; + const blockedTypes = [DocumentType.PRESSLIDE, DocumentType.CONFIG, DocumentType.KVP, DocumentType.FONTICON, DocumentType.BUTTON, DocumentType.SCRIPTING]; const blockedKeys = matchKeyNames ? [] : Object.entries(DocOptions) - .filter(([, info]: [string, FInfo]) => !info?.searchable()) + .filter(([, info]: [string, FieldType | FInfo | undefined]) => (info instanceof FInfo ? !info.searchable() : true)) .map(([key]) => key); const exact = queryIn.startsWith('='); @@ -21,18 +28,19 @@ export namespace SearchUtil { const results = new ObservableMap<Doc, string[]>(); if (collectionDoc) { - const docs = DocListCast(collectionDoc[Doc.LayoutFieldKey(collectionDoc)]); - // eslint-disable-next-line @typescript-eslint/ban-types - const docIDs: String[] = []; + const docs = DocListCast(collectionDoc[Doc.LayoutDataKey(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>(); - (onlyKeys ?? SearchUtil.documentKeys(doc)).forEach( - key => - (val => (exact ? val === query.toLowerCase() : val.includes(query.toLowerCase())))( - matchKeyNames ? key : Field.toString(doc[key] as FieldType)) - && hlights.add(key) + const fieldsToSearch = onlyKeys ?? SearchUtil.documentKeys(doc); + fieldsToSearch.forEach( + key => { + const val = (matchKeyNames ? key : Field.toString(doc[key] as FieldType)).toLowerCase(); + const accept = (exact ? val === query.toLowerCase() : val.includes(query.toLowerCase())); + accept && hlights.add(key); + } ); // prettier-ignore blockedKeys.forEach(key => hlights.delete(key)); @@ -46,18 +54,17 @@ export namespace SearchUtil { return results; } /** - * @param {Doc} doc - doc for which keys are returned + * @param {Doc} doc - Doc to search for used field names * - * This method returns a list of a document doc's keys. + * An array of all field names used by the Doc or its prototypes. */ 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)); + return Object.keys(Doc.GetAllPrototypes(doc).filter(proto => proto).reduce( + (keys, proto) => { + Object.keys(proto).forEach(keys.add.bind(keys)); + return keys; + }, + new Set<string>())); // prettier-ignore } /** @@ -77,7 +84,7 @@ export namespace SearchUtil { // eslint-disable-next-line no-loop-func docs.filter(d => d && !visited.includes(d)).forEach(d => { visited.push(d); - const fieldKey = Doc.LayoutFieldKey(d); + const fieldKey = Doc.LayoutDataKey(d); const annos = !Field.toString(Doc.LayoutField(d) as FieldType).includes('CollectionView'); const data = d[annos ? fieldKey + '_annotations' : fieldKey]; data && newarray.push(...DocListCast(data)); |
