@itwin/tree-widget-react 4.0.0-alpha.24 → 4.0.0-alpha.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -1
- package/lib/esm/tree-widget-react/components/TreeWidgetUiItemsProvider.js +2 -1
- package/lib/esm/tree-widget-react/components/TreeWidgetUiItemsProvider.js.map +1 -1
- package/lib/esm/tree-widget-react/components/tree-header/WidgetHeader.js +1 -1
- package/lib/esm/tree-widget-react/components/tree-header/WidgetHeader.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.d.ts +4 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.js +4 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.d.ts +1 -0
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js +36 -47
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.d.ts +2 -0
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.js +4 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.d.ts +4 -2
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js +87 -38
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeNode.d.ts +86 -0
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeNode.js +50 -0
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeNode.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.d.ts +4 -2
- package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js +38 -23
- package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.d.ts +11 -21
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js +16 -168
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeNodeInternal.d.ts +65 -0
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeNodeInternal.js +22 -0
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeNodeInternal.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/UseSearchPaths.d.ts +2 -2
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/UseSearchPaths.js +4 -4
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/UseSearchPaths.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/CategoriesTreeVisibilityHandler.d.ts +6 -12
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/CategoriesTreeVisibilityHandler.js +192 -127
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/CategoriesTreeVisibilityHandler.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/CategoriesTreeVisibilityHelper.d.ts +14 -5
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/CategoriesTreeVisibilityHelper.js +43 -24
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/CategoriesTreeVisibilityHelper.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/SearchResultsTree.d.ts +3 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/SearchResultsTree.js +78 -17
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/visibility/SearchResultsTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeComponent.d.ts +2 -0
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeComponent.js +4 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeComponent.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeDefinition.js +91 -114
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeDefinition.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeIcon.d.ts +2 -2
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeIcon.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeNode.d.ts +32 -0
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeNode.js +26 -0
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeNode.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/UseClassificationsTree.d.ts +13 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/UseClassificationsTree.js +62 -32
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/UseClassificationsTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/UseClassificationsTreeDefinition.d.ts +12 -9
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/UseClassificationsTreeDefinition.js +42 -38
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/UseClassificationsTreeDefinition.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeIdsCache.d.ts +15 -38
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeIdsCache.js +59 -242
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeIdsCache.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeNodeInternal.d.ts +29 -0
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeNodeInternal.js +19 -0
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeNodeInternal.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/ClassificationsTreeVisibilityHandler.d.ts +5 -9
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/ClassificationsTreeVisibilityHandler.js +155 -84
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/ClassificationsTreeVisibilityHandler.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/ClassificationsTreeVisibilityHelper.js +20 -6
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/ClassificationsTreeVisibilityHelper.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/SearchResultsTree.d.ts +6 -10
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/SearchResultsTree.js +104 -63
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/visibility/SearchResultsTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/SharedTreeContextProvider.d.ts +7 -0
- package/lib/esm/tree-widget-react/components/trees/common/SharedTreeContextProvider.js +14 -0
- package/lib/esm/tree-widget-react/components/trees/common/SharedTreeContextProvider.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/TreeWidgetViewport.js +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/TreeWidgetViewport.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/UseHierarchyVisibility.js +2 -2
- package/lib/esm/tree-widget-react/components/trees/common/UseHierarchyVisibility.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/Utils.js +2 -2
- package/lib/esm/tree-widget-react/components/trees/common/Utils.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/Tree.d.ts +4 -4
- package/lib/esm/tree-widget-react/components/trees/common/components/Tree.js +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/Tree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/TreeNodeVisibilityButton.d.ts +4 -4
- package/lib/esm/tree-widget-react/components/trees/common/components/TreeNodeVisibilityButton.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/TreeRenderer.js +7 -5
- package/lib/esm/tree-widget-react/components/trees/common/components/TreeRenderer.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/UseVisibilityButtonHandler.d.ts +2 -2
- package/lib/esm/tree-widget-react/components/trees/common/components/UseVisibilityButtonHandler.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.js +5 -5
- package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/internal/SharedTreeContextProviderInternal.d.ts +20 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/SharedTreeContextProviderInternal.js +44 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/SharedTreeContextProviderInternal.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/Types.d.ts +4 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/Types.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/internal/UseIModelAccess.d.ts +12 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/UseIModelAccess.js +2 -1
- package/lib/esm/tree-widget-react/components/trees/common/internal/UseIModelAccess.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.d.ts +17 -6
- package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.js +58 -29
- package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityUtils.d.ts +8 -14
- package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityUtils.js +22 -26
- package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityUtils.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/internal/{AlwaysAndNeverDrawnElementInfo.d.ts → caches/AlwaysAndNeverDrawnElementInfoCache.d.ts} +15 -21
- package/lib/esm/tree-widget-react/components/trees/common/internal/{AlwaysAndNeverDrawnElementInfo.js → caches/AlwaysAndNeverDrawnElementInfoCache.js} +40 -38
- package/lib/esm/tree-widget-react/components/trees/common/internal/caches/AlwaysAndNeverDrawnElementInfoCache.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/caches/BaseIdsCache.d.ts +68 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/caches/BaseIdsCache.js +148 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/caches/BaseIdsCache.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ElementChildrenCache.d.ts +30 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ElementChildrenCache.js +151 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ElementChildrenCache.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ElementModelCategoriesCache.d.ts +32 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ElementModelCategoriesCache.js +106 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ElementModelCategoriesCache.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/{ModelCategoryElementsCountCache.d.ts → caches/ModelCategoryElementsCountCache.d.ts} +9 -2
- package/lib/esm/tree-widget-react/components/trees/common/internal/{ModelCategoryElementsCountCache.js → caches/ModelCategoryElementsCountCache.js} +17 -21
- package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ModelCategoryElementsCountCache.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ModeledElementsCache.d.ts +27 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ModeledElementsCache.js +106 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ModeledElementsCache.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/caches/SubCategoriesCache.d.ts +23 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/caches/SubCategoriesCache.js +56 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/caches/SubCategoriesCache.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseCachedVisibility.d.ts +6 -6
- package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseCachedVisibility.js +27 -17
- package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseCachedVisibility.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.d.ts +7 -13
- package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.js +36 -35
- package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/internal/visibility/BaseSearchResultsTree.d.ts +18 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/visibility/BaseSearchResultsTree.js +14 -1
- package/lib/esm/tree-widget-react/components/trees/common/internal/visibility/BaseSearchResultsTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/internal/visibility/BaseVisibilityHelper.d.ts +46 -70
- package/lib/esm/tree-widget-react/components/trees/common/internal/visibility/BaseVisibilityHelper.js +229 -361
- package/lib/esm/tree-widget-react/components/trees/common/internal/visibility/BaseVisibilityHelper.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTree.d.ts +2 -2
- package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeComponent.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.d.ts +2 -2
- package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeComponent.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeDefinition.js +1 -1
- package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeDefinition.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/internal/IModelContentTreeIdsCache.js +32 -19
- package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/internal/IModelContentTreeIdsCache.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/index.d.ts +5 -1
- package/lib/esm/tree-widget-react/components/trees/index.js +5 -1
- package/lib/esm/tree-widget-react/components/trees/index.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTree.d.ts +4 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTree.js +4 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.d.ts +7 -3
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.js +36 -35
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeComponent.d.ts +1 -0
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeComponent.js +3 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeComponent.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.d.ts +3 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js +70 -26
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeNode.d.ts +63 -0
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeNode.js +56 -0
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeNode.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.d.ts +5 -3
- package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.js +26 -13
- package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.d.ts +11 -23
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js +56 -189
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNodeInternal.d.ts +52 -0
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNodeInternal.js +22 -0
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNodeInternal.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseSearchPaths.d.ts +2 -2
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseSearchPaths.js +8 -8
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseSearchPaths.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/ModelsTreeVisibilityHandler.d.ts +6 -12
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/ModelsTreeVisibilityHandler.js +190 -114
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/ModelsTreeVisibilityHandler.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/ModelsTreeVisibilityHelper.d.ts +6 -0
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/ModelsTreeVisibilityHelper.js +20 -8
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/ModelsTreeVisibilityHelper.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/SearchResultsTree.d.ts +4 -2
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/SearchResultsTree.js +73 -13
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/visibility/SearchResultsTree.js.map +1 -1
- package/lib/esm/tree-widget-react-internal.d.ts +1 -1
- package/lib/esm/tree-widget-react-internal.js +1 -1
- package/lib/esm/tree-widget-react-internal.js.map +1 -1
- package/package.json +77 -82
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeNode.d.ts +0 -41
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeNode.js +0 -50
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeNode.js.map +0 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeNode.d.ts +0 -19
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeNode.js +0 -32
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeNode.js.map +0 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/UseSearchPaths.d.ts +0 -20
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/UseSearchPaths.js +0 -53
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/UseSearchPaths.js.map +0 -1
- package/lib/esm/tree-widget-react/components/trees/common/internal/AlwaysAndNeverDrawnElementInfo.js.map +0 -1
- package/lib/esm/tree-widget-react/components/trees/common/internal/ModelCategoryElementsCountCache.js.map +0 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNode.d.ts +0 -37
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNode.js +0 -54
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNode.js.map +0 -1
package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ElementChildrenCache.js
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
3
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
|
5
|
+
import { defaultIfEmpty, defer, EMPTY, firstValueFrom, from, map, mergeMap, reduce, tap } from "rxjs";
|
|
6
|
+
import { Guid, Id64 } from "@itwin/core-bentley";
|
|
7
|
+
import { catchBeSQLiteInterrupts } from "../UseErrorState.js";
|
|
8
|
+
import { getOptimalBatchSize } from "../Utils.js";
|
|
9
|
+
/** @internal */
|
|
10
|
+
export class ElementChildrenCache {
|
|
11
|
+
#queryExecutor;
|
|
12
|
+
#elementClassName;
|
|
13
|
+
#componentId;
|
|
14
|
+
#componentName;
|
|
15
|
+
#childElementsMap;
|
|
16
|
+
/** Stores element ids which have children query scheduled to execute. */
|
|
17
|
+
#childElementsLoadingMap;
|
|
18
|
+
constructor(props) {
|
|
19
|
+
this.#queryExecutor = props.queryExecutor;
|
|
20
|
+
this.#elementClassName = props.elementClassName;
|
|
21
|
+
this.#componentId = props.componentId;
|
|
22
|
+
this.#componentName = "ElementChildrenCache";
|
|
23
|
+
this.#childElementsMap = new Map();
|
|
24
|
+
this.#childElementsLoadingMap = new Map();
|
|
25
|
+
}
|
|
26
|
+
queryChildren({ elementIds }) {
|
|
27
|
+
if (elementIds.length === 0) {
|
|
28
|
+
return EMPTY;
|
|
29
|
+
}
|
|
30
|
+
return defer(() => {
|
|
31
|
+
const ctes = [
|
|
32
|
+
`
|
|
33
|
+
ElementChildren(id, parentId) AS (
|
|
34
|
+
SELECT ECInstanceId id, Parent.Id parentId
|
|
35
|
+
FROM ${this.#elementClassName}
|
|
36
|
+
WHERE Parent.Id IN (${elementIds.join(", ")})
|
|
37
|
+
UNION ALL
|
|
38
|
+
SELECT c.ECInstanceId id, c.Parent.Id
|
|
39
|
+
FROM ${this.#elementClassName} c
|
|
40
|
+
JOIN ElementChildren p ON c.Parent.Id = p.id
|
|
41
|
+
)
|
|
42
|
+
`,
|
|
43
|
+
];
|
|
44
|
+
const ecsql = `
|
|
45
|
+
SELECT id, parentId
|
|
46
|
+
FROM ElementChildren
|
|
47
|
+
`;
|
|
48
|
+
return this.#queryExecutor.createQueryReader({ ecsql, ctes }, { rowFormat: "ECSqlPropertyNames", limit: "unbounded", restartToken: `${this.#componentName}/${this.#componentId}/children/${Guid.createValue()}` });
|
|
49
|
+
}).pipe(catchBeSQLiteInterrupts, map((row) => {
|
|
50
|
+
return { id: row.id, parentId: row.parentId };
|
|
51
|
+
}));
|
|
52
|
+
}
|
|
53
|
+
getChildElementsTreeFromMap({ elementIds }) {
|
|
54
|
+
const result = new Map();
|
|
55
|
+
if (Id64.sizeOf(elementIds) === 0 || this.#childElementsMap.size === 0) {
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
for (const elementId of Id64.iterable(elementIds)) {
|
|
59
|
+
const entry = this.#childElementsMap.get(elementId);
|
|
60
|
+
if (!entry?.children) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
const elementChildrenTree = new Map();
|
|
64
|
+
result.set(elementId, { children: elementChildrenTree });
|
|
65
|
+
for (const childId of entry.children) {
|
|
66
|
+
const childrenTreeOfChild = this.getChildElementsTreeFromMap({ elementIds: childId });
|
|
67
|
+
// Need to add children tree created from childId. This tree includes childId as root element
|
|
68
|
+
// If child does not have children, children tree won't be created. Need to add childId with undefined children
|
|
69
|
+
elementChildrenTree.set(childId, { children: childrenTreeOfChild.size > 0 ? childrenTreeOfChild : undefined });
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return result;
|
|
73
|
+
}
|
|
74
|
+
getChildElementsCountMap({ elementIds }) {
|
|
75
|
+
const result = new Map();
|
|
76
|
+
for (const elementId of Id64.iterable(elementIds)) {
|
|
77
|
+
const entry = this.#childElementsMap.get(elementId);
|
|
78
|
+
if (entry?.children) {
|
|
79
|
+
let totalChildrenCount = entry.children.length;
|
|
80
|
+
for (const childrenOfChildCount of this.getChildElementsCountMap({ elementIds: entry.children }).values()) {
|
|
81
|
+
totalChildrenCount += childrenOfChildCount;
|
|
82
|
+
}
|
|
83
|
+
result.set(elementId, totalChildrenCount);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Populates #childElementsLoadingMap with promises. When these promises resolve, they will populate #childElementsMap with values and delete entries from #childElementsLoadingMap.
|
|
90
|
+
*/
|
|
91
|
+
createChildElementsLoadingMapEntries({ elementsToQuery }) {
|
|
92
|
+
const getElementsToQueryPromise = async (batchedElementsToQuery) => firstValueFrom(this.queryChildren({ elementIds: batchedElementsToQuery }).pipe(
|
|
93
|
+
// Want to have void at the end instead of void[], so using reduce
|
|
94
|
+
reduce((acc, { parentId, id }) => {
|
|
95
|
+
let entry = this.#childElementsMap.get(parentId);
|
|
96
|
+
if (!entry) {
|
|
97
|
+
entry = { children: [] };
|
|
98
|
+
this.#childElementsMap.set(parentId, entry);
|
|
99
|
+
}
|
|
100
|
+
if (!entry.children) {
|
|
101
|
+
entry.children = [];
|
|
102
|
+
}
|
|
103
|
+
// Add child to parent's entry and add child to children map
|
|
104
|
+
entry.children.push(id);
|
|
105
|
+
if (!this.#childElementsMap.has(id)) {
|
|
106
|
+
this.#childElementsMap.set(id, { children: undefined });
|
|
107
|
+
}
|
|
108
|
+
return acc;
|
|
109
|
+
}, (() => { })()), tap({ complete: () => batchedElementsToQuery.forEach((elementId) => this.#childElementsLoadingMap.delete(elementId)) }), defaultIfEmpty((() => { })())));
|
|
110
|
+
const maximumBatchSize = 1000;
|
|
111
|
+
const totalSize = elementsToQuery.length;
|
|
112
|
+
const optimalBatchSize = getOptimalBatchSize({ totalSize, maximumBatchSize });
|
|
113
|
+
const loadingMapEntries = new Array();
|
|
114
|
+
// Don't want to slice if its not necessary
|
|
115
|
+
if (totalSize <= maximumBatchSize) {
|
|
116
|
+
loadingMapEntries.push(getElementsToQueryPromise(elementsToQuery));
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
for (let i = 0; i < elementsToQuery.length; i += optimalBatchSize) {
|
|
120
|
+
loadingMapEntries.push(getElementsToQueryPromise(elementsToQuery.slice(i, i + optimalBatchSize)));
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
elementsToQuery.forEach((elementId, index) => this.#childElementsLoadingMap.set(elementId, loadingMapEntries[Math.floor(index / optimalBatchSize)]));
|
|
124
|
+
return { loadingMapEntries: Promise.all(loadingMapEntries).then(() => { }) };
|
|
125
|
+
}
|
|
126
|
+
createChildElementsMapEntries({ elementIds }) {
|
|
127
|
+
return from(Id64.iterable(elementIds)).pipe(reduce((acc, elementId) => {
|
|
128
|
+
if (this.#childElementsMap.has(elementId)) {
|
|
129
|
+
return acc;
|
|
130
|
+
}
|
|
131
|
+
const loadingPromise = this.#childElementsLoadingMap.get(elementId);
|
|
132
|
+
if (loadingPromise) {
|
|
133
|
+
acc.existingPromises.push(loadingPromise);
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
acc.elementsToQuery.push(elementId);
|
|
137
|
+
}
|
|
138
|
+
return acc;
|
|
139
|
+
}, { existingPromises: new Array(), elementsToQuery: new Array() }), mergeMap(async ({ elementsToQuery, existingPromises }) => {
|
|
140
|
+
existingPromises.push(this.createChildElementsLoadingMapEntries({ elementsToQuery }).loadingMapEntries);
|
|
141
|
+
return Promise.all(existingPromises);
|
|
142
|
+
}));
|
|
143
|
+
}
|
|
144
|
+
getChildElementsTree({ elementIds }) {
|
|
145
|
+
return this.createChildElementsMapEntries({ elementIds }).pipe(map(() => this.getChildElementsTreeFromMap({ elementIds })));
|
|
146
|
+
}
|
|
147
|
+
getAllChildElementsCount({ elementIds }) {
|
|
148
|
+
return this.createChildElementsMapEntries({ elementIds }).pipe(map(() => this.getChildElementsCountMap({ elementIds })));
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=ElementChildrenCache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ElementChildrenCache.js","sourceRoot":"","sources":["../../../../../../../../src/tree-widget-react/components/trees/common/internal/caches/ElementChildrenCache.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { defaultIfEmpty, defer, EMPTY, firstValueFrom, from, map, mergeMap, reduce, tap } from \"rxjs\";\nimport { Guid, Id64 } from \"@itwin/core-bentley\";\nimport { catchBeSQLiteInterrupts } from \"../UseErrorState.js\";\nimport { getOptimalBatchSize } from \"../Utils.js\";\n\nimport type { Observable } from \"rxjs\";\nimport type { GuidString, Id64Arg, Id64Array, Id64String } from \"@itwin/core-bentley\";\nimport type { LimitingECSqlQueryExecutor } from \"@itwin/presentation-hierarchies\";\nimport type { ChildrenTree } from \"../Utils.js\";\n\ntype ChildElementsMap = Map<Id64String, { children: Id64Array | undefined }>;\ntype ChildElementsLoadingMap = Map<Id64String, Promise<void>>;\n\ninterface ElementChildrenCacheProps {\n queryExecutor: LimitingECSqlQueryExecutor;\n elementClassName: string;\n componentId: GuidString;\n}\n\n/** @internal */\nexport class ElementChildrenCache {\n #queryExecutor: LimitingECSqlQueryExecutor;\n readonly #elementClassName: string;\n #componentId: GuidString;\n #componentName: string;\n #childElementsMap: ChildElementsMap;\n /** Stores element ids which have children query scheduled to execute. */\n #childElementsLoadingMap: ChildElementsLoadingMap;\n\n constructor(props: ElementChildrenCacheProps) {\n this.#queryExecutor = props.queryExecutor;\n this.#elementClassName = props.elementClassName;\n this.#componentId = props.componentId;\n this.#componentName = \"ElementChildrenCache\";\n this.#childElementsMap = new Map();\n this.#childElementsLoadingMap = new Map();\n }\n\n private queryChildren({ elementIds }: { elementIds: Id64Array }): Observable<{ id: Id64String; parentId: Id64String }> {\n if (elementIds.length === 0) {\n return EMPTY;\n }\n\n return defer(() => {\n const ctes = [\n `\n ElementChildren(id, parentId) AS (\n SELECT ECInstanceId id, Parent.Id parentId\n FROM ${this.#elementClassName}\n WHERE Parent.Id IN (${elementIds.join(\", \")})\n UNION ALL\n SELECT c.ECInstanceId id, c.Parent.Id\n FROM ${this.#elementClassName} c\n JOIN ElementChildren p ON c.Parent.Id = p.id\n )\n `,\n ];\n const ecsql = `\n SELECT id, parentId\n FROM ElementChildren\n `;\n return this.#queryExecutor.createQueryReader(\n { ecsql, ctes },\n { rowFormat: \"ECSqlPropertyNames\", limit: \"unbounded\", restartToken: `${this.#componentName}/${this.#componentId}/children/${Guid.createValue()}` },\n );\n }).pipe(\n catchBeSQLiteInterrupts,\n map((row) => {\n return { id: row.id, parentId: row.parentId };\n }),\n );\n }\n\n private getChildElementsTreeFromMap({ elementIds }: { elementIds: Id64Arg }): ChildrenTree {\n const result: ChildrenTree = new Map();\n if (Id64.sizeOf(elementIds) === 0 || this.#childElementsMap.size === 0) {\n return result;\n }\n for (const elementId of Id64.iterable(elementIds)) {\n const entry = this.#childElementsMap.get(elementId);\n if (!entry?.children) {\n continue;\n }\n const elementChildrenTree: ChildrenTree = new Map();\n result.set(elementId, { children: elementChildrenTree });\n for (const childId of entry.children) {\n const childrenTreeOfChild = this.getChildElementsTreeFromMap({ elementIds: childId });\n // Need to add children tree created from childId. This tree includes childId as root element\n // If child does not have children, children tree won't be created. Need to add childId with undefined children\n elementChildrenTree.set(childId, { children: childrenTreeOfChild.size > 0 ? childrenTreeOfChild : undefined });\n }\n }\n return result;\n }\n\n private getChildElementsCountMap({ elementIds }: { elementIds: Id64Arg }): Map<Id64String, number> {\n const result = new Map<Id64String, number>();\n for (const elementId of Id64.iterable(elementIds)) {\n const entry = this.#childElementsMap.get(elementId);\n if (entry?.children) {\n let totalChildrenCount = entry.children.length;\n for (const childrenOfChildCount of this.getChildElementsCountMap({ elementIds: entry.children }).values()) {\n totalChildrenCount += childrenOfChildCount;\n }\n result.set(elementId, totalChildrenCount);\n }\n }\n return result;\n }\n\n /**\n * Populates #childElementsLoadingMap with promises. When these promises resolve, they will populate #childElementsMap with values and delete entries from #childElementsLoadingMap.\n */\n private createChildElementsLoadingMapEntries({ elementsToQuery }: { elementsToQuery: Id64Array }): { loadingMapEntries: Promise<void> } {\n const getElementsToQueryPromise = async (batchedElementsToQuery: Id64Array) =>\n firstValueFrom(\n this.queryChildren({ elementIds: batchedElementsToQuery }).pipe(\n // Want to have void at the end instead of void[], so using reduce\n reduce(\n (acc, { parentId, id }) => {\n let entry = this.#childElementsMap.get(parentId);\n if (!entry) {\n entry = { children: [] };\n this.#childElementsMap.set(parentId, entry);\n }\n if (!entry.children) {\n entry.children = [];\n }\n // Add child to parent's entry and add child to children map\n entry.children.push(id);\n if (!this.#childElementsMap.has(id)) {\n this.#childElementsMap.set(id, { children: undefined });\n }\n return acc;\n },\n (() => {})(),\n ),\n tap({ complete: () => batchedElementsToQuery.forEach((elementId) => this.#childElementsLoadingMap.delete(elementId)) }),\n defaultIfEmpty((() => {})()),\n ),\n );\n const maximumBatchSize = 1000;\n const totalSize = elementsToQuery.length;\n const optimalBatchSize = getOptimalBatchSize({ totalSize, maximumBatchSize });\n const loadingMapEntries = new Array<Promise<void>>();\n // Don't want to slice if its not necessary\n if (totalSize <= maximumBatchSize) {\n loadingMapEntries.push(getElementsToQueryPromise(elementsToQuery));\n } else {\n for (let i = 0; i < elementsToQuery.length; i += optimalBatchSize) {\n loadingMapEntries.push(getElementsToQueryPromise(elementsToQuery.slice(i, i + optimalBatchSize)));\n }\n }\n\n elementsToQuery.forEach((elementId, index) => this.#childElementsLoadingMap.set(elementId, loadingMapEntries[Math.floor(index / optimalBatchSize)]));\n return { loadingMapEntries: Promise.all(loadingMapEntries).then(() => {}) };\n }\n\n private createChildElementsMapEntries({ elementIds }: { elementIds: Id64Arg }): Observable<void[]> {\n return from(Id64.iterable(elementIds)).pipe(\n reduce(\n (acc, elementId) => {\n if (this.#childElementsMap.has(elementId)) {\n return acc;\n }\n const loadingPromise = this.#childElementsLoadingMap.get(elementId);\n if (loadingPromise) {\n acc.existingPromises.push(loadingPromise);\n } else {\n acc.elementsToQuery.push(elementId);\n }\n return acc;\n },\n { existingPromises: new Array<Promise<void>>(), elementsToQuery: new Array<Id64String>() },\n ),\n mergeMap(async ({ elementsToQuery, existingPromises }) => {\n existingPromises.push(this.createChildElementsLoadingMapEntries({ elementsToQuery }).loadingMapEntries);\n return Promise.all(existingPromises);\n }),\n );\n }\n\n public getChildElementsTree({ elementIds }: { elementIds: Id64Arg }): Observable<ChildrenTree> {\n return this.createChildElementsMapEntries({ elementIds }).pipe(map(() => this.getChildElementsTreeFromMap({ elementIds })));\n }\n\n public getAllChildElementsCount({ elementIds }: { elementIds: Id64Arg }): Observable<Map<Id64String, number>> {\n return this.createChildElementsMapEntries({ elementIds }).pipe(map(() => this.getChildElementsCountMap({ elementIds })));\n }\n}\n"]}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { Observable } from "rxjs";
|
|
2
|
+
import type { GuidString, Id64Array, Id64Set, Id64String } from "@itwin/core-bentley";
|
|
3
|
+
import type { LimitingECSqlQueryExecutor } from "@itwin/presentation-hierarchies";
|
|
4
|
+
import type { ModelId } from "../Types.js";
|
|
5
|
+
import type { ModeledElementsCache } from "./ModeledElementsCache.js";
|
|
6
|
+
interface ElementModelCategoriesCacheProps {
|
|
7
|
+
queryExecutor: LimitingECSqlQueryExecutor;
|
|
8
|
+
componentId: GuidString;
|
|
9
|
+
elementClassName: string;
|
|
10
|
+
modeledElementsCache: ModeledElementsCache;
|
|
11
|
+
}
|
|
12
|
+
/** @internal */
|
|
13
|
+
export declare class ElementModelCategoriesCache {
|
|
14
|
+
#private;
|
|
15
|
+
constructor(props: ElementModelCategoriesCacheProps);
|
|
16
|
+
private queryElementModelCategories;
|
|
17
|
+
private getModelsCategoriesInfo;
|
|
18
|
+
getCategoryElementModels(props: {
|
|
19
|
+
categoryId: Id64String;
|
|
20
|
+
includeSubModels?: boolean;
|
|
21
|
+
includeOnlyIfCategoryOfTopMostElement?: boolean;
|
|
22
|
+
}): Observable<Array<ModelId>>;
|
|
23
|
+
getModelCategoryIds({ modelId, includeOnlyIfCategoryOfTopMostElement, }: {
|
|
24
|
+
modelId: Id64String;
|
|
25
|
+
includeOnlyIfCategoryOfTopMostElement?: boolean;
|
|
26
|
+
}): Observable<Id64Set>;
|
|
27
|
+
getCategoriesOfModelsTopMostElements(modelIds: Id64Array): Observable<Id64Set>;
|
|
28
|
+
getAllCategoriesOfElements(): Observable<Id64Set>;
|
|
29
|
+
getAllModels(): Observable<Array<ModelId>>;
|
|
30
|
+
}
|
|
31
|
+
export {};
|
|
32
|
+
//# sourceMappingURL=ElementModelCategoriesCache.d.ts.map
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
3
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
|
5
|
+
import { defer, forkJoin, from, map, mergeMap, reduce, shareReplay } from "rxjs";
|
|
6
|
+
import { CLASS_NAME_Model } from "../ClassNameDefinitions.js";
|
|
7
|
+
import { catchBeSQLiteInterrupts } from "../UseErrorState.js";
|
|
8
|
+
/** @internal */
|
|
9
|
+
export class ElementModelCategoriesCache {
|
|
10
|
+
#queryExecutor;
|
|
11
|
+
#componentId;
|
|
12
|
+
#componentName;
|
|
13
|
+
#elementClassName;
|
|
14
|
+
#modeledElementsCache;
|
|
15
|
+
#modelsCategoriesInfo;
|
|
16
|
+
constructor(props) {
|
|
17
|
+
this.#queryExecutor = props.queryExecutor;
|
|
18
|
+
this.#elementClassName = props.elementClassName;
|
|
19
|
+
this.#modeledElementsCache = props.modeledElementsCache;
|
|
20
|
+
this.#componentId = props.componentId;
|
|
21
|
+
this.#componentName = "ElementModelCategoriesCache";
|
|
22
|
+
}
|
|
23
|
+
queryElementModelCategories() {
|
|
24
|
+
return defer(() => {
|
|
25
|
+
const query = `
|
|
26
|
+
SELECT * FROM (
|
|
27
|
+
SELECT
|
|
28
|
+
this.Model.Id modelId,
|
|
29
|
+
this.Category.Id categoryId,
|
|
30
|
+
MAX(IIF(this.Parent.Id IS NULL, 1, 0)) isTopMostElementCategory
|
|
31
|
+
FROM ${CLASS_NAME_Model} m
|
|
32
|
+
JOIN ${this.#elementClassName} this ON m.ECInstanceId = this.Model.Id
|
|
33
|
+
WHERE m.IsPrivate = false
|
|
34
|
+
GROUP BY modelId, categoryId
|
|
35
|
+
)
|
|
36
|
+
`;
|
|
37
|
+
return this.#queryExecutor.createQueryReader({ ecsql: query }, { rowFormat: "ECSqlPropertyNames", limit: "unbounded", restartToken: `${this.#componentName}/${this.#componentId}/element-models-and-categories` });
|
|
38
|
+
}).pipe(catchBeSQLiteInterrupts, map((row) => {
|
|
39
|
+
return { modelId: row.modelId, categoryId: row.categoryId, isTopMostElementCategory: !!row.isTopMostElementCategory };
|
|
40
|
+
}));
|
|
41
|
+
}
|
|
42
|
+
getModelsCategoriesInfo() {
|
|
43
|
+
this.#modelsCategoriesInfo ??= forkJoin({
|
|
44
|
+
modelCategories: this.queryElementModelCategories().pipe(reduce((acc, queriedCategory) => {
|
|
45
|
+
let modelEntry = acc.get(queriedCategory.modelId);
|
|
46
|
+
if (modelEntry === undefined) {
|
|
47
|
+
modelEntry = { categoriesOfTopMostElements: new Set(), allCategories: new Set() };
|
|
48
|
+
acc.set(queriedCategory.modelId, modelEntry);
|
|
49
|
+
}
|
|
50
|
+
modelEntry.allCategories.add(queriedCategory.categoryId);
|
|
51
|
+
if (queriedCategory.isTopMostElementCategory) {
|
|
52
|
+
modelEntry.categoriesOfTopMostElements.add(queriedCategory.categoryId);
|
|
53
|
+
}
|
|
54
|
+
return acc;
|
|
55
|
+
}, new Map())),
|
|
56
|
+
allSubModels: this.#modeledElementsCache.getModeledElementsInfo().pipe(map(({ allSubModels }) => allSubModels)),
|
|
57
|
+
}).pipe(map(({ modelCategories, allSubModels }) => {
|
|
58
|
+
const result = new Map();
|
|
59
|
+
for (const [modelId, { categoriesOfTopMostElements, allCategories }] of modelCategories) {
|
|
60
|
+
const isSubModel = allSubModels.has(modelId);
|
|
61
|
+
result.set(modelId, {
|
|
62
|
+
categoriesOfTopMostElements,
|
|
63
|
+
allCategories,
|
|
64
|
+
isSubModel,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
68
|
+
}), shareReplay());
|
|
69
|
+
return this.#modelsCategoriesInfo;
|
|
70
|
+
}
|
|
71
|
+
getCategoryElementModels(props) {
|
|
72
|
+
const { categoryId, includeSubModels } = props;
|
|
73
|
+
return this.getModelsCategoriesInfo().pipe(map((modelCategories) => {
|
|
74
|
+
const categoryModels = new Array();
|
|
75
|
+
for (const [modelId, { allCategories, categoriesOfTopMostElements, isSubModel }] of modelCategories) {
|
|
76
|
+
if ((includeSubModels || !isSubModel) &&
|
|
77
|
+
(props.includeOnlyIfCategoryOfTopMostElement ? categoriesOfTopMostElements.has(categoryId) : allCategories.has(categoryId))) {
|
|
78
|
+
categoryModels.push(modelId);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return categoryModels;
|
|
82
|
+
}));
|
|
83
|
+
}
|
|
84
|
+
getModelCategoryIds({ modelId, includeOnlyIfCategoryOfTopMostElement, }) {
|
|
85
|
+
return this.getModelsCategoriesInfo().pipe(map((modelCategories) => (includeOnlyIfCategoryOfTopMostElement ? modelCategories.get(modelId)?.categoriesOfTopMostElements : modelCategories.get(modelId)?.allCategories) ??
|
|
86
|
+
new Set()));
|
|
87
|
+
}
|
|
88
|
+
getCategoriesOfModelsTopMostElements(modelIds) {
|
|
89
|
+
return this.getModelsCategoriesInfo().pipe(mergeMap((modelCategories) => from(modelIds).pipe(mergeMap((modelId) => modelCategories.get(modelId)?.categoriesOfTopMostElements ?? []))), reduce((acc, categoryId) => {
|
|
90
|
+
acc.add(categoryId);
|
|
91
|
+
return acc;
|
|
92
|
+
}, new Set()));
|
|
93
|
+
}
|
|
94
|
+
getAllCategoriesOfElements() {
|
|
95
|
+
return this.getModelsCategoriesInfo().pipe(mergeMap((modelCategories) => modelCategories.values()), reduce((acc, { allCategories }) => {
|
|
96
|
+
for (const categoryId of allCategories) {
|
|
97
|
+
acc.add(categoryId);
|
|
98
|
+
}
|
|
99
|
+
return acc;
|
|
100
|
+
}, new Set()));
|
|
101
|
+
}
|
|
102
|
+
getAllModels() {
|
|
103
|
+
return this.getModelsCategoriesInfo().pipe(map((modelCategories) => [...modelCategories.keys()]));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=ElementModelCategoriesCache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ElementModelCategoriesCache.js","sourceRoot":"","sources":["../../../../../../../../src/tree-widget-react/components/trees/common/internal/caches/ElementModelCategoriesCache.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { defer, forkJoin, from, map, mergeMap, reduce, shareReplay } from \"rxjs\";\nimport { CLASS_NAME_Model } from \"../ClassNameDefinitions.js\";\nimport { catchBeSQLiteInterrupts } from \"../UseErrorState.js\";\n\nimport type { Observable } from \"rxjs\";\nimport type { GuidString, Id64Array, Id64Set, Id64String } from \"@itwin/core-bentley\";\nimport type { LimitingECSqlQueryExecutor } from \"@itwin/presentation-hierarchies\";\nimport type { CategoryId, ModelId } from \"../Types.js\";\nimport type { ModeledElementsCache } from \"./ModeledElementsCache.js\";\n\ninterface ElementModelCategoriesCacheProps {\n queryExecutor: LimitingECSqlQueryExecutor;\n componentId: GuidString;\n elementClassName: string;\n modeledElementsCache: ModeledElementsCache;\n}\n\n/** @internal */\nexport class ElementModelCategoriesCache {\n #queryExecutor: LimitingECSqlQueryExecutor;\n #componentId: GuidString;\n #componentName: string;\n #elementClassName: string;\n #modeledElementsCache: ModeledElementsCache;\n #modelsCategoriesInfo:\n | Observable<Map<ModelId, { categoriesOfTopMostElements: Set<CategoryId>; allCategories: Set<CategoryId>; isSubModel: boolean }>>\n | undefined;\n\n constructor(props: ElementModelCategoriesCacheProps) {\n this.#queryExecutor = props.queryExecutor;\n this.#elementClassName = props.elementClassName;\n this.#modeledElementsCache = props.modeledElementsCache;\n this.#componentId = props.componentId;\n this.#componentName = \"ElementModelCategoriesCache\";\n }\n\n private queryElementModelCategories(): Observable<{\n modelId: Id64String;\n categoryId: Id64String;\n isTopMostElementCategory: boolean;\n }> {\n return defer(() => {\n const query = `\n SELECT * FROM (\n SELECT\n this.Model.Id modelId,\n this.Category.Id categoryId,\n MAX(IIF(this.Parent.Id IS NULL, 1, 0)) isTopMostElementCategory\n FROM ${CLASS_NAME_Model} m\n JOIN ${this.#elementClassName} this ON m.ECInstanceId = this.Model.Id\n WHERE m.IsPrivate = false\n GROUP BY modelId, categoryId\n )\n `;\n return this.#queryExecutor.createQueryReader(\n { ecsql: query },\n { rowFormat: \"ECSqlPropertyNames\", limit: \"unbounded\", restartToken: `${this.#componentName}/${this.#componentId}/element-models-and-categories` },\n );\n }).pipe(\n catchBeSQLiteInterrupts,\n map((row) => {\n return { modelId: row.modelId, categoryId: row.categoryId, isTopMostElementCategory: !!row.isTopMostElementCategory };\n }),\n );\n }\n\n private getModelsCategoriesInfo() {\n this.#modelsCategoriesInfo ??= forkJoin({\n modelCategories: this.queryElementModelCategories().pipe(\n reduce((acc, queriedCategory) => {\n let modelEntry = acc.get(queriedCategory.modelId);\n if (modelEntry === undefined) {\n modelEntry = { categoriesOfTopMostElements: new Set(), allCategories: new Set() };\n acc.set(queriedCategory.modelId, modelEntry);\n }\n modelEntry.allCategories.add(queriedCategory.categoryId);\n if (queriedCategory.isTopMostElementCategory) {\n modelEntry.categoriesOfTopMostElements.add(queriedCategory.categoryId);\n }\n return acc;\n }, new Map<ModelId, { categoriesOfTopMostElements: Set<CategoryId>; allCategories: Set<CategoryId> }>()),\n ),\n allSubModels: this.#modeledElementsCache.getModeledElementsInfo().pipe(map(({ allSubModels }) => allSubModels)),\n }).pipe(\n map(({ modelCategories, allSubModels }) => {\n const result = new Map<ModelId, { categoriesOfTopMostElements: Set<CategoryId>; allCategories: Set<CategoryId>; isSubModel: boolean }>();\n for (const [modelId, { categoriesOfTopMostElements, allCategories }] of modelCategories) {\n const isSubModel = allSubModels.has(modelId);\n result.set(modelId, {\n categoriesOfTopMostElements,\n allCategories,\n isSubModel,\n });\n }\n return result;\n }),\n shareReplay(),\n );\n return this.#modelsCategoriesInfo;\n }\n\n public getCategoryElementModels(props: {\n categoryId: Id64String;\n includeSubModels?: boolean;\n includeOnlyIfCategoryOfTopMostElement?: boolean;\n }): Observable<Array<ModelId>> {\n const { categoryId, includeSubModels } = props;\n return this.getModelsCategoriesInfo().pipe(\n map((modelCategories) => {\n const categoryModels = new Array<ModelId>();\n for (const [modelId, { allCategories, categoriesOfTopMostElements, isSubModel }] of modelCategories) {\n if (\n (includeSubModels || !isSubModel) &&\n (props.includeOnlyIfCategoryOfTopMostElement ? categoriesOfTopMostElements.has(categoryId) : allCategories.has(categoryId))\n ) {\n categoryModels.push(modelId);\n }\n }\n return categoryModels;\n }),\n );\n }\n\n public getModelCategoryIds({\n modelId,\n includeOnlyIfCategoryOfTopMostElement,\n }: {\n modelId: Id64String;\n includeOnlyIfCategoryOfTopMostElement?: boolean;\n }): Observable<Id64Set> {\n return this.getModelsCategoriesInfo().pipe(\n map(\n (modelCategories) =>\n (includeOnlyIfCategoryOfTopMostElement ? modelCategories.get(modelId)?.categoriesOfTopMostElements : modelCategories.get(modelId)?.allCategories) ??\n new Set(),\n ),\n );\n }\n\n public getCategoriesOfModelsTopMostElements(modelIds: Id64Array): Observable<Id64Set> {\n return this.getModelsCategoriesInfo().pipe(\n mergeMap((modelCategories) => from(modelIds).pipe(mergeMap((modelId) => modelCategories.get(modelId)?.categoriesOfTopMostElements ?? []))),\n reduce((acc, categoryId) => {\n acc.add(categoryId);\n return acc;\n }, new Set<Id64String>()),\n );\n }\n\n public getAllCategoriesOfElements(): Observable<Id64Set> {\n return this.getModelsCategoriesInfo().pipe(\n mergeMap((modelCategories) => modelCategories.values()),\n reduce((acc, { allCategories }) => {\n for (const categoryId of allCategories) {\n acc.add(categoryId);\n }\n return acc;\n }, new Set<CategoryId>()),\n );\n }\n\n public getAllModels(): Observable<Array<ModelId>> {\n return this.getModelsCategoriesInfo().pipe(map((modelCategories) => [...modelCategories.keys()]));\n }\n}\n"]}
|
|
@@ -4,9 +4,16 @@ import type { LimitingECSqlQueryExecutor } from "@itwin/presentation-hierarchies
|
|
|
4
4
|
/** @internal */
|
|
5
5
|
export declare class ModelCategoryElementsCountCache implements Disposable {
|
|
6
6
|
#private;
|
|
7
|
-
constructor(
|
|
7
|
+
constructor(props: {
|
|
8
|
+
queryExecutor: LimitingECSqlQueryExecutor;
|
|
9
|
+
elementClassName: string;
|
|
10
|
+
componentId: GuidString;
|
|
11
|
+
});
|
|
8
12
|
private queryCategoryElementCounts;
|
|
9
13
|
[Symbol.dispose](): void;
|
|
10
|
-
getCategoryElementsCount(modelId
|
|
14
|
+
getCategoryElementsCount({ modelId, categoryId }: {
|
|
15
|
+
modelId: Id64String;
|
|
16
|
+
categoryId: Id64String;
|
|
17
|
+
}): Observable<number>;
|
|
11
18
|
}
|
|
12
19
|
//# sourceMappingURL=ModelCategoryElementsCountCache.d.ts.map
|
|
@@ -4,21 +4,21 @@
|
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
5
|
import { bufferCount, bufferTime, defer, filter, from, map, mergeAll, mergeMap, reduce, ReplaySubject, Subject, take, toArray } from "rxjs";
|
|
6
6
|
import { assert, Guid } from "@itwin/core-bentley";
|
|
7
|
-
import { catchBeSQLiteInterrupts } from "
|
|
8
|
-
import { releaseMainThreadOnItemsCount } from "
|
|
7
|
+
import { catchBeSQLiteInterrupts } from "../UseErrorState.js";
|
|
8
|
+
import { releaseMainThreadOnItemsCount } from "../Utils.js";
|
|
9
9
|
/** @internal */
|
|
10
10
|
export class ModelCategoryElementsCountCache {
|
|
11
11
|
#cache = new Map();
|
|
12
12
|
#requestsStream = new Subject();
|
|
13
13
|
#subscription;
|
|
14
14
|
#queryExecutor;
|
|
15
|
-
#
|
|
15
|
+
#elementClassName;
|
|
16
16
|
#componentId;
|
|
17
17
|
#componentName;
|
|
18
|
-
constructor(
|
|
19
|
-
this.#componentId = componentId;
|
|
20
|
-
this.#queryExecutor = queryExecutor;
|
|
21
|
-
this.#
|
|
18
|
+
constructor(props) {
|
|
19
|
+
this.#componentId = props.componentId;
|
|
20
|
+
this.#queryExecutor = props.queryExecutor;
|
|
21
|
+
this.#elementClassName = props.elementClassName;
|
|
22
22
|
this.#componentName = "ModelCategoryElementsCountCache";
|
|
23
23
|
this.#subscription = this.#requestsStream
|
|
24
24
|
.pipe(bufferTime(20), filter((requests) => requests.length > 0), mergeMap((requests) => this.queryCategoryElementCounts(requests)), mergeAll())
|
|
@@ -44,10 +44,11 @@ export class ModelCategoryElementsCountCache {
|
|
|
44
44
|
// we may have thousands of where clauses here, and sending a single query with all of them could take a
|
|
45
45
|
// long time - instead, split it into smaller chunks
|
|
46
46
|
bufferCount(100), mergeMap((whereClauses) => defer(() => this.#queryExecutor.createQueryReader({
|
|
47
|
-
ctes:
|
|
48
|
-
|
|
47
|
+
ctes: [
|
|
48
|
+
`
|
|
49
|
+
CategoryElements(id, modelId, categoryId) AS (
|
|
49
50
|
SELECT ECInstanceId, Model.Id, Category.Id
|
|
50
|
-
FROM ${
|
|
51
|
+
FROM ${this.#elementClassName}
|
|
51
52
|
WHERE
|
|
52
53
|
Parent.Id IS NULL
|
|
53
54
|
AND (
|
|
@@ -57,19 +58,14 @@ export class ModelCategoryElementsCountCache {
|
|
|
57
58
|
UNION ALL
|
|
58
59
|
|
|
59
60
|
SELECT c.ECInstanceId, p.modelId, p.categoryId
|
|
60
|
-
FROM ${
|
|
61
|
-
JOIN CategoryElements
|
|
61
|
+
FROM ${this.#elementClassName} c
|
|
62
|
+
JOIN CategoryElements p ON c.Parent.Id = p.id
|
|
62
63
|
)
|
|
63
|
-
|
|
64
|
+
`,
|
|
65
|
+
],
|
|
64
66
|
ecsql: `
|
|
65
67
|
SELECT modelId, categoryId, COUNT(id) elementsCount
|
|
66
|
-
FROM (
|
|
67
|
-
${this.#elementsClassNames
|
|
68
|
-
.map((_, index) => `
|
|
69
|
-
SELECT * FROM CategoryElements${index}
|
|
70
|
-
`)
|
|
71
|
-
.join(" UNION ALL ")}
|
|
72
|
-
)
|
|
68
|
+
FROM (SELECT * FROM CategoryElements)
|
|
73
69
|
GROUP BY modelId, categoryId
|
|
74
70
|
`,
|
|
75
71
|
}, {
|
|
@@ -98,7 +94,7 @@ export class ModelCategoryElementsCountCache {
|
|
|
98
94
|
[Symbol.dispose]() {
|
|
99
95
|
this.#subscription.unsubscribe();
|
|
100
96
|
}
|
|
101
|
-
getCategoryElementsCount(modelId, categoryId) {
|
|
97
|
+
getCategoryElementsCount({ modelId, categoryId }) {
|
|
102
98
|
const cacheKey = `${modelId}-${categoryId}`;
|
|
103
99
|
let result = this.#cache.get(cacheKey);
|
|
104
100
|
if (result !== undefined) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ModelCategoryElementsCountCache.js","sourceRoot":"","sources":["../../../../../../../../src/tree-widget-react/components/trees/common/internal/caches/ModelCategoryElementsCountCache.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { bufferCount, bufferTime, defer, filter, from, map, mergeAll, mergeMap, reduce, ReplaySubject, Subject, take, toArray } from \"rxjs\";\nimport { assert, Guid } from \"@itwin/core-bentley\";\nimport { catchBeSQLiteInterrupts } from \"../UseErrorState.js\";\nimport { releaseMainThreadOnItemsCount } from \"../Utils.js\";\n\nimport type { Observable, Subscription } from \"rxjs\";\nimport type { GuidString, Id64Set, Id64String } from \"@itwin/core-bentley\";\nimport type { LimitingECSqlQueryExecutor } from \"@itwin/presentation-hierarchies\";\nimport type { CategoryId, ModelId } from \"../Types.js\";\n\ntype ModelCategoryKey = `${ModelId}-${CategoryId}`;\n\n/** @internal */\nexport class ModelCategoryElementsCountCache implements Disposable {\n #cache = new Map<ModelCategoryKey, Subject<number>>();\n #requestsStream = new Subject<{ modelId: Id64String; categoryId: Id64String }>();\n #subscription: Subscription;\n #queryExecutor: LimitingECSqlQueryExecutor;\n #elementClassName: string;\n #componentId: GuidString;\n #componentName: string;\n\n public constructor(props: { queryExecutor: LimitingECSqlQueryExecutor; elementClassName: string; componentId: GuidString }) {\n this.#componentId = props.componentId;\n this.#queryExecutor = props.queryExecutor;\n this.#elementClassName = props.elementClassName;\n this.#componentName = \"ModelCategoryElementsCountCache\";\n this.#subscription = this.#requestsStream\n .pipe(\n bufferTime(20),\n filter((requests) => requests.length > 0),\n mergeMap((requests) => this.queryCategoryElementCounts(requests)),\n mergeAll(),\n )\n .subscribe({\n next: ({ modelId, categoryId, elementsCount }) => {\n const subject = this.#cache.get(`${modelId}-${categoryId}`);\n assert(!!subject);\n subject.next(elementsCount);\n },\n });\n }\n\n private queryCategoryElementCounts(\n input: Array<{ modelId: Id64String; categoryId: Id64String }>,\n ): Observable<Array<{ modelId: Id64String; categoryId: Id64String; elementsCount: number }>> {\n return from(input).pipe(\n reduce((acc, { modelId, categoryId }) => {\n const entry = acc.get(modelId);\n if (!entry) {\n acc.set(modelId, new Set([categoryId]));\n } else {\n entry.add(categoryId);\n }\n return acc;\n }, new Map<Id64String, Id64Set>()),\n mergeMap((modelCategoryMap) => modelCategoryMap.entries()),\n map(([modelId, categoryIds]) => `Model.Id = ${modelId} AND Category.Id IN (${[...categoryIds].join(\", \")})`),\n // we may have thousands of where clauses here, and sending a single query with all of them could take a\n // long time - instead, split it into smaller chunks\n bufferCount(100),\n mergeMap((whereClauses) =>\n defer(() =>\n this.#queryExecutor.createQueryReader(\n {\n ctes: [\n `\n CategoryElements(id, modelId, categoryId) AS (\n SELECT ECInstanceId, Model.Id, Category.Id\n FROM ${this.#elementClassName}\n WHERE\n Parent.Id IS NULL\n AND (\n ${whereClauses.join(\" OR \")}\n )\n\n UNION ALL\n\n SELECT c.ECInstanceId, p.modelId, p.categoryId\n FROM ${this.#elementClassName} c\n JOIN CategoryElements p ON c.Parent.Id = p.id\n )\n `,\n ],\n ecsql: `\n SELECT modelId, categoryId, COUNT(id) elementsCount\n FROM (SELECT * FROM CategoryElements)\n GROUP BY modelId, categoryId\n `,\n },\n {\n rowFormat: \"ECSqlPropertyNames\",\n limit: \"unbounded\",\n restartToken: `${this.#componentName}/${this.#componentId}/category-element-counts/${Guid.createValue()}`,\n },\n ),\n ).pipe(catchBeSQLiteInterrupts),\n ),\n releaseMainThreadOnItemsCount(500),\n reduce(\n ({ acc, createKey }, row) => {\n acc.set(createKey({ modelId: row.modelId, categoryId: row.categoryId }), {\n modelId: row.modelId,\n categoryId: row.categoryId,\n elementsCount: row.elementsCount,\n });\n return { acc, createKey };\n },\n {\n acc: new Map<string, { modelId: Id64String; categoryId: Id64String; elementsCount: number }>(),\n createKey: (keyProps: { modelId: Id64String; categoryId: Id64String }) => `${keyProps.modelId}-${keyProps.categoryId}`,\n },\n ),\n mergeMap(({ acc: result, createKey }) => {\n input.forEach(({ modelId, categoryId }) => {\n if (!result.has(createKey({ modelId, categoryId }))) {\n result.set(createKey({ modelId, categoryId }), { categoryId, modelId, elementsCount: 0 });\n }\n });\n\n return from(result.values());\n }),\n toArray(),\n );\n }\n\n public [Symbol.dispose]() {\n this.#subscription.unsubscribe();\n }\n\n public getCategoryElementsCount({ modelId, categoryId }: { modelId: Id64String; categoryId: Id64String }): Observable<number> {\n const cacheKey: ModelCategoryKey = `${modelId}-${categoryId}`;\n let result = this.#cache.get(cacheKey);\n if (result !== undefined) {\n return from(result).pipe(take(1));\n }\n\n result = new ReplaySubject(1);\n this.#cache.set(cacheKey, result);\n this.#requestsStream.next({ modelId, categoryId });\n return from(result).pipe(take(1));\n }\n}\n"]}
|
package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ModeledElementsCache.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Observable } from "rxjs";
|
|
2
|
+
import type { GuidString, Id64Array, Id64String } from "@itwin/core-bentley";
|
|
3
|
+
import type { LimitingECSqlQueryExecutor } from "@itwin/presentation-hierarchies";
|
|
4
|
+
import type { CategoryId, ElementId, ModelId } from "../Types.js";
|
|
5
|
+
interface ModeledElementsCacheProps {
|
|
6
|
+
queryExecutor: LimitingECSqlQueryExecutor;
|
|
7
|
+
componentId: GuidString;
|
|
8
|
+
elementClassName: string;
|
|
9
|
+
}
|
|
10
|
+
/** @internal */
|
|
11
|
+
export declare class ModeledElementsCache {
|
|
12
|
+
#private;
|
|
13
|
+
constructor(props: ModeledElementsCacheProps);
|
|
14
|
+
private queryModeledElements;
|
|
15
|
+
getModeledElementsInfo(): Observable<{
|
|
16
|
+
modelWithCategoryModeledElements: Map<ModelId, Map<CategoryId, Set<ElementId>>>;
|
|
17
|
+
allSubModels: Set<ElementId>;
|
|
18
|
+
childSubModels: Map<ElementId, Set<ElementId>>;
|
|
19
|
+
}>;
|
|
20
|
+
getSubModelsUnderElement(elementId: Id64String): Observable<Id64Array>;
|
|
21
|
+
getCategoryModeledElements({ modelId, categoryId }: {
|
|
22
|
+
modelId: Id64String;
|
|
23
|
+
categoryId: Id64String;
|
|
24
|
+
}): Observable<Id64String>;
|
|
25
|
+
}
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=ModeledElementsCache.d.ts.map
|
package/lib/esm/tree-widget-react/components/trees/common/internal/caches/ModeledElementsCache.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
3
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
|
5
|
+
import { defer, map, mergeMap, reduce, shareReplay } from "rxjs";
|
|
6
|
+
import { CLASS_NAME_Model } from "../ClassNameDefinitions.js";
|
|
7
|
+
import { catchBeSQLiteInterrupts } from "../UseErrorState.js";
|
|
8
|
+
/** @internal */
|
|
9
|
+
export class ModeledElementsCache {
|
|
10
|
+
#queryExecutor;
|
|
11
|
+
#componentId;
|
|
12
|
+
#componentName;
|
|
13
|
+
#elementClassName;
|
|
14
|
+
// ElementId here is also a ModelId, since those elements are sub models.
|
|
15
|
+
#modeledElementsInfo;
|
|
16
|
+
constructor(props) {
|
|
17
|
+
this.#queryExecutor = props.queryExecutor;
|
|
18
|
+
this.#componentId = props.componentId;
|
|
19
|
+
this.#elementClassName = props.elementClassName;
|
|
20
|
+
this.#componentName = "ModeledElementsCache";
|
|
21
|
+
}
|
|
22
|
+
queryModeledElements() {
|
|
23
|
+
return defer(() => {
|
|
24
|
+
const query = `
|
|
25
|
+
SELECT
|
|
26
|
+
me.ECInstanceId modeledElementId,
|
|
27
|
+
me.Category.Id categoryId,
|
|
28
|
+
me.Model.Id modelId,
|
|
29
|
+
IIF(me.Parent.Id IS NULL,
|
|
30
|
+
'',
|
|
31
|
+
(
|
|
32
|
+
WITH RECURSIVE ModeledElementParents(parentId, parentPath) AS (
|
|
33
|
+
SELECT p.Parent.Id, CAST(IdToHex(p.ECInstanceId) AS TEXT)
|
|
34
|
+
FROM ${this.#elementClassName} p
|
|
35
|
+
WHERE p.ECInstanceId = me.Parent.Id
|
|
36
|
+
UNION ALL
|
|
37
|
+
SELECT pOfp.Parent.Id, CAST(IdToHex(pOfp.ECInstanceId) AS TEXT) || ';' || c.parentPath
|
|
38
|
+
FROM ${this.#elementClassName} pOfp
|
|
39
|
+
JOIN ModeledElementParents c ON c.parentId = pOfp.ECInstanceId
|
|
40
|
+
)
|
|
41
|
+
SELECT parentPath
|
|
42
|
+
FROM ModeledElementParents
|
|
43
|
+
WHERE parentId IS NULL
|
|
44
|
+
)
|
|
45
|
+
) parentElements
|
|
46
|
+
FROM ${CLASS_NAME_Model} m
|
|
47
|
+
JOIN ${this.#elementClassName} me ON me.ECInstanceId = m.ModeledElement.Id
|
|
48
|
+
WHERE
|
|
49
|
+
m.IsPrivate = false
|
|
50
|
+
AND m.ECInstanceId IN (SELECT Model.Id FROM ${this.#elementClassName})
|
|
51
|
+
`;
|
|
52
|
+
return this.#queryExecutor.createQueryReader({ ecsql: query }, { rowFormat: "ECSqlPropertyNames", limit: "unbounded", restartToken: `${this.#componentName}/${this.#componentId}/modeled-elements` });
|
|
53
|
+
}).pipe(catchBeSQLiteInterrupts, map((row) => {
|
|
54
|
+
return { modelId: row.modelId, categoryId: row.categoryId, modeledElementId: row.modeledElementId, parentElements: row.parentElements.split(";") };
|
|
55
|
+
}));
|
|
56
|
+
}
|
|
57
|
+
getModeledElementsInfo() {
|
|
58
|
+
this.#modeledElementsInfo ??= this.queryModeledElements().pipe(reduce((acc, { modelId, categoryId, modeledElementId, parentElements }) => {
|
|
59
|
+
let modelEntry = acc.modelWithCategoryModeledElements.get(modelId);
|
|
60
|
+
if (!modelEntry) {
|
|
61
|
+
modelEntry = new Map();
|
|
62
|
+
acc.modelWithCategoryModeledElements.set(modelId, modelEntry);
|
|
63
|
+
}
|
|
64
|
+
const categoryEntry = modelEntry.get(categoryId);
|
|
65
|
+
if (!categoryEntry) {
|
|
66
|
+
modelEntry.set(categoryId, new Set([modeledElementId]));
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
categoryEntry.add(modeledElementId);
|
|
70
|
+
}
|
|
71
|
+
acc.allSubModels.add(modeledElementId);
|
|
72
|
+
parentElements.forEach((parentElementId) => {
|
|
73
|
+
const entry = acc.childSubModels.get(parentElementId);
|
|
74
|
+
if (!entry) {
|
|
75
|
+
acc.childSubModels.set(parentElementId, new Set([modeledElementId]));
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
entry.add(modeledElementId);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
return acc;
|
|
82
|
+
}, {
|
|
83
|
+
modelWithCategoryModeledElements: new Map(),
|
|
84
|
+
allSubModels: new Set(),
|
|
85
|
+
childSubModels: new Map(),
|
|
86
|
+
}), shareReplay());
|
|
87
|
+
return this.#modeledElementsInfo;
|
|
88
|
+
}
|
|
89
|
+
getSubModelsUnderElement(elementId) {
|
|
90
|
+
return this.getModeledElementsInfo().pipe(map(({ allSubModels, childSubModels }) => {
|
|
91
|
+
const subModels = new Array();
|
|
92
|
+
if (allSubModels.has(elementId)) {
|
|
93
|
+
subModels.push(elementId);
|
|
94
|
+
}
|
|
95
|
+
const elementEntry = childSubModels.get(elementId);
|
|
96
|
+
for (const childSubModelId of elementEntry ?? []) {
|
|
97
|
+
subModels.push(childSubModelId);
|
|
98
|
+
}
|
|
99
|
+
return subModels;
|
|
100
|
+
}));
|
|
101
|
+
}
|
|
102
|
+
getCategoryModeledElements({ modelId, categoryId }) {
|
|
103
|
+
return this.getModeledElementsInfo().pipe(mergeMap(({ modelWithCategoryModeledElements }) => modelWithCategoryModeledElements.get(modelId)?.get(categoryId) ?? new Set()));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=ModeledElementsCache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ModeledElementsCache.js","sourceRoot":"","sources":["../../../../../../../../src/tree-widget-react/components/trees/common/internal/caches/ModeledElementsCache.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { defer, map, mergeMap, reduce, shareReplay } from \"rxjs\";\nimport { CLASS_NAME_Model } from \"../ClassNameDefinitions.js\";\nimport { catchBeSQLiteInterrupts } from \"../UseErrorState.js\";\n\nimport type { Observable } from \"rxjs\";\nimport type { GuidString, Id64Array, Id64String } from \"@itwin/core-bentley\";\nimport type { LimitingECSqlQueryExecutor } from \"@itwin/presentation-hierarchies\";\nimport type { CategoryId, ElementId, ModelId } from \"../Types.js\";\n\ninterface ModeledElementsCacheProps {\n queryExecutor: LimitingECSqlQueryExecutor;\n componentId: GuidString;\n elementClassName: string;\n}\n\n/** @internal */\nexport class ModeledElementsCache {\n #queryExecutor: LimitingECSqlQueryExecutor;\n #componentId: GuidString;\n #componentName: string;\n #elementClassName: string;\n // ElementId here is also a ModelId, since those elements are sub models.\n #modeledElementsInfo:\n | Observable<{\n modelWithCategoryModeledElements: Map<ModelId, Map<CategoryId, Set<ElementId>>>;\n allSubModels: Set<ElementId>;\n childSubModels: Map<ElementId, Set<ElementId>>;\n }>\n | undefined;\n\n constructor(props: ModeledElementsCacheProps) {\n this.#queryExecutor = props.queryExecutor;\n this.#componentId = props.componentId;\n this.#elementClassName = props.elementClassName;\n this.#componentName = \"ModeledElementsCache\";\n }\n\n private queryModeledElements(): Observable<{\n modelId: Id64String;\n modeledElementId: Id64String;\n categoryId: Id64String;\n parentElements: Id64Array;\n }> {\n return defer(() => {\n const query = `\n SELECT\n me.ECInstanceId modeledElementId,\n me.Category.Id categoryId,\n me.Model.Id modelId,\n IIF(me.Parent.Id IS NULL,\n '',\n (\n WITH RECURSIVE ModeledElementParents(parentId, parentPath) AS (\n SELECT p.Parent.Id, CAST(IdToHex(p.ECInstanceId) AS TEXT)\n FROM ${this.#elementClassName} p\n WHERE p.ECInstanceId = me.Parent.Id\n UNION ALL\n SELECT pOfp.Parent.Id, CAST(IdToHex(pOfp.ECInstanceId) AS TEXT) || ';' || c.parentPath\n FROM ${this.#elementClassName} pOfp\n JOIN ModeledElementParents c ON c.parentId = pOfp.ECInstanceId\n )\n SELECT parentPath\n FROM ModeledElementParents\n WHERE parentId IS NULL\n )\n ) parentElements\n FROM ${CLASS_NAME_Model} m\n JOIN ${this.#elementClassName} me ON me.ECInstanceId = m.ModeledElement.Id\n WHERE\n m.IsPrivate = false\n AND m.ECInstanceId IN (SELECT Model.Id FROM ${this.#elementClassName})\n `;\n return this.#queryExecutor.createQueryReader(\n { ecsql: query },\n { rowFormat: \"ECSqlPropertyNames\", limit: \"unbounded\", restartToken: `${this.#componentName}/${this.#componentId}/modeled-elements` },\n );\n }).pipe(\n catchBeSQLiteInterrupts,\n map((row) => {\n return { modelId: row.modelId, categoryId: row.categoryId, modeledElementId: row.modeledElementId, parentElements: row.parentElements.split(\";\") };\n }),\n );\n }\n\n public getModeledElementsInfo() {\n this.#modeledElementsInfo ??= this.queryModeledElements().pipe(\n reduce(\n (acc, { modelId, categoryId, modeledElementId, parentElements }) => {\n let modelEntry = acc.modelWithCategoryModeledElements.get(modelId);\n if (!modelEntry) {\n modelEntry = new Map();\n acc.modelWithCategoryModeledElements.set(modelId, modelEntry);\n }\n const categoryEntry = modelEntry.get(categoryId);\n if (!categoryEntry) {\n modelEntry.set(categoryId, new Set([modeledElementId]));\n } else {\n categoryEntry.add(modeledElementId);\n }\n acc.allSubModels.add(modeledElementId);\n parentElements.forEach((parentElementId) => {\n const entry = acc.childSubModels.get(parentElementId);\n if (!entry) {\n acc.childSubModels.set(parentElementId, new Set([modeledElementId]));\n } else {\n entry.add(modeledElementId);\n }\n });\n return acc;\n },\n {\n modelWithCategoryModeledElements: new Map<ModelId, Map<CategoryId, Set<ElementId>>>(),\n allSubModels: new Set<ElementId>(),\n childSubModels: new Map<ElementId, Set<ElementId>>(),\n },\n ),\n shareReplay(),\n );\n return this.#modeledElementsInfo;\n }\n\n public getSubModelsUnderElement(elementId: Id64String): Observable<Id64Array> {\n return this.getModeledElementsInfo().pipe(\n map(({ allSubModels, childSubModels }) => {\n const subModels = new Array<ElementId>();\n if (allSubModels.has(elementId)) {\n subModels.push(elementId);\n }\n const elementEntry = childSubModels.get(elementId);\n for (const childSubModelId of elementEntry ?? []) {\n subModels.push(childSubModelId);\n }\n return subModels;\n }),\n );\n }\n\n public getCategoryModeledElements({ modelId, categoryId }: { modelId: Id64String; categoryId: Id64String }): Observable<Id64String> {\n return this.getModeledElementsInfo().pipe(\n mergeMap(({ modelWithCategoryModeledElements }) => modelWithCategoryModeledElements.get(modelId)?.get(categoryId) ?? new Set<Id64String>()),\n );\n }\n}\n"]}
|