@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.
- package/CHANGELOG.md +25 -1
- package/README.md +143 -35
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeDefinition.d.ts +0 -10
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeDefinition.js +54 -132
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeDefinition.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeIcon.js +2 -6
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/ClassificationsTreeIcon.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeIdsCache.d.ts +11 -10
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeIdsCache.js +61 -48
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeIdsCache.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeNode.d.ts +0 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeNode.js +0 -4
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeNode.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeVisibilityHandler.js +25 -21
- package/lib/esm/tree-widget-react/components/trees/classifications-tree/internal/ClassificationsTreeVisibilityHandler.js.map +1 -1
- package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.d.ts +27 -0
- 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/UseFilteredPaths.d.ts +3 -0
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseFilteredPaths.js +1 -0
- package/lib/esm/tree-widget-react/components/trees/models-tree/internal/UseFilteredPaths.js.map +1 -1
- 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
|
|
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
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
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 {
|
|
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
|
|
106
|
-
return
|
|
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 (${
|
|
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:
|
|
144
|
-
const
|
|
138
|
+
const { parentNodeInstanceIds: parentClassificationIds, instanceFilter } = props;
|
|
139
|
+
const classificationIds = await this._props.idsCache.getDirectChildClassifications(parentClassificationIds);
|
|
145
140
|
return [
|
|
146
141
|
// load child classifications
|
|
147
|
-
...(
|
|
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 (${
|
|
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 #
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
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
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
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 #
|
|
300
|
-
const
|
|
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:
|
|
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:
|
|
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
|
|
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
|
-
),
|
|
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":"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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 {\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"]}
|