@itwin/tree-widget-react 4.0.0-alpha.11 → 4.0.0-alpha.12

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.
Files changed (21) hide show
  1. package/CHANGELOG.md +25 -1
  2. package/README.md +143 -35
  3. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeDefinition.d.ts +0 -10
  4. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeDefinition.js +54 -132
  5. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeDefinition.js.map +1 -1
  6. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeIcon.js +2 -6
  7. package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeIcon.js.map +1 -1
  8. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeIdsCache.d.ts +11 -10
  9. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeIdsCache.js +61 -48
  10. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeIdsCache.js.map +1 -1
  11. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeNode.d.ts +0 -1
  12. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeNode.js +0 -4
  13. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeNode.js.map +1 -1
  14. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeVisibilityHandler.js +25 -21
  15. package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeVisibilityHandler.js.map +1 -1
  16. package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.d.ts +27 -0
  17. package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.js.map +1 -1
  18. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseFilteredPaths.d.ts +3 -0
  19. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseFilteredPaths.js +1 -0
  20. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseFilteredPaths.js.map +1 -1
  21. package/package.json +28 -34
package/CHANGELOG.md CHANGED
@@ -1,9 +1,33 @@
1
1
  # Change Log - @itwin/tree-widget-react
2
2
 
3
- This log was last generated on Thu, 15 May 2025 05:33:32 GMT and should not be manually modified.
3
+ This log was last generated on Fri, 20 Jun 2025 17:05:06 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## 3.10.1
8
+
9
+ Fri, 20 Jun 2025 17:05:06 GMT
10
+
11
+ ### Patches
12
+
13
+ - Update itwinjs-core dependencies to v5.0.0 ([#1349](https://github.com/iTwin/viewer-components-react/pull/1349))
14
+
15
+ ## 3.10.0
16
+
17
+ Mon, 02 Jun 2025 13:19:21 GMT
18
+
19
+ ### Minor changes
20
+
21
+ - `useModelsTree`: The `getFilteredPaths` callback prop now has a `filter` prop, which matches the value of `filter` prop passed to `useModelsTree` hook. This make it more convenient for consumers to filter by instance keys and label at the same time. ([#1335](https://github.com/iTwin/viewer-components-react/pull/1335))
22
+
23
+ ## 3.9.0
24
+
25
+ Mon, 19 May 2025 16:58:21 GMT
26
+
27
+ ### Minor changes
28
+
29
+ - Add support for iTwin.js v5.0 ([#1326](https://github.com/iTwin/viewer-components-react/pull/1326))
30
+
7
31
  ## 3.8.0
8
32
 
9
33
  Thu, 15 May 2025 05:33:32 GMT
package/README.md CHANGED
@@ -191,41 +191,149 @@ function CustomModelsTreeComponent({ imodel, viewport, selectionStorage }: Custo
191
191
 
192
192
  #### Displaying a subset of the tree
193
193
 
194
- Models tree allows displaying a subset of all nodes by providing a `getFilteredPaths` function, which receives a `createInstanceKeyPaths` function for creating hierarchy node paths from instance keys or an instance label and returns a list of hierarchy node paths targeting some nodes. When these paths are provided, the displayed hierarchy consists only of the targeted nodes, their ancestors, and their children. Example implementation of `getFilteredPaths`:
195
-
196
- ```tsx
197
- type UseModelsTreeProps = Parameters<typeof useModelsTree>[0];
198
- type GetFilteredPathsType = Exclude<UseModelsTreeProps["getFilteredPaths"], undefined>;
199
- interface CustomModelsTreeProps {
200
- viewport: Viewport;
201
- selectionStorage: SelectionStorage;
202
- imodel: IModelConnection;
203
- targetItems: InstanceKey[];
204
- }
205
-
206
- function CustomModelsTreeComponent({ viewport, selectionStorage, imodel, targetItems }: CustomModelsTreeProps) {
207
- const getFilteredPaths = useCallback<GetFilteredPathsType>(
208
- async ({ createInstanceKeyPaths }) => {
209
- return createInstanceKeyPaths({
210
- // list of instance keys representing nodes that should be displayed in the hierarchy
211
- targetItems,
212
- });
213
- },
214
- [targetItems],
215
- );
216
-
217
- const { modelsTreeProps, rendererProps } = useModelsTree({ activeView: viewport, getFilteredPaths });
218
-
219
- return (
220
- <VisibilityTree
221
- {...modelsTreeProps}
222
- selectionStorage={selectionStorage}
223
- imodel={imodel}
224
- treeRenderer={(props) => <VisibilityTreeRenderer {...props} {...rendererProps} />}
225
- />
226
- );
227
- }
228
- ```
194
+ Models tree allows displaying a subset of all nodes by providing a `getFilteredPaths` function. This function receives a helper function called `createInstanceKeyPaths`, which can generate paths from either:
195
+
196
+ - a list of instance keys (`targetItems`)
197
+ - a label string
198
+
199
+ Based on the returned paths, the displayed hierarchy consists only of the targeted nodes, their ancestors, and their children.
200
+
201
+ Use `getFilteredPaths` when you need more control over which nodes are shown. Here are some example use cases:
202
+
203
+ - **Filter by known instance keys**: You already have a list of `InstanceKey` items that should remain in the tree. Pass them as `targetItems` to `createInstanceKeyPaths`.
204
+ <!-- [[include: [TreeWidget.GetFilteredPathsComponentWithTargetItemsExample], tsx]] -->
205
+ <!-- BEGIN EXTRACTION -->
206
+
207
+ ```tsx
208
+ type UseModelsTreeProps = Parameters<typeof useModelsTree>[0];
209
+ type GetFilteredPathsType = Exclude<UseModelsTreeProps["getFilteredPaths"], undefined>;
210
+
211
+ function CustomModelsTreeComponentWithTargetItems({
212
+ viewport,
213
+ selectionStorage,
214
+ imodel,
215
+ targetItems,
216
+ }: {
217
+ viewport: Viewport;
218
+ selectionStorage: SelectionStorage;
219
+ imodel: IModelConnection;
220
+ targetItems: InstanceKey[];
221
+ }) {
222
+ const getFilteredPaths = useCallback<GetFilteredPathsType>(
223
+ async ({ createInstanceKeyPaths }) => {
224
+ return createInstanceKeyPaths({
225
+ // list of instance keys representing nodes that should be displayed in the hierarchy
226
+ targetItems,
227
+ });
228
+ },
229
+ [targetItems],
230
+ );
231
+
232
+ const { modelsTreeProps, rendererProps } = useModelsTree({ activeView: viewport, getFilteredPaths });
233
+
234
+ return (
235
+ <VisibilityTree
236
+ {...modelsTreeProps}
237
+ getSchemaContext={getSchemaContext}
238
+ selectionStorage={selectionStorage}
239
+ imodel={imodel}
240
+ treeRenderer={(props) => <VisibilityTreeRenderer {...props} {...rendererProps} />}
241
+ />
242
+ );
243
+ }
244
+ ```
245
+
246
+ <!-- END EXTRACTION -->
247
+
248
+ - **Post-process the paths created `createInstanceKeyPaths`**: Use `filter` string to generate the paths, then apply additional filtering - e.g., remove paths that are too long.
249
+ <!-- [[include: [TreeWidget.GetFilteredPathsComponentWithPostProcessingExample], tsx]] -->
250
+ <!-- BEGIN EXTRACTION -->
251
+
252
+ ```tsx
253
+ function CustomModelsTreeComponentWithPostProcessing({
254
+ viewport,
255
+ selectionStorage,
256
+ imodel,
257
+ }: {
258
+ viewport: Viewport;
259
+ selectionStorage: SelectionStorage;
260
+ imodel: IModelConnection;
261
+ }) {
262
+ const getFilteredPaths = useCallback<GetFilteredPathsType>(async ({ createInstanceKeyPaths, filter }) => {
263
+ const defaultPaths = await createInstanceKeyPaths({ label: filter ?? "test" });
264
+ const result = new Array<HierarchyFilteringPath>();
265
+ for (const path of defaultPaths) {
266
+ const normalizedPath = HierarchyFilteringPath.normalize(path);
267
+ if (normalizedPath.path.length < 5) {
268
+ normalizedPath.options = { autoExpand: true };
269
+ result.push(normalizedPath);
270
+ }
271
+ }
272
+ return result;
273
+ }, []);
274
+
275
+ const { modelsTreeProps, rendererProps } = useModelsTree({ activeView: viewport, getFilteredPaths });
276
+
277
+ return (
278
+ <VisibilityTree
279
+ {...modelsTreeProps}
280
+ getSchemaContext={getSchemaContext}
281
+ selectionStorage={selectionStorage}
282
+ imodel={imodel}
283
+ treeRenderer={(props) => <VisibilityTreeRenderer {...props} {...rendererProps} />}
284
+ />
285
+ );
286
+ }
287
+ ```
288
+
289
+ <!-- END EXTRACTION -->
290
+
291
+ - **Apply custom logic to generate instance keys**: Generate instance keys using custom implementation. For example: query elements that have specified filter in their user label and provide them as targetItems.
292
+ <!-- [[include: [TreeWidget.GetFilteredPathsComponentWithFilterAndTargetItemsExample], tsx]] -->
293
+ <!-- BEGIN EXTRACTION -->
294
+ ```tsx
295
+ function CustomModelsTreeComponentWithFilterAndTargetItems({
296
+ viewport,
297
+ selectionStorage,
298
+ imodel,
299
+ }: {
300
+ viewport: Viewport;
301
+ selectionStorage: SelectionStorage;
302
+ imodel: IModelConnection;
303
+ }) {
304
+ const getFilteredPaths = useCallback<GetFilteredPathsType>(
305
+ async ({ createInstanceKeyPaths, filter }) => {
306
+ const targetItems = new Array<InstanceKey>();
307
+ for await (const row of imodel.createQueryReader(
308
+ `
309
+ SELECT ec_classname(e.ECClassId, 's.c') className, e.ECInstanceId id
310
+ FROM BisCore.Element e
311
+ WHERE UserLabel LIKE '%${filter ?? ""}%'
312
+ `,
313
+ undefined,
314
+ { rowFormat: QueryRowFormat.UseJsPropertyNames },
315
+ )) {
316
+ targetItems.push({ id: row.id, className: row.className });
317
+ }
318
+ return createInstanceKeyPaths({ targetItems });
319
+ },
320
+ [imodel],
321
+ );
322
+
323
+ const { modelsTreeProps, rendererProps } = useModelsTree({ activeView: viewport, getFilteredPaths, filter: "test" });
324
+
325
+ return (
326
+ <VisibilityTree
327
+ {...modelsTreeProps}
328
+ getSchemaContext={getSchemaContext}
329
+ selectionStorage={selectionStorage}
330
+ imodel={imodel}
331
+ treeRenderer={(props) => <VisibilityTreeRenderer {...props} {...rendererProps} />}
332
+ />
333
+ );
334
+ }
335
+ ```
336
+ <!-- END EXTRACTION -->
229
337
 
230
338
  ### Categories tree
231
339
 
@@ -13,16 +13,6 @@ export interface ClassificationsTreeHierarchyConfiguration {
13
13
  * root `ClassificationSystem`.
14
14
  */
15
15
  rootClassificationSystemCode: string;
16
- /**
17
- * In case consumer knows the name of relationship between a `Classification` and a `Category`, it can be provided
18
- * here. With this relationship, Categories for a given Classification can be loaded directly, without going through
19
- * geometric elements. That has a couple of effects:
20
- * - Performance is better, as it allows us to avoid scanning all elements under specific Classification.
21
- * - Categories related to a Classification are displayed, even if they don't have any elements assigned to them.
22
- *
23
- * It's expected that source of the relationship is `BisCore.Category` and target - `ClassificationSystems.Classification`.
24
- */
25
- categorySymbolizesClassificationRelationshipName?: string;
26
16
  }
27
17
  /** @internal */
28
18
  export declare class ClassificationsTreeDefinition implements HierarchyDefinition {
@@ -3,9 +3,8 @@
3
3
  * See LICENSE.md in the project root for license terms and full copyright notice.
4
4
  *--------------------------------------------------------------------------------------------*/
5
5
  import { createNodesQueryClauseFactory, createPredicateBasedHierarchyDefinition } from "@itwin/presentation-hierarchies";
6
- import { createBisInstanceLabelSelectClauseFactory, ECSql } from "@itwin/presentation-shared";
7
- import { CLASS_NAME_Category, CLASS_NAME_Classification, CLASS_NAME_ClassificationSystem, CLASS_NAME_ClassificationTable, CLASS_NAME_Element, CLASS_NAME_ElementHasClassifications, CLASS_NAME_GeometricElement, CLASS_NAME_GeometricElement2d, CLASS_NAME_GeometricElement3d, CLASS_NAME_SpatialCategory, } from "../common/internal/ClassNameDefinitions.js";
8
- import { createIdsSelector, parseIdsSelectorResult } from "../common/internal/Utils.js";
6
+ import { createBisInstanceLabelSelectClauseFactory, ECSql, parseFullClassName } from "@itwin/presentation-shared";
7
+ import { CLASS_NAME_Classification, CLASS_NAME_ClassificationSystem, CLASS_NAME_ClassificationTable, CLASS_NAME_Element, CLASS_NAME_ElementHasClassifications, CLASS_NAME_GeometricElement, CLASS_NAME_GeometricElement2d, CLASS_NAME_GeometricElement3d, } from "../common/internal/ClassNameDefinitions.js";
9
8
  /** @internal */
10
9
  export class ClassificationsTreeDefinition {
11
10
  _props;
@@ -32,10 +31,6 @@ export class ClassificationsTreeDefinition {
32
31
  parentInstancesNodePredicate: CLASS_NAME_Classification,
33
32
  definitions: async (requestProps) => this.#createClassificationChildrenQuery(requestProps),
34
33
  },
35
- {
36
- parentInstancesNodePredicate: CLASS_NAME_Category,
37
- definitions: async (requestProps) => this.#createCategoryChildrenQuery(requestProps),
38
- },
39
34
  {
40
35
  parentInstancesNodePredicate: CLASS_NAME_GeometricElement,
41
36
  definitions: async (requestProps) => this.#createGeometricElementChildrenQuery(requestProps),
@@ -102,8 +97,8 @@ export class ClassificationsTreeDefinition {
102
97
  filter: instanceFilter,
103
98
  contentClass: { fullName: CLASS_NAME_Classification, alias: "this" },
104
99
  });
105
- const childrenInfo = await this._props.idsCache.getDirectCategoriesAndClassifications(classificationTableIds);
106
- return childrenInfo.classificationIds.length
100
+ const classificationIds = await this._props.idsCache.getDirectChildClassifications(classificationTableIds);
101
+ return classificationIds.length
107
102
  ? [
108
103
  {
109
104
  fullClassName: CLASS_NAME_Classification,
@@ -131,7 +126,7 @@ export class ClassificationsTreeDefinition {
131
126
  ${instanceFilterClauses.from} this
132
127
  ${instanceFilterClauses.joins}
133
128
  WHERE
134
- this.ECInstanceId IN (${childrenInfo.classificationIds.join(",")})
129
+ this.ECInstanceId IN (${classificationIds.join(",")})
135
130
  ${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : ""}
136
131
  `,
137
132
  },
@@ -140,11 +135,11 @@ export class ClassificationsTreeDefinition {
140
135
  : [];
141
136
  }
142
137
  async #createClassificationChildrenQuery(props) {
143
- const { parentNodeInstanceIds: classificationIds, instanceFilter } = props;
144
- const childrenInfo = await this._props.idsCache.getDirectCategoriesAndClassifications(classificationIds);
138
+ const { parentNodeInstanceIds: parentClassificationIds, instanceFilter } = props;
139
+ const classificationIds = await this._props.idsCache.getDirectChildClassifications(parentClassificationIds);
145
140
  return [
146
141
  // load child classifications
147
- ...(childrenInfo.classificationIds.length
142
+ ...(classificationIds.length
148
143
  ? [
149
144
  await (async () => {
150
145
  const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({
@@ -177,66 +172,7 @@ export class ClassificationsTreeDefinition {
177
172
  ${instanceFilterClauses.from} this
178
173
  ${instanceFilterClauses.joins}
179
174
  WHERE
180
- this.ECInstanceId IN (${childrenInfo.classificationIds.join(",")})
181
- ${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : ""}
182
- `,
183
- },
184
- };
185
- })(),
186
- ]
187
- : []),
188
- // load referenced categories
189
- ...(childrenInfo.categoryIds.length
190
- ? [
191
- await (async () => {
192
- const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({
193
- filter: instanceFilter,
194
- contentClass: { fullName: CLASS_NAME_Category, alias: "this" },
195
- });
196
- return {
197
- fullClassName: CLASS_NAME_Category,
198
- query: {
199
- ecsql: `
200
- SELECT
201
- ${await this._selectQueryFactory.createSelectClause({
202
- ecClassId: { selector: ECSql.createRawPropertyValueSelector("this", "ECClassId") },
203
- ecInstanceId: { selector: "this.ECInstanceId" },
204
- nodeLabel: {
205
- selector: await this._nodeLabelSelectClauseFactory.createSelectClause({
206
- classAlias: "this",
207
- className: CLASS_NAME_Category,
208
- }),
209
- },
210
- hasChildren: this._props.hierarchyConfig.categorySymbolizesClassificationRelationshipName
211
- ? {
212
- selector: `COALESCE(
213
- (
214
- SELECT 1
215
- FROM ${CLASS_NAME_GeometricElement3d} e3d
216
- WHERE e3d.Category.Id = this.ECInstanceId
217
- LIMIT 1
218
- ),
219
- (
220
- SELECT 1
221
- FROM ${CLASS_NAME_GeometricElement2d} e2d
222
- WHERE e2d.Category.Id = this.ECInstanceId
223
- LIMIT 1
224
- ),
225
- 0
226
- )`,
227
- }
228
- : true, // we won't get the category if it doesn't have elements, and if it has elements, it will have children
229
- extendedData: {
230
- type: { selector: `IIF(ec_classname(this.ECClassId, 'c') = 'SpatialCategory', 'SpatialCategory', 'DrawingCategory')` },
231
- classificationIds: { selector: createIdsSelector(classificationIds) },
232
- },
233
- supportsFiltering: true,
234
- })}
235
- FROM
236
- ${instanceFilterClauses.from} this
237
- ${instanceFilterClauses.joins}
238
- WHERE
239
- this.ECInstanceId IN (${childrenInfo.categoryIds.join(",")})
175
+ this.ECInstanceId IN (${classificationIds.join(",")})
240
176
  ${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : ""}
241
177
  `,
242
178
  },
@@ -244,67 +180,60 @@ export class ClassificationsTreeDefinition {
244
180
  })(),
245
181
  ]
246
182
  : []),
183
+ // load classification elements
184
+ ...(await Promise.all([CLASS_NAME_GeometricElement2d, CLASS_NAME_GeometricElement3d].map(async (elementClassName) => {
185
+ const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({
186
+ filter: instanceFilter,
187
+ contentClass: { fullName: elementClassName, alias: "this" },
188
+ });
189
+ return {
190
+ fullClassName: elementClassName,
191
+ query: {
192
+ ecsql: `
193
+ SELECT ${await this.#createElementSelectClause(elementClassName)}
194
+ FROM ${instanceFilterClauses.from} this
195
+ JOIN ${CLASS_NAME_ElementHasClassifications} ehc ON ehc.SourceECInstanceId = this.ECInstanceId
196
+ ${instanceFilterClauses.joins}
197
+ WHERE
198
+ ehc.TargetECInstanceId IN (${parentClassificationIds.join(",")})
199
+ AND this.Parent.Id IS NULL
200
+ ${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : ""}
201
+ `,
202
+ },
203
+ };
204
+ }))),
247
205
  ];
248
206
  }
249
- async #createCategoryChildrenQuery({ parentNode, parentNodeClassName, parentNodeInstanceIds: categoryIds, instanceFilter, }) {
250
- const elementsClassName = parentNodeClassName === CLASS_NAME_SpatialCategory ? CLASS_NAME_GeometricElement3d : CLASS_NAME_GeometricElement2d;
251
- const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({
252
- filter: instanceFilter,
253
- contentClass: { fullName: elementsClassName, alias: "this" },
254
- });
255
- const classificationIds = parseIdsSelectorResult(parentNode.extendedData?.classificationIds);
256
- if (classificationIds.length === 0) {
257
- return [];
258
- }
259
- return [
260
- {
261
- fullClassName: elementsClassName,
262
- query: {
263
- ecsql: `
264
- SELECT ${await this.#createGeometricElementSelectClause(parentNodeClassName)}
265
- FROM ${instanceFilterClauses.from} this
266
- JOIN ${CLASS_NAME_ElementHasClassifications} ehc ON ehc.SourceECInstanceId = this.ECInstanceId
267
- ${instanceFilterClauses.joins}
268
- WHERE
269
- this.Category.Id IN (${categoryIds.join(",")})
270
- AND ehc.TargetECInstanceId IN (${classificationIds.join(",")})
271
- AND this.Parent.Id IS NULL
272
- ${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : ""}
273
- `,
274
- },
275
- },
276
- ];
277
- }
278
- async #createGeometricElementChildrenQuery({ parentNodeClassName, parentNodeInstanceIds: parentElementIds, instanceFilter, }) {
279
- const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({
280
- filter: instanceFilter,
281
- contentClass: { fullName: CLASS_NAME_Element, alias: "this" },
282
- });
283
- return [
284
- {
285
- fullClassName: CLASS_NAME_Element,
207
+ async #createGeometricElementChildrenQuery({ parentNodeInstanceIds: parentElementIds, instanceFilter, }) {
208
+ return Promise.all([CLASS_NAME_GeometricElement2d, CLASS_NAME_GeometricElement3d].map(async (elementClassName) => {
209
+ const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({
210
+ filter: instanceFilter,
211
+ contentClass: { fullName: elementClassName, alias: "this" },
212
+ });
213
+ return {
214
+ fullClassName: elementClassName,
286
215
  query: {
287
216
  ecsql: `
288
- SELECT ${await this.#createGeometricElementSelectClause(parentNodeClassName)}
289
- FROM ${instanceFilterClauses.from} this
290
- ${instanceFilterClauses.joins}
291
- WHERE
292
- this.Parent.Id IN (${parentElementIds.join(",")})
293
- ${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : ""}
294
- `,
217
+ SELECT ${await this.#createElementSelectClause(elementClassName)}
218
+ FROM ${instanceFilterClauses.from} this
219
+ ${instanceFilterClauses.joins}
220
+ WHERE
221
+ this.Parent.Id IN (${parentElementIds.join(",")})
222
+ ${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : ""}
223
+ `,
295
224
  },
296
- },
297
- ];
225
+ };
226
+ }));
298
227
  }
299
- async #createGeometricElementSelectClause(parentNodeClassName) {
300
- const elementsClassName = parentNodeClassName === CLASS_NAME_SpatialCategory ? "GeometricElement3d" : "GeometricElement2d";
228
+ async #createElementSelectClause(elementFullClassName) {
229
+ const { className: elementClassName } = parseFullClassName(elementFullClassName);
301
230
  return this._selectQueryFactory.createSelectClause({
302
231
  ecClassId: { selector: "this.ECClassId" },
303
232
  ecInstanceId: { selector: "this.ECInstanceId" },
304
233
  nodeLabel: {
305
234
  selector: await this._nodeLabelSelectClauseFactory.createSelectClause({
306
235
  classAlias: "this",
307
- className: `BisCore.${elementsClassName}`,
236
+ className: elementFullClassName,
308
237
  }),
309
238
  },
310
239
  hasChildren: {
@@ -318,7 +247,7 @@ export class ClassificationsTreeDefinition {
318
247
  `,
319
248
  },
320
249
  extendedData: {
321
- type: elementsClassName,
250
+ type: elementClassName,
322
251
  modelId: { selector: "IdToHex(this.Model.Id)" },
323
252
  categoryId: { selector: "IdToHex(this.Category.Id)" },
324
253
  },
@@ -326,7 +255,7 @@ export class ClassificationsTreeDefinition {
326
255
  });
327
256
  }
328
257
  }
329
- function createClassificationHasChildrenSelector(classificationAlias, classificationSymbolizedByCategoryRelationshipName) {
258
+ function createClassificationHasChildrenSelector(classificationAlias) {
330
259
  return `
331
260
  COALESCE((
332
261
  SELECT 1
@@ -338,14 +267,7 @@ function createClassificationHasChildrenSelector(classificationAlias, classifica
338
267
  FROM ${CLASS_NAME_ElementHasClassifications} ehc
339
268
  WHERE ehc.TargetECInstanceId = ${classificationAlias}.ECInstanceId
340
269
  LIMIT 1
341
- ), ${classificationSymbolizedByCategoryRelationshipName
342
- ? `(
343
- SELECT 1
344
- FROM ${classificationSymbolizedByCategoryRelationshipName} csc
345
- WHERE csc.SourceECInstanceId = ${classificationAlias}.ECInstanceId
346
- LIMIT 1
347
- )`
348
- : ``}
270
+ ),
349
271
  0
350
272
  )
351
273
  `;
@@ -1 +1 @@
1
- {"version":3,"file":"ClassificationsTreeDefinition.js","sourceRoot":"","sources":["../../../../../../src/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeDefinition.ts"],"names":[],"mappings":"AAAA;;;gGAGgG;AAEhG,OAAO,EAAE,6BAA6B,EAAE,uCAAuC,EAAE,MAAM,iCAAiC,CAAC;AACzH,OAAO,EAAE,yCAAyC,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAC;AAC9F,OAAO,EACL,mBAAmB,EACnB,yBAAyB,EACzB,+BAA+B,EAC/B,8BAA8B,EAC9B,kBAAkB,EAClB,oCAAoC,EACpC,2BAA2B,EAC3B,6BAA6B,EAC7B,6BAA6B,EAC7B,0BAA0B,GAC3B,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AA0CxF,gBAAgB;AAChB,MAAM,OAAO,6BAA6B;IAKb;IAJnB,KAAK,CAAsB;IAC3B,mBAAmB,CAA0B;IAC7C,6BAA6B,CAAoC;IAEzE,YAA2B,MAA0C;QAA1C,WAAM,GAAN,MAAM,CAAoC;QACnE,IAAI,CAAC,6BAA6B,GAAG,yCAAyC,CAAC,EAAE,uBAAuB,EAAE,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;QACtI,IAAI,CAAC,mBAAmB,GAAG,6BAA6B,CAAC;YACvD,YAAY,EAAE,IAAI,CAAC,MAAM,CAAC,YAAY;YACtC,gCAAgC,EAAE,IAAI,CAAC,6BAA6B;SACrE,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,GAAG,uCAAuC,CAAC;YACnD,uBAAuB,EAAE,IAAI,CAAC,MAAM,CAAC,YAAY;YACjD,SAAS,EAAE;gBACT,SAAS,EAAE,KAAK,EAAE,YAA2C,EAAE,EAAE,CAAC,IAAI,CAAC,gCAAgC,CAAC,YAAY,CAAC;gBACrH,UAAU,EAAE;oBACV;wBACE,4BAA4B,EAAE,8BAA8B;wBAC5D,WAAW,EAAE,KAAK,EAAE,YAAwD,EAAE,EAAE,CAAC,IAAI,CAAC,uCAAuC,CAAC,YAAY,CAAC;qBAC5I;oBACD;wBACE,4BAA4B,EAAE,yBAAyB;wBACvD,WAAW,EAAE,KAAK,EAAE,YAAwD,EAAE,EAAE,CAAC,IAAI,CAAC,kCAAkC,CAAC,YAAY,CAAC;qBACvI;oBACD;wBACE,4BAA4B,EAAE,mBAAmB;wBACjD,WAAW,EAAE,KAAK,EAAE,YAAwD,EAAE,EAAE,CAAC,IAAI,CAAC,4BAA4B,CAAC,YAAY,CAAC;qBACjI;oBACD;wBACE,4BAA4B,EAAE,2BAA2B;wBACzD,WAAW,EAAE,KAAK,EAAE,YAAwD,EAAE,EAAE,CAAC,IAAI,CAAC,oCAAoC,CAAC,YAAY,CAAC;qBACzI;iBACF;aACF;SACF,CAAC,CAAC;IACL,CAAC;IAEM,KAAK,CAAC,oBAAoB,CAAC,KAAgC;QAChE,OAAO,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,gCAAgC,CAAC,KAAiD;QACtF,MAAM,EAAE,cAAc,EAAE,GAAG,KAAK,CAAC;QACjC,MAAM,qBAAqB,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,mBAAmB,CAAC;YAC/E,MAAM,EAAE,cAAc;YACtB,YAAY,EAAE,EAAE,QAAQ,EAAE,8BAA8B,EAAE,KAAK,EAAE,MAAM,EAAE;SAC1E,CAAC,CAAC;QACH,OAAO;YACL;gBACE,aAAa,EAAE,8BAA8B;gBAC7C,KAAK,EAAE;oBACL,KAAK,EAAE;;gBAED,MAAM,IAAI,CAAC,mBAAmB,CAAC,kBAAkB,CAAC;wBAClD,SAAS,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,8BAA8B,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE;wBAClF,YAAY,EAAE,EAAE,QAAQ,EAAE,mBAAmB,EAAE;wBAC/C,SAAS,EAAE;4BACT,QAAQ,EAAE,MAAM,IAAI,CAAC,6BAA6B,CAAC,kBAAkB,CAAC;gCACpE,UAAU,EAAE,MAAM;gCAClB,SAAS,EAAE,8BAA8B;6BAC1C,CAAC;yBACH;wBACD,WAAW,EAAE;4BACX,QAAQ,EAAE;;;6BAGC,yBAAyB;;;;mBAInC;yBACF;wBACD,YAAY,EAAE;4BACZ,IAAI,EAAE,qBAAqB;yBAC5B;wBACD,iBAAiB,EAAE,IAAI;qBACxB,CAAC;;gBAEA,qBAAqB,CAAC,IAAI;mBACvB,+BAA+B;cACpC,qBAAqB,CAAC,KAAK;;oCAEL,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,4BAA4B;;gBAE5E,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,qBAAqB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE;WAC5E;iBACF;aACF;SACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,uCAAuC,CAAC,KAG7C;QACC,MAAM,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,cAAc,EAAE,GAAG,KAAK,CAAC;QAChF,MAAM,qBAAqB,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,mBAAmB,CAAC;YAC/E,MAAM,EAAE,cAAc;YACtB,YAAY,EAAE,EAAE,QAAQ,EAAE,yBAAyB,EAAE,KAAK,EAAE,MAAM,EAAE;SACrE,CAAC,CAAC;QACH,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,qCAAqC,CAAC,sBAAsB,CAAC,CAAC;QAC9G,OAAO,YAAY,CAAC,iBAAiB,CAAC,MAAM;YAC1C,CAAC,CAAC;gBACE;oBACE,aAAa,EAAE,yBAAyB;oBACxC,KAAK,EAAE;wBACL,KAAK,EAAE;;oBAED,MAAM,IAAI,CAAC,mBAAmB,CAAC,kBAAkB,CAAC;4BAClD,SAAS,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,8BAA8B,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE;4BAClF,YAAY,EAAE,EAAE,QAAQ,EAAE,mBAAmB,EAAE;4BAC/C,SAAS,EAAE;gCACT,QAAQ,EAAE,MAAM,IAAI,CAAC,6BAA6B,CAAC,kBAAkB,CAAC;oCACpE,UAAU,EAAE,MAAM;oCAClB,SAAS,EAAE,yBAAyB;iCACrC,CAAC;6BACH;4BACD,WAAW,EAAE;gCACX,QAAQ,EAAE,uCAAuC,CAAC,MAAM,CAAC;6BAC1D;4BACD,YAAY,EAAE;gCACZ,IAAI,EAAE,gBAAgB;6BACvB;4BACD,iBAAiB,EAAE,IAAI;yBACxB,CAAC;;oBAEA,qBAAqB,CAAC,IAAI;kBAC5B,qBAAqB,CAAC,KAAK;;0CAEH,YAAY,CAAC,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC;oBAC9D,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,qBAAqB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE;eAC5E;qBACF;iBACF;aACF;YACH,CAAC,CAAC,EAAE,CAAC;IACT,CAAC;IAED,KAAK,CAAC,kCAAkC,CAAC,KAGxC;QACC,MAAM,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,cAAc,EAAE,GAAG,KAAK,CAAC;QAC3E,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,qCAAqC,CAAC,iBAAiB,CAAC,CAAC;QACzG,OAAO;YACL,6BAA6B;YAC7B,GAAG,CAAC,YAAY,CAAC,iBAAiB,CAAC,MAAM;gBACvC,CAAC,CAAC;oBACE,MAAK,CAAC,KAAK,IAAI,EAAE;wBACf,MAAM,qBAAqB,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,mBAAmB,CAAC;4BAC/E,MAAM,EAAE,cAAc;4BACtB,YAAY,EAAE,EAAE,QAAQ,EAAE,yBAAyB,EAAE,KAAK,EAAE,MAAM,EAAE;yBACrE,CAAC,CAAC;wBACH,OAAO;4BACL,aAAa,EAAE,yBAAyB;4BACxC,KAAK,EAAE;gCACL,KAAK,EAAE;;wBAED,MAAM,IAAI,CAAC,mBAAmB,CAAC,kBAAkB,CAAC;oCAClD,SAAS,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,8BAA8B,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE;oCAClF,YAAY,EAAE,EAAE,QAAQ,EAAE,mBAAmB,EAAE;oCAC/C,SAAS,EAAE;wCACT,QAAQ,EAAE,MAAM,IAAI,CAAC,6BAA6B,CAAC,kBAAkB,CAAC;4CACpE,UAAU,EAAE,MAAM;4CAClB,SAAS,EAAE,yBAAyB;yCACrC,CAAC;qCACH;oCACD,WAAW,EAAE;wCACX,QAAQ,EAAE,uCAAuC,CAAC,MAAM,CAAC;qCAC1D;oCACD,YAAY,EAAE;wCACZ,IAAI,EAAE,gBAAgB;qCACvB;oCACD,iBAAiB,EAAE,IAAI;iCACxB,CAAC;;wBAEA,qBAAqB,CAAC,IAAI;sBAC5B,qBAAqB,CAAC,KAAK;;8CAEH,YAAY,CAAC,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC;wBAC9D,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,qBAAqB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE;mBAC5E;6BACF;yBACF,CAAC;oBACJ,CAAC,CAAC,EAAE;iBACL;gBACH,CAAC,CAAC,EAAE,CAAC;YACP,6BAA6B;YAC7B,GAAG,CAAC,YAAY,CAAC,WAAW,CAAC,MAAM;gBACjC,CAAC,CAAC;oBACE,MAAK,CAAC,KAAK,IAAI,EAAE;wBACf,MAAM,qBAAqB,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,mBAAmB,CAAC;4BAC/E,MAAM,EAAE,cAAc;4BACtB,YAAY,EAAE,EAAE,QAAQ,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,EAAE;yBAC/D,CAAC,CAAC;wBACH,OAAO;4BACL,aAAa,EAAE,mBAAmB;4BAClC,KAAK,EAAE;gCACL,KAAK,EAAE;;wBAED,MAAM,IAAI,CAAC,mBAAmB,CAAC,kBAAkB,CAAC;oCAClD,SAAS,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,8BAA8B,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE;oCAClF,YAAY,EAAE,EAAE,QAAQ,EAAE,mBAAmB,EAAE;oCAC/C,SAAS,EAAE;wCACT,QAAQ,EAAE,MAAM,IAAI,CAAC,6BAA6B,CAAC,kBAAkB,CAAC;4CACpE,UAAU,EAAE,MAAM;4CAClB,SAAS,EAAE,mBAAmB;yCAC/B,CAAC;qCACH;oCACD,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,gDAAgD;wCACvF,CAAC,CAAC;4CACE,QAAQ,EAAE;;;yCAGC,6BAA6B;;;;;;yCAM7B,6BAA6B;;;;;gCAKtC;yCACH;wCACH,CAAC,CAAC,IAAI,EAAE,uGAAuG;oCACjH,YAAY,EAAE;wCACZ,IAAI,EAAE,EAAE,QAAQ,EAAE,kGAAkG,EAAE;wCACtH,iBAAiB,EAAE,EAAE,QAAQ,EAAE,iBAAiB,CAAC,iBAAiB,CAAC,EAAE;qCACtE;oCACD,iBAAiB,EAAE,IAAI;iCACxB,CAAC;;wBAEA,qBAAqB,CAAC,IAAI;sBAC5B,qBAAqB,CAAC,KAAK;;8CAEH,YAAY,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC;wBACxD,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,qBAAqB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE;mBAC5E;6BACF;yBACF,CAAC;oBACJ,CAAC,CAAC,EAAE;iBACL;gBACH,CAAC,CAAC,EAAE,CAAC;SACR,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,4BAA4B,CAAC,EACjC,UAAU,EACV,mBAAmB,EACnB,qBAAqB,EAAE,WAAW,EAClC,cAAc,GAC6B;QAC3C,MAAM,iBAAiB,GAAG,mBAAmB,KAAK,0BAA0B,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC,CAAC,6BAA6B,CAAC;QAC7I,MAAM,qBAAqB,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,mBAAmB,CAAC;YAC/E,MAAM,EAAE,cAAc;YACtB,YAAY,EAAE,EAAE,QAAQ,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,EAAE;SAC7D,CAAC,CAAC;QACH,MAAM,iBAAiB,GAAG,sBAAsB,CAAC,UAAU,CAAC,YAAY,EAAE,iBAAiB,CAAC,CAAC;QAC7F,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACnC,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,OAAO;YACL;gBACE,aAAa,EAAE,iBAAiB;gBAChC,KAAK,EAAE;oBACL,KAAK,EAAE;qBACI,MAAM,IAAI,CAAC,mCAAmC,CAAC,mBAAmB,CAAC;mBACrE,qBAAqB,CAAC,IAAI;mBAC1B,oCAAoC;cACzC,qBAAqB,CAAC,KAAK;;qCAEJ,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC;+CACX,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC;;gBAE1D,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,qBAAqB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE;WAC5E;iBACF;aACF;SACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,oCAAoC,CAAC,EACzC,mBAAmB,EACnB,qBAAqB,EAAE,gBAAgB,EACvC,cAAc,GAC6B;QAC3C,MAAM,qBAAqB,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,mBAAmB,CAAC;YAC/E,MAAM,EAAE,cAAc;YACtB,YAAY,EAAE,EAAE,QAAQ,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,EAAE;SAC9D,CAAC,CAAC;QACH,OAAO;YACL;gBACE,aAAa,EAAE,kBAAkB;gBACjC,KAAK,EAAE;oBACL,KAAK,EAAE;qBACI,MAAM,IAAI,CAAC,mCAAmC,CAAC,mBAAmB,CAAC;mBACrE,qBAAqB,CAAC,IAAI;cAC/B,qBAAqB,CAAC,KAAK;;mCAEN,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC;gBAC7C,qBAAqB,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,qBAAqB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE;WAC5E;iBACF;aACF;SACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,mCAAmC,CAAC,mBAA2B;QACnE,MAAM,iBAAiB,GAAG,mBAAmB,KAAK,0BAA0B,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,oBAAoB,CAAC;QAC3H,OAAO,IAAI,CAAC,mBAAmB,CAAC,kBAAkB,CAAC;YACjD,SAAS,EAAE,EAAE,QAAQ,EAAE,gBAAgB,EAAE;YACzC,YAAY,EAAE,EAAE,QAAQ,EAAE,mBAAmB,EAAE;YAC/C,SAAS,EAAE;gBACT,QAAQ,EAAE,MAAM,IAAI,CAAC,6BAA6B,CAAC,kBAAkB,CAAC;oBACpE,UAAU,EAAE,MAAM;oBAClB,SAAS,EAAE,WAAW,iBAAiB,EAAE;iBAC1C,CAAC;aACH;YACD,WAAW,EAAE;gBACX,QAAQ,EAAE;;;mBAGC,kBAAkB;;;;SAI5B;aACF;YACD,YAAY,EAAE;gBACZ,IAAI,EAAE,iBAAiB;gBACvB,OAAO,EAAE,EAAE,QAAQ,EAAE,wBAAwB,EAAE;gBAC/C,UAAU,EAAE,EAAE,QAAQ,EAAE,2BAA2B,EAAE;aACtD;YACD,iBAAiB,EAAE,IAAI;SACxB,CAAC,CAAC;IACL,CAAC;CACF;AAED,SAAS,uCAAuC,CAAC,mBAA2B,EAAE,kDAA2D;IACvI,OAAO;;;eAGM,yBAAyB;2CACG,mBAAmB;;;;eAI/C,oCAAoC;yCACV,mBAAmB;;WAGpD,kDAAkD;QAChD,CAAC,CAAC;;qBAES,kDAAkD;+CACxB,mBAAmB;;cAEpD;QACJ,CAAC,CAAC,EACN;;;GAGH,CAAC;AACJ,CAAC","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 {\n CLASS_NAME_Category,\n CLASS_NAME_Classification,\n CLASS_NAME_ClassificationSystem,\n CLASS_NAME_ClassificationTable,\n CLASS_NAME_Element,\n CLASS_NAME_ElementHasClassifications,\n CLASS_NAME_GeometricElement,\n CLASS_NAME_GeometricElement2d,\n CLASS_NAME_GeometricElement3d,\n CLASS_NAME_SpatialCategory,\n} from \"../common/internal/ClassNameDefinitions.js\";\nimport { createIdsSelector, parseIdsSelectorResult } from \"../common/internal/Utils.js\";\n\nimport type { Id64Array } from \"@itwin/core-bentley\";\nimport type {\n DefineHierarchyLevelProps,\n DefineInstanceNodeChildHierarchyLevelProps,\n DefineRootHierarchyLevelProps,\n GenericInstanceFilter,\n HierarchyDefinition,\n HierarchyLevelDefinition,\n LimitingECSqlQueryExecutor,\n NodesQueryClauseFactory,\n} from \"@itwin/presentation-hierarchies\";\nimport type { ECClassHierarchyInspector, ECSchemaProvider, IInstanceLabelSelectClauseFactory } from \"@itwin/presentation-shared\";\nimport type { ClassificationsTreeIdsCache } from \"./internal/ClassificationsTreeIdsCache.js\";\n\ninterface ClassificationsTreeDefinitionProps {\n imodelAccess: ECSchemaProvider & ECClassHierarchyInspector & LimitingECSqlQueryExecutor;\n idsCache: ClassificationsTreeIdsCache;\n hierarchyConfig: ClassificationsTreeHierarchyConfiguration;\n}\n\n/** @alpha */\nexport interface ClassificationsTreeHierarchyConfiguration {\n /**\n * The classifications' hierarchy starts at the root `ClassificationSystem` element. This attribute identifiers that\n * root `ClassificationSystem`.\n */\n rootClassificationSystemCode: string;\n\n /**\n * In case consumer knows the name of relationship between a `Classification` and a `Category`, it can be provided\n * here. With this relationship, Categories for a given Classification can be loaded directly, without going through\n * geometric elements. That has a couple of effects:\n * - Performance is better, as it allows us to avoid scanning all elements under specific Classification.\n * - Categories related to a Classification are displayed, even if they don't have any elements assigned to them.\n *\n * It's expected that source of the relationship is `BisCore.Category` and target - `ClassificationSystems.Classification`.\n */\n categorySymbolizesClassificationRelationshipName?: string;\n}\n\n/** @internal */\nexport class ClassificationsTreeDefinition implements HierarchyDefinition {\n private _impl: HierarchyDefinition;\n private _selectQueryFactory: NodesQueryClauseFactory;\n private _nodeLabelSelectClauseFactory: IInstanceLabelSelectClauseFactory;\n\n public constructor(private _props: ClassificationsTreeDefinitionProps) {\n this._nodeLabelSelectClauseFactory = createBisInstanceLabelSelectClauseFactory({ classHierarchyInspector: this._props.imodelAccess });\n this._selectQueryFactory = createNodesQueryClauseFactory({\n imodelAccess: this._props.imodelAccess,\n instanceLabelSelectClauseFactory: this._nodeLabelSelectClauseFactory,\n });\n this._impl = createPredicateBasedHierarchyDefinition({\n classHierarchyInspector: this._props.imodelAccess,\n hierarchy: {\n rootNodes: async (requestProps: DefineRootHierarchyLevelProps) => this.#createClassificationTablesQuery(requestProps),\n childNodes: [\n {\n parentInstancesNodePredicate: CLASS_NAME_ClassificationTable,\n definitions: async (requestProps: DefineInstanceNodeChildHierarchyLevelProps) => this.#createClassificationTableChildrenQuery(requestProps),\n },\n {\n parentInstancesNodePredicate: CLASS_NAME_Classification,\n definitions: async (requestProps: DefineInstanceNodeChildHierarchyLevelProps) => this.#createClassificationChildrenQuery(requestProps),\n },\n {\n parentInstancesNodePredicate: CLASS_NAME_Category,\n definitions: async (requestProps: DefineInstanceNodeChildHierarchyLevelProps) => this.#createCategoryChildrenQuery(requestProps),\n },\n {\n parentInstancesNodePredicate: CLASS_NAME_GeometricElement,\n definitions: async (requestProps: DefineInstanceNodeChildHierarchyLevelProps) => this.#createGeometricElementChildrenQuery(requestProps),\n },\n ],\n },\n });\n }\n\n public async defineHierarchyLevel(props: DefineHierarchyLevelProps) {\n return this._impl.defineHierarchyLevel(props);\n }\n\n async #createClassificationTablesQuery(props: { instanceFilter?: GenericInstanceFilter }): Promise<HierarchyLevelDefinition> {\n const { instanceFilter } = props;\n const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({\n filter: instanceFilter,\n contentClass: { fullName: CLASS_NAME_ClassificationTable, alias: \"this\" },\n });\n return [\n {\n fullClassName: CLASS_NAME_ClassificationTable,\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: CLASS_NAME_ClassificationTable,\n }),\n },\n hasChildren: {\n selector: `\n IFNULL((\n SELECT 1\n FROM ${CLASS_NAME_Classification} classification\n WHERE classification.Model.Id = this.ECInstanceId\n LIMIT 1\n ), 0)\n `,\n },\n extendedData: {\n type: \"ClassificationTable\",\n },\n supportsFiltering: true,\n })}\n FROM\n ${instanceFilterClauses.from} this\n JOIN ${CLASS_NAME_ClassificationSystem} system ON system.ECInstanceId = this.Parent.Id\n ${instanceFilterClauses.joins}\n WHERE\n system.CodeValue = '${this._props.hierarchyConfig.rootClassificationSystemCode}'\n AND NOT this.IsPrivate\n ${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : \"\"}\n `,\n },\n },\n ];\n }\n\n async #createClassificationTableChildrenQuery(props: {\n parentNodeInstanceIds: Id64Array;\n instanceFilter?: GenericInstanceFilter;\n }): Promise<HierarchyLevelDefinition> {\n const { parentNodeInstanceIds: classificationTableIds, instanceFilter } = props;\n const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({\n filter: instanceFilter,\n contentClass: { fullName: CLASS_NAME_Classification, alias: \"this\" },\n });\n const childrenInfo = await this._props.idsCache.getDirectCategoriesAndClassifications(classificationTableIds);\n return childrenInfo.classificationIds.length\n ? [\n {\n fullClassName: CLASS_NAME_Classification,\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: CLASS_NAME_Classification,\n }),\n },\n hasChildren: {\n selector: createClassificationHasChildrenSelector(\"this\"),\n },\n extendedData: {\n type: \"Classification\",\n },\n supportsFiltering: true,\n })}\n FROM\n ${instanceFilterClauses.from} this\n ${instanceFilterClauses.joins}\n WHERE\n this.ECInstanceId IN (${childrenInfo.classificationIds.join(\",\")})\n ${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : \"\"}\n `,\n },\n },\n ]\n : [];\n }\n\n async #createClassificationChildrenQuery(props: {\n parentNodeInstanceIds: Id64Array;\n instanceFilter?: GenericInstanceFilter;\n }): Promise<HierarchyLevelDefinition> {\n const { parentNodeInstanceIds: classificationIds, instanceFilter } = props;\n const childrenInfo = await this._props.idsCache.getDirectCategoriesAndClassifications(classificationIds);\n return [\n // load child classifications\n ...(childrenInfo.classificationIds.length\n ? [\n await(async () => {\n const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({\n filter: instanceFilter,\n contentClass: { fullName: CLASS_NAME_Classification, alias: \"this\" },\n });\n return {\n fullClassName: CLASS_NAME_Classification,\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: CLASS_NAME_Classification,\n }),\n },\n hasChildren: {\n selector: createClassificationHasChildrenSelector(\"this\"),\n },\n extendedData: {\n type: \"Classification\",\n },\n supportsFiltering: true,\n })}\n FROM\n ${instanceFilterClauses.from} this\n ${instanceFilterClauses.joins}\n WHERE\n this.ECInstanceId IN (${childrenInfo.classificationIds.join(\",\")})\n ${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : \"\"}\n `,\n },\n };\n })(),\n ]\n : []),\n // load referenced categories\n ...(childrenInfo.categoryIds.length\n ? [\n await(async () => {\n const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({\n filter: instanceFilter,\n contentClass: { fullName: CLASS_NAME_Category, alias: \"this\" },\n });\n return {\n fullClassName: CLASS_NAME_Category,\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: CLASS_NAME_Category,\n }),\n },\n hasChildren: this._props.hierarchyConfig.categorySymbolizesClassificationRelationshipName\n ? {\n selector: `COALESCE(\n (\n SELECT 1\n FROM ${CLASS_NAME_GeometricElement3d} e3d\n WHERE e3d.Category.Id = this.ECInstanceId\n LIMIT 1\n ),\n (\n SELECT 1\n FROM ${CLASS_NAME_GeometricElement2d} e2d\n WHERE e2d.Category.Id = this.ECInstanceId\n LIMIT 1\n ),\n 0\n )`,\n }\n : true, // we won't get the category if it doesn't have elements, and if it has elements, it will have children\n extendedData: {\n type: { selector: `IIF(ec_classname(this.ECClassId, 'c') = 'SpatialCategory', 'SpatialCategory', 'DrawingCategory')` },\n classificationIds: { selector: createIdsSelector(classificationIds) },\n },\n supportsFiltering: true,\n })}\n FROM\n ${instanceFilterClauses.from} this\n ${instanceFilterClauses.joins}\n WHERE\n this.ECInstanceId IN (${childrenInfo.categoryIds.join(\",\")})\n ${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : \"\"}\n `,\n },\n };\n })(),\n ]\n : []),\n ];\n }\n\n async #createCategoryChildrenQuery({\n parentNode,\n parentNodeClassName,\n parentNodeInstanceIds: categoryIds,\n instanceFilter,\n }: DefineInstanceNodeChildHierarchyLevelProps): Promise<HierarchyLevelDefinition> {\n const elementsClassName = parentNodeClassName === CLASS_NAME_SpatialCategory ? CLASS_NAME_GeometricElement3d : CLASS_NAME_GeometricElement2d;\n const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({\n filter: instanceFilter,\n contentClass: { fullName: elementsClassName, alias: \"this\" },\n });\n const classificationIds = parseIdsSelectorResult(parentNode.extendedData?.classificationIds);\n if (classificationIds.length === 0) {\n return [];\n }\n return [\n {\n fullClassName: elementsClassName,\n query: {\n ecsql: `\n SELECT ${await this.#createGeometricElementSelectClause(parentNodeClassName)}\n FROM ${instanceFilterClauses.from} this\n JOIN ${CLASS_NAME_ElementHasClassifications} ehc ON ehc.SourceECInstanceId = this.ECInstanceId\n ${instanceFilterClauses.joins}\n WHERE\n this.Category.Id IN (${categoryIds.join(\",\")})\n AND ehc.TargetECInstanceId IN (${classificationIds.join(\",\")})\n AND this.Parent.Id IS NULL\n ${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : \"\"}\n `,\n },\n },\n ];\n }\n\n async #createGeometricElementChildrenQuery({\n parentNodeClassName,\n parentNodeInstanceIds: parentElementIds,\n instanceFilter,\n }: DefineInstanceNodeChildHierarchyLevelProps): Promise<HierarchyLevelDefinition> {\n const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({\n filter: instanceFilter,\n contentClass: { fullName: CLASS_NAME_Element, alias: \"this\" },\n });\n return [\n {\n fullClassName: CLASS_NAME_Element,\n query: {\n ecsql: `\n SELECT ${await this.#createGeometricElementSelectClause(parentNodeClassName)}\n FROM ${instanceFilterClauses.from} this\n ${instanceFilterClauses.joins}\n WHERE\n this.Parent.Id IN (${parentElementIds.join(\",\")})\n ${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : \"\"}\n `,\n },\n },\n ];\n }\n\n async #createGeometricElementSelectClause(parentNodeClassName: string): Promise<string> {\n const elementsClassName = parentNodeClassName === CLASS_NAME_SpatialCategory ? \"GeometricElement3d\" : \"GeometricElement2d\";\n return 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.${elementsClassName}`,\n }),\n },\n hasChildren: {\n selector: `\n IFNULL((\n SELECT 1\n FROM ${CLASS_NAME_Element} ce\n WHERE ce.Parent.Id = this.ECInstanceId\n LIMIT 1\n ), 0)\n `,\n },\n extendedData: {\n type: elementsClassName,\n modelId: { selector: \"IdToHex(this.Model.Id)\" },\n categoryId: { selector: \"IdToHex(this.Category.Id)\" },\n },\n supportsFiltering: true,\n });\n }\n}\n\nfunction createClassificationHasChildrenSelector(classificationAlias: string, classificationSymbolizedByCategoryRelationshipName?: string) {\n return `\n COALESCE((\n SELECT 1\n FROM ${CLASS_NAME_Classification} classification\n WHERE classification.Parent.Id = ${classificationAlias}.ECInstanceId\n LIMIT 1\n ), (\n SELECT 1\n FROM ${CLASS_NAME_ElementHasClassifications} ehc\n WHERE ehc.TargetECInstanceId = ${classificationAlias}.ECInstanceId\n LIMIT 1\n ), ${\n classificationSymbolizedByCategoryRelationshipName\n ? `(\n SELECT 1\n FROM ${classificationSymbolizedByCategoryRelationshipName} csc\n WHERE csc.SourceECInstanceId = ${classificationAlias}.ECInstanceId\n LIMIT 1\n )`\n : ``\n }\n 0\n )\n `;\n}\n"]}
1
+ {"version":3,"file":"ClassificationsTreeDefinition.js","sourceRoot":"","sources":["../../../../../../src/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeDefinition.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, parseFullClassName } from \"@itwin/presentation-shared\";\nimport {\n CLASS_NAME_Classification,\n CLASS_NAME_ClassificationSystem,\n CLASS_NAME_ClassificationTable,\n CLASS_NAME_Element,\n CLASS_NAME_ElementHasClassifications,\n CLASS_NAME_GeometricElement,\n CLASS_NAME_GeometricElement2d,\n CLASS_NAME_GeometricElement3d,\n} from \"../common/internal/ClassNameDefinitions.js\";\n\nimport type {\n DefineHierarchyLevelProps,\n DefineInstanceNodeChildHierarchyLevelProps,\n DefineRootHierarchyLevelProps,\n GenericInstanceFilter,\n HierarchyDefinition,\n HierarchyLevelDefinition,\n LimitingECSqlQueryExecutor,\n NodesQueryClauseFactory,\n} from \"@itwin/presentation-hierarchies\";\nimport type { ECClassHierarchyInspector, ECSchemaProvider, IInstanceLabelSelectClauseFactory } from \"@itwin/presentation-shared\";\nimport type { ClassificationId, ClassificationsTreeIdsCache, ClassificationTableId } from \"./internal/ClassificationsTreeIdsCache.js\";\n\ninterface ClassificationsTreeDefinitionProps {\n imodelAccess: ECSchemaProvider & ECClassHierarchyInspector & LimitingECSqlQueryExecutor;\n idsCache: ClassificationsTreeIdsCache;\n hierarchyConfig: ClassificationsTreeHierarchyConfiguration;\n}\n\n/** @alpha */\nexport interface ClassificationsTreeHierarchyConfiguration {\n /**\n * The classifications' hierarchy starts at the root `ClassificationSystem` element. This attribute identifiers that\n * root `ClassificationSystem`.\n */\n rootClassificationSystemCode: string;\n}\n\n/** @internal */\nexport class ClassificationsTreeDefinition implements HierarchyDefinition {\n private _impl: HierarchyDefinition;\n private _selectQueryFactory: NodesQueryClauseFactory;\n private _nodeLabelSelectClauseFactory: IInstanceLabelSelectClauseFactory;\n\n public constructor(private _props: ClassificationsTreeDefinitionProps) {\n this._nodeLabelSelectClauseFactory = createBisInstanceLabelSelectClauseFactory({ classHierarchyInspector: this._props.imodelAccess });\n this._selectQueryFactory = createNodesQueryClauseFactory({\n imodelAccess: this._props.imodelAccess,\n instanceLabelSelectClauseFactory: this._nodeLabelSelectClauseFactory,\n });\n this._impl = createPredicateBasedHierarchyDefinition({\n classHierarchyInspector: this._props.imodelAccess,\n hierarchy: {\n rootNodes: async (requestProps: DefineRootHierarchyLevelProps) => this.#createClassificationTablesQuery(requestProps),\n childNodes: [\n {\n parentInstancesNodePredicate: CLASS_NAME_ClassificationTable,\n definitions: async (requestProps: DefineInstanceNodeChildHierarchyLevelProps) => this.#createClassificationTableChildrenQuery(requestProps),\n },\n {\n parentInstancesNodePredicate: CLASS_NAME_Classification,\n definitions: async (requestProps: DefineInstanceNodeChildHierarchyLevelProps) => this.#createClassificationChildrenQuery(requestProps),\n },\n {\n parentInstancesNodePredicate: CLASS_NAME_GeometricElement,\n definitions: async (requestProps: DefineInstanceNodeChildHierarchyLevelProps) => this.#createGeometricElementChildrenQuery(requestProps),\n },\n ],\n },\n });\n }\n\n public async defineHierarchyLevel(props: DefineHierarchyLevelProps) {\n return this._impl.defineHierarchyLevel(props);\n }\n\n async #createClassificationTablesQuery(props: { instanceFilter?: GenericInstanceFilter }): Promise<HierarchyLevelDefinition> {\n const { instanceFilter } = props;\n const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({\n filter: instanceFilter,\n contentClass: { fullName: CLASS_NAME_ClassificationTable, alias: \"this\" },\n });\n return [\n {\n fullClassName: CLASS_NAME_ClassificationTable,\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: CLASS_NAME_ClassificationTable,\n }),\n },\n hasChildren: {\n selector: `\n IFNULL((\n SELECT 1\n FROM ${CLASS_NAME_Classification} classification\n WHERE classification.Model.Id = this.ECInstanceId\n LIMIT 1\n ), 0)\n `,\n },\n extendedData: {\n type: \"ClassificationTable\",\n },\n supportsFiltering: true,\n })}\n FROM\n ${instanceFilterClauses.from} this\n JOIN ${CLASS_NAME_ClassificationSystem} system ON system.ECInstanceId = this.Parent.Id\n ${instanceFilterClauses.joins}\n WHERE\n system.CodeValue = '${this._props.hierarchyConfig.rootClassificationSystemCode}'\n AND NOT this.IsPrivate\n ${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : \"\"}\n `,\n },\n },\n ];\n }\n\n async #createClassificationTableChildrenQuery(props: {\n parentNodeInstanceIds: ClassificationTableId[];\n instanceFilter?: GenericInstanceFilter;\n }): Promise<HierarchyLevelDefinition> {\n const { parentNodeInstanceIds: classificationTableIds, instanceFilter } = props;\n const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({\n filter: instanceFilter,\n contentClass: { fullName: CLASS_NAME_Classification, alias: \"this\" },\n });\n const classificationIds = await this._props.idsCache.getDirectChildClassifications(classificationTableIds);\n return classificationIds.length\n ? [\n {\n fullClassName: CLASS_NAME_Classification,\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: CLASS_NAME_Classification,\n }),\n },\n hasChildren: {\n selector: createClassificationHasChildrenSelector(\"this\"),\n },\n extendedData: {\n type: \"Classification\",\n },\n supportsFiltering: true,\n })}\n FROM\n ${instanceFilterClauses.from} this\n ${instanceFilterClauses.joins}\n WHERE\n this.ECInstanceId IN (${classificationIds.join(\",\")})\n ${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : \"\"}\n `,\n },\n },\n ]\n : [];\n }\n\n async #createClassificationChildrenQuery(props: {\n parentNodeInstanceIds: ClassificationId[];\n instanceFilter?: GenericInstanceFilter;\n }): Promise<HierarchyLevelDefinition> {\n const { parentNodeInstanceIds: parentClassificationIds, instanceFilter } = props;\n const classificationIds = await this._props.idsCache.getDirectChildClassifications(parentClassificationIds);\n return [\n // load child classifications\n ...(classificationIds.length\n ? [\n await (async () => {\n const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({\n filter: instanceFilter,\n contentClass: { fullName: CLASS_NAME_Classification, alias: \"this\" },\n });\n return {\n fullClassName: CLASS_NAME_Classification,\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: CLASS_NAME_Classification,\n }),\n },\n hasChildren: {\n selector: createClassificationHasChildrenSelector(\"this\"),\n },\n extendedData: {\n type: \"Classification\",\n },\n supportsFiltering: true,\n })}\n FROM\n ${instanceFilterClauses.from} this\n ${instanceFilterClauses.joins}\n WHERE\n this.ECInstanceId IN (${classificationIds.join(\",\")})\n ${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : \"\"}\n `,\n },\n };\n })(),\n ]\n : []),\n // load classification elements\n ...(await Promise.all(\n [CLASS_NAME_GeometricElement2d, CLASS_NAME_GeometricElement3d].map(async (elementClassName) => {\n const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({\n filter: instanceFilter,\n contentClass: { fullName: elementClassName, alias: \"this\" },\n });\n return {\n fullClassName: elementClassName,\n query: {\n ecsql: `\n SELECT ${await this.#createElementSelectClause(elementClassName)}\n FROM ${instanceFilterClauses.from} this\n JOIN ${CLASS_NAME_ElementHasClassifications} ehc ON ehc.SourceECInstanceId = this.ECInstanceId\n ${instanceFilterClauses.joins}\n WHERE\n ehc.TargetECInstanceId IN (${parentClassificationIds.join(\",\")})\n AND this.Parent.Id IS NULL\n ${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : \"\"}\n `,\n },\n };\n }),\n )),\n ];\n }\n\n async #createGeometricElementChildrenQuery({\n parentNodeInstanceIds: parentElementIds,\n instanceFilter,\n }: DefineInstanceNodeChildHierarchyLevelProps): Promise<HierarchyLevelDefinition> {\n return Promise.all(\n [CLASS_NAME_GeometricElement2d, CLASS_NAME_GeometricElement3d].map(async (elementClassName) => {\n const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({\n filter: instanceFilter,\n contentClass: { fullName: elementClassName, alias: \"this\" },\n });\n return {\n fullClassName: elementClassName,\n query: {\n ecsql: `\n SELECT ${await this.#createElementSelectClause(elementClassName)}\n FROM ${instanceFilterClauses.from} this\n ${instanceFilterClauses.joins}\n WHERE\n this.Parent.Id IN (${parentElementIds.join(\",\")})\n ${instanceFilterClauses.where ? `AND ${instanceFilterClauses.where}` : \"\"}\n `,\n },\n };\n }),\n );\n }\n\n async #createElementSelectClause(elementFullClassName: string): Promise<string> {\n const { className: elementClassName } = parseFullClassName(elementFullClassName);\n return 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: elementFullClassName,\n }),\n },\n hasChildren: {\n selector: `\n IFNULL((\n SELECT 1\n FROM ${CLASS_NAME_Element} ce\n WHERE ce.Parent.Id = this.ECInstanceId\n LIMIT 1\n ), 0)\n `,\n },\n extendedData: {\n type: elementClassName,\n modelId: { selector: \"IdToHex(this.Model.Id)\" },\n categoryId: { selector: \"IdToHex(this.Category.Id)\" },\n },\n supportsFiltering: true,\n });\n }\n}\n\nfunction createClassificationHasChildrenSelector(classificationAlias: string) {\n return `\n COALESCE((\n SELECT 1\n FROM ${CLASS_NAME_Classification} classification\n WHERE classification.Parent.Id = ${classificationAlias}.ECInstanceId\n LIMIT 1\n ), (\n SELECT 1\n FROM ${CLASS_NAME_ElementHasClassifications} ehc\n WHERE ehc.TargetECInstanceId = ${classificationAlias}.ECInstanceId\n LIMIT 1\n ),\n 0\n )\n `;\n}\n"]}