UNPKG

@itwin/presentation-hierarchies

Version:

A package for creating hierarchies based on data in iTwin.js iModels.

71 lines 4.14 kB
/*--------------------------------------------------------------------------------------------- * 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"; // cspell:words doesnt 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( /* v8 ignore next -- @preserve */ log({ category: LOGGING_NAMESPACE, message: (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( /* v8 ignore next -- @preserve */ log({ category: LOGGING_NAMESPACE, message: (n) => `${createNodeIdentifierForLogging(n)}: doesn't need hide` })), merge(determinedChildren.pipe( /* v8 ignore next -- @preserve */ log({ category: LOGGING_NAMESPACE, message: (n) => `${createNodeIdentifierForLogging(n)}: needs hide, has children`, })), undeterminedChildren.pipe( /* v8 ignore next -- @preserve */ log({ category: LOGGING_NAMESPACE, message: (n) => `${createNodeIdentifierForLogging(n)}: needs hide, needs children`, }), mergeMap((n) => defer(() => { /* v8 ignore next -- @preserve */ doLog({ category: LOGGING_NAMESPACE, message: () => `${createNodeIdentifierForLogging(n)}: requesting children flag`, }); return hasNodes(n).pipe( /* v8 ignore next -- @preserve */ log({ category: LOGGING_NAMESPACE, message: (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), /* v8 ignore next -- @preserve */ log({ category: LOGGING_NAMESPACE, message: (n) => `${createNodeIdentifierForLogging(n)}: needs hide, determined children: ${hasChildren(n)}`, }))).pipe(filter(hasChildren))).pipe( /* v8 ignore next -- @preserve */ log({ category: LOGGING_NAMESPACE, message: (n) => `out: ${createNodeIdentifierForLogging(n)}` })); }; } //# sourceMappingURL=HideIfNoChildren.js.map