@itwin/tree-widget-react 3.15.0 → 3.16.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 (126) hide show
  1. package/CHANGELOG.md +22 -2
  2. package/lib/cjs/tree-widget-react/TreeWidget.d.ts +1 -2
  3. package/lib/cjs/tree-widget-react/TreeWidget.js +12 -12
  4. package/lib/cjs/tree-widget-react/TreeWidget.js.map +1 -1
  5. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.d.ts +2 -3
  6. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js +5 -4
  7. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js.map +1 -1
  8. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.d.ts +4 -7
  9. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js +39 -31
  10. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js.map +1 -1
  11. package/lib/cjs/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js +6 -2
  12. package/lib/cjs/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js.map +1 -1
  13. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.d.ts +3 -11
  14. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js +45 -36
  15. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js.map +1 -1
  16. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.d.ts +1 -3
  17. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js +30 -30
  18. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js.map +1 -1
  19. package/lib/cjs/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.d.ts +2 -7
  20. package/lib/cjs/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js +8 -21
  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/internal/useTreeHooks/UseIdsCache.d.ts +3 -0
  23. package/lib/cjs/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.js +7 -7
  24. package/lib/cjs/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.js.map +1 -1
  25. package/lib/cjs/tree-widget-react/components/trees/common/useGuid.d.ts +2 -0
  26. package/lib/cjs/tree-widget-react/components/trees/common/useGuid.js +14 -0
  27. package/lib/cjs/tree-widget-react/components/trees/common/useGuid.js.map +1 -0
  28. package/lib/cjs/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTree.js +4 -1
  29. package/lib/cjs/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTree.js.map +1 -1
  30. package/lib/cjs/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeDefinition.d.ts +4 -6
  31. package/lib/cjs/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeDefinition.js +31 -26
  32. package/lib/cjs/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeDefinition.js.map +1 -1
  33. package/lib/cjs/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.d.ts +1 -1
  34. package/lib/cjs/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.js +4 -2
  35. package/lib/cjs/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.js.map +1 -1
  36. package/lib/cjs/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeDefinition.d.ts +1 -5
  37. package/lib/cjs/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeDefinition.js +44 -44
  38. package/lib/cjs/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeDefinition.js.map +1 -1
  39. package/lib/cjs/tree-widget-react/components/trees/imodel-content-tree/internal/IModelContentTreeIdsCache.d.ts +3 -6
  40. package/lib/cjs/tree-widget-react/components/trees/imodel-content-tree/internal/IModelContentTreeIdsCache.js +20 -16
  41. package/lib/cjs/tree-widget-react/components/trees/imodel-content-tree/internal/IModelContentTreeIdsCache.js.map +1 -1
  42. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.js +3 -1
  43. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.js.map +1 -1
  44. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.d.ts +6 -10
  45. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js +107 -64
  46. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js.map +1 -1
  47. package/lib/cjs/tree-widget-react/components/trees/models-tree/UseModelsTree.js +18 -8
  48. package/lib/cjs/tree-widget-react/components/trees/models-tree/UseModelsTree.js.map +1 -1
  49. package/lib/cjs/tree-widget-react/components/trees/models-tree/Utils.d.ts +24 -0
  50. package/lib/cjs/tree-widget-react/components/trees/models-tree/Utils.js +46 -0
  51. package/lib/cjs/tree-widget-react/components/trees/models-tree/Utils.js.map +1 -1
  52. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.d.ts +40 -9
  53. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js +68 -39
  54. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js.map +1 -1
  55. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/FilteredTree.d.ts +13 -5
  56. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js +20 -14
  57. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js.map +1 -1
  58. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.d.ts +5 -13
  59. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js +70 -60
  60. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js.map +1 -1
  61. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.d.ts +6 -2
  62. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js +189 -197
  63. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js.map +1 -1
  64. package/lib/esm/tree-widget-react/TreeWidget.d.ts +1 -2
  65. package/lib/esm/tree-widget-react/TreeWidget.js +12 -12
  66. package/lib/esm/tree-widget-react/TreeWidget.js.map +1 -1
  67. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.d.ts +2 -3
  68. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js +5 -3
  69. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js.map +1 -1
  70. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.d.ts +4 -7
  71. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js +39 -31
  72. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js.map +1 -1
  73. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js +6 -2
  74. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js.map +1 -1
  75. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.d.ts +3 -11
  76. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js +45 -36
  77. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js.map +1 -1
  78. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.d.ts +1 -3
  79. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js +30 -30
  80. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js.map +1 -1
  81. package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.d.ts +2 -7
  82. package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js +8 -20
  83. package/lib/esm/tree-widget-react/components/trees/common/CategoriesVisibilityUtils.js.map +1 -1
  84. package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.d.ts +3 -0
  85. package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.js +7 -7
  86. package/lib/esm/tree-widget-react/components/trees/common/internal/useTreeHooks/UseIdsCache.js.map +1 -1
  87. package/lib/esm/tree-widget-react/components/trees/common/useGuid.d.ts +2 -0
  88. package/lib/esm/tree-widget-react/components/trees/common/useGuid.js +11 -0
  89. package/lib/esm/tree-widget-react/components/trees/common/useGuid.js.map +1 -0
  90. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTree.js +4 -1
  91. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTree.js.map +1 -1
  92. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeDefinition.d.ts +4 -6
  93. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeDefinition.js +31 -26
  94. package/lib/esm/tree-widget-react/components/trees/external-sources-tree/ExternalSourcesTreeDefinition.js.map +1 -1
  95. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.d.ts +1 -1
  96. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.js +4 -2
  97. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTree.js.map +1 -1
  98. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeDefinition.d.ts +1 -5
  99. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeDefinition.js +44 -44
  100. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/IModelContentTreeDefinition.js.map +1 -1
  101. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/internal/IModelContentTreeIdsCache.d.ts +3 -6
  102. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/internal/IModelContentTreeIdsCache.js +21 -17
  103. package/lib/esm/tree-widget-react/components/trees/imodel-content-tree/internal/IModelContentTreeIdsCache.js.map +1 -1
  104. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.js +3 -1
  105. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.js.map +1 -1
  106. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.d.ts +6 -10
  107. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js +107 -64
  108. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js.map +1 -1
  109. package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.js +18 -8
  110. package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.js.map +1 -1
  111. package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.d.ts +24 -0
  112. package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.js +44 -0
  113. package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.js.map +1 -1
  114. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.d.ts +40 -9
  115. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js +70 -41
  116. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/AlwaysAndNeverDrawnElementInfo.js.map +1 -1
  117. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/FilteredTree.d.ts +13 -5
  118. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js +22 -16
  119. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/FilteredTree.js.map +1 -1
  120. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.d.ts +5 -13
  121. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js +71 -61
  122. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js.map +1 -1
  123. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.d.ts +6 -2
  124. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js +192 -200
  125. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js.map +1 -1
  126. package/package.json +8 -8
@@ -3,6 +3,7 @@
3
3
  * See LICENSE.md in the project root for license terms and full copyright notice.
4
4
  *--------------------------------------------------------------------------------------------*/
5
5
  import { bufferCount, defaultIfEmpty, defer, firstValueFrom, from, fromEvent, identity, lastValueFrom, map, merge, mergeAll, mergeMap, reduce, switchMap, takeUntil, toArray, } from "rxjs";
6
+ import { Guid } from "@itwin/core-bentley";
6
7
  import { IModel } from "@itwin/core-common";
7
8
  import { createNodesQueryClauseFactory, createPredicateBasedHierarchyDefinition, HierarchyFilteringPath, NodeSelectClauseColumnNames, ProcessedHierarchyNode, } from "@itwin/presentation-hierarchies";
8
9
  import { createBisInstanceLabelSelectClauseFactory, ECSql } from "@itwin/presentation-shared";
@@ -28,18 +29,20 @@ export var ModelsTreeInstanceKeyPathsProps;
28
29
  ModelsTreeInstanceKeyPathsProps.isLabelProps = isLabelProps;
29
30
  })(ModelsTreeInstanceKeyPathsProps || (ModelsTreeInstanceKeyPathsProps = {}));
30
31
  export class ModelsTreeDefinition {
31
- _impl;
32
- _idsCache;
33
- _hierarchyConfig;
34
- _selectQueryFactory;
35
- _nodeLabelSelectClauseFactory;
36
- _queryExecutor;
37
- _isSupported;
32
+ #impl;
33
+ #idsCache;
34
+ #hierarchyConfig;
35
+ #selectQueryFactory;
36
+ #nodeLabelSelectClauseFactory;
37
+ #queryExecutor;
38
+ #isSupported;
39
+ static #componentName = "ModelsTreeDefinition";
40
+ #componentId;
38
41
  constructor(props) {
39
- this._impl = createPredicateBasedHierarchyDefinition({
42
+ this.#impl = createPredicateBasedHierarchyDefinition({
40
43
  classHierarchyInspector: props.imodelAccess,
41
44
  hierarchy: {
42
- rootNodes: async (requestProps) => this.createSubjectChildrenQuery({ ...requestProps, parentNodeInstanceIds: this._hierarchyConfig.hideRootSubject ? [IModel.rootSubjectId] : [] }),
45
+ rootNodes: async (requestProps) => this.createSubjectChildrenQuery({ ...requestProps, parentNodeInstanceIds: this.#hierarchyConfig.hideRootSubject ? [IModel.rootSubjectId] : [] }),
43
46
  childNodes: [
44
47
  {
45
48
  parentInstancesNodePredicate: "BisCore.Subject",
@@ -64,24 +67,48 @@ export class ModelsTreeDefinition {
64
67
  ],
65
68
  },
66
69
  });
67
- this._idsCache = props.idsCache;
68
- this._queryExecutor = props.imodelAccess;
69
- this._hierarchyConfig = props.hierarchyConfig;
70
- this._nodeLabelSelectClauseFactory = createBisInstanceLabelSelectClauseFactory({ classHierarchyInspector: props.imodelAccess });
71
- this._selectQueryFactory = createNodesQueryClauseFactory({
70
+ this.#componentId = props.componentId ?? Guid.createValue();
71
+ this.#idsCache = props.idsCache;
72
+ this.#queryExecutor = props.imodelAccess;
73
+ this.#hierarchyConfig = props.hierarchyConfig;
74
+ this.#nodeLabelSelectClauseFactory = createBisInstanceLabelSelectClauseFactory({ classHierarchyInspector: props.imodelAccess });
75
+ this.#selectQueryFactory = createNodesQueryClauseFactory({
72
76
  imodelAccess: props.imodelAccess,
73
- instanceLabelSelectClauseFactory: this._nodeLabelSelectClauseFactory,
77
+ instanceLabelSelectClauseFactory: this.#nodeLabelSelectClauseFactory,
74
78
  });
75
79
  }
76
80
  async postProcessNode(node) {
77
81
  if (ProcessedHierarchyNode.isGroupingNode(node)) {
82
+ let hasDirectNonFilteredTargets = false;
83
+ let hasFilterTargetAncestor = false;
84
+ for (const child of node.children) {
85
+ if (child.filtering) {
86
+ if (child.filtering.hasFilterTargetAncestor) {
87
+ hasFilterTargetAncestor = true;
88
+ break;
89
+ }
90
+ if (!child.filtering.isFilterTarget) {
91
+ hasDirectNonFilteredTargets = true;
92
+ break;
93
+ }
94
+ }
95
+ }
78
96
  return {
79
97
  ...node,
80
- label: this._hierarchyConfig.elementClassGrouping === "enableWithCounts" ? `${node.label} (${node.children.length})` : node.label,
98
+ ...(hasFilterTargetAncestor
99
+ ? {
100
+ filtering: {
101
+ ...(node.filtering ?? {}),
102
+ hasFilterTargetAncestor,
103
+ },
104
+ }
105
+ : {}),
106
+ label: this.#hierarchyConfig.elementClassGrouping === "enableWithCounts" ? `${node.label} (${node.children.length})` : node.label,
81
107
  extendedData: {
82
108
  ...node.extendedData,
83
109
  // add `modelId` and `categoryId` from the first grouped element
84
110
  ...node.children[0].extendedData,
111
+ ...(hasDirectNonFilteredTargets ? { hasDirectNonFilteredTargets } : {}),
85
112
  // `imageId` is assigned to instance nodes at query time, but grouping ones need to
86
113
  // be handled during post-processing
87
114
  imageId: "icon-ec-class",
@@ -91,27 +118,27 @@ export class ModelsTreeDefinition {
91
118
  return node;
92
119
  }
93
120
  async defineHierarchyLevel(props) {
94
- if (this._isSupported === undefined) {
95
- this._isSupported = this.isSupported();
121
+ if (this.#isSupported === undefined) {
122
+ this.#isSupported = this.isSupported();
96
123
  }
97
- if ((await this._isSupported) === false) {
124
+ if ((await this.#isSupported) === false) {
98
125
  return [];
99
126
  }
100
- return this._impl.defineHierarchyLevel(props);
127
+ return this.#impl.defineHierarchyLevel(props);
101
128
  }
102
129
  async createSubjectChildrenQuery({ parentNodeInstanceIds: parentSubjectIds, instanceFilter, }) {
103
130
  const [subjectFilterClauses, modelFilterClauses] = await Promise.all([
104
- this._selectQueryFactory.createFilterClauses({
131
+ this.#selectQueryFactory.createFilterClauses({
105
132
  filter: instanceFilter,
106
133
  contentClass: { fullName: "BisCore.Subject", alias: "this" },
107
134
  }),
108
- this._selectQueryFactory.createFilterClauses({
135
+ this.#selectQueryFactory.createFilterClauses({
109
136
  filter: instanceFilter,
110
137
  contentClass: { fullName: "BisCore.GeometricModel3d", alias: "this" },
111
138
  }),
112
139
  ]);
113
140
  const [childSubjectIds, childModelIds] = parentSubjectIds.length
114
- ? await Promise.all([this._idsCache.getChildSubjectIds(parentSubjectIds), this._idsCache.getChildSubjectModelIds(parentSubjectIds)])
141
+ ? await Promise.all([this.#idsCache.getChildSubjectIds(parentSubjectIds), this.#idsCache.getChildSubjectModelIds(parentSubjectIds)])
115
142
  : [[IModel.rootSubjectId], []];
116
143
  const defs = new Array();
117
144
  childSubjectIds.length &&
@@ -120,11 +147,11 @@ export class ModelsTreeDefinition {
120
147
  query: {
121
148
  ecsql: `
122
149
  SELECT
123
- ${await this._selectQueryFactory.createSelectClause({
150
+ ${await this.#selectQueryFactory.createSelectClause({
124
151
  ecClassId: { selector: "this.ECClassId" },
125
152
  ecInstanceId: { selector: "this.ECInstanceId" },
126
153
  nodeLabel: {
127
- selector: await this._nodeLabelSelectClauseFactory.createSelectClause({
154
+ selector: await this.#nodeLabelSelectClauseFactory.createSelectClause({
128
155
  classAlias: "this",
129
156
  className: "BisCore.Subject",
130
157
  }),
@@ -146,7 +173,7 @@ export class ModelsTreeDefinition {
146
173
  ${subjectFilterClauses.where ? `AND ${subjectFilterClauses.where}` : ""}
147
174
  `,
148
175
  bindings: [
149
- { type: "idset", value: await this._idsCache.getParentSubjectIds() },
176
+ { type: "idset", value: await this.#idsCache.getParentSubjectIds() },
150
177
  ...childSubjectIds.map((id) => ({ type: "id", value: id })),
151
178
  ],
152
179
  },
@@ -159,11 +186,11 @@ export class ModelsTreeDefinition {
159
186
  SELECT model.ECInstanceId AS ECInstanceId, model.*
160
187
  FROM (
161
188
  SELECT
162
- ${await this._selectQueryFactory.createSelectClause({
189
+ ${await this.#selectQueryFactory.createSelectClause({
163
190
  ecClassId: { selector: "m.ECClassId" },
164
191
  ecInstanceId: { selector: "m.ECInstanceId" },
165
192
  nodeLabel: {
166
- selector: await this._nodeLabelSelectClauseFactory.createSelectClause({
193
+ selector: await this.#nodeLabelSelectClauseFactory.createSelectClause({
167
194
  classAlias: "partition",
168
195
  className: "BisCore.InformationPartitionElement",
169
196
  }),
@@ -179,12 +206,12 @@ export class ModelsTreeDefinition {
179
206
  END
180
207
  `,
181
208
  },
182
- hasChildren: this._hierarchyConfig.showEmptyModels
209
+ hasChildren: this.#hierarchyConfig.showEmptyModels
183
210
  ? {
184
211
  selector: `
185
212
  IFNULL((
186
213
  SELECT 1
187
- FROM ${this._hierarchyConfig.elementClassSpecification} e
214
+ FROM ${this.#hierarchyConfig.elementClassSpecification} e
188
215
  WHERE e.Model.Id = m.ECInstanceId
189
216
  LIMIT 1
190
217
  ), 0)
@@ -220,7 +247,7 @@ export class ModelsTreeDefinition {
220
247
  query: {
221
248
  ecsql: `
222
249
  SELECT
223
- ${await this._selectQueryFactory.createSelectClause({
250
+ ${await this.#selectQueryFactory.createSelectClause({
224
251
  ecClassId: { selector: "this.ECClassId" },
225
252
  ecInstanceId: { selector: "this.ECInstanceId" },
226
253
  nodeLabel: "", // doesn't matter - the node is always hidden
@@ -230,7 +257,7 @@ export class ModelsTreeDefinition {
230
257
  WHERE
231
258
  this.ModeledElement.Id IN (${elementIds.map(() => "?").join(",")})
232
259
  AND NOT this.IsPrivate
233
- AND this.ECInstanceId IN (SELECT Model.Id FROM ${this._hierarchyConfig.elementClassSpecification})
260
+ AND this.ECInstanceId IN (SELECT Model.Id FROM ${this.#hierarchyConfig.elementClassSpecification})
234
261
  `,
235
262
  bindings: [...elementIds.map((id) => ({ type: "id", value: id }))],
236
263
  },
@@ -238,7 +265,7 @@ export class ModelsTreeDefinition {
238
265
  ];
239
266
  }
240
267
  async createGeometricModel3dChildrenQuery({ parentNodeInstanceIds: modelIds, instanceFilter, }) {
241
- const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({
268
+ const instanceFilterClauses = await this.#selectQueryFactory.createFilterClauses({
242
269
  filter: instanceFilter,
243
270
  contentClass: { fullName: "BisCore.SpatialCategory", alias: "this" },
244
271
  });
@@ -248,11 +275,11 @@ export class ModelsTreeDefinition {
248
275
  query: {
249
276
  ecsql: `
250
277
  SELECT
251
- ${await this._selectQueryFactory.createSelectClause({
278
+ ${await this.#selectQueryFactory.createSelectClause({
252
279
  ecClassId: { selector: "this.ECClassId" },
253
280
  ecInstanceId: { selector: "this.ECInstanceId" },
254
281
  nodeLabel: {
255
- selector: await this._nodeLabelSelectClauseFactory.createSelectClause({
282
+ selector: await this.#nodeLabelSelectClauseFactory.createSelectClause({
256
283
  classAlias: "this",
257
284
  className: "BisCore.SpatialCategory",
258
285
  }),
@@ -271,7 +298,7 @@ export class ModelsTreeDefinition {
271
298
  WHERE
272
299
  EXISTS (
273
300
  SELECT 1
274
- FROM ${this._hierarchyConfig.elementClassSpecification} element
301
+ FROM ${this.#hierarchyConfig.elementClassSpecification} element
275
302
  WHERE
276
303
  element.Model.Id IN (${modelIds.map(() => "?").join(",")})
277
304
  AND element.Category.Id = +this.ECInstanceId
@@ -289,30 +316,30 @@ export class ModelsTreeDefinition {
289
316
  if (modelIds.length === 0) {
290
317
  throw new Error(`Invalid category node "${parentNode.label}" - missing model information.`);
291
318
  }
292
- const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({
319
+ const instanceFilterClauses = await this.#selectQueryFactory.createFilterClauses({
293
320
  filter: instanceFilter,
294
- contentClass: { fullName: this._hierarchyConfig.elementClassSpecification, alias: "this" },
321
+ contentClass: { fullName: this.#hierarchyConfig.elementClassSpecification, alias: "this" },
295
322
  });
296
- const modeledElements = await firstValueFrom(from(modelIds).pipe(mergeMap(async (modelId) => this._idsCache.getCategoriesModeledElements(modelId, categoryIds)), reduce((acc, foundModeledElements) => {
323
+ const modeledElements = await firstValueFrom(from(modelIds).pipe(mergeMap(async (modelId) => this.#idsCache.getCategoriesModeledElements(modelId, categoryIds)), reduce((acc, foundModeledElements) => {
297
324
  return acc.concat(foundModeledElements);
298
325
  }, new Array())));
299
326
  return [
300
327
  {
301
- fullClassName: this._hierarchyConfig.elementClassSpecification,
328
+ fullClassName: this.#hierarchyConfig.elementClassSpecification,
302
329
  query: {
303
330
  ecsql: `
304
331
  SELECT
305
- ${await this._selectQueryFactory.createSelectClause({
332
+ ${await this.#selectQueryFactory.createSelectClause({
306
333
  ecClassId: { selector: "this.ECClassId" },
307
334
  ecInstanceId: { selector: "this.ECInstanceId" },
308
335
  nodeLabel: {
309
- selector: await this._nodeLabelSelectClauseFactory.createSelectClause({
336
+ selector: await this.#nodeLabelSelectClauseFactory.createSelectClause({
310
337
  classAlias: "this",
311
- className: this._hierarchyConfig.elementClassSpecification,
338
+ className: this.#hierarchyConfig.elementClassSpecification,
312
339
  }),
313
340
  },
314
341
  grouping: {
315
- byClass: this._hierarchyConfig.elementClassGrouping !== "disable",
342
+ byClass: this.#hierarchyConfig.elementClassGrouping !== "disable",
316
343
  },
317
344
  hasChildren: {
318
345
  selector: `
@@ -321,7 +348,7 @@ export class ModelsTreeDefinition {
321
348
  1,
322
349
  IFNULL((
323
350
  SELECT 1
324
- FROM ${this._hierarchyConfig.elementClassSpecification} ce
351
+ FROM ${this.#hierarchyConfig.elementClassSpecification} ce
325
352
  WHERE ce.Parent.Id = this.ECInstanceId
326
353
  LIMIT 1
327
354
  ), 0)
@@ -349,33 +376,33 @@ export class ModelsTreeDefinition {
349
376
  ];
350
377
  }
351
378
  async createGeometricElement3dChildrenQuery({ parentNodeInstanceIds: elementIds, instanceFilter, }) {
352
- const instanceFilterClauses = await this._selectQueryFactory.createFilterClauses({
379
+ const instanceFilterClauses = await this.#selectQueryFactory.createFilterClauses({
353
380
  filter: instanceFilter,
354
- contentClass: { fullName: this._hierarchyConfig.elementClassSpecification, alias: "this" },
381
+ contentClass: { fullName: this.#hierarchyConfig.elementClassSpecification, alias: "this" },
355
382
  });
356
383
  return [
357
384
  {
358
- fullClassName: this._hierarchyConfig.elementClassSpecification,
385
+ fullClassName: this.#hierarchyConfig.elementClassSpecification,
359
386
  query: {
360
387
  ecsql: `
361
388
  SELECT
362
- ${await this._selectQueryFactory.createSelectClause({
389
+ ${await this.#selectQueryFactory.createSelectClause({
363
390
  ecClassId: { selector: "this.ECClassId" },
364
391
  ecInstanceId: { selector: "this.ECInstanceId" },
365
392
  nodeLabel: {
366
- selector: await this._nodeLabelSelectClauseFactory.createSelectClause({
393
+ selector: await this.#nodeLabelSelectClauseFactory.createSelectClause({
367
394
  classAlias: "this",
368
- className: this._hierarchyConfig.elementClassSpecification,
395
+ className: this.#hierarchyConfig.elementClassSpecification,
369
396
  }),
370
397
  },
371
398
  grouping: {
372
- byClass: this._hierarchyConfig.elementClassGrouping !== "disable",
399
+ byClass: this.#hierarchyConfig.elementClassGrouping !== "disable",
373
400
  },
374
401
  hasChildren: {
375
402
  selector: `
376
403
  IFNULL((
377
404
  SELECT 1
378
- FROM ${this._hierarchyConfig.elementClassSpecification} ce
405
+ FROM ${this.#hierarchyConfig.elementClassSpecification} ce
379
406
  JOIN BisCore.Model m ON ce.Model.Id = m.ECInstanceId
380
407
  WHERE ce.Parent.Id = this.ECInstanceId OR (ce.Model.Id = this.ECInstanceId AND m.IsPrivate = false)
381
408
  LIMIT 1
@@ -402,20 +429,25 @@ export class ModelsTreeDefinition {
402
429
  }
403
430
  static async createInstanceKeyPaths(props) {
404
431
  return lastValueFrom(defer(() => {
432
+ const componentInfo = { componentId: props.componentId ?? Guid.createValue(), componentName: this.#componentName };
405
433
  if (ModelsTreeInstanceKeyPathsProps.isLabelProps(props)) {
406
434
  const labelsFactory = createBisInstanceLabelSelectClauseFactory({ classHierarchyInspector: props.imodelAccess });
407
- return createInstanceKeyPathsFromInstanceLabelObs({ ...props, labelsFactory });
435
+ return createInstanceKeyPathsFromInstanceLabelObs({
436
+ ...props,
437
+ ...componentInfo,
438
+ labelsFactory,
439
+ });
408
440
  }
409
- return createInstanceKeyPathsFromTargetItemsObs(props);
441
+ return createInstanceKeyPathsFromTargetItemsObs({ ...props, ...componentInfo });
410
442
  }).pipe(props.abortSignal ? takeUntil(fromEvent(props.abortSignal, "abort")) : identity, defaultIfEmpty([])));
411
443
  }
412
444
  supportsFiltering() {
413
- return this._hierarchyConfig.hierarchyLevelFiltering === "enable";
445
+ return this.#hierarchyConfig.hierarchyLevelFiltering === "enable";
414
446
  }
415
447
  async isSupported() {
416
- const [schemaName, className] = this._hierarchyConfig.elementClassSpecification.split(/[\.:]/);
448
+ const [schemaName, className] = this.#hierarchyConfig.elementClassSpecification.split(/[\.:]/);
417
449
  if (!schemaName || !className) {
418
- throw new Error(`Provided class specification ${this._hierarchyConfig.elementClassSpecification} should be in format {SchemaName}:{ClassName} or {SchemaName}.{ClassName}`);
450
+ throw new Error(`Provided class specification ${this.#hierarchyConfig.elementClassSpecification} should be in format {SchemaName}:{ClassName} or {SchemaName}.{ClassName}`);
419
451
  }
420
452
  const query = {
421
453
  ecsql: `
@@ -429,13 +461,16 @@ export class ModelsTreeDefinition {
429
461
  { type: "string", value: className },
430
462
  ],
431
463
  };
432
- for await (const _row of this._queryExecutor.createQueryReader(query)) {
464
+ for await (const _row of this.#queryExecutor.createQueryReader(query, {
465
+ restartToken: `${ModelsTreeDefinition.#componentName}/${this.#componentId}/is-class-supported`,
466
+ })) {
433
467
  return true;
434
468
  }
435
469
  return false;
436
470
  }
437
471
  }
438
- function createGeometricElementInstanceKeyPaths(imodelAccess, idsCache, hierarchyConfig, targetItems) {
472
+ function createGeometricElementInstanceKeyPaths(props) {
473
+ const { targetItems, chunkIndex, componentId, componentName, hierarchyConfig, idsCache, imodelAccess } = props;
439
474
  const elementIds = targetItems.filter((info) => typeof info === "string");
440
475
  const groupInfos = targetItems.filter((info) => typeof info !== "string");
441
476
  const separator = ";";
@@ -495,7 +530,7 @@ function createGeometricElementInstanceKeyPaths(imodelAccess, idsCache, hierarch
495
530
  FROM ModelsCategoriesElementsHierarchy mce
496
531
  WHERE mce.ParentId IS NULL
497
532
  `;
498
- return imodelAccess.createQueryReader({ ctes, ecsql }, { rowFormat: "Indexes", limit: "unbounded" });
533
+ return imodelAccess.createQueryReader({ ctes, ecsql }, { rowFormat: "Indexes", limit: "unbounded", restartToken: `${componentName}/${componentId}/geometric-element-paths/${chunkIndex}` });
499
534
  }).pipe(releaseMainThreadOnItemsCount(300), map((row) => parseQueryRow(row, groupInfos, separator, hierarchyConfig.elementClassSpecification)), mergeMap(({ modelId, elementHierarchyPath, groupingNode }) => from(idsCache.createModelInstanceKeyPaths(modelId)).pipe(mergeAll(), map((modelPath) => {
500
535
  // We don't want to modify the original path, we create a copy that we can modify
501
536
  const newModelPath = [...modelPath];
@@ -537,7 +572,7 @@ function parseQueryRow(row, groupInfos, separator, elementClassName) {
537
572
  groupingNode: row[2] === -1 ? undefined : groupInfos[row[2]].groupingNode,
538
573
  };
539
574
  }
540
- function createInstanceKeyPathsFromTargetItemsObs({ targetItems, imodelAccess, hierarchyConfig, idsCache, limit, }) {
575
+ function createInstanceKeyPathsFromTargetItemsObs({ targetItems, imodelAccess, hierarchyConfig, idsCache, limit, componentId, componentName, }) {
541
576
  if (limit !== "unbounded" && targetItems.length > (limit ?? MAX_FILTERING_INSTANCE_KEY_COUNT)) {
542
577
  throw new FilterLimitExceededError(limit ?? MAX_FILTERING_INSTANCE_KEY_COUNT);
543
578
  }
@@ -577,7 +612,15 @@ function createInstanceKeyPathsFromTargetItemsObs({ targetItems, imodelAccess, h
577
612
  elements: new Array(),
578
613
  }), switchMap(async (ids) => {
579
614
  const elementsLength = ids.elements.length;
580
- return collect(merge(from(ids.subjects).pipe(mergeMap((id) => from(idsCache.createSubjectInstanceKeysPath(id)).pipe(map(HierarchyFilteringPath.normalize)))), from(ids.models).pipe(mergeMap((id) => from(idsCache.createModelInstanceKeyPaths(id)).pipe(mergeAll(), map(HierarchyFilteringPath.normalize)))), from(ids.categories).pipe(mergeMap((id) => from(idsCache.createCategoryInstanceKeyPaths(id)).pipe(mergeAll(), map(HierarchyFilteringPath.normalize)))), from(ids.elements).pipe(bufferCount(Math.ceil(elementsLength / Math.ceil(elementsLength / 5000))), releaseMainThreadOnItemsCount(1), mergeMap((block) => createGeometricElementInstanceKeyPaths(imodelAccess, idsCache, hierarchyConfig, block), 10))));
615
+ return collect(merge(from(ids.subjects).pipe(mergeMap((id) => from(idsCache.createSubjectInstanceKeysPath(id)).pipe(map(HierarchyFilteringPath.normalize)))), from(ids.models).pipe(mergeMap((id) => from(idsCache.createModelInstanceKeyPaths(id)).pipe(mergeAll(), map(HierarchyFilteringPath.normalize)))), from(ids.categories).pipe(mergeMap((id) => from(idsCache.createCategoryInstanceKeyPaths(id)).pipe(mergeAll(), map(HierarchyFilteringPath.normalize)))), from(ids.elements).pipe(bufferCount(Math.ceil(elementsLength / Math.ceil(elementsLength / 5000))), releaseMainThreadOnItemsCount(1), mergeMap((block, chunkIndex) => createGeometricElementInstanceKeyPaths({
616
+ imodelAccess,
617
+ idsCache,
618
+ hierarchyConfig,
619
+ targetItems: block,
620
+ componentId,
621
+ componentName,
622
+ chunkIndex,
623
+ }), 10))));
581
624
  }));
582
625
  }
583
626
  function createInstanceKeyPathsFromInstanceLabelObs(props) {
@@ -620,7 +663,7 @@ function createInstanceKeyPathsFromInstanceLabelObs(props) {
620
663
  }).pipe(mergeMap((queryProps) => {
621
664
  return imodelAccess.createQueryReader(queryProps, {
622
665
  rowFormat: "Indexes",
623
- restartToken: "tree-widget/models-tree/filter-by-label-query",
666
+ restartToken: `${props.componentName}/${props.componentId}/filter-by-label`,
624
667
  limit,
625
668
  });
626
669
  }), map((row) => ({ className: row[0], id: row[1] })), toArray(), mergeMap((targetKeys) => createInstanceKeyPathsFromTargetItemsObs({ ...props, targetItems: targetKeys })));