@itwin/tree-widget-react 3.4.2 → 3.5.0

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