@itwin/tree-widget-react 4.0.0-alpha.6 → 4.0.0-alpha.7
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 +22 -1
- package/README.md +2 -1
- package/lib/esm/tree-widget-react/TreeWidget.js +1 -1
- package/lib/esm/tree-widget-react/TreeWidget.js.map +1 -1
- package/lib/esm/tree-widget-react/components/tree-header/SearchBox.d.ts +1 -0
- package/lib/esm/tree-widget-react/components/tree-header/SearchBox.js +1 -0
- package/lib/esm/tree-widget-react/components/tree-header/SearchBox.js.map +1 -1
- package/lib/esm/tree-widget-react/components/tree-header/SelectableTree.css +2 -0
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.d.ts +9 -2
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js +50 -4
- 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.js +1 -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 +17 -3
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js +561 -161
- 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/UseCategoriesTree.d.ts +6 -2
- package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js +115 -40
- 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 +30 -15
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js +192 -38
- 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/CategoriesTreeNode.d.ts +18 -3
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeNode.js +30 -3
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeNode.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeVisibilityHandler.d.ts +24 -0
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeVisibilityHandler.js +785 -0
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeVisibilityHandler.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/FilteredTree.d.ts +39 -0
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/FilteredTree.js +221 -0
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/FilteredTree.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.d.ts +5 -17
- package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js +5 -62
- package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/UseHierarchyVisibility.d.ts +2 -0
- package/lib/esm/tree-widget-react/components/trees/common/UseHierarchyVisibility.js +4 -2
- package/lib/esm/tree-widget-react/components/trees/common/UseHierarchyVisibility.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/UseNodeHighlighting.d.ts +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/UseNodeHighlighting.js +2 -1
- package/lib/esm/tree-widget-react/components/trees/common/UseNodeHighlighting.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/UseTelemetryContext.d.ts +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/UseTelemetryContext.js +2 -1
- package/lib/esm/tree-widget-react/components/trees/common/UseTelemetryContext.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/Utils.d.ts +33 -23
- package/lib/esm/tree-widget-react/components/trees/common/Utils.js +60 -47
- package/lib/esm/tree-widget-react/components/trees/common/Utils.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/BaseTreeRenderer.js +3 -3
- package/lib/esm/tree-widget-react/components/trees/common/components/BaseTreeRenderer.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/Delayed.d.ts +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/components/Delayed.js +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/components/Delayed.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/ProgressOverlay.d.ts +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/components/ProgressOverlay.js +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/components/ProgressOverlay.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/Tree.css +2 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/Tree.js +4 -4
- 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/UseVisibilityButtonHandler.d.ts +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/components/UseVisibilityButtonHandler.js +1 -0
- 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/VisibilityTree.js +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTree.js.map +1 -1
- 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/AlwaysAndNeverDrawnElementInfo.d.ts +44 -0
- package/lib/esm/tree-widget-react/components/trees/{models-tree → common}/internal/AlwaysAndNeverDrawnElementInfo.js +81 -31
- package/lib/esm/tree-widget-react/components/trees/common/internal/AlwaysAndNeverDrawnElementInfo.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/ClassNameDefinitions.d.ts +33 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/ClassNameDefinitions.js +37 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/ClassNameDefinitions.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/ModelCategoryElementsCountCache.d.ts +16 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/ModelCategoryElementsCountCache.js +72 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/ModelCategoryElementsCountCache.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/{Rxjs.d.ts → internal/Rxjs.d.ts} +9 -2
- package/lib/esm/tree-widget-react/components/trees/common/{Rxjs.js → internal/Rxjs.js} +9 -2
- package/lib/esm/tree-widget-react/components/trees/common/internal/Rxjs.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/{Tooltip.d.ts → internal/Tooltip.d.ts} +5 -1
- package/lib/esm/tree-widget-react/components/trees/common/{Tooltip.js → internal/Tooltip.js} +7 -1
- package/lib/esm/tree-widget-react/components/trees/common/internal/Tooltip.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/Types.d.ts +14 -0
- package/lib/esm/tree-widget-react/components/trees/{categories-tree/internal/ClassNameDefinitions.js → common/internal/Types.js} +2 -7
- package/lib/esm/tree-widget-react/components/trees/common/internal/Types.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/UseActiveViewport.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/{UseHierarchiesLocalization.d.ts → internal/UseHierarchiesLocalization.d.ts} +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/{UseHierarchiesLocalization.js → internal/UseHierarchiesLocalization.js} +6 -2
- package/lib/esm/tree-widget-react/components/trees/common/internal/UseHierarchiesLocalization.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/{UseHierarchyFiltering.d.ts → internal/UseHierarchyFiltering.d.ts} +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/{UseHierarchyFiltering.js → internal/UseHierarchyFiltering.js} +4 -3
- package/lib/esm/tree-widget-react/components/trees/common/internal/UseHierarchyFiltering.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/{UseIModelChangeListener.d.ts → internal/UseIModelChangeListener.d.ts} +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/{UseIModelChangeListener.js → internal/UseIModelChangeListener.js} +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/UseIModelChangeListener.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.d.ts +47 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.js +101 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/Utils.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityChangeEventListener.d.ts +20 -0
- package/lib/esm/tree-widget-react/components/trees/{models-tree → common}/internal/VisibilityChangeEventListener.js +17 -9
- package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityChangeEventListener.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityUtils.d.ts +82 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityUtils.js +234 -0
- package/lib/esm/tree-widget-react/components/trees/common/internal/VisibilityUtils.js.map +1 -0
- 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/external-sources-tree/ExternalSourcesTreeDefinition.d.ts +1 -0
- package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeDefinition.js +1 -0
- package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeDefinition.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.d.ts +3 -1
- package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.js +13 -9
- 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.d.ts +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.d.ts +13 -0
- package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeDefinition.js +39 -38
- 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.d.ts +5 -5
- package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/internal/IModelContentTreeIdsCache.js +25 -24
- 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/models-tree/ModelsTreeButtons.js +9 -5
- 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.js +1 -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 +7 -2
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js +73 -70
- 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/UseModelsTree.js +47 -29
- 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/FilteredTree.d.ts +7 -9
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js +4 -6
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.d.ts +4 -5
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js +54 -104
- 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/ModelsTreeVisibilityHandler.d.ts +0 -26
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js +75 -291
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js.map +1 -1
- package/lib/public/locales/en/TreeWidget.json +51 -6
- package/package.json +17 -18
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.d.ts +0 -37
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js +0 -214
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js.map +0 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/ClassNameDefinitions.d.ts +0 -7
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/ClassNameDefinitions.js.map +0 -1
- package/lib/esm/tree-widget-react/components/trees/common/Rxjs.js.map +0 -1
- package/lib/esm/tree-widget-react/components/trees/common/Tooltip.js.map +0 -1
- package/lib/esm/tree-widget-react/components/trees/common/UseActiveViewport.js.map +0 -1
- package/lib/esm/tree-widget-react/components/trees/common/UseFiltering.d.ts +0 -11
- package/lib/esm/tree-widget-react/components/trees/common/UseFiltering.js +0 -24
- package/lib/esm/tree-widget-react/components/trees/common/UseFiltering.js.map +0 -1
- package/lib/esm/tree-widget-react/components/trees/common/UseHierarchiesLocalization.js.map +0 -1
- package/lib/esm/tree-widget-react/components/trees/common/UseHierarchyFiltering.js.map +0 -1
- package/lib/esm/tree-widget-react/components/trees/common/UseIModelChangeListener.js.map +0 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.d.ts +0 -7
- package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.js +0 -21
- package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.js.map +0 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.d.ts +0 -29
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js.map +0 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/VisibilityChangeEventListener.d.ts +0 -12
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/VisibilityChangeEventListener.js.map +0 -1
- /package/lib/esm/tree-widget-react/components/trees/common/{UseActiveViewport.d.ts → internal/UseActiveViewport.d.ts} +0 -0
- /package/lib/esm/tree-widget-react/components/trees/common/{UseActiveViewport.js → internal/UseActiveViewport.js} +0 -0
package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js
CHANGED
|
@@ -2,21 +2,23 @@
|
|
|
2
2
|
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
3
3
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
|
-
import { defer,
|
|
6
|
-
import {
|
|
5
|
+
import { bufferCount, defer, firstValueFrom, from, lastValueFrom, map, merge, mergeMap, of, reduce, toArray } from "rxjs";
|
|
6
|
+
import { assert } from "@itwin/core-bentley";
|
|
7
|
+
import { createNodesQueryClauseFactory, createPredicateBasedHierarchyDefinition, ProcessedHierarchyNode } from "@itwin/presentation-hierarchies";
|
|
7
8
|
import { createBisInstanceLabelSelectClauseFactory, ECSql } from "@itwin/presentation-shared";
|
|
9
|
+
import { DEFINITION_CONTAINER_CLASS_NAME, INFORMATION_PARTITION_ELEMENT_CLASS_NAME, MODEL_CLASS_NAME, SUB_CATEGORY_CLASS_NAME, SUB_MODELED_ELEMENT_CLASS_NAME, } from "../common/internal/ClassNameDefinitions.js";
|
|
10
|
+
import { createIdsSelector, getClassesByView, getDistinctMapValues, parseIdsSelectorResult, releaseMainThreadOnItemsCount } from "../common/internal/Utils.js";
|
|
8
11
|
import { FilterLimitExceededError } from "../common/TreeErrors.js";
|
|
9
|
-
import { getClassesByView } from "./internal/CategoriesTreeIdsCache.js";
|
|
10
|
-
import { DEFINITION_CONTAINER_CLASS, DEFINITION_ELEMENT_CLASS, SUB_CATEGORY_CLASS } from "./internal/ClassNameDefinitions.js";
|
|
11
12
|
const MAX_FILTERING_INSTANCE_KEY_COUNT = 100;
|
|
12
13
|
/** @internal */
|
|
13
14
|
export const defaultHierarchyConfiguration = {
|
|
14
15
|
hideSubCategories: false,
|
|
16
|
+
showElements: false,
|
|
15
17
|
};
|
|
18
|
+
/** @internal */
|
|
16
19
|
export class CategoriesTreeDefinition {
|
|
17
20
|
constructor(props) {
|
|
18
21
|
this._iModelAccess = props.imodelAccess;
|
|
19
|
-
this._viewType = props.viewType;
|
|
20
22
|
this._idsCache = props.idsCache;
|
|
21
23
|
this._nodeLabelSelectClauseFactory = createBisInstanceLabelSelectClauseFactory({ classHierarchyInspector: props.imodelAccess });
|
|
22
24
|
this._selectQueryFactory = createNodesQueryClauseFactory({
|
|
@@ -24,6 +26,40 @@ export class CategoriesTreeDefinition {
|
|
|
24
26
|
instanceLabelSelectClauseFactory: this._nodeLabelSelectClauseFactory,
|
|
25
27
|
});
|
|
26
28
|
this._hierarchyConfig = props.hierarchyConfig;
|
|
29
|
+
const { categoryClass, elementClass, modelClass } = getClassesByView(props.viewType);
|
|
30
|
+
this._categoryClass = categoryClass;
|
|
31
|
+
this._categoryElementClass = elementClass;
|
|
32
|
+
this._categoryModelClass = modelClass;
|
|
33
|
+
}
|
|
34
|
+
async postProcessNode(node) {
|
|
35
|
+
if (ProcessedHierarchyNode.isGroupingNode(node)) {
|
|
36
|
+
const modelElementsMap = new Map();
|
|
37
|
+
node.children.forEach((child) => {
|
|
38
|
+
let modelEntry = modelElementsMap.get(child.extendedData?.modelId);
|
|
39
|
+
if (!modelEntry) {
|
|
40
|
+
modelEntry = new Set();
|
|
41
|
+
modelElementsMap.set(child.extendedData?.modelId, modelEntry);
|
|
42
|
+
}
|
|
43
|
+
assert(child.key.type === "instances");
|
|
44
|
+
for (const { id } of child.key.instanceKeys) {
|
|
45
|
+
modelEntry.add(id);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
return {
|
|
49
|
+
...node,
|
|
50
|
+
label: node.label,
|
|
51
|
+
extendedData: {
|
|
52
|
+
...node.extendedData,
|
|
53
|
+
// add `categoryId` from the first grouped element
|
|
54
|
+
categoryId: node.children[0].extendedData?.categoryId,
|
|
55
|
+
modelElementsMap,
|
|
56
|
+
// `imageId` is assigned to instance nodes at query time, but grouping ones need to
|
|
57
|
+
// be handled during post-processing
|
|
58
|
+
imageId: "icon-ec-class",
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
return node;
|
|
27
63
|
}
|
|
28
64
|
async getHierarchyDefinition() {
|
|
29
65
|
this._impl ??= (async () => {
|
|
@@ -31,24 +67,37 @@ export class CategoriesTreeDefinition {
|
|
|
31
67
|
return createPredicateBasedHierarchyDefinition({
|
|
32
68
|
classHierarchyInspector: this._iModelAccess,
|
|
33
69
|
hierarchy: {
|
|
34
|
-
rootNodes: async (requestProps) => this.createDefinitionContainersAndCategoriesQuery(
|
|
70
|
+
rootNodes: async (requestProps) => this.createDefinitionContainersAndCategoriesQuery(requestProps),
|
|
35
71
|
childNodes: [
|
|
36
|
-
...(this._hierarchyConfig.
|
|
72
|
+
...(this._hierarchyConfig.showElements
|
|
73
|
+
? [
|
|
74
|
+
{
|
|
75
|
+
parentInstancesNodePredicate: this._categoryElementClass,
|
|
76
|
+
definitions: async (requestProps) => this.createElementChildrenQuery(requestProps),
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
parentInstancesNodePredicate: SUB_MODELED_ELEMENT_CLASS_NAME,
|
|
80
|
+
definitions: async (requestProps) => this.createISubModeledElementChildrenQuery(requestProps),
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
parentInstancesNodePredicate: this._categoryModelClass,
|
|
84
|
+
definitions: async (requestProps) => this.createGeometricModel3dChildrenQuery(requestProps),
|
|
85
|
+
},
|
|
86
|
+
]
|
|
87
|
+
: []),
|
|
88
|
+
...(this._hierarchyConfig.hideSubCategories && !this._hierarchyConfig.showElements
|
|
37
89
|
? []
|
|
38
90
|
: [
|
|
39
91
|
{
|
|
40
|
-
parentInstancesNodePredicate:
|
|
41
|
-
definitions: async (requestProps) => this.
|
|
92
|
+
parentInstancesNodePredicate: this._categoryClass,
|
|
93
|
+
definitions: async (requestProps) => this.createCategoryChildrenQuery(requestProps),
|
|
42
94
|
},
|
|
43
95
|
]),
|
|
44
96
|
...(isDefinitionContainerSupported
|
|
45
97
|
? [
|
|
46
98
|
{
|
|
47
|
-
parentInstancesNodePredicate:
|
|
48
|
-
definitions: async (requestProps) => this.createDefinitionContainersAndCategoriesQuery(
|
|
49
|
-
...requestProps,
|
|
50
|
-
viewType: this._viewType,
|
|
51
|
-
}),
|
|
99
|
+
parentInstancesNodePredicate: DEFINITION_CONTAINER_CLASS_NAME,
|
|
100
|
+
definitions: async (requestProps) => this.createDefinitionContainersAndCategoriesQuery(requestProps),
|
|
52
101
|
},
|
|
53
102
|
]
|
|
54
103
|
: []),
|
|
@@ -61,118 +110,215 @@ export class CategoriesTreeDefinition {
|
|
|
61
110
|
async defineHierarchyLevel(props) {
|
|
62
111
|
return (await this.getHierarchyDefinition()).defineHierarchyLevel(props);
|
|
63
112
|
}
|
|
113
|
+
async createISubModeledElementChildrenQuery({ parentNodeInstanceIds: elementIds, }) {
|
|
114
|
+
// note: we do not apply hierarchy level filtering on this hierarchy level, because it's always
|
|
115
|
+
// hidden - the filter will get applied on the child hierarchy levels
|
|
116
|
+
return [
|
|
117
|
+
{
|
|
118
|
+
fullClassName: this._categoryModelClass,
|
|
119
|
+
query: {
|
|
120
|
+
ecsql: `
|
|
121
|
+
SELECT
|
|
122
|
+
${await this._selectQueryFactory.createSelectClause({
|
|
123
|
+
ecClassId: { selector: "this.ECClassId" },
|
|
124
|
+
ecInstanceId: { selector: "this.ECInstanceId" },
|
|
125
|
+
nodeLabel: "",
|
|
126
|
+
hideNodeInHierarchy: true,
|
|
127
|
+
hasChildren: true,
|
|
128
|
+
extendedData: {
|
|
129
|
+
isModel: true,
|
|
130
|
+
},
|
|
131
|
+
})}
|
|
132
|
+
FROM ${this._categoryModelClass} this
|
|
133
|
+
WHERE
|
|
134
|
+
this.ModeledElement.Id IN (${elementIds.map(() => "?").join(",")})
|
|
135
|
+
AND NOT this.IsPrivate
|
|
136
|
+
AND this.ECInstanceId IN (SELECT Model.Id FROM ${this._categoryElementClass})
|
|
137
|
+
`,
|
|
138
|
+
bindings: [...elementIds.map((id) => ({ type: "id", value: id }))],
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
];
|
|
142
|
+
}
|
|
143
|
+
async createGeometricModel3dChildrenQuery({ parentNodeInstanceIds: modelIds, instanceFilter, }) {
|
|
144
|
+
const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({
|
|
145
|
+
filter: instanceFilter,
|
|
146
|
+
contentClass: { fullName: this._categoryClass, alias: "this" },
|
|
147
|
+
});
|
|
148
|
+
return [
|
|
149
|
+
{
|
|
150
|
+
fullClassName: this._categoryClass,
|
|
151
|
+
query: {
|
|
152
|
+
ecsql: `
|
|
153
|
+
SELECT
|
|
154
|
+
${await this._selectQueryFactory.createSelectClause({
|
|
155
|
+
ecClassId: { selector: "this.ECClassId" },
|
|
156
|
+
ecInstanceId: { selector: "this.ECInstanceId" },
|
|
157
|
+
nodeLabel: {
|
|
158
|
+
selector: await this._nodeLabelSelectClauseFactory.createSelectClause({
|
|
159
|
+
classAlias: "this",
|
|
160
|
+
className: this._categoryClass,
|
|
161
|
+
}),
|
|
162
|
+
},
|
|
163
|
+
grouping: { byLabel: { action: "merge", groupId: "category" } },
|
|
164
|
+
hasChildren: true,
|
|
165
|
+
extendedData: {
|
|
166
|
+
imageId: "icon-layers",
|
|
167
|
+
isCategory: true,
|
|
168
|
+
modelIds: { selector: createIdsSelector(modelIds) },
|
|
169
|
+
isCategoryOfSubModel: true,
|
|
170
|
+
},
|
|
171
|
+
supportsFiltering: true,
|
|
172
|
+
})}
|
|
173
|
+
FROM ${instanceFilterClauses.from} this
|
|
174
|
+
${instanceFilterClauses.joins}
|
|
175
|
+
WHERE
|
|
176
|
+
EXISTS (
|
|
177
|
+
SELECT 1
|
|
178
|
+
FROM ${this._categoryElementClass} element
|
|
179
|
+
WHERE
|
|
180
|
+
element.Model.Id IN (${modelIds.join(",")})
|
|
181
|
+
AND element.Category.Id = +this.ECInstanceId
|
|
182
|
+
AND element.Parent.Id IS NULL
|
|
183
|
+
)
|
|
184
|
+
${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : ""}
|
|
185
|
+
`,
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
];
|
|
189
|
+
}
|
|
64
190
|
async createDefinitionContainersAndCategoriesQuery(props) {
|
|
65
|
-
const { parentNodeInstanceIds, instanceFilter
|
|
191
|
+
const { parentNodeInstanceIds, instanceFilter } = props;
|
|
66
192
|
const { definitionContainers, categories } = parentNodeInstanceIds === undefined
|
|
67
193
|
? await this._idsCache.getRootDefinitionContainersAndCategories()
|
|
68
194
|
: await this._idsCache.getDirectChildDefinitionContainersAndCategories(parentNodeInstanceIds);
|
|
69
|
-
|
|
70
|
-
|
|
195
|
+
const hierarchyDefinition = new Array();
|
|
196
|
+
if (categories.length > 0) {
|
|
197
|
+
hierarchyDefinition.push(...(await this.createCategoriesQuery({ categories, instanceFilter })));
|
|
71
198
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
categoriesWithSingleChild.push(category.id);
|
|
80
|
-
}
|
|
81
|
-
});
|
|
82
|
-
const dataToDetermineHasChildren = categoriesWithSingleChild.length > categoriesWithMultipleChildren.length
|
|
83
|
-
? { ids: categoriesWithMultipleChildren, ifTrue: 1, ifFalse: 0 }
|
|
84
|
-
: { ids: categoriesWithSingleChild, ifTrue: 0, ifFalse: 1 };
|
|
85
|
-
const { categoryClass } = getClassesByView(viewType);
|
|
86
|
-
const [categoriesInstanceFilterClauses, definitionContainersInstanceFilterClauses] = await Promise.all([categoryClass, ...(definitionContainers.length > 0 ? [DEFINITION_CONTAINER_CLASS] : [])].map(async (className) => this._selectQueryFactory.createFilterClauses({
|
|
199
|
+
if (definitionContainers.length > 0) {
|
|
200
|
+
hierarchyDefinition.push(...(await this.createDefinitionContainersQuery({ definitionContainerIds: definitionContainers, instanceFilter })));
|
|
201
|
+
}
|
|
202
|
+
return hierarchyDefinition;
|
|
203
|
+
}
|
|
204
|
+
async createDefinitionContainersQuery({ definitionContainerIds, instanceFilter, }) {
|
|
205
|
+
const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({
|
|
87
206
|
filter: instanceFilter,
|
|
88
|
-
contentClass: { fullName:
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
nodeLabel: {
|
|
97
|
-
selector: await this._nodeLabelSelectClauseFactory.createSelectClause({
|
|
98
|
-
classAlias: "this",
|
|
99
|
-
className: DEFINITION_CONTAINER_CLASS,
|
|
100
|
-
}),
|
|
101
|
-
},
|
|
102
|
-
extendedData: {
|
|
103
|
-
isDefinitionContainer: true,
|
|
104
|
-
imageId: "icon-definition-container",
|
|
105
|
-
},
|
|
106
|
-
hasChildren: true,
|
|
107
|
-
supportsFiltering: true,
|
|
108
|
-
})}
|
|
109
|
-
FROM
|
|
110
|
-
${definitionContainersInstanceFilterClauses.from} this
|
|
111
|
-
${definitionContainersInstanceFilterClauses.joins}
|
|
112
|
-
WHERE
|
|
113
|
-
this.ECInstanceId IN (${definitionContainers.join(", ")})
|
|
114
|
-
${definitionContainersInstanceFilterClauses.where ? `AND ${definitionContainersInstanceFilterClauses.where}` : ""}
|
|
115
|
-
`
|
|
116
|
-
: undefined;
|
|
117
|
-
const categoriesQuery = categories.length > 0
|
|
118
|
-
? `
|
|
119
|
-
SELECT
|
|
207
|
+
contentClass: { fullName: DEFINITION_CONTAINER_CLASS_NAME, alias: "this" },
|
|
208
|
+
});
|
|
209
|
+
return [
|
|
210
|
+
{
|
|
211
|
+
fullClassName: DEFINITION_CONTAINER_CLASS_NAME,
|
|
212
|
+
query: {
|
|
213
|
+
ecsql: `
|
|
214
|
+
SELECT
|
|
120
215
|
${await this._selectQueryFactory.createSelectClause({
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
${dataToDetermineHasChildren.ifTrue},
|
|
137
|
-
${dataToDetermineHasChildren.ifFalse}
|
|
138
|
-
)
|
|
139
|
-
`,
|
|
140
|
-
},
|
|
141
|
-
}
|
|
142
|
-
: { hasChildren: !!dataToDetermineHasChildren.ifFalse }),
|
|
143
|
-
extendedData: {
|
|
144
|
-
description: { selector: "this.Description" },
|
|
145
|
-
isCategory: true,
|
|
146
|
-
imageId: "icon-layers",
|
|
147
|
-
},
|
|
148
|
-
supportsFiltering: true,
|
|
149
|
-
})}
|
|
216
|
+
ecClassId: { selector: ECSql.createRawPropertyValueSelector("this", "ECClassId") },
|
|
217
|
+
ecInstanceId: { selector: "this.ECInstanceId" },
|
|
218
|
+
nodeLabel: {
|
|
219
|
+
selector: await this._nodeLabelSelectClauseFactory.createSelectClause({
|
|
220
|
+
classAlias: "this",
|
|
221
|
+
className: DEFINITION_CONTAINER_CLASS_NAME,
|
|
222
|
+
}),
|
|
223
|
+
},
|
|
224
|
+
extendedData: {
|
|
225
|
+
isDefinitionContainer: true,
|
|
226
|
+
imageId: "icon-definition-container",
|
|
227
|
+
},
|
|
228
|
+
hasChildren: true,
|
|
229
|
+
supportsFiltering: true,
|
|
230
|
+
})}
|
|
150
231
|
FROM
|
|
151
|
-
${
|
|
152
|
-
${
|
|
232
|
+
${instanceFilterClauses.from} this
|
|
233
|
+
${instanceFilterClauses.joins}
|
|
153
234
|
WHERE
|
|
154
|
-
this.ECInstanceId IN (${
|
|
155
|
-
${
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
235
|
+
this.ECInstanceId IN (${definitionContainerIds.join(", ")})
|
|
236
|
+
${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : ""}
|
|
237
|
+
`,
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
];
|
|
241
|
+
}
|
|
242
|
+
async createCategoriesQuery({ categories, instanceFilter, }) {
|
|
243
|
+
const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({
|
|
244
|
+
filter: instanceFilter,
|
|
245
|
+
contentClass: { fullName: this._categoryClass, alias: "this" },
|
|
246
|
+
});
|
|
247
|
+
const categoriesWithMultipleSubCategories = categories
|
|
248
|
+
.filter((categoryInfo) => categoryInfo.subCategoryChildCount > 1)
|
|
249
|
+
.map((categoryInfo) => categoryInfo.id);
|
|
250
|
+
const hasChildrenSelector = () => {
|
|
251
|
+
const conditions = new Array();
|
|
252
|
+
if (!this._hierarchyConfig.hideSubCategories && categoriesWithMultipleSubCategories.length > 0) {
|
|
253
|
+
conditions.push(`this.ECInstanceId IN (${categoriesWithMultipleSubCategories.join(",")})`);
|
|
254
|
+
}
|
|
255
|
+
if (this._hierarchyConfig.showElements) {
|
|
256
|
+
conditions.push(`
|
|
257
|
+
this.ECInstanceId IN (
|
|
258
|
+
SELECT e.Category.Id
|
|
259
|
+
FROM ${this._categoryElementClass} e
|
|
260
|
+
WHERE
|
|
261
|
+
e.Parent.Id IS NULL
|
|
262
|
+
AND e.ECInstanceId NOT IN (SELECT m.ECInstanceId FROM ${this._categoryModelClass} m)
|
|
263
|
+
)`);
|
|
264
|
+
}
|
|
265
|
+
return conditions.length > 0
|
|
266
|
+
? {
|
|
267
|
+
selector: `IIF(${conditions.join(" OR ")}, 1, 0)`,
|
|
268
|
+
}
|
|
269
|
+
: false;
|
|
270
|
+
};
|
|
159
271
|
return [
|
|
160
272
|
{
|
|
161
|
-
fullClassName:
|
|
273
|
+
fullClassName: this._categoryClass,
|
|
162
274
|
query: {
|
|
163
|
-
ecsql:
|
|
275
|
+
ecsql: `
|
|
276
|
+
SELECT
|
|
277
|
+
${await this._selectQueryFactory.createSelectClause({
|
|
278
|
+
ecClassId: { selector: ECSql.createRawPropertyValueSelector("this", "ECClassId") },
|
|
279
|
+
ecInstanceId: { selector: "this.ECInstanceId" },
|
|
280
|
+
nodeLabel: {
|
|
281
|
+
selector: await this._nodeLabelSelectClauseFactory.createSelectClause({
|
|
282
|
+
classAlias: "this",
|
|
283
|
+
className: this._categoryClass,
|
|
284
|
+
}),
|
|
285
|
+
},
|
|
286
|
+
hasChildren: hasChildrenSelector(),
|
|
287
|
+
extendedData: {
|
|
288
|
+
description: { selector: "this.Description" },
|
|
289
|
+
isCategory: true,
|
|
290
|
+
imageId: "icon-layers",
|
|
291
|
+
hasSubCategories: categoriesWithMultipleSubCategories.length > 0
|
|
292
|
+
? { selector: `IIF(this.ECInstanceId IN (${categoriesWithMultipleSubCategories.join(",")}), true, false) ` }
|
|
293
|
+
: false,
|
|
294
|
+
},
|
|
295
|
+
supportsFiltering: true,
|
|
296
|
+
})}
|
|
297
|
+
FROM
|
|
298
|
+
${instanceFilterClauses.from} this
|
|
299
|
+
${instanceFilterClauses.joins}
|
|
300
|
+
WHERE
|
|
301
|
+
this.ECInstanceId IN (${categories.map((category) => category.id).join(", ")})
|
|
302
|
+
${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : ""}
|
|
303
|
+
`,
|
|
164
304
|
},
|
|
165
305
|
},
|
|
166
306
|
];
|
|
167
307
|
}
|
|
168
|
-
async
|
|
308
|
+
async createCategoryChildrenQuery(props) {
|
|
309
|
+
return (await Promise.all([
|
|
310
|
+
...(!this._hierarchyConfig.hideSubCategories && props.parentNode.extendedData?.hasSubCategories ? [this.createSubCategoriesQuery(props)] : []),
|
|
311
|
+
...(this._hierarchyConfig.showElements ? [this.createCategoryElementsQuery(props)] : []),
|
|
312
|
+
])).reduce((acc, levelDefinition) => acc.concat(levelDefinition), new Array());
|
|
313
|
+
}
|
|
314
|
+
async createSubCategoriesQuery({ parentNodeInstanceIds: categoryIds, instanceFilter, }) {
|
|
169
315
|
const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({
|
|
170
316
|
filter: instanceFilter,
|
|
171
|
-
contentClass: { fullName:
|
|
317
|
+
contentClass: { fullName: SUB_CATEGORY_CLASS_NAME, alias: "this" },
|
|
172
318
|
});
|
|
173
319
|
return [
|
|
174
320
|
{
|
|
175
|
-
fullClassName:
|
|
321
|
+
fullClassName: SUB_CATEGORY_CLASS_NAME,
|
|
176
322
|
query: {
|
|
177
323
|
ecsql: `
|
|
178
324
|
SELECT
|
|
@@ -182,7 +328,7 @@ export class CategoriesTreeDefinition {
|
|
|
182
328
|
nodeLabel: {
|
|
183
329
|
selector: await this._nodeLabelSelectClauseFactory.createSelectClause({
|
|
184
330
|
classAlias: "this",
|
|
185
|
-
className:
|
|
331
|
+
className: SUB_CATEGORY_CLASS_NAME,
|
|
186
332
|
}),
|
|
187
333
|
},
|
|
188
334
|
extendedData: {
|
|
@@ -195,30 +341,149 @@ export class CategoriesTreeDefinition {
|
|
|
195
341
|
FROM ${instanceFilterClauses.from} this
|
|
196
342
|
${instanceFilterClauses.joins}
|
|
197
343
|
WHERE
|
|
198
|
-
NOT this.IsPrivate AND this.Parent.Id IN (${
|
|
344
|
+
NOT this.IsPrivate AND this.Parent.Id IN (${categoryIds.join(",")})
|
|
345
|
+
${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : ""}
|
|
346
|
+
`,
|
|
347
|
+
},
|
|
348
|
+
},
|
|
349
|
+
];
|
|
350
|
+
}
|
|
351
|
+
async createCategoryElementsQuery({ parentNodeInstanceIds: categoryIds, instanceFilter, parentNode, }) {
|
|
352
|
+
const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({
|
|
353
|
+
filter: instanceFilter,
|
|
354
|
+
contentClass: { fullName: this._categoryElementClass, alias: "this" },
|
|
355
|
+
});
|
|
356
|
+
const modelIds = parentNode.extendedData?.isCategoryOfSubModel
|
|
357
|
+
? parseIdsSelectorResult(parentNode.extendedData?.modelIds)
|
|
358
|
+
: [...getDistinctMapValues(await this._idsCache.getCategoriesElementModels(categoryIds))];
|
|
359
|
+
if (modelIds.length === 0) {
|
|
360
|
+
return [];
|
|
361
|
+
}
|
|
362
|
+
const modeledElements = await firstValueFrom(from(modelIds).pipe(mergeMap(async (modelId) => this._idsCache.getCategoriesModeledElements(modelId, categoryIds)), reduce((acc, foundModeledElements) => {
|
|
363
|
+
return acc.concat(foundModeledElements);
|
|
364
|
+
}, new Array())));
|
|
365
|
+
return [
|
|
366
|
+
{
|
|
367
|
+
fullClassName: this._categoryElementClass,
|
|
368
|
+
query: {
|
|
369
|
+
ecsql: `
|
|
370
|
+
SELECT
|
|
371
|
+
${await this._selectQueryFactory.createSelectClause({
|
|
372
|
+
ecClassId: { selector: "this.ECClassId" },
|
|
373
|
+
ecInstanceId: { selector: "this.ECInstanceId" },
|
|
374
|
+
nodeLabel: {
|
|
375
|
+
selector: await this._nodeLabelSelectClauseFactory.createSelectClause({
|
|
376
|
+
classAlias: "this",
|
|
377
|
+
className: this._categoryElementClass,
|
|
378
|
+
}),
|
|
379
|
+
},
|
|
380
|
+
hasChildren: {
|
|
381
|
+
selector: `
|
|
382
|
+
IIF(
|
|
383
|
+
${modeledElements.length ? `this.ECInstanceId IN (${modeledElements.join(",")})` : `FALSE`},
|
|
384
|
+
1,
|
|
385
|
+
IFNULL((
|
|
386
|
+
SELECT 1
|
|
387
|
+
FROM ${this._categoryElementClass} ce
|
|
388
|
+
WHERE ce.Parent.Id = this.ECInstanceId
|
|
389
|
+
LIMIT 1
|
|
390
|
+
), 0)
|
|
391
|
+
)
|
|
392
|
+
`,
|
|
393
|
+
},
|
|
394
|
+
grouping: {
|
|
395
|
+
byClass: true,
|
|
396
|
+
},
|
|
397
|
+
extendedData: {
|
|
398
|
+
modelId: { selector: "IdToHex(this.Model.Id)" },
|
|
399
|
+
categoryId: { selector: "IdToHex(this.Category.Id)" },
|
|
400
|
+
imageId: "icon-item",
|
|
401
|
+
isElement: true,
|
|
402
|
+
},
|
|
403
|
+
supportsFiltering: true,
|
|
404
|
+
})}
|
|
405
|
+
FROM ${instanceFilterClauses.from} this
|
|
406
|
+
${parentNode.extendedData?.isCategoryOfSubModel ? "" : `JOIN ${INFORMATION_PARTITION_ELEMENT_CLASS_NAME} ipe ON ipe.ECInstanceId = this.Model.Id`}
|
|
407
|
+
${instanceFilterClauses.joins}
|
|
408
|
+
WHERE
|
|
409
|
+
this.Category.Id IN (${categoryIds.join(",")})
|
|
410
|
+
AND this.Model.Id IN (${modelIds.join(",")})
|
|
411
|
+
AND this.Parent.Id IS NULL
|
|
412
|
+
${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : ""}
|
|
413
|
+
`,
|
|
414
|
+
},
|
|
415
|
+
},
|
|
416
|
+
];
|
|
417
|
+
}
|
|
418
|
+
async createElementChildrenQuery({ parentNodeInstanceIds: elementIds, instanceFilter, }) {
|
|
419
|
+
const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({
|
|
420
|
+
filter: instanceFilter,
|
|
421
|
+
contentClass: { fullName: this._categoryElementClass, alias: "this" },
|
|
422
|
+
});
|
|
423
|
+
return [
|
|
424
|
+
{
|
|
425
|
+
fullClassName: this._categoryElementClass,
|
|
426
|
+
query: {
|
|
427
|
+
ecsql: `
|
|
428
|
+
SELECT
|
|
429
|
+
${await this._selectQueryFactory.createSelectClause({
|
|
430
|
+
ecClassId: { selector: "this.ECClassId" },
|
|
431
|
+
ecInstanceId: { selector: "this.ECInstanceId" },
|
|
432
|
+
nodeLabel: {
|
|
433
|
+
selector: await this._nodeLabelSelectClauseFactory.createSelectClause({
|
|
434
|
+
classAlias: "this",
|
|
435
|
+
className: this._categoryElementClass,
|
|
436
|
+
}),
|
|
437
|
+
},
|
|
438
|
+
hasChildren: {
|
|
439
|
+
selector: `
|
|
440
|
+
IFNULL((
|
|
441
|
+
SELECT 1
|
|
442
|
+
FROM ${this._categoryElementClass} ce
|
|
443
|
+
JOIN ${MODEL_CLASS_NAME} m ON ce.Model.Id = m.ECInstanceId
|
|
444
|
+
WHERE ce.Parent.Id = this.ECInstanceId OR (ce.Model.Id = this.ECInstanceId AND m.IsPrivate = false)
|
|
445
|
+
LIMIT 1
|
|
446
|
+
), 0)
|
|
447
|
+
`,
|
|
448
|
+
},
|
|
449
|
+
grouping: {
|
|
450
|
+
byClass: true,
|
|
451
|
+
},
|
|
452
|
+
extendedData: {
|
|
453
|
+
modelId: { selector: "IdToHex(this.Model.Id)" },
|
|
454
|
+
categoryId: { selector: "IdToHex(this.Category.Id)" },
|
|
455
|
+
imageId: "icon-item",
|
|
456
|
+
isElement: true,
|
|
457
|
+
},
|
|
458
|
+
supportsFiltering: true,
|
|
459
|
+
})}
|
|
460
|
+
FROM ${instanceFilterClauses.from} this
|
|
461
|
+
${instanceFilterClauses.joins}
|
|
462
|
+
WHERE
|
|
463
|
+
this.Parent.Id IN (${elementIds.join(",")})
|
|
199
464
|
${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : ""}
|
|
200
465
|
`,
|
|
201
|
-
bindings: elementIds.map((id) => ({ type: "id", value: id })),
|
|
202
466
|
},
|
|
203
467
|
},
|
|
204
468
|
];
|
|
205
469
|
}
|
|
206
470
|
static async createInstanceKeyPaths(props) {
|
|
207
471
|
const labelsFactory = createBisInstanceLabelSelectClauseFactory({ classHierarchyInspector: props.imodelAccess });
|
|
208
|
-
return createInstanceKeyPathsFromInstanceLabel({ ...props, labelsFactory
|
|
472
|
+
return createInstanceKeyPathsFromInstanceLabel({ ...props, labelsFactory });
|
|
209
473
|
}
|
|
210
474
|
}
|
|
211
475
|
async function createInstanceKeyPathsFromInstanceLabel(props) {
|
|
212
|
-
const { definitionContainers, categories } = await props.
|
|
476
|
+
const { definitionContainers, categories } = await props.idsCache.getAllDefinitionContainersAndCategories();
|
|
213
477
|
if (categories.length === 0) {
|
|
214
478
|
return [];
|
|
215
479
|
}
|
|
216
|
-
const { categoryClass } = getClassesByView(props.viewType);
|
|
480
|
+
const { categoryClass, elementClass } = getClassesByView(props.viewType);
|
|
217
481
|
const adjustedLabel = props.label.replace(/[%_\\]/g, "\\$&");
|
|
218
482
|
const CATEGORIES_WITH_LABELS_CTE = "CategoriesWithLabels";
|
|
483
|
+
const ELEMENTS_WITH_LABELS_CTE = "ElementsWithLabels";
|
|
219
484
|
const SUBCATEGORIES_WITH_LABELS_CTE = "SubCategoriesWithLabels";
|
|
220
485
|
const DEFINITION_CONTAINERS_WITH_LABELS_CTE = "DefinitionContainersWithLabels";
|
|
221
|
-
const [categoryLabelSelectClause, subCategoryLabelSelectClause, definitionContainerLabelSelectClause] = await Promise.all([categoryClass,
|
|
486
|
+
const [categoryLabelSelectClause, subCategoryLabelSelectClause, elementLabelSelectClause, definitionContainerLabelSelectClause] = await Promise.all([categoryClass, SUB_CATEGORY_CLASS_NAME, elementClass, ...(definitionContainers.length > 0 ? [DEFINITION_CONTAINER_CLASS_NAME] : [])].map(async (className) => props.labelsFactory.createSelectClause({ classAlias: "this", className })));
|
|
222
487
|
return lastValueFrom(defer(() => {
|
|
223
488
|
const ctes = [
|
|
224
489
|
`${CATEGORIES_WITH_LABELS_CTE}(ClassName, ECInstanceId, ChildCount, DisplayLabel) AS (
|
|
@@ -229,11 +494,28 @@ async function createInstanceKeyPathsFromInstanceLabel(props) {
|
|
|
229
494
|
${categoryLabelSelectClause}
|
|
230
495
|
FROM
|
|
231
496
|
${categoryClass} this
|
|
232
|
-
JOIN ${
|
|
497
|
+
JOIN ${SUB_CATEGORY_CLASS_NAME} sc ON sc.Parent.Id = this.ECInstanceId
|
|
233
498
|
WHERE
|
|
234
499
|
this.ECInstanceId IN (${categories.join(", ")})
|
|
235
500
|
GROUP BY this.ECInstanceId
|
|
236
501
|
)`,
|
|
502
|
+
...(props.hierarchyConfig.showElements
|
|
503
|
+
? [
|
|
504
|
+
`${ELEMENTS_WITH_LABELS_CTE}(ClassName, ECInstanceId, ParentId, DisplayLabel) AS (
|
|
505
|
+
SELECT
|
|
506
|
+
'e',
|
|
507
|
+
this.ECInstanceId,
|
|
508
|
+
this.Parent.Id,
|
|
509
|
+
${elementLabelSelectClause}
|
|
510
|
+
FROM
|
|
511
|
+
${elementClass} this
|
|
512
|
+
JOIN ${MODEL_CLASS_NAME} m ON this.Model.Id = m.ECInstanceId
|
|
513
|
+
WHERE
|
|
514
|
+
NOT m.IsPrivate
|
|
515
|
+
AND this.Category.Id IN (${categories.join(", ")})
|
|
516
|
+
)`,
|
|
517
|
+
]
|
|
518
|
+
: []),
|
|
237
519
|
...(props.hierarchyConfig.hideSubCategories
|
|
238
520
|
? []
|
|
239
521
|
: [
|
|
@@ -244,7 +526,7 @@ async function createInstanceKeyPathsFromInstanceLabel(props) {
|
|
|
244
526
|
this.Parent.Id,
|
|
245
527
|
${subCategoryLabelSelectClause}
|
|
246
528
|
FROM
|
|
247
|
-
${
|
|
529
|
+
${SUB_CATEGORY_CLASS_NAME} this
|
|
248
530
|
WHERE
|
|
249
531
|
NOT this.IsPrivate
|
|
250
532
|
AND this.Parent.Id IN (${categories.join(", ")})
|
|
@@ -258,7 +540,7 @@ async function createInstanceKeyPathsFromInstanceLabel(props) {
|
|
|
258
540
|
this.ECInstanceId,
|
|
259
541
|
${definitionContainerLabelSelectClause}
|
|
260
542
|
FROM
|
|
261
|
-
${
|
|
543
|
+
${DEFINITION_CONTAINER_CLASS_NAME} this
|
|
262
544
|
WHERE
|
|
263
545
|
this.ECInstanceId IN (${definitionContainers.join(", ")})
|
|
264
546
|
)`,
|
|
@@ -267,72 +549,190 @@ async function createInstanceKeyPathsFromInstanceLabel(props) {
|
|
|
267
549
|
];
|
|
268
550
|
const ecsql = `
|
|
269
551
|
SELECT * FROM (
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
552
|
+
SELECT
|
|
553
|
+
c.ClassName AS ClassName,
|
|
554
|
+
c.ECInstanceId AS ECInstanceId
|
|
555
|
+
FROM
|
|
556
|
+
${CATEGORIES_WITH_LABELS_CTE} c
|
|
557
|
+
WHERE
|
|
558
|
+
c.DisplayLabel LIKE '%' || ? || '%' ESCAPE '\\'
|
|
559
|
+
${props.hierarchyConfig.showElements
|
|
560
|
+
? `
|
|
561
|
+
UNION ALL
|
|
562
|
+
SELECT
|
|
563
|
+
e.ClassName AS ClassName,
|
|
564
|
+
e.ECInstanceId AS ECInstanceId
|
|
565
|
+
FROM
|
|
566
|
+
${ELEMENTS_WITH_LABELS_CTE} e
|
|
567
|
+
WHERE
|
|
568
|
+
e.DisplayLabel LIKE '%' || ? || '%' ESCAPE '\\'
|
|
569
|
+
`
|
|
570
|
+
: ""}
|
|
571
|
+
${props.hierarchyConfig.hideSubCategories
|
|
278
572
|
? ""
|
|
279
573
|
: `
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
574
|
+
UNION ALL
|
|
575
|
+
SELECT
|
|
576
|
+
sc.ClassName AS ClassName,
|
|
577
|
+
sc.ECInstanceId AS ECInstanceId
|
|
578
|
+
FROM
|
|
579
|
+
${CATEGORIES_WITH_LABELS_CTE} c
|
|
580
|
+
JOIN ${SUBCATEGORIES_WITH_LABELS_CTE} sc ON sc.ParentId = c.ECInstanceId
|
|
581
|
+
WHERE
|
|
582
|
+
c.ChildCount > 1
|
|
583
|
+
AND sc.DisplayLabel LIKE '%' || ? || '%' ESCAPE '\\'
|
|
584
|
+
`}
|
|
585
|
+
${definitionContainers.length > 0
|
|
292
586
|
? `
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
587
|
+
UNION ALL
|
|
588
|
+
SELECT
|
|
589
|
+
dc.ClassName AS ClassName,
|
|
590
|
+
dc.ECInstanceId AS ECInstanceId
|
|
591
|
+
FROM
|
|
592
|
+
${DEFINITION_CONTAINERS_WITH_LABELS_CTE} dc
|
|
593
|
+
WHERE
|
|
594
|
+
dc.DisplayLabel LIKE '%' || ? || '%' ESCAPE '\\'
|
|
595
|
+
`
|
|
302
596
|
: ""}
|
|
303
597
|
)
|
|
304
598
|
${props.limit === undefined ? `LIMIT ${MAX_FILTERING_INSTANCE_KEY_COUNT + 1}` : props.limit !== "unbounded" ? `LIMIT ${props.limit}` : ""}
|
|
305
599
|
`;
|
|
306
600
|
const bindings = [
|
|
307
601
|
{ type: "string", value: adjustedLabel },
|
|
602
|
+
...(props.hierarchyConfig.showElements ? [{ type: "string", value: adjustedLabel }] : []),
|
|
308
603
|
...(props.hierarchyConfig.hideSubCategories ? [] : [{ type: "string", value: adjustedLabel }]),
|
|
309
604
|
...(definitionContainers.length > 0 ? [{ type: "string", value: adjustedLabel }] : []),
|
|
310
605
|
];
|
|
311
606
|
return props.imodelAccess.createQueryReader({ ctes, ecsql, bindings }, { restartToken: "tree-widget/categories-tree/filter-by-label-query", limit: props.limit });
|
|
312
|
-
}).pipe(map((row) =>
|
|
313
|
-
className
|
|
314
|
-
|
|
315
|
-
|
|
607
|
+
}).pipe(map((row) => {
|
|
608
|
+
let className;
|
|
609
|
+
switch (row.ClassName) {
|
|
610
|
+
case "c":
|
|
611
|
+
className = categoryClass;
|
|
612
|
+
break;
|
|
613
|
+
case "sc":
|
|
614
|
+
className = SUB_CATEGORY_CLASS_NAME;
|
|
615
|
+
break;
|
|
616
|
+
case "e":
|
|
617
|
+
className = elementClass;
|
|
618
|
+
break;
|
|
619
|
+
default:
|
|
620
|
+
className = DEFINITION_CONTAINER_CLASS_NAME;
|
|
621
|
+
break;
|
|
622
|
+
}
|
|
623
|
+
return {
|
|
624
|
+
className,
|
|
625
|
+
id: row.ECInstanceId,
|
|
626
|
+
};
|
|
627
|
+
}), toArray(), mergeMap((targetItems) => createInstanceKeyPathsFromTargetItems({ ...props, targetItems })), toArray()));
|
|
316
628
|
}
|
|
317
|
-
function createInstanceKeyPathsFromTargetItems(
|
|
318
|
-
const { limit, targetItems, viewType, idsCache, hierarchyConfig } = props;
|
|
629
|
+
function createInstanceKeyPathsFromTargetItems({ targetItems, imodelAccess, viewType, hierarchyConfig, idsCache, limit, }) {
|
|
319
630
|
if (limit !== "unbounded" && targetItems.length > (limit ?? MAX_FILTERING_INSTANCE_KEY_COUNT)) {
|
|
320
631
|
throw new FilterLimitExceededError(limit ?? MAX_FILTERING_INSTANCE_KEY_COUNT);
|
|
321
632
|
}
|
|
322
|
-
if (targetItems.length === 0) {
|
|
323
|
-
return EMPTY;
|
|
324
|
-
}
|
|
325
633
|
const { categoryClass } = getClassesByView(viewType);
|
|
326
|
-
return from(targetItems).pipe(
|
|
327
|
-
if (
|
|
328
|
-
|
|
634
|
+
return from(targetItems).pipe(releaseMainThreadOnItemsCount(2000), reduce((acc, { id, className }) => {
|
|
635
|
+
if (className === categoryClass) {
|
|
636
|
+
acc.categoryIds.push(id);
|
|
637
|
+
return acc;
|
|
329
638
|
}
|
|
330
|
-
if (
|
|
331
|
-
|
|
639
|
+
if (className === DEFINITION_CONTAINER_CLASS_NAME) {
|
|
640
|
+
acc.definitionContainerIds.push(id);
|
|
641
|
+
return acc;
|
|
642
|
+
}
|
|
643
|
+
if (className === SUB_CATEGORY_CLASS_NAME) {
|
|
644
|
+
if (hierarchyConfig.hideSubCategories) {
|
|
645
|
+
return acc;
|
|
646
|
+
}
|
|
647
|
+
acc.subCategoryIds.push(id);
|
|
648
|
+
return acc;
|
|
332
649
|
}
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
650
|
+
if (!hierarchyConfig.showElements) {
|
|
651
|
+
return acc;
|
|
652
|
+
}
|
|
653
|
+
acc.elementIds.push(id);
|
|
654
|
+
return acc;
|
|
655
|
+
}, {
|
|
656
|
+
definitionContainerIds: new Array(),
|
|
657
|
+
categoryIds: new Array(),
|
|
658
|
+
subCategoryIds: new Array(),
|
|
659
|
+
elementIds: new Array(),
|
|
660
|
+
}), mergeMap((ids) => {
|
|
661
|
+
const elementsLength = ids.elementIds.length;
|
|
662
|
+
return merge(from(ids.definitionContainerIds).pipe(mergeMap(async (id) => ({ path: await idsCache.getInstanceKeyPaths({ definitionContainerId: id }), options: { autoExpand: true } }))), from(ids.categoryIds).pipe(mergeMap(async (id) => ({ path: await idsCache.getInstanceKeyPaths({ categoryId: id }), options: { autoExpand: true } }))), from(ids.subCategoryIds).pipe(mergeMap(async (id) => ({ path: await idsCache.getInstanceKeyPaths({ subCategoryId: id }), options: { autoExpand: true } }))), from(ids.elementIds).pipe(bufferCount(Math.ceil(elementsLength / Math.ceil(elementsLength / 5000))), releaseMainThreadOnItemsCount(1), mergeMap((block) => createGeometricElementInstanceKeyPaths(imodelAccess, idsCache, hierarchyConfig, viewType, block), 10)));
|
|
663
|
+
}));
|
|
664
|
+
}
|
|
665
|
+
function createGeometricElementInstanceKeyPaths(imodelAccess, idsCache, hierarchyConfig, viewType, targetItems) {
|
|
666
|
+
const separator = ";";
|
|
667
|
+
const { categoryClass, elementClass, modelClass } = getClassesByView(viewType);
|
|
668
|
+
if (targetItems.length === 0 || !hierarchyConfig.showElements) {
|
|
669
|
+
return of([]);
|
|
670
|
+
}
|
|
671
|
+
return defer(() => {
|
|
672
|
+
const ctes = [
|
|
673
|
+
`CategoriesElementsHierarchy(ECInstanceId, ParentId, ModelId, Path) AS (
|
|
674
|
+
SELECT
|
|
675
|
+
e.ECInstanceId,
|
|
676
|
+
e.Parent.Id,
|
|
677
|
+
e.Model.Id,
|
|
678
|
+
IIF(e.Parent.Id IS NULL,
|
|
679
|
+
'm${separator}' || CAST(IdToHex([m].[ECInstanceId]) AS TEXT) || '${separator}c${separator}' || CAST(IdToHex([c].[ECInstanceId]) AS TEXT) || '${separator}e${separator}' || CAST(IdToHex([e].[ECInstanceId]) AS TEXT),
|
|
680
|
+
'e${separator}' || CAST(IdToHex([e].[ECInstanceId]) AS TEXT)
|
|
681
|
+
)
|
|
682
|
+
FROM ${elementClass} e
|
|
683
|
+
LEFT JOIN ${modelClass} m ON (e.Parent.Id IS NULL AND m.ECInstanceId = e.Model.Id)
|
|
684
|
+
LEFT JOIN ${categoryClass} c ON (e.Parent.Id IS NULL AND c.ECInstanceId = e.Category.Id)
|
|
685
|
+
WHERE e.ECInstanceId IN (${targetItems.join(",")})
|
|
686
|
+
|
|
687
|
+
UNION ALL
|
|
688
|
+
|
|
689
|
+
SELECT
|
|
690
|
+
pe.ECInstanceId,
|
|
691
|
+
pe.Parent.Id,
|
|
692
|
+
pe.Model.Id,
|
|
693
|
+
IIF(pe.Parent.Id IS NULL,
|
|
694
|
+
'm${separator}' || CAST(IdToHex([m].[ECInstanceId]) AS TEXT) || '${separator}c${separator}' || CAST(IdToHex([c].[ECInstanceId]) AS TEXT) || '${separator}e${separator}' || CAST(IdToHex([pe].[ECInstanceId]) AS TEXT) || '${separator}' || ce.Path,
|
|
695
|
+
'e${separator}' || CAST(IdToHex([pe].[ECInstanceId]) AS TEXT) || '${separator}' || ce.Path
|
|
696
|
+
)
|
|
697
|
+
FROM CategoriesElementsHierarchy ce
|
|
698
|
+
JOIN ${elementClass} pe ON (pe.ECInstanceId = ce.ParentId OR pe.ECInstanceId = ce.ModelId AND ce.ParentId IS NULL)
|
|
699
|
+
LEFT JOIN ${modelClass} m ON (pe.Parent.Id IS NULL AND m.ECInstanceId = pe.Model.Id)
|
|
700
|
+
LEFT JOIN ${categoryClass} c ON (pe.Parent.Id IS NULL AND c.ECInstanceId = pe.Category.Id)
|
|
701
|
+
)`,
|
|
702
|
+
];
|
|
703
|
+
const ecsql = `
|
|
704
|
+
SELECT mce.Path
|
|
705
|
+
FROM CategoriesElementsHierarchy mce
|
|
706
|
+
WHERE mce.ParentId IS NULL
|
|
707
|
+
`;
|
|
708
|
+
return imodelAccess.createQueryReader({ ctes, ecsql }, { rowFormat: "Indexes", limit: "unbounded", restartToken: "tree-widget/categories-tree/elements-filter-paths-query" });
|
|
709
|
+
}).pipe(releaseMainThreadOnItemsCount(300), map((row) => parseQueryRow(row, separator, elementClass, categoryClass, modelClass)), mergeMap(async (elementHierarchyPath) => {
|
|
710
|
+
const pathToCategory = await idsCache.getInstanceKeyPaths({ categoryId: elementHierarchyPath[0].id });
|
|
711
|
+
pathToCategory.pop(); // category is already included in the element hierarchy path
|
|
712
|
+
const path = [...pathToCategory, ...elementHierarchyPath];
|
|
713
|
+
return { path, options: { autoExpand: true } };
|
|
336
714
|
}));
|
|
337
715
|
}
|
|
716
|
+
function parseQueryRow(row, separator, elementClassName, categoryClassName, modelClassName) {
|
|
717
|
+
const rowElements = row[0].split(separator);
|
|
718
|
+
const path = new Array();
|
|
719
|
+
for (let i = 0; i < rowElements.length; i += 2) {
|
|
720
|
+
switch (rowElements[i]) {
|
|
721
|
+
case "e":
|
|
722
|
+
path.push({ className: elementClassName, id: rowElements[i + 1] });
|
|
723
|
+
break;
|
|
724
|
+
case "c":
|
|
725
|
+
path.push({ className: categoryClassName, id: rowElements[i + 1] });
|
|
726
|
+
break;
|
|
727
|
+
case "m":
|
|
728
|
+
// Ignore first model since it isn't in hierarchy
|
|
729
|
+
if (i === 0) {
|
|
730
|
+
break;
|
|
731
|
+
}
|
|
732
|
+
path.push({ className: modelClassName, id: rowElements[i + 1] });
|
|
733
|
+
break;
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
return path;
|
|
737
|
+
}
|
|
338
738
|
//# sourceMappingURL=CategoriesTreeDefinition.js.map
|