@itwin/presentation-hierarchies
Version:
A package for creating hierarchies based on data in iTwin.js iModels.
48 lines • 3.8 kB
JavaScript
/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
import { defer, filter, map, merge, mergeMap } from "rxjs";
import { createNodeIdentifierForLogging, createOperatorLoggingNamespace, hasChildren, LOGGING_NAMESPACE_INTERNAL } from "../../internal/Common.js";
import { doLog, log } from "../../internal/LoggingUtils.js";
import { partition } from "../../internal/operators/Partition.js";
import { ProcessedHierarchyNode } from "../IModelHierarchyNode.js";
const OPERATOR_NAME = "HideIfNoChildren";
/** @internal */
export const LOGGING_NAMESPACE = createOperatorLoggingNamespace(OPERATOR_NAME, LOGGING_NAMESPACE_INTERNAL);
/**
* Creates an operator that hides nodes with no children if they have a `hideIfNoChildren` handling param.
*
* @internal
*/
export function createHideIfNoChildrenOperator(hasNodes) {
return function (nodes) {
const inputNodes = nodes.pipe(log({ category: LOGGING_NAMESPACE, message: /* c8 ignore next */ (n) => `in: ${createNodeIdentifierForLogging(n)}` }));
// split input into 3 pieces:
// - `doesntNeedHide` - nodes without the flag (return no matter if they have children or not)
// - `determinedChildren` - nodes with the flag and known children
// - `undeterminedChildren` - nodes with the flag and unknown children
const [needsHide, doesntNeedHide] = partition(inputNodes, (n) => (ProcessedHierarchyNode.isGeneric(n) || ProcessedHierarchyNode.isInstancesNode(n)) && !!n.processingParams?.hideIfNoChildren);
const [determinedChildren, undeterminedChildren] = partition(needsHide, (n) => n.children !== undefined);
return merge(doesntNeedHide.pipe(log({ category: LOGGING_NAMESPACE, message: /* c8 ignore next */ (n) => `${createNodeIdentifierForLogging(n)}: doesn't need hide` })), merge(determinedChildren.pipe(log({ category: LOGGING_NAMESPACE, message: /* c8 ignore next */ (n) => `${createNodeIdentifierForLogging(n)}: needs hide, has children` })), undeterminedChildren.pipe(log({ category: LOGGING_NAMESPACE, message: /* c8 ignore next */ (n) => `${createNodeIdentifierForLogging(n)}: needs hide, needs children` }), mergeMap((n) => defer(() => {
doLog({
category: LOGGING_NAMESPACE,
message: /* c8 ignore next */ () => `${createNodeIdentifierForLogging(n)}: requesting children flag`,
});
return hasNodes(n).pipe(log({
category: LOGGING_NAMESPACE,
message: /* c8 ignore next */ (childrenFlag) => `${createNodeIdentifierForLogging(n)}: determined children: ${childrenFlag}`,
}), map((children) => Object.assign(n, { children })));
}),
// Sending child check requests for all nodes without any limit greatly slows down
// the following case:
// - NodeX (determining children) -> ... lots of children with "hide if no children" -> ...
// We check the nodes with "hide if no children" at most 2 at a time to prefer going deep into
// the hierarchy, where we're more likely to find an answer, rather than going wide.
2), log({
category: LOGGING_NAMESPACE,
message: /* c8 ignore next */ (n) => `${createNodeIdentifierForLogging(n)}: needs hide, determined children: ${hasChildren(n)}`,
}))).pipe(filter(hasChildren))).pipe(log({ category: LOGGING_NAMESPACE, message: /* c8 ignore next */ (n) => `out: ${createNodeIdentifierForLogging(n)}` }));
};
}
//# sourceMappingURL=HideIfNoChildren.js.map