@itwin/tree-widget-react 4.0.0-alpha.2 → 4.0.0-alpha.4
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 +34 -1
- package/README.md +1 -3
- package/lib/esm/tree-widget-react/components/TreeWidgetUiItemsProvider.js +3 -2
- package/lib/esm/tree-widget-react/components/TreeWidgetUiItemsProvider.js.map +1 -1
- package/lib/esm/tree-widget-react/components/tree-header/ErrorState.js +2 -2
- package/lib/esm/tree-widget-react/components/tree-header/ErrorState.js.map +1 -1
- package/lib/esm/tree-widget-react/components/tree-header/SearchBox.js +4 -4
- 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 +1 -1
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js +6 -6
- 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/CategoriesTreeDefinition.d.ts +10 -2
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js +246 -129
- 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.js +69 -20
- 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 +54 -0
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js +280 -0
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeNode.d.ts +26 -0
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeNode.js +23 -0
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeNode.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/categories-tree/{CategoriesVisibilityHandler.d.ts → internal/CategoriesVisibilityHandler.d.ts} +18 -9
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js +214 -0
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/ClassNameDefinitions.d.ts +7 -0
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/ClassNameDefinitions.js +11 -0
- package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/ClassNameDefinitions.js.map +1 -0
- package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.d.ts +0 -4
- package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/FocusedInstancesContext.d.ts +28 -4
- package/lib/esm/tree-widget-react/components/trees/common/FocusedInstancesContext.js +73 -2
- package/lib/esm/tree-widget-react/components/trees/common/FocusedInstancesContext.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/Tree.d.ts +1 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/Tree.js +3 -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/TreeNodeVisibilityButton.css +2 -1
- package/lib/esm/tree-widget-react/components/trees/common/components/TreeNodeVisibilityButton.js +6 -6
- package/lib/esm/tree-widget-react/components/trees/common/components/TreeNodeVisibilityButton.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTree.js +9 -9
- package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.js +15 -15
- package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/index.d.ts +1 -0
- package/lib/esm/tree-widget-react/components/trees/index.js +1 -0
- package/lib/esm/tree-widget-react/components/trees/index.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.js +12 -12
- 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 +6 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeComponent.js +7 -3
- 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/UseModelsTree.js +11 -11
- 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/AlwaysAndNeverDrawnElementInfo.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.d.ts +5 -0
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js +45 -0
- 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 +2 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js +128 -38
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js.map +1 -1
- package/lib/public/locales/en/TreeWidget.json +15 -4
- package/package.json +8 -11
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesVisibilityHandler.js +0 -87
- package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesVisibilityHandler.js.map +0 -1
- package/lib/esm/tree-widget-react/components/trees/common/FocusedInstancesContextProvider.d.ts +0 -7
- package/lib/esm/tree-widget-react/components/trees/common/FocusedInstancesContextProvider.js +0 -66
- package/lib/esm/tree-widget-react/components/trees/common/FocusedInstancesContextProvider.js.map +0 -1
package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js
CHANGED
|
@@ -2,81 +2,154 @@
|
|
|
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, EMPTY, from, lastValueFrom, map, mergeMap, toArray } from "rxjs";
|
|
5
6
|
import { createNodesQueryClauseFactory, createPredicateBasedHierarchyDefinition } from "@itwin/presentation-hierarchies";
|
|
6
7
|
import { createBisInstanceLabelSelectClauseFactory, ECSql } from "@itwin/presentation-shared";
|
|
7
8
|
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";
|
|
8
11
|
const MAX_FILTERING_INSTANCE_KEY_COUNT = 100;
|
|
9
12
|
export class CategoriesTreeDefinition {
|
|
10
13
|
constructor(props) {
|
|
11
|
-
this.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
rootNodes: async (requestProps) => this.createRootHierarchyLevelDefinition({ ...requestProps, viewType: props.viewType }),
|
|
15
|
-
childNodes: [
|
|
16
|
-
{
|
|
17
|
-
parentInstancesNodePredicate: "BisCore.Category",
|
|
18
|
-
definitions: async (requestProps) => this.createSubcategoryQuery(requestProps),
|
|
19
|
-
},
|
|
20
|
-
],
|
|
21
|
-
},
|
|
22
|
-
});
|
|
14
|
+
this._iModelAccess = props.imodelAccess;
|
|
15
|
+
this._viewType = props.viewType;
|
|
16
|
+
this._idsCache = props.idsCache;
|
|
23
17
|
this._nodeLabelSelectClauseFactory = createBisInstanceLabelSelectClauseFactory({ classHierarchyInspector: props.imodelAccess });
|
|
24
18
|
this._selectQueryFactory = createNodesQueryClauseFactory({
|
|
25
19
|
imodelAccess: props.imodelAccess,
|
|
26
20
|
instanceLabelSelectClauseFactory: this._nodeLabelSelectClauseFactory,
|
|
27
21
|
});
|
|
28
22
|
}
|
|
23
|
+
async getHierarchyDefinition() {
|
|
24
|
+
this._impl ??= (async () => {
|
|
25
|
+
const isDefinitionContainerSupported = await this._idsCache.getIsDefinitionContainerSupported();
|
|
26
|
+
return createPredicateBasedHierarchyDefinition({
|
|
27
|
+
classHierarchyInspector: this._iModelAccess,
|
|
28
|
+
hierarchy: {
|
|
29
|
+
rootNodes: async (requestProps) => this.createDefinitionContainersAndCategoriesQuery({ ...requestProps, viewType: this._viewType }),
|
|
30
|
+
childNodes: [
|
|
31
|
+
{
|
|
32
|
+
parentInstancesNodePredicate: "BisCore.Category",
|
|
33
|
+
definitions: async (requestProps) => this.createSubcategoryQuery(requestProps),
|
|
34
|
+
},
|
|
35
|
+
...(isDefinitionContainerSupported
|
|
36
|
+
? [
|
|
37
|
+
{
|
|
38
|
+
parentInstancesNodePredicate: DEFINITION_CONTAINER_CLASS,
|
|
39
|
+
definitions: async (requestProps) => this.createDefinitionContainersAndCategoriesQuery({
|
|
40
|
+
...requestProps,
|
|
41
|
+
viewType: this._viewType,
|
|
42
|
+
}),
|
|
43
|
+
},
|
|
44
|
+
]
|
|
45
|
+
: []),
|
|
46
|
+
],
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
})();
|
|
50
|
+
return this._impl;
|
|
51
|
+
}
|
|
29
52
|
async defineHierarchyLevel(props) {
|
|
30
|
-
return this.
|
|
53
|
+
return (await this.getHierarchyDefinition()).defineHierarchyLevel(props);
|
|
31
54
|
}
|
|
32
|
-
async
|
|
33
|
-
const {
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
55
|
+
async createDefinitionContainersAndCategoriesQuery(props) {
|
|
56
|
+
const { parentNodeInstanceIds, instanceFilter, viewType } = props;
|
|
57
|
+
const { definitionContainers, categories } = parentNodeInstanceIds === undefined
|
|
58
|
+
? await this._idsCache.getRootDefinitionContainersAndCategories()
|
|
59
|
+
: await this._idsCache.getDirectChildDefinitionContainersAndCategories(parentNodeInstanceIds);
|
|
60
|
+
if (categories.length === 0 && definitionContainers.length === 0) {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
const categoriesWithSingleChild = new Array();
|
|
64
|
+
const categoriesWithMultipleChildren = new Array();
|
|
65
|
+
categories.forEach((category) => {
|
|
66
|
+
if (category.childCount > 1) {
|
|
67
|
+
categoriesWithMultipleChildren.push(category.id);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
categoriesWithSingleChild.push(category.id);
|
|
71
|
+
}
|
|
37
72
|
});
|
|
38
|
-
|
|
39
|
-
{
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
73
|
+
const dataToDetermineHasChildren = categoriesWithSingleChild.length > categoriesWithMultipleChildren.length
|
|
74
|
+
? { ids: categoriesWithMultipleChildren, ifTrue: 1, ifFalse: 0 }
|
|
75
|
+
: { ids: categoriesWithSingleChild, ifTrue: 0, ifFalse: 1 };
|
|
76
|
+
const { categoryClass } = getClassesByView(viewType);
|
|
77
|
+
const [categoriesInstanceFilterClauses, definitionContainersInstanceFilterClauses] = await Promise.all([categoryClass, ...(definitionContainers.length > 0 ? [DEFINITION_CONTAINER_CLASS] : [])].map(async (className) => this._selectQueryFactory.createFilterClauses({
|
|
78
|
+
filter: instanceFilter,
|
|
79
|
+
contentClass: { fullName: className, alias: "this" },
|
|
80
|
+
})));
|
|
81
|
+
const definitionContainersQuery = definitionContainers.length > 0
|
|
82
|
+
? `
|
|
83
|
+
SELECT
|
|
84
|
+
${await this._selectQueryFactory.createSelectClause({
|
|
85
|
+
ecClassId: { selector: ECSql.createRawPropertyValueSelector("this", "ECClassId") },
|
|
86
|
+
ecInstanceId: { selector: "this.ECInstanceId" },
|
|
87
|
+
nodeLabel: {
|
|
88
|
+
selector: await this._nodeLabelSelectClauseFactory.createSelectClause({
|
|
89
|
+
classAlias: "this",
|
|
90
|
+
className: DEFINITION_CONTAINER_CLASS,
|
|
91
|
+
}),
|
|
92
|
+
},
|
|
93
|
+
extendedData: {
|
|
94
|
+
isDefinitionContainer: true,
|
|
95
|
+
imageId: "icon-definition-container",
|
|
96
|
+
},
|
|
97
|
+
hasChildren: true,
|
|
98
|
+
supportsFiltering: true,
|
|
99
|
+
})}
|
|
100
|
+
FROM
|
|
101
|
+
${definitionContainersInstanceFilterClauses.from} this
|
|
102
|
+
${definitionContainersInstanceFilterClauses.joins}
|
|
103
|
+
WHERE
|
|
104
|
+
this.ECInstanceId IN (${definitionContainers.join(", ")})
|
|
105
|
+
${definitionContainersInstanceFilterClauses.where ? `AND ${definitionContainersInstanceFilterClauses.where}` : ""}
|
|
106
|
+
`
|
|
107
|
+
: undefined;
|
|
108
|
+
const categoriesQuery = categories.length > 0
|
|
109
|
+
? `
|
|
110
|
+
SELECT
|
|
44
111
|
${await this._selectQueryFactory.createSelectClause({
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
112
|
+
ecClassId: { selector: ECSql.createRawPropertyValueSelector("this", "ECClassId") },
|
|
113
|
+
ecInstanceId: { selector: "this.ECInstanceId" },
|
|
114
|
+
nodeLabel: {
|
|
115
|
+
selector: await this._nodeLabelSelectClauseFactory.createSelectClause({
|
|
116
|
+
classAlias: "this",
|
|
117
|
+
className: categoryClass,
|
|
118
|
+
}),
|
|
119
|
+
},
|
|
120
|
+
...(dataToDetermineHasChildren.ids.length > 0
|
|
121
|
+
? {
|
|
53
122
|
hasChildren: {
|
|
54
123
|
selector: `
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
WHERE sc.Parent.Id = this.ECInstanceId
|
|
61
|
-
)
|
|
62
|
-
WHERE ChildCount > 1
|
|
63
|
-
), 0)
|
|
64
|
-
`,
|
|
124
|
+
IIF(this.ECInstanceId IN (${dataToDetermineHasChildren.ids.join(",")}),
|
|
125
|
+
${dataToDetermineHasChildren.ifTrue},
|
|
126
|
+
${dataToDetermineHasChildren.ifFalse}
|
|
127
|
+
)
|
|
128
|
+
`,
|
|
65
129
|
},
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
130
|
+
}
|
|
131
|
+
: { hasChildren: !!dataToDetermineHasChildren.ifFalse }),
|
|
132
|
+
extendedData: {
|
|
133
|
+
description: { selector: "this.Description" },
|
|
134
|
+
isCategory: true,
|
|
135
|
+
imageId: "icon-layers",
|
|
136
|
+
},
|
|
137
|
+
supportsFiltering: true,
|
|
138
|
+
})}
|
|
139
|
+
FROM
|
|
140
|
+
${categoriesInstanceFilterClauses.from} this
|
|
141
|
+
${categoriesInstanceFilterClauses.joins}
|
|
74
142
|
WHERE
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
143
|
+
this.ECInstanceId IN (${categories.map((category) => category.id).join(", ")})
|
|
144
|
+
${categoriesInstanceFilterClauses.where ? `AND ${categoriesInstanceFilterClauses.where}` : ""}
|
|
145
|
+
`
|
|
146
|
+
: undefined;
|
|
147
|
+
const queries = [categoriesQuery, definitionContainersQuery].filter((query) => query !== undefined);
|
|
148
|
+
return [
|
|
149
|
+
{
|
|
150
|
+
fullClassName: DEFINITION_ELEMENT_CLASS,
|
|
151
|
+
query: {
|
|
152
|
+
ecsql: queries.join(" UNION ALL "),
|
|
80
153
|
},
|
|
81
154
|
},
|
|
82
155
|
];
|
|
@@ -84,11 +157,11 @@ export class CategoriesTreeDefinition {
|
|
|
84
157
|
async createSubcategoryQuery({ parentNodeInstanceIds: elementIds, instanceFilter, }) {
|
|
85
158
|
const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({
|
|
86
159
|
filter: instanceFilter,
|
|
87
|
-
contentClass: { fullName:
|
|
160
|
+
contentClass: { fullName: SUB_CATEGORY_CLASS, alias: "this" },
|
|
88
161
|
});
|
|
89
162
|
return [
|
|
90
163
|
{
|
|
91
|
-
fullClassName:
|
|
164
|
+
fullClassName: SUB_CATEGORY_CLASS,
|
|
92
165
|
query: {
|
|
93
166
|
ecsql: `
|
|
94
167
|
SELECT
|
|
@@ -98,11 +171,13 @@ export class CategoriesTreeDefinition {
|
|
|
98
171
|
nodeLabel: {
|
|
99
172
|
selector: await this._nodeLabelSelectClauseFactory.createSelectClause({
|
|
100
173
|
classAlias: "this",
|
|
101
|
-
className:
|
|
174
|
+
className: SUB_CATEGORY_CLASS,
|
|
102
175
|
}),
|
|
103
176
|
},
|
|
104
177
|
extendedData: {
|
|
105
178
|
categoryId: { selector: "printf('0x%x', this.Parent.Id)" },
|
|
179
|
+
isSubCategory: true,
|
|
180
|
+
imageId: "icon-layers-isolate",
|
|
106
181
|
},
|
|
107
182
|
supportsFiltering: false,
|
|
108
183
|
})}
|
|
@@ -119,85 +194,127 @@ export class CategoriesTreeDefinition {
|
|
|
119
194
|
}
|
|
120
195
|
static async createInstanceKeyPaths(props) {
|
|
121
196
|
const labelsFactory = createBisInstanceLabelSelectClauseFactory({ classHierarchyInspector: props.imodelAccess });
|
|
122
|
-
return createInstanceKeyPathsFromInstanceLabel({ ...props, labelsFactory });
|
|
197
|
+
return createInstanceKeyPathsFromInstanceLabel({ ...props, labelsFactory, cache: props.idsCache });
|
|
123
198
|
}
|
|
124
199
|
}
|
|
125
|
-
function getClassesByView(viewType) {
|
|
126
|
-
return viewType === "2d"
|
|
127
|
-
? { categoryClass: "BisCore.DrawingCategory", categoryElementClass: "BisCore:GeometricElement2d" }
|
|
128
|
-
: { categoryClass: "BisCore.SpatialCategory", categoryElementClass: "BisCore:GeometricElement3d" };
|
|
129
|
-
}
|
|
130
200
|
async function createInstanceKeyPathsFromInstanceLabel(props) {
|
|
131
|
-
const {
|
|
201
|
+
const { definitionContainers, categories } = await props.cache.getAllDefinitionContainersAndCategories();
|
|
202
|
+
if (categories.length === 0) {
|
|
203
|
+
return [];
|
|
204
|
+
}
|
|
205
|
+
const { categoryClass } = getClassesByView(props.viewType);
|
|
132
206
|
const adjustedLabel = props.label.replace(/[%_\\]/g, "\\$&");
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
207
|
+
const CATEGORIES_WITH_LABELS_CTE = "CategoriesWithLabels";
|
|
208
|
+
const SUBCATEGORIES_WITH_LABELS_CTE = "SubCategoriesWithLabels";
|
|
209
|
+
const DEFINITION_CONTAINERS_WITH_LABELS_CTE = "DefinitionContainersWithLabels";
|
|
210
|
+
const [categoryLabelSelectClause, subCategoryLabelSelectClause, definitionContainerLabelSelectClause] = await Promise.all([categoryClass, SUB_CATEGORY_CLASS, ...(definitionContainers.length > 0 ? [DEFINITION_CONTAINER_CLASS] : [])].map(async (className) => props.labelsFactory.createSelectClause({ classAlias: "this", className })));
|
|
211
|
+
return lastValueFrom(defer(() => {
|
|
212
|
+
const ctes = [
|
|
213
|
+
`${CATEGORIES_WITH_LABELS_CTE}(ClassName, ECInstanceId, ChildCount, DisplayLabel) AS (
|
|
214
|
+
SELECT
|
|
215
|
+
'c',
|
|
216
|
+
this.ECInstanceId,
|
|
217
|
+
COUNT(sc.ECInstanceId),
|
|
218
|
+
${categoryLabelSelectClause}
|
|
219
|
+
FROM
|
|
220
|
+
${categoryClass} this
|
|
221
|
+
JOIN ${SUB_CATEGORY_CLASS} sc ON sc.Parent.Id = this.ECInstanceId
|
|
222
|
+
WHERE
|
|
223
|
+
this.ECInstanceId IN (${categories.join(", ")})
|
|
224
|
+
GROUP BY this.ECInstanceId
|
|
225
|
+
)`,
|
|
226
|
+
`${SUBCATEGORIES_WITH_LABELS_CTE}(ClassName, ECInstanceId, ParentId, DisplayLabel) AS (
|
|
227
|
+
SELECT
|
|
228
|
+
'sc',
|
|
229
|
+
this.ECInstanceId,
|
|
230
|
+
this.Parent.Id,
|
|
231
|
+
${subCategoryLabelSelectClause}
|
|
232
|
+
FROM
|
|
233
|
+
${SUB_CATEGORY_CLASS} this
|
|
234
|
+
WHERE
|
|
235
|
+
NOT this.IsPrivate
|
|
236
|
+
AND this.Parent.Id IN (${categories.join(", ")})
|
|
237
|
+
)`,
|
|
238
|
+
...(definitionContainers.length > 0
|
|
239
|
+
? [
|
|
240
|
+
`${DEFINITION_CONTAINERS_WITH_LABELS_CTE}(ClassName, ECInstanceId, DisplayLabel) AS (
|
|
241
|
+
SELECT
|
|
242
|
+
'dc',
|
|
243
|
+
this.ECInstanceId,
|
|
244
|
+
${definitionContainerLabelSelectClause}
|
|
245
|
+
FROM
|
|
246
|
+
${DEFINITION_CONTAINER_CLASS} this
|
|
247
|
+
WHERE
|
|
248
|
+
this.ECInstanceId IN (${definitionContainers.join(", ")})
|
|
249
|
+
)`,
|
|
250
|
+
]
|
|
251
|
+
: []),
|
|
252
|
+
];
|
|
253
|
+
const ecsql = `
|
|
254
|
+
SELECT * FROM (
|
|
255
|
+
SELECT
|
|
256
|
+
sc.ClassName AS ClassName,
|
|
257
|
+
sc.ECInstanceId AS ECInstanceId
|
|
258
|
+
FROM
|
|
259
|
+
${CATEGORIES_WITH_LABELS_CTE} c
|
|
260
|
+
JOIN ${SUBCATEGORIES_WITH_LABELS_CTE} sc ON sc.ParentId = c.ECInstanceId
|
|
261
|
+
WHERE
|
|
262
|
+
c.ChildCount > 1
|
|
263
|
+
AND sc.DisplayLabel LIKE '%' || ? || '%' ESCAPE '\\'
|
|
264
|
+
|
|
265
|
+
UNION ALL
|
|
266
|
+
|
|
267
|
+
SELECT
|
|
268
|
+
c.ClassName AS ClassName,
|
|
269
|
+
c.ECInstanceId AS ECInstanceId
|
|
270
|
+
FROM
|
|
271
|
+
${CATEGORIES_WITH_LABELS_CTE} c
|
|
272
|
+
WHERE
|
|
273
|
+
c.DisplayLabel LIKE '%' || ? || '%' ESCAPE '\\'
|
|
274
|
+
|
|
275
|
+
${definitionContainers.length > 0
|
|
276
|
+
? `
|
|
277
|
+
UNION ALL
|
|
278
|
+
SELECT
|
|
279
|
+
dc.ClassName AS ClassName,
|
|
280
|
+
dc.ECInstanceId AS ECInstanceId
|
|
281
|
+
FROM
|
|
282
|
+
${DEFINITION_CONTAINERS_WITH_LABELS_CTE} dc
|
|
283
|
+
WHERE
|
|
284
|
+
dc.DisplayLabel LIKE '%' || ? || '%' ESCAPE '\\'
|
|
285
|
+
`
|
|
286
|
+
: ""}
|
|
184
287
|
)
|
|
185
|
-
LIMIT ${MAX_FILTERING_INSTANCE_KEY_COUNT + 1}
|
|
186
|
-
|
|
187
|
-
bindings
|
|
288
|
+
${props.limit === undefined ? `LIMIT ${MAX_FILTERING_INSTANCE_KEY_COUNT + 1}` : props.limit !== "unbounded" ? `LIMIT ${props.limit}` : ""}
|
|
289
|
+
`;
|
|
290
|
+
const bindings = [
|
|
188
291
|
{ type: "string", value: adjustedLabel },
|
|
189
292
|
{ type: "string", value: adjustedLabel },
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
293
|
+
...(definitionContainers.length > 0 ? [{ type: "string", value: adjustedLabel }] : []),
|
|
294
|
+
];
|
|
295
|
+
return props.imodelAccess.createQueryReader({ ctes, ecsql, bindings }, { restartToken: "tree-widget/categories-tree/filter-by-label-query", limit: props.limit });
|
|
296
|
+
}).pipe(map((row) => ({
|
|
297
|
+
className: row.ClassName === "c" ? categoryClass : row.ClassName === "sc" ? SUB_CATEGORY_CLASS : DEFINITION_CONTAINER_CLASS,
|
|
298
|
+
id: row.ECInstanceId,
|
|
299
|
+
})), toArray(), mergeMap((targetItems) => createInstanceKeyPathsFromTargetItems({ ...props, targetItems })), toArray()));
|
|
300
|
+
}
|
|
301
|
+
function createInstanceKeyPathsFromTargetItems(props) {
|
|
302
|
+
const { limit, targetItems, viewType, idsCache } = props;
|
|
303
|
+
if (limit !== "unbounded" && targetItems.length > (limit ?? MAX_FILTERING_INSTANCE_KEY_COUNT)) {
|
|
304
|
+
throw new FilterLimitExceededError(limit ?? MAX_FILTERING_INSTANCE_KEY_COUNT);
|
|
197
305
|
}
|
|
198
|
-
if (
|
|
199
|
-
|
|
306
|
+
if (targetItems.length === 0) {
|
|
307
|
+
return EMPTY;
|
|
200
308
|
}
|
|
201
|
-
|
|
309
|
+
const { categoryClass } = getClassesByView(viewType);
|
|
310
|
+
return from(targetItems).pipe(mergeMap(async (targetItem) => {
|
|
311
|
+
if (targetItem.className === SUB_CATEGORY_CLASS) {
|
|
312
|
+
return { path: await idsCache.getInstanceKeyPaths({ subCategoryId: targetItem.id }), options: { autoExpand: true } };
|
|
313
|
+
}
|
|
314
|
+
if (targetItem.className === categoryClass) {
|
|
315
|
+
return { path: await idsCache.getInstanceKeyPaths({ categoryId: targetItem.id }), options: { autoExpand: true } };
|
|
316
|
+
}
|
|
317
|
+
return { path: await idsCache.getInstanceKeyPaths({ definitionContainerId: targetItem.id }), options: { autoExpand: true } };
|
|
318
|
+
}));
|
|
202
319
|
}
|
|
203
320
|
//# sourceMappingURL=CategoriesTreeDefinition.js.map
|
package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CategoriesTreeDefinition.js","sourceRoot":"","sources":["../../../../../../src/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.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 { createNodesQueryClauseFactory, createPredicateBasedHierarchyDefinition } from \"@itwin/presentation-hierarchies\";\nimport { createBisInstanceLabelSelectClauseFactory, ECSql } from \"@itwin/presentation-shared\";\nimport { FilterLimitExceededError } from \"../common/TreeErrors.js\";\n\nimport type { ECClassHierarchyInspector, ECSchemaProvider, IInstanceLabelSelectClauseFactory } from \"@itwin/presentation-shared\";\nimport type {\n DefineHierarchyLevelProps,\n DefineInstanceNodeChildHierarchyLevelProps,\n DefineRootHierarchyLevelProps,\n HierarchyDefinition,\n HierarchyFilteringPath,\n HierarchyLevelDefinition,\n LimitingECSqlQueryExecutor,\n NodesQueryClauseFactory,\n} from \"@itwin/presentation-hierarchies\";\n\nconst MAX_FILTERING_INSTANCE_KEY_COUNT = 100;\n\ninterface CategoriesTreeDefinitionProps {\n imodelAccess: ECSchemaProvider & ECClassHierarchyInspector;\n viewType: \"2d\" | \"3d\";\n}\n\ninterface CategoriesTreeInstanceKeyPathsFromInstanceLabelProps {\n imodelAccess: ECClassHierarchyInspector & LimitingECSqlQueryExecutor;\n label: string;\n viewType: \"2d\" | \"3d\";\n}\n\nexport class CategoriesTreeDefinition implements HierarchyDefinition {\n private _impl: HierarchyDefinition;\n private _selectQueryFactory: NodesQueryClauseFactory;\n private _nodeLabelSelectClauseFactory: IInstanceLabelSelectClauseFactory;\n\n public constructor(props: CategoriesTreeDefinitionProps) {\n this._impl = createPredicateBasedHierarchyDefinition({\n classHierarchyInspector: props.imodelAccess,\n hierarchy: {\n rootNodes: async (requestProps) => this.createRootHierarchyLevelDefinition({ ...requestProps, viewType: props.viewType }),\n childNodes: [\n {\n parentInstancesNodePredicate: \"BisCore.Category\",\n definitions: async (requestProps: DefineInstanceNodeChildHierarchyLevelProps) => this.createSubcategoryQuery(requestProps),\n },\n ],\n },\n });\n this._nodeLabelSelectClauseFactory = createBisInstanceLabelSelectClauseFactory({ classHierarchyInspector: props.imodelAccess });\n this._selectQueryFactory = createNodesQueryClauseFactory({\n imodelAccess: props.imodelAccess,\n instanceLabelSelectClauseFactory: this._nodeLabelSelectClauseFactory,\n });\n }\n\n public async defineHierarchyLevel(props: DefineHierarchyLevelProps) {\n return this._impl.defineHierarchyLevel(props);\n }\n\n private async createRootHierarchyLevelDefinition(props: DefineRootHierarchyLevelProps & { viewType: \"2d\" | \"3d\" }): Promise<HierarchyLevelDefinition> {\n const { categoryClass, categoryElementClass } = getClassesByView(props.viewType);\n const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({\n filter: props.instanceFilter,\n contentClass: { fullName: categoryClass, alias: \"this\" },\n });\n return [\n {\n fullClassName: categoryClass,\n query: {\n ecsql: `\n SELECT\n ${await this._selectQueryFactory.createSelectClause({\n ecClassId: { selector: ECSql.createRawPropertyValueSelector(\"this\", \"ECClassId\") },\n ecInstanceId: { selector: \"this.ECInstanceId\" },\n nodeLabel: {\n selector: await this._nodeLabelSelectClauseFactory.createSelectClause({\n classAlias: \"this\",\n className: categoryClass,\n }),\n },\n hasChildren: {\n selector: `\n IFNULL((\n SELECT 1\n FROM (\n SELECT COUNT(1) AS ChildCount\n FROM BisCore.SubCategory sc\n WHERE sc.Parent.Id = this.ECInstanceId\n )\n WHERE ChildCount > 1\n ), 0)\n `,\n },\n extendedData: {\n description: { selector: \"this.Description\" },\n },\n supportsFiltering: true,\n })}\n FROM ${instanceFilterClauses.from} this\n ${instanceFilterClauses.joins}\n JOIN BisCore.Model m ON m.ECInstanceId = this.Model.Id\n WHERE\n NOT this.IsPrivate\n AND (NOT m.IsPrivate OR m.ECClassId IS (BisCore.DictionaryModel))\n AND EXISTS (SELECT 1 FROM ${categoryElementClass} e WHERE e.Category.Id = this.ECInstanceId)\n ${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : \"\"}\n `,\n },\n },\n ];\n }\n\n private async createSubcategoryQuery({\n parentNodeInstanceIds: elementIds,\n instanceFilter,\n }: DefineInstanceNodeChildHierarchyLevelProps): Promise<HierarchyLevelDefinition> {\n const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({\n filter: instanceFilter,\n contentClass: { fullName: \"BisCore.SubCategory\", alias: \"this\" },\n });\n return [\n {\n fullClassName: \"BisCore.SubCategory\",\n query: {\n ecsql: `\n SELECT\n ${await this._selectQueryFactory.createSelectClause({\n ecClassId: { selector: \"this.ECClassId\" },\n ecInstanceId: { selector: \"this.ECInstanceId\" },\n nodeLabel: {\n selector: await this._nodeLabelSelectClauseFactory.createSelectClause({\n classAlias: \"this\",\n className: \"BisCore.SubCategory\",\n }),\n },\n extendedData: {\n categoryId: { selector: \"printf('0x%x', this.Parent.Id)\" },\n },\n supportsFiltering: false,\n })}\n FROM ${instanceFilterClauses.from} this\n ${instanceFilterClauses.joins}\n WHERE\n NOT this.IsPrivate AND this.Parent.Id IN (${elementIds.map(() => \"?\").join(\",\")})\n ${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : \"\"}\n `,\n bindings: elementIds.map((id) => ({ type: \"id\", value: id })),\n },\n },\n ];\n }\n\n public static async createInstanceKeyPaths(props: CategoriesTreeInstanceKeyPathsFromInstanceLabelProps) {\n const labelsFactory = createBisInstanceLabelSelectClauseFactory({ classHierarchyInspector: props.imodelAccess });\n return createInstanceKeyPathsFromInstanceLabel({ ...props, labelsFactory });\n }\n}\n\nfunction getClassesByView(viewType: \"2d\" | \"3d\") {\n return viewType === \"2d\"\n ? { categoryClass: \"BisCore.DrawingCategory\", categoryElementClass: \"BisCore:GeometricElement2d\" }\n : { categoryClass: \"BisCore.SpatialCategory\", categoryElementClass: \"BisCore:GeometricElement3d\" };\n}\n\nasync function createInstanceKeyPathsFromInstanceLabel(\n props: CategoriesTreeInstanceKeyPathsFromInstanceLabelProps & { labelsFactory: IInstanceLabelSelectClauseFactory },\n) {\n const { categoryClass, categoryElementClass } = getClassesByView(props.viewType);\n const adjustedLabel = props.label.replace(/[%_\\\\]/g, \"\\\\$&\");\n const reader = props.imodelAccess.createQueryReader(\n {\n ctes: [\n `RootCategoriesWithLabels(ClassName, ECInstanceId, ChildCount, DisplayLabel) as (\n SELECT\n ec_classname(this.ECClassId, 's.c'),\n this.ECInstanceId,\n COUNT(sc.ECInstanceId),\n ${await props.labelsFactory.createSelectClause({\n classAlias: \"this\",\n className: categoryClass,\n })}\n FROM ${categoryClass} this\n JOIN BisCore.Model m ON m.ECInstanceId = this.Model.Id\n JOIN BisCore.SubCategory sc ON sc.Parent.Id = this.ECInstanceId\n WHERE\n NOT this.IsPrivate\n AND (NOT m.IsPrivate OR m.ECClassId IS (BisCore.DictionaryModel))\n AND EXISTS (SELECT 1 FROM ${categoryElementClass} e WHERE e.Category.Id = this.ECInstanceId)\n GROUP BY this.ECInstanceId\n )`,\n `SubCategoriesWithLabels(ClassName, ECInstanceId, ParentId, DisplayLabel) as (\n SELECT\n ec_classname(this.ECClassId, 's.c'),\n this.ECInstanceId,\n this.Parent.Id,\n ${await props.labelsFactory.createSelectClause({\n classAlias: \"this\",\n className: \"BisCore.SubCategory\",\n })}\n FROM BisCore.SubCategory this\n WHERE NOT this.IsPrivate\n )`,\n ],\n ecsql: `\n SELECT * FROM (\n SELECT\n c.ClassName AS CategoryClass,\n c.ECInstanceId AS CategoryId,\n sc.ClassName AS SubcategoryClass,\n sc.ECInstanceId AS SubcategoryId\n FROM RootCategoriesWithLabels c\n JOIN SubCategoriesWithLabels sc ON sc.ParentId = c.ECInstanceId\n WHERE c.ChildCount > 1 AND sc.DisplayLabel LIKE '%' || ? || '%' ESCAPE '\\\\'\n UNION ALL\n SELECT\n c.ClassName AS CategoryClass,\n c.ECInstanceId AS CategoryId,\n CAST(NULL AS TEXT) AS SubcategoryClass,\n CAST(NULL AS TEXT) AS SubcategoryId\n FROM RootCategoriesWithLabels c\n WHERE c.DisplayLabel LIKE '%' || ? || '%' ESCAPE '\\\\'\n )\n LIMIT ${MAX_FILTERING_INSTANCE_KEY_COUNT + 1}\n `,\n bindings: [\n { type: \"string\", value: adjustedLabel },\n { type: \"string\", value: adjustedLabel },\n ],\n },\n { restartToken: \"tree-widget/categories-tree/filter-by-label-query\" },\n );\n const paths: HierarchyFilteringPath[] = [];\n for await (const row of reader) {\n const path = { path: [{ className: row.CategoryClass, id: row.CategoryId }], options: { autoExpand: true } };\n row.SubcategoryId && path.path.push({ className: row.SubcategoryClass, id: row.SubcategoryId });\n paths.push(path);\n }\n if (paths.length > MAX_FILTERING_INSTANCE_KEY_COUNT) {\n throw new FilterLimitExceededError(MAX_FILTERING_INSTANCE_KEY_COUNT);\n }\n return paths;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"CategoriesTreeDefinition.js","sourceRoot":"","sources":["../../../../../../src/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.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, EMPTY, from, lastValueFrom, map, mergeMap, toArray } from \"rxjs\";\nimport { createNodesQueryClauseFactory, createPredicateBasedHierarchyDefinition } from \"@itwin/presentation-hierarchies\";\nimport { createBisInstanceLabelSelectClauseFactory, ECSql } from \"@itwin/presentation-shared\";\nimport { FilterLimitExceededError } from \"../common/TreeErrors.js\";\nimport { getClassesByView } from \"./internal/CategoriesTreeIdsCache.js\";\nimport { DEFINITION_CONTAINER_CLASS, DEFINITION_ELEMENT_CLASS, SUB_CATEGORY_CLASS } from \"./internal/ClassNameDefinitions.js\";\n\nimport type { Observable } from \"rxjs\";\nimport type { Id64Array, Id64String } from \"@itwin/core-bentley\";\nimport type { ECClassHierarchyInspector, ECSchemaProvider, IInstanceLabelSelectClauseFactory, InstanceKey } from \"@itwin/presentation-shared\";\nimport type { CategoriesTreeIdsCache } from \"./internal/CategoriesTreeIdsCache.js\";\nimport type {\n DefineHierarchyLevelProps,\n DefineInstanceNodeChildHierarchyLevelProps,\n DefineRootHierarchyLevelProps,\n GenericInstanceFilter,\n HierarchyDefinition,\n HierarchyFilteringPath,\n HierarchyLevelDefinition,\n LimitingECSqlQueryExecutor,\n NodesQueryClauseFactory,\n} from \"@itwin/presentation-hierarchies\";\n\nconst MAX_FILTERING_INSTANCE_KEY_COUNT = 100;\n\ninterface CategoriesTreeDefinitionProps {\n imodelAccess: ECSchemaProvider & ECClassHierarchyInspector & LimitingECSqlQueryExecutor;\n viewType: \"2d\" | \"3d\";\n idsCache: CategoriesTreeIdsCache;\n}\n\ninterface CategoriesTreeInstanceKeyPathsFromInstanceLabelProps {\n imodelAccess: ECClassHierarchyInspector & LimitingECSqlQueryExecutor;\n label: string;\n viewType: \"2d\" | \"3d\";\n limit?: number | \"unbounded\";\n idsCache: CategoriesTreeIdsCache;\n}\n\nexport class CategoriesTreeDefinition implements HierarchyDefinition {\n private _impl: Promise<HierarchyDefinition> | undefined;\n private _selectQueryFactory: NodesQueryClauseFactory;\n private _nodeLabelSelectClauseFactory: IInstanceLabelSelectClauseFactory;\n private _idsCache: CategoriesTreeIdsCache;\n private _viewType: \"2d\" | \"3d\";\n private _iModelAccess: ECSchemaProvider & ECClassHierarchyInspector & LimitingECSqlQueryExecutor;\n\n public constructor(props: CategoriesTreeDefinitionProps) {\n this._iModelAccess = props.imodelAccess;\n this._viewType = props.viewType;\n this._idsCache = props.idsCache;\n this._nodeLabelSelectClauseFactory = createBisInstanceLabelSelectClauseFactory({ classHierarchyInspector: props.imodelAccess });\n this._selectQueryFactory = createNodesQueryClauseFactory({\n imodelAccess: props.imodelAccess,\n instanceLabelSelectClauseFactory: this._nodeLabelSelectClauseFactory,\n });\n }\n\n private async getHierarchyDefinition(): Promise<HierarchyDefinition> {\n this._impl ??= (async () => {\n const isDefinitionContainerSupported = await this._idsCache.getIsDefinitionContainerSupported();\n return createPredicateBasedHierarchyDefinition({\n classHierarchyInspector: this._iModelAccess,\n hierarchy: {\n rootNodes: async (requestProps: DefineRootHierarchyLevelProps) =>\n this.createDefinitionContainersAndCategoriesQuery({ ...requestProps, viewType: this._viewType }),\n childNodes: [\n {\n parentInstancesNodePredicate: \"BisCore.Category\",\n definitions: async (requestProps: DefineInstanceNodeChildHierarchyLevelProps) => this.createSubcategoryQuery(requestProps),\n },\n ...(isDefinitionContainerSupported\n ? [\n {\n parentInstancesNodePredicate: DEFINITION_CONTAINER_CLASS,\n definitions: async (requestProps: DefineInstanceNodeChildHierarchyLevelProps) =>\n this.createDefinitionContainersAndCategoriesQuery({\n ...requestProps,\n viewType: this._viewType,\n }),\n },\n ]\n : []),\n ],\n },\n });\n })();\n return this._impl;\n }\n\n public async defineHierarchyLevel(props: DefineHierarchyLevelProps) {\n return (await this.getHierarchyDefinition()).defineHierarchyLevel(props);\n }\n\n private async createDefinitionContainersAndCategoriesQuery(props: {\n parentNodeInstanceIds?: Id64Array;\n instanceFilter?: GenericInstanceFilter;\n viewType: \"2d\" | \"3d\";\n }): Promise<HierarchyLevelDefinition> {\n const { parentNodeInstanceIds, instanceFilter, viewType } = props;\n const { definitionContainers, categories } =\n parentNodeInstanceIds === undefined\n ? await this._idsCache.getRootDefinitionContainersAndCategories()\n : await this._idsCache.getDirectChildDefinitionContainersAndCategories(parentNodeInstanceIds);\n if (categories.length === 0 && definitionContainers.length === 0) {\n return [];\n }\n\n const categoriesWithSingleChild = new Array<Id64String>();\n const categoriesWithMultipleChildren = new Array<Id64String>();\n categories.forEach((category) => {\n if (category.childCount > 1) {\n categoriesWithMultipleChildren.push(category.id);\n } else {\n categoriesWithSingleChild.push(category.id);\n }\n });\n const dataToDetermineHasChildren =\n categoriesWithSingleChild.length > categoriesWithMultipleChildren.length\n ? { ids: categoriesWithMultipleChildren, ifTrue: 1, ifFalse: 0 }\n : { ids: categoriesWithSingleChild, ifTrue: 0, ifFalse: 1 };\n\n const { categoryClass } = getClassesByView(viewType);\n\n const [categoriesInstanceFilterClauses, definitionContainersInstanceFilterClauses] = await Promise.all(\n [categoryClass, ...(definitionContainers.length > 0 ? [DEFINITION_CONTAINER_CLASS] : [])].map(async (className) =>\n this._selectQueryFactory.createFilterClauses({\n filter: instanceFilter,\n contentClass: { fullName: className, alias: \"this\" },\n }),\n ),\n );\n\n const definitionContainersQuery =\n definitionContainers.length > 0\n ? `\n SELECT\n ${await this._selectQueryFactory.createSelectClause({\n ecClassId: { selector: ECSql.createRawPropertyValueSelector(\"this\", \"ECClassId\") },\n ecInstanceId: { selector: \"this.ECInstanceId\" },\n nodeLabel: {\n selector: await this._nodeLabelSelectClauseFactory.createSelectClause({\n classAlias: \"this\",\n className: DEFINITION_CONTAINER_CLASS,\n }),\n },\n extendedData: {\n isDefinitionContainer: true,\n imageId: \"icon-definition-container\",\n },\n hasChildren: true,\n supportsFiltering: true,\n })}\n FROM\n ${definitionContainersInstanceFilterClauses.from} this\n ${definitionContainersInstanceFilterClauses.joins}\n WHERE\n this.ECInstanceId IN (${definitionContainers.join(\", \")})\n ${definitionContainersInstanceFilterClauses.where ? `AND ${definitionContainersInstanceFilterClauses.where}` : \"\"}\n `\n : undefined;\n\n const categoriesQuery =\n categories.length > 0\n ? `\n SELECT\n ${await this._selectQueryFactory.createSelectClause({\n ecClassId: { selector: ECSql.createRawPropertyValueSelector(\"this\", \"ECClassId\") },\n ecInstanceId: { selector: \"this.ECInstanceId\" },\n nodeLabel: {\n selector: await this._nodeLabelSelectClauseFactory.createSelectClause({\n classAlias: \"this\",\n className: categoryClass,\n }),\n },\n ...(dataToDetermineHasChildren.ids.length > 0\n ? {\n hasChildren: {\n selector: `\n IIF(this.ECInstanceId IN (${dataToDetermineHasChildren.ids.join(\",\")}),\n ${dataToDetermineHasChildren.ifTrue},\n ${dataToDetermineHasChildren.ifFalse}\n )\n `,\n },\n }\n : { hasChildren: !!dataToDetermineHasChildren.ifFalse }),\n extendedData: {\n description: { selector: \"this.Description\" },\n isCategory: true,\n imageId: \"icon-layers\",\n },\n supportsFiltering: true,\n })}\n FROM\n ${categoriesInstanceFilterClauses.from} this\n ${categoriesInstanceFilterClauses.joins}\n WHERE\n this.ECInstanceId IN (${categories.map((category) => category.id).join(\", \")})\n ${categoriesInstanceFilterClauses.where ? `AND ${categoriesInstanceFilterClauses.where}` : \"\"}\n `\n : undefined;\n const queries = [categoriesQuery, definitionContainersQuery].filter((query) => query !== undefined);\n return [\n {\n fullClassName: DEFINITION_ELEMENT_CLASS,\n query: {\n ecsql: queries.join(\" UNION ALL \"),\n },\n },\n ];\n }\n\n private async createSubcategoryQuery({\n parentNodeInstanceIds: elementIds,\n instanceFilter,\n }: DefineInstanceNodeChildHierarchyLevelProps): Promise<HierarchyLevelDefinition> {\n const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({\n filter: instanceFilter,\n contentClass: { fullName: SUB_CATEGORY_CLASS, alias: \"this\" },\n });\n return [\n {\n fullClassName: SUB_CATEGORY_CLASS,\n query: {\n ecsql: `\n SELECT\n ${await this._selectQueryFactory.createSelectClause({\n ecClassId: { selector: \"this.ECClassId\" },\n ecInstanceId: { selector: \"this.ECInstanceId\" },\n nodeLabel: {\n selector: await this._nodeLabelSelectClauseFactory.createSelectClause({\n classAlias: \"this\",\n className: SUB_CATEGORY_CLASS,\n }),\n },\n extendedData: {\n categoryId: { selector: \"printf('0x%x', this.Parent.Id)\" },\n isSubCategory: true,\n imageId: \"icon-layers-isolate\",\n },\n supportsFiltering: false,\n })}\n FROM ${instanceFilterClauses.from} this\n ${instanceFilterClauses.joins}\n WHERE\n NOT this.IsPrivate AND this.Parent.Id IN (${elementIds.map(() => \"?\").join(\",\")})\n ${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : \"\"}\n `,\n bindings: elementIds.map((id) => ({ type: \"id\", value: id })),\n },\n },\n ];\n }\n\n public static async createInstanceKeyPaths(props: CategoriesTreeInstanceKeyPathsFromInstanceLabelProps): Promise<HierarchyFilteringPath[]> {\n const labelsFactory = createBisInstanceLabelSelectClauseFactory({ classHierarchyInspector: props.imodelAccess });\n return createInstanceKeyPathsFromInstanceLabel({ ...props, labelsFactory, cache: props.idsCache });\n }\n}\n\nasync function createInstanceKeyPathsFromInstanceLabel(\n props: CategoriesTreeInstanceKeyPathsFromInstanceLabelProps & { labelsFactory: IInstanceLabelSelectClauseFactory; cache: CategoriesTreeIdsCache },\n): Promise<HierarchyFilteringPath[]> {\n const { definitionContainers, categories } = await props.cache.getAllDefinitionContainersAndCategories();\n if (categories.length === 0) {\n return [];\n }\n\n const { categoryClass } = getClassesByView(props.viewType);\n const adjustedLabel = props.label.replace(/[%_\\\\]/g, \"\\\\$&\");\n\n const CATEGORIES_WITH_LABELS_CTE = \"CategoriesWithLabels\";\n const SUBCATEGORIES_WITH_LABELS_CTE = \"SubCategoriesWithLabels\";\n const DEFINITION_CONTAINERS_WITH_LABELS_CTE = \"DefinitionContainersWithLabels\";\n const [categoryLabelSelectClause, subCategoryLabelSelectClause, definitionContainerLabelSelectClause] = await Promise.all(\n [categoryClass, SUB_CATEGORY_CLASS, ...(definitionContainers.length > 0 ? [DEFINITION_CONTAINER_CLASS] : [])].map(async (className) =>\n props.labelsFactory.createSelectClause({ classAlias: \"this\", className }),\n ),\n );\n return lastValueFrom(\n defer(() => {\n const ctes = [\n `${CATEGORIES_WITH_LABELS_CTE}(ClassName, ECInstanceId, ChildCount, DisplayLabel) AS (\n SELECT\n 'c',\n this.ECInstanceId,\n COUNT(sc.ECInstanceId),\n ${categoryLabelSelectClause}\n FROM\n ${categoryClass} this\n JOIN ${SUB_CATEGORY_CLASS} sc ON sc.Parent.Id = this.ECInstanceId\n WHERE\n this.ECInstanceId IN (${categories.join(\", \")})\n GROUP BY this.ECInstanceId\n )`,\n `${SUBCATEGORIES_WITH_LABELS_CTE}(ClassName, ECInstanceId, ParentId, DisplayLabel) AS (\n SELECT\n 'sc',\n this.ECInstanceId,\n this.Parent.Id,\n ${subCategoryLabelSelectClause}\n FROM\n ${SUB_CATEGORY_CLASS} this\n WHERE\n NOT this.IsPrivate\n AND this.Parent.Id IN (${categories.join(\", \")})\n )`,\n ...(definitionContainers.length > 0\n ? [\n `${DEFINITION_CONTAINERS_WITH_LABELS_CTE}(ClassName, ECInstanceId, DisplayLabel) AS (\n SELECT\n 'dc',\n this.ECInstanceId,\n ${definitionContainerLabelSelectClause}\n FROM\n ${DEFINITION_CONTAINER_CLASS} this\n WHERE\n this.ECInstanceId IN (${definitionContainers.join(\", \")})\n )`,\n ]\n : []),\n ];\n const ecsql = `\n SELECT * FROM (\n SELECT\n sc.ClassName AS ClassName,\n sc.ECInstanceId AS ECInstanceId\n FROM\n ${CATEGORIES_WITH_LABELS_CTE} c\n JOIN ${SUBCATEGORIES_WITH_LABELS_CTE} sc ON sc.ParentId = c.ECInstanceId\n WHERE\n c.ChildCount > 1\n AND sc.DisplayLabel LIKE '%' || ? || '%' ESCAPE '\\\\'\n\n UNION ALL\n\n SELECT\n c.ClassName AS ClassName,\n c.ECInstanceId AS ECInstanceId\n FROM\n ${CATEGORIES_WITH_LABELS_CTE} c\n WHERE\n c.DisplayLabel LIKE '%' || ? || '%' ESCAPE '\\\\'\n\n ${\n definitionContainers.length > 0\n ? `\n UNION ALL\n SELECT\n dc.ClassName AS ClassName,\n dc.ECInstanceId AS ECInstanceId\n FROM\n ${DEFINITION_CONTAINERS_WITH_LABELS_CTE} dc\n WHERE\n dc.DisplayLabel LIKE '%' || ? || '%' ESCAPE '\\\\'\n `\n : \"\"\n }\n )\n ${props.limit === undefined ? `LIMIT ${MAX_FILTERING_INSTANCE_KEY_COUNT + 1}` : props.limit !== \"unbounded\" ? `LIMIT ${props.limit}` : \"\"}\n `;\n const bindings = [\n { type: \"string\" as const, value: adjustedLabel },\n { type: \"string\" as const, value: adjustedLabel },\n ...(definitionContainers.length > 0 ? [{ type: \"string\" as const, value: adjustedLabel }] : []),\n ];\n return props.imodelAccess.createQueryReader(\n { ctes, ecsql, bindings },\n { restartToken: \"tree-widget/categories-tree/filter-by-label-query\", limit: props.limit },\n );\n }).pipe(\n map(\n (row): InstanceKey => ({\n className: row.ClassName === \"c\" ? categoryClass : row.ClassName === \"sc\" ? SUB_CATEGORY_CLASS : DEFINITION_CONTAINER_CLASS,\n id: row.ECInstanceId,\n }),\n ),\n toArray(),\n mergeMap((targetItems): Observable<HierarchyFilteringPath> => createInstanceKeyPathsFromTargetItems({ ...props, targetItems })),\n toArray(),\n ),\n );\n}\n\nfunction createInstanceKeyPathsFromTargetItems(\n props: Pick<CategoriesTreeInstanceKeyPathsFromInstanceLabelProps, \"idsCache\" | \"limit\" | \"viewType\"> & {\n targetItems: InstanceKey[];\n },\n): Observable<HierarchyFilteringPath> {\n const { limit, targetItems, viewType, idsCache } = props;\n if (limit !== \"unbounded\" && targetItems.length > (limit ?? MAX_FILTERING_INSTANCE_KEY_COUNT)) {\n throw new FilterLimitExceededError(limit ?? MAX_FILTERING_INSTANCE_KEY_COUNT);\n }\n\n if (targetItems.length === 0) {\n return EMPTY;\n }\n\n const { categoryClass } = getClassesByView(viewType);\n return from(targetItems).pipe(\n mergeMap(async (targetItem) => {\n if (targetItem.className === SUB_CATEGORY_CLASS) {\n return { path: await idsCache.getInstanceKeyPaths({ subCategoryId: targetItem.id }), options: { autoExpand: true } };\n }\n if (targetItem.className === categoryClass) {\n return { path: await idsCache.getInstanceKeyPaths({ categoryId: targetItem.id }), options: { autoExpand: true } };\n }\n return { path: await idsCache.getInstanceKeyPaths({ definitionContainerId: targetItem.id }), options: { autoExpand: true } };\n }),\n );\n}\n"]}
|