Last active
November 18, 2022 19:45
-
-
Save btaillon-coveo/92aa59e6922f4582c9f5ff2af350a68f to your computer and use it in GitHub Desktop.
JSUI folding like Headless
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @typedef IQueryResult | |
* @property {IQueryResult[]} [childResults] | |
* @property {IQueryResult} [parentResult] | |
* @property {{ foldingcollection?: string, foldingparent?: string, foldingchild?: string, source: string }} raw | |
*/ | |
/** | |
* @param {IQueryResult} parent | |
* @param {IQueryResult[]} results | |
* @param {string} [resolvedAncestors] | |
* @returns {IQueryResult[]} | |
*/ | |
function resolveChildrenFromFields( | |
parent, | |
results, | |
resolvedAncestors = [] | |
) { | |
const sourceChildValue = parent.raw.foldingchild; | |
if (!sourceChildValue) { | |
return []; | |
} | |
if (resolvedAncestors.indexOf(sourceChildValue) !== -1) { | |
return []; | |
} | |
return results | |
.filter((result) => { | |
const isSameResultAsSource = | |
result.raw.foldingchild === parent.raw.foldingchild; | |
const isChildOfSource = | |
result.raw.foldingparent === sourceChildValue; | |
return isChildOfSource && !isSameResultAsSource; | |
}) | |
.map((result) => ({ | |
...result, | |
parentResult: undefined, | |
childResults: resolveChildrenFromFields(result, results, [ | |
...resolvedAncestors, | |
sourceChildValue, | |
]), | |
})); | |
} | |
/** | |
* @param {T | undefined} value1 | |
* @param {T | undefined} value2 | |
* @template T | |
*/ | |
function areDefinedAndEqual( | |
value1, | |
value2 | |
) { | |
return (value1 || value2) !== undefined && value1 === value2; | |
} | |
/** | |
* @param {IQueryResult[]} results | |
*/ | |
function resolveRootFromFields( | |
results | |
) { | |
return results.find((result) => { | |
const hasNoParent = result.raw.foldingparent === undefined; | |
const isParentOfItself = areDefinedAndEqual( | |
result.raw.foldingparent, | |
result.raw.foldingchild | |
); | |
return hasNoParent || isParentOfItself; | |
}); | |
} | |
/** | |
* @param {IQueryResult} result | |
* @returns {IQueryResult[]} | |
*/ | |
function getChildResultsRecursively(result) { | |
if (!result.childResults) { | |
return []; | |
} | |
return result.childResults.flatMap((childResult) => [ | |
childResult, | |
...getChildResultsRecursively(childResult), | |
]); | |
} | |
/** | |
* @param {T[]} arr | |
* @param {(value: T, index: number) => string} getIdentifier | |
* @returns {T[]} | |
* @template T | |
*/ | |
function removeDuplicates( | |
arr, | |
getIdentifier | |
) { | |
return Object.values( | |
arr.reduce( | |
(existingValues, value, index) => ({ | |
...existingValues, | |
[getIdentifier(value, index)]: value, | |
}), | |
{} | |
) | |
); | |
} | |
/** | |
* @param {IQueryResult} relevantResult | |
*/ | |
function getAllIncludedResultsFrom(relevantResult) { | |
const foldedResults = getChildResultsRecursively(relevantResult); | |
const parentResults = [relevantResult, ...foldedResults] | |
.filter((result) => result.parentResult) | |
.map((result) => result.parentResult); | |
const resultsInCollection = removeDuplicates( | |
[relevantResult, ...foldedResults, ...parentResults], | |
(result) => result.uniqueId | |
); | |
return resultsInCollection; | |
} | |
/** | |
* @param {IQueryResult} relevantResult | |
* @returns {IQueryResult} | |
*/ | |
function foldResultWithFields( | |
relevantResult | |
) { | |
const resultsInCollection = getAllIncludedResultsFrom(relevantResult); | |
const resultToUseAsRoot = | |
resolveRootFromFields(resultsInCollection); | |
if (!resultToUseAsRoot) { | |
console.warn(`Could not find the root for:`, relevantResult); | |
return relevantResult; | |
} | |
return { | |
...resultToUseAsRoot, | |
parentResult: undefined, | |
childResults: resolveChildrenFromFields( | |
resultToUseAsRoot, | |
resultsInCollection | |
), | |
}; | |
} | |
/** | |
* @param {IQueryResult} result | |
* @returns {IQueryResult} | |
* @export | |
*/ | |
function getResult(result) { | |
if (result.raw.source === 'University') { | |
return foldResultWithFields(result); | |
} | |
return Coveo.Folding.defaultGetResult(result); | |
} | |
/** | |
* Usage: | |
* ```js | |
* Coveo.init( | |
* searchInterface, | |
* { | |
* Folding: { | |
* getResult | |
* } | |
* } | |
* ); | |
* ``` | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment