in uui-core/src/data/processing/views/tree/treeStructure/helpers/FetchingHelper.ts [70:193]
private static async loadMissing<TItem, TId, TFilter = any>({
tree,
options,
dataSourceState,
}: LoadOptionsMissing<TItem, TId, TFilter>) {
const requiredRowsCount = dataSourceState.topIndex + dataSourceState.visibleCount;
const byParentId = newMap<TId, TId[]>(tree.getParams());
const nodeInfoById = newMap<TId, ITreeNodeInfo>(tree.getParams());
const newItemsMap = newMap<TId, TItem>(tree.getParams());
const flatten = dataSourceState.search && options.flattenSearchResults;
const loadAllChildren: (id: TId) => LoadAllConfig = options.loadAllChildren ?? (() => ({ nestedChildren: true, children: false }));
let newItems: TItem[] = [];
const loadRecursive = async (
parentId: TId,
parent: TItem,
{ children: parentLoadAllChildren, nestedChildren: parentLoadAllNestedChildren }: LoadAllConfig,
remainingRowsCount: number,
) => {
let recursiveLoadedCount = 0;
const { ids, nodeInfo, loadedItems } = await this.loadItems<TItem, TId, TFilter>({
tree,
byParentId,
options,
parentId,
parent,
dataSourceState,
remainingRowsCount,
loadAll: parentLoadAllChildren,
});
const { ids: originalIds, ...originalNodeInfo } = tree.getItems(parentId);
const currentIds = byParentId.has(parentId) ? byParentId.get(parentId) : originalIds;
if (ids !== currentIds
|| nodeInfo.count !== originalNodeInfo.count
|| nodeInfo.totalCount !== originalNodeInfo.totalCount
|| nodeInfo.assumedCount !== originalNodeInfo.assumedCount
|| nodeInfo.cursor !== originalNodeInfo.cursor) {
nodeInfoById.set(parentId, nodeInfo);
}
byParentId.set(parentId, ids);
recursiveLoadedCount += ids.length;
if (loadedItems.length > 0) {
loadedItems.forEach((item) => {
const id = tree.getParams().getId(item);
const prevNodeInfo = nodeInfoById.get(id) ?? {};
const assumedCount = flatten ? undefined : prevNodeInfo.assumedCount ?? tree.getParams().getChildCount?.(item);
nodeInfoById.set(id, { ...prevNodeInfo, ...(tree.getParams().getChildCount ? { assumedCount } : {}) });
newItemsMap.set(id, item);
});
newItems = newItems.concat(loadedItems);
}
if (!flatten && tree.getParams().getChildCount) {
const childrenPromises: Promise<any>[] = [];
for (let n = 0; n < ids.length; n++) {
const id = ids[n];
const itemInTree = tree.getById(id);
let item: TItem = itemInTree === NOT_FOUND_RECORD ? undefined : itemInTree;
if (newItemsMap.has(id)) {
item = newItemsMap.get(id);
}
let isFolded = false;
let hasChildren = false;
if (tree.getParams().getChildCount) {
// not a root node
const childrenCount = tree.getParams().getChildCount(item);
if (childrenCount) {
// foldable
isFolded = options.isFolded(item);
hasChildren = true;
}
}
const { nestedChildren, children } = loadAllChildren(id);
const shouldLoadAllChildren = hasChildren && children;
const loadAll = parentLoadAllNestedChildren ? parentLoadAllChildren || shouldLoadAllChildren : shouldLoadAllChildren;
remainingRowsCount--;
if (hasChildren && ((!isFolded && remainingRowsCount > 0) || loadAll)) {
const childPromise = loadRecursive(id, item, { children: loadAll, nestedChildren }, remainingRowsCount);
childrenPromises.push(childPromise);
if (options.fetchStrategy === 'sequential') {
const loadedCount = await childPromise;
remainingRowsCount -= loadedCount;
recursiveLoadedCount += loadedCount;
}
}
}
const childCounts = await Promise.all(childrenPromises);
if (options.fetchStrategy === 'parallel') {
const recursiveChildrenCount = childCounts.reduce((a, b) => a + b, 0);
recursiveLoadedCount += recursiveChildrenCount;
remainingRowsCount -= recursiveChildrenCount;
}
}
return recursiveLoadedCount;
};
await loadRecursive(undefined, undefined, loadAllChildren(undefined), requiredRowsCount);
return {
tree,
loadedItemsMap: newItemsMap,
loadedItems: newItems,
byParentId,
nodeInfoById,
};
}