UNPKG

@itwin/presentation-hierarchies

Version:

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

80 lines 4.79 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Bentley Systems, Incorporated. All rights reserved. * See LICENSE.md in the project root for license terms and full copyright notice. *--------------------------------------------------------------------------------------------*/ import { concat, defer, EMPTY, filter, finalize, map, merge, mergeAll, mergeMap, take } from "rxjs"; import { assert } from "@itwin/core-bentley"; import { HierarchyNodeKey } from "../../HierarchyNodeKey.js"; 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 { reduceToMergeMapItem } from "../../internal/operators/ReduceToMergeMap.js"; import { ProcessedHierarchyNode, } from "../IModelHierarchyNode.js"; import { mergeInstanceNodes } from "../Utils.js"; const OPERATOR_NAME = "HideNodesInHierarchy"; /** @internal */ export const LOGGING_NAMESPACE = createOperatorLoggingNamespace(OPERATOR_NAME, LOGGING_NAMESPACE_INTERNAL); /** * Creates an operator that hides nodes and instead returns their children if the nodes have a `hideInHierarchy` handling param. * * @internal */ export function createHideNodesInHierarchyOperator(getNodes, stopOnFirstChild) { return function (nodes) { const inputNodes = nodes.pipe( /* v8 ignore next -- @preserve */ log({ category: LOGGING_NAMESPACE, message: (n) => `in: ${createNodeIdentifierForLogging(n)}` })); const [withFlag, withoutFlag] = partition(inputNodes, (n) => (ProcessedHierarchyNode.isGeneric(n) || ProcessedHierarchyNode.isInstancesNode(n)) && !!n.processingParams?.hideInHierarchy); // Defer to create a new seed for reduce on every subscribe const withLoadedChildren = defer(() => withFlag.pipe( /* v8 ignore next -- @preserve */ log({ category: LOGGING_NAMESPACE, message: (n) => `${createNodeIdentifierForLogging(n)} needs hide and needs children to be loaded`, }), filter((node) => node.children !== false), reduceToMergeMapItem((node) => createMergeMapKey(node), (node, mergedNode) => { if (mergedNode) { if (ProcessedHierarchyNode.isGeneric(mergedNode)) { // we don't merge generic nodes, just return the first one return mergedNode; } assert(ProcessedHierarchyNode.isInstancesNode(node)); return mergeInstanceNodes(mergedNode, node); } return node; }), /* v8 ignore next -- @preserve */ log({ category: LOGGING_NAMESPACE, message: (mm) => `created a merge map of size ${mm.size}` }), mergeMap((mm) => [...mm.values()].map((mergedNode) => defer(() => getNodes(mergedNode)))), mergeAll(), map((n) => n))); return merge(withoutFlag.pipe( /* v8 ignore next -- @preserve */ log({ category: LOGGING_NAMESPACE, message: (n) => `${createNodeIdentifierForLogging(n)} doesn't need hide, return the node`, })), stopOnFirstChild ? concat( // a small hack to handle situation when we're here to only check if parent node has children and one of them has `hideIfNoChildren` flag // with a `hasChildren = true` - we just return the hidden node itself in that case to avoid digging deeper into the hierarchy inputNodes.pipe(filter(hasChildren), /* v8 ignore next -- @preserve */ log({ category: LOGGING_NAMESPACE, message: (n) => `\`stopOnFirstChild = true\` and node ${createNodeIdentifierForLogging(n)} is set to always have nodes - return the hidden node without loading children`, })), EMPTY.pipe(finalize(() => { /* v8 ignore next -- @preserve */ doLog({ category: LOGGING_NAMESPACE, message: () => `\`stopOnFirstChild = true\` but none of the nodes had children determined to \`true\` - do load children`, }); })), withLoadedChildren).pipe(take(1)) : withLoadedChildren).pipe( /* v8 ignore next -- @preserve */ log({ category: LOGGING_NAMESPACE, message: (n) => `out: ${createNodeIdentifierForLogging(n)}` })); }; } function createMergeMapKey(node) { if (HierarchyNodeKey.isGeneric(node.key)) { return `${node.key.source ? `${node.key.source}:` : ""}${node.key.id}`; } return node.key.instanceKeys[0].className; } //# sourceMappingURL=HideNodesInHierarchy.js.map