@itwin/tree-widget-react 3.16.1 → 3.17.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 (120) hide show
  1. package/CHANGELOG.md +15 -2
  2. package/lib/cjs/tree-widget-react/components/SelectableTree.js.map +1 -1
  3. package/lib/cjs/tree-widget-react/components/TreeSelector.js.map +1 -1
  4. package/lib/cjs/tree-widget-react/components/TreeWidgetUiItemsProvider.js +1 -1
  5. package/lib/cjs/tree-widget-react/components/TreeWidgetUiItemsProvider.js.map +1 -1
  6. package/lib/cjs/tree-widget-react/components/tree-header/TreeHeader.js.map +1 -1
  7. package/lib/cjs/tree-widget-react/components/tree-header/TreeWithHeader.js.map +1 -1
  8. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTree.d.ts +2 -2
  9. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTree.js +2 -1
  10. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTree.js.map +1 -1
  11. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js.map +1 -1
  12. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.d.ts +1 -1
  13. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.js.map +1 -1
  14. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.d.ts +13 -0
  15. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js +90 -73
  16. package/lib/cjs/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js.map +1 -1
  17. package/lib/cjs/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.d.ts +3 -1
  18. package/lib/cjs/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js +21 -8
  19. package/lib/cjs/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js.map +1 -1
  20. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.d.ts +21 -9
  21. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js +290 -242
  22. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js.map +1 -1
  23. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.d.ts +2 -0
  24. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js +16 -7
  25. package/lib/cjs/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js.map +1 -1
  26. package/lib/cjs/tree-widget-react/components/trees/common/UseActiveViewport.js.map +1 -1
  27. package/lib/cjs/tree-widget-react/components/trees/common/UseHierarchyVisibility.js.map +1 -1
  28. package/lib/cjs/tree-widget-react/components/trees/common/components/ProgressOverlay.js.map +1 -1
  29. package/lib/cjs/tree-widget-react/components/trees/common/components/Tree.d.ts +2 -2
  30. package/lib/cjs/tree-widget-react/components/trees/common/components/Tree.js.map +1 -1
  31. package/lib/cjs/tree-widget-react/components/trees/common/components/TreeNodeCheckbox.d.ts +1 -1
  32. package/lib/cjs/tree-widget-react/components/trees/common/components/TreeNodeCheckbox.js.map +1 -1
  33. package/lib/cjs/tree-widget-react/components/trees/common/components/TreeRenderer.d.ts +1 -1
  34. package/lib/cjs/tree-widget-react/components/trees/common/components/TreeRenderer.js +2 -2
  35. package/lib/cjs/tree-widget-react/components/trees/common/components/TreeRenderer.js.map +1 -1
  36. package/lib/cjs/tree-widget-react/components/trees/common/components/VisibilityTree.d.ts +3 -3
  37. package/lib/cjs/tree-widget-react/components/trees/common/components/VisibilityTree.js.map +1 -1
  38. package/lib/cjs/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.d.ts +1 -1
  39. package/lib/cjs/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.js.map +1 -1
  40. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTree.d.ts +1 -1
  41. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTree.js.map +1 -1
  42. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.js.map +1 -1
  43. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeComponent.js.map +1 -1
  44. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js +8 -5
  45. package/lib/cjs/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js.map +1 -1
  46. package/lib/cjs/tree-widget-react/components/trees/models-tree/UseModelsTree.js +2 -1
  47. package/lib/cjs/tree-widget-react/components/trees/models-tree/UseModelsTree.js.map +1 -1
  48. package/lib/cjs/tree-widget-react/components/trees/models-tree/Utils.d.ts +1 -4
  49. package/lib/cjs/tree-widget-react/components/trees/models-tree/Utils.js +1 -4
  50. package/lib/cjs/tree-widget-react/components/trees/models-tree/Utils.js.map +1 -1
  51. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.d.ts +13 -12
  52. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js +251 -278
  53. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js.map +1 -1
  54. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNode.d.ts +1 -1
  55. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNode.js.map +1 -1
  56. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js +47 -35
  57. package/lib/cjs/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js.map +1 -1
  58. package/lib/cjs/tree-widget-react-internal.d.ts +2 -1
  59. package/lib/cjs/tree-widget-react-internal.js +4 -1
  60. package/lib/cjs/tree-widget-react-internal.js.map +1 -1
  61. package/lib/esm/tree-widget-react/components/SelectableTree.js.map +1 -1
  62. package/lib/esm/tree-widget-react/components/TreeSelector.js.map +1 -1
  63. package/lib/esm/tree-widget-react/components/TreeWidgetUiItemsProvider.js +1 -1
  64. package/lib/esm/tree-widget-react/components/TreeWidgetUiItemsProvider.js.map +1 -1
  65. package/lib/esm/tree-widget-react/components/tree-header/TreeHeader.js.map +1 -1
  66. package/lib/esm/tree-widget-react/components/tree-header/TreeWithHeader.js.map +1 -1
  67. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.d.ts +2 -2
  68. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.js +2 -1
  69. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTree.js.map +1 -1
  70. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeButtons.js.map +1 -1
  71. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.d.ts +1 -1
  72. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeComponent.js.map +1 -1
  73. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.d.ts +13 -0
  74. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js +90 -73
  75. package/lib/esm/tree-widget-react/components/trees/categories-tree/CategoriesTreeDefinition.js.map +1 -1
  76. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.d.ts +3 -1
  77. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js +22 -9
  78. package/lib/esm/tree-widget-react/components/trees/categories-tree/UseCategoriesTree.js.map +1 -1
  79. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.d.ts +21 -9
  80. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js +290 -242
  81. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesTreeIdsCache.js.map +1 -1
  82. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.d.ts +2 -0
  83. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js +16 -7
  84. package/lib/esm/tree-widget-react/components/trees/categories-tree/internal/CategoriesVisibilityHandler.js.map +1 -1
  85. package/lib/esm/tree-widget-react/components/trees/common/UseActiveViewport.js.map +1 -1
  86. package/lib/esm/tree-widget-react/components/trees/common/UseHierarchyVisibility.js.map +1 -1
  87. package/lib/esm/tree-widget-react/components/trees/common/components/ProgressOverlay.js.map +1 -1
  88. package/lib/esm/tree-widget-react/components/trees/common/components/Tree.d.ts +2 -2
  89. package/lib/esm/tree-widget-react/components/trees/common/components/Tree.js.map +1 -1
  90. package/lib/esm/tree-widget-react/components/trees/common/components/TreeNodeCheckbox.d.ts +1 -1
  91. package/lib/esm/tree-widget-react/components/trees/common/components/TreeNodeCheckbox.js.map +1 -1
  92. package/lib/esm/tree-widget-react/components/trees/common/components/TreeRenderer.d.ts +1 -1
  93. package/lib/esm/tree-widget-react/components/trees/common/components/TreeRenderer.js +2 -2
  94. package/lib/esm/tree-widget-react/components/trees/common/components/TreeRenderer.js.map +1 -1
  95. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTree.d.ts +3 -3
  96. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTree.js.map +1 -1
  97. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.d.ts +1 -1
  98. package/lib/esm/tree-widget-react/components/trees/common/components/VisibilityTreeRenderer.js.map +1 -1
  99. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTree.d.ts +1 -1
  100. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTree.js.map +1 -1
  101. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeButtons.js.map +1 -1
  102. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeComponent.js.map +1 -1
  103. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js +9 -6
  104. package/lib/esm/tree-widget-react/components/trees/models-tree/ModelsTreeDefinition.js.map +1 -1
  105. package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.js +2 -1
  106. package/lib/esm/tree-widget-react/components/trees/models-tree/UseModelsTree.js.map +1 -1
  107. package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.d.ts +1 -4
  108. package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.js +1 -4
  109. package/lib/esm/tree-widget-react/components/trees/models-tree/Utils.js.map +1 -1
  110. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.d.ts +13 -12
  111. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js +252 -279
  112. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeIdsCache.js.map +1 -1
  113. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNode.d.ts +1 -1
  114. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeNode.js.map +1 -1
  115. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js +47 -35
  116. package/lib/esm/tree-widget-react/components/trees/models-tree/internal/ModelsTreeVisibilityHandler.js.map +1 -1
  117. package/lib/esm/tree-widget-react-internal.d.ts +2 -1
  118. package/lib/esm/tree-widget-react-internal.js +2 -1
  119. package/lib/esm/tree-widget-react-internal.js.map +1 -1
  120. package/package.json +1 -1
@@ -2,6 +2,7 @@
2
2
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
3
  * See LICENSE.md in the project root for license terms and full copyright notice.
4
4
  *--------------------------------------------------------------------------------------------*/
5
+ import { defer, forkJoin, from, map, mergeMap, of, reduce, shareReplay, toArray } from "rxjs";
5
6
  import { Guid } from "@itwin/core-bentley";
6
7
  import { DEFINITION_CONTAINER_CLASS, SUB_CATEGORY_CLASS } from "./ClassNameDefinitions.js";
7
8
  /** @internal */
@@ -27,311 +28,355 @@ export class CategoriesTreeIdsCache {
27
28
  this.#componentName = "CategoriesTreeIdsCache";
28
29
  }
29
30
  [Symbol.dispose]() { }
30
- async *queryElementModelCategories() {
31
- const query = `
32
- SELECT this.Model.Id modelId, this.Category.Id categoryId
33
- FROM ${this.#categoryModelClass} m
34
- JOIN ${this.#categoryElementClass} this ON m.ECInstanceId = this.Model.Id
35
- WHERE m.IsPrivate = false
36
- GROUP BY modelId, categoryId
37
- `;
38
- for await (const row of this.#queryExecutor.createQueryReader({ ecsql: query }, {
39
- rowFormat: "ECSqlPropertyNames",
40
- limit: "unbounded",
41
- restartToken: `${this.#componentName}/${this.#componentId}/element-models-and-categories`,
42
- })) {
43
- yield { modelId: row.modelId, categoryId: row.categoryId };
44
- }
31
+ queryElementModelCategories() {
32
+ return defer(() => {
33
+ const query = `
34
+ SELECT this.Model.Id modelId, this.Category.Id categoryId
35
+ FROM ${this.#categoryModelClass} m
36
+ JOIN ${this.#categoryElementClass} this ON m.ECInstanceId = this.Model.Id
37
+ WHERE m.IsPrivate = false
38
+ GROUP BY modelId, categoryId
39
+ `;
40
+ return this.#queryExecutor.createQueryReader({ ecsql: query }, {
41
+ rowFormat: "ECSqlPropertyNames",
42
+ limit: "unbounded",
43
+ restartToken: `${this.#componentName}/${this.#componentId}/element-models-and-categories`,
44
+ });
45
+ }).pipe(map((row) => {
46
+ return { modelId: row.modelId, categoryId: row.categoryId };
47
+ }));
45
48
  }
46
- async *queryCategories() {
47
- const isDefinitionContainerSupported = await this.getIsDefinitionContainerSupported();
48
- const categoriesQuery = `
49
- SELECT
50
- this.ECInstanceId id,
51
- COUNT(sc.ECInstanceId) childCount,
52
- this.Model.Id modelId,
53
- ${isDefinitionContainerSupported
54
- ? `
55
- IIF(this.Model.Id IN (SELECT dc.ECInstanceId FROM ${DEFINITION_CONTAINER_CLASS} dc),
56
- true,
57
- false
58
- )`
59
- : "false"} parentDefinitionContainerExists
60
- FROM
61
- ${this.#categoryClass} this
62
- JOIN ${SUB_CATEGORY_CLASS} sc ON sc.Parent.Id = this.ECInstanceId
63
- JOIN BisCore.Model m ON m.ECInstanceId = this.Model.Id
64
- WHERE
65
- NOT this.IsPrivate
66
- AND (NOT m.IsPrivate OR m.ECClassId IS (BisCore.DictionaryModel))
67
- AND EXISTS (SELECT 1 FROM ${this.#categoryElementClass} e WHERE e.Category.Id = this.ECInstanceId)
68
- GROUP BY this.ECInstanceId
69
- `;
70
- for await (const row of this.#queryExecutor.createQueryReader({ ecsql: categoriesQuery }, { rowFormat: "ECSqlPropertyNames", limit: "unbounded", restartToken: `${this.#componentName}/${this.#componentId}/categories` })) {
71
- yield { id: row.id, modelId: row.modelId, parentDefinitionContainerExists: row.parentDefinitionContainerExists, childCount: row.childCount };
72
- }
49
+ queryCategories() {
50
+ return this.getIsDefinitionContainerSupported().pipe(mergeMap((isDefinitionContainerSupported) => defer(() => {
51
+ const categoriesQuery = `
52
+ SELECT
53
+ this.ECInstanceId id,
54
+ COUNT(sc.ECInstanceId) childCount,
55
+ this.Model.Id modelId,
56
+ ${isDefinitionContainerSupported
57
+ ? `
58
+ IIF(this.Model.Id IN (SELECT dc.ECInstanceId FROM ${DEFINITION_CONTAINER_CLASS} dc),
59
+ true,
60
+ false
61
+ )`
62
+ : "false"} parentDefinitionContainerExists,
63
+ IFNULL(
64
+ (SELECT 1 FROM ${this.#categoryElementClass} e WHERE e.Category.Id = this.ECInstanceId LIMIT 1),
65
+ 0
66
+ ) hasElements
67
+ FROM
68
+ ${this.#categoryClass} this
69
+ JOIN ${SUB_CATEGORY_CLASS} sc ON sc.Parent.Id = this.ECInstanceId
70
+ JOIN BisCore.Model m ON m.ECInstanceId = this.Model.Id
71
+ WHERE
72
+ NOT this.IsPrivate
73
+ AND (NOT m.IsPrivate OR m.ECClassId IS (BisCore.DictionaryModel))
74
+ GROUP BY this.ECInstanceId
75
+ `;
76
+ return this.#queryExecutor.createQueryReader({ ecsql: categoriesQuery }, { rowFormat: "ECSqlPropertyNames", limit: "unbounded", restartToken: `${this.#componentName}/${this.#componentId}/categories` });
77
+ }).pipe(map((row) => {
78
+ return {
79
+ id: row.id,
80
+ modelId: row.modelId,
81
+ parentDefinitionContainerExists: row.parentDefinitionContainerExists,
82
+ childCount: row.childCount,
83
+ hasElements: !!row.hasElements,
84
+ };
85
+ }))));
73
86
  }
74
- async queryIsDefinitionContainersSupported() {
75
- const query = `
76
- SELECT
77
- 1
78
- FROM
79
- ECDbMeta.ECSchemaDef s
80
- JOIN ECDbMeta.ECClassDef c ON c.Schema.Id = s.ECInstanceId
81
- WHERE
82
- s.Name = 'BisCore'
83
- AND c.Name = 'DefinitionContainer'
84
- `;
85
- for await (const _row of this.#queryExecutor.createQueryReader({ ecsql: query }, { restartToken: `${this.#componentName}/${this.#componentId}/is-definition-container-supported` })) {
86
- return true;
87
- }
88
- return false;
87
+ queryIsDefinitionContainersSupported() {
88
+ return defer(() => {
89
+ const query = `
90
+ SELECT
91
+ 1
92
+ FROM
93
+ ECDbMeta.ECSchemaDef s
94
+ JOIN ECDbMeta.ECClassDef c ON c.Schema.Id = s.ECInstanceId
95
+ WHERE
96
+ s.Name = 'BisCore'
97
+ AND c.Name = 'DefinitionContainer'
98
+ LIMIT 1
99
+ `;
100
+ return this.#queryExecutor.createQueryReader({ ecsql: query }, { restartToken: `${this.#componentName}/${this.#componentId}/is-definition-container-supported` });
101
+ }).pipe(toArray(), map((rows) => rows.length > 0));
89
102
  }
90
- async *queryDefinitionContainers() {
91
- // DefinitionModel ECInstanceId will always be the same as modeled DefinitionContainer ECInstanceId, if this wasn't the case, we would need to do something like:
92
- // JOIN BisCore.DefinitionModel dm ON dm.ECInstanceId = ${modelIdAccessor}
93
- // JOIN BisCore.DefinitionModelBreaksDownDefinitionContainer dr ON dr.SourceECInstanceId = dm.ECInstanceId
94
- // JOIN BisCore.DefinitionContainer dc ON dc.ECInstanceId = dr.TargetECInstanceId
95
- const DEFINITION_CONTAINERS_CTE = "DefinitionContainers";
96
- const ctes = [
97
- `
98
- ${DEFINITION_CONTAINERS_CTE}(ECInstanceId, ModelId) AS (
103
+ queryDefinitionContainers() {
104
+ return defer(() => {
105
+ // DefinitionModel ECInstanceId will always be the same as modeled DefinitionContainer ECInstanceId, if this wasn't the case, we would need to do something like:
106
+ // JOIN BisCore.DefinitionModel dm ON dm.ECInstanceId = ${modelIdAccessor}
107
+ // JOIN BisCore.DefinitionModelBreaksDownDefinitionContainer dr ON dr.SourceECInstanceId = dm.ECInstanceId
108
+ // JOIN BisCore.DefinitionContainer dc ON dc.ECInstanceId = dr.TargetECInstanceId
109
+ const DEFINITION_CONTAINERS_CTE = "DefinitionContainers";
110
+ const CATEGORIES_MODELS_CTE = "CategoriesModels";
111
+ const ctes = [
112
+ `${CATEGORIES_MODELS_CTE}(ModelId, HasElements) AS (
99
113
  SELECT
100
- dc.ECInstanceId,
101
- dc.Model.Id
114
+ c.Model.Id,
115
+ IFNULL((
116
+ SELECT 1
117
+ FROM ${this.#categoryElementClass} e
118
+ WHERE e.Category.Id = c.ECInstanceId
119
+ LIMIT 1
120
+ ), 0)
102
121
  FROM
103
- ${DEFINITION_CONTAINER_CLASS} dc
122
+ ${this.#categoryClass} c
104
123
  WHERE
105
- dc.ECInstanceId IN (SELECT c.Model.Id FROM ${this.#categoryClass} c WHERE NOT c.IsPrivate AND EXISTS (SELECT 1 FROM ${this.#categoryElementClass} e WHERE e.Category.Id = c.ECInstanceId))
106
- AND NOT dc.IsPrivate
124
+ NOT c.IsPrivate
125
+ )`,
126
+ `
127
+ ${DEFINITION_CONTAINERS_CTE}(ECInstanceId, ModelId, HasElements) AS (
128
+ SELECT
129
+ dc.ECInstanceId,
130
+ dc.Model.Id,
131
+ c.HasElements
132
+ FROM ${DEFINITION_CONTAINER_CLASS} dc
133
+ JOIN ${CATEGORIES_MODELS_CTE} c ON dc.ECInstanceId = c.ModelId
134
+ WHERE NOT dc.IsPrivate
107
135
 
108
- UNION ALL
136
+ UNION ALL
109
137
 
110
- SELECT
111
- pdc.ECInstanceId,
112
- pdc.Model.Id
113
- FROM
114
- ${DEFINITION_CONTAINERS_CTE} cdc
115
- JOIN ${DEFINITION_CONTAINER_CLASS} pdc ON pdc.ECInstanceId = cdc.ModelId
116
- WHERE
117
- NOT pdc.IsPrivate
118
- )
119
- `,
120
- ];
121
- const definitionsQuery = `
122
- SELECT dc.ECInstanceId id, dc.ModelId modelId FROM ${DEFINITION_CONTAINERS_CTE} dc GROUP BY dc.ECInstanceId
123
- `;
124
- for await (const row of this.#queryExecutor.createQueryReader({ ctes, ecsql: definitionsQuery }, { rowFormat: "ECSqlPropertyNames", limit: "unbounded", restartToken: `${this.#componentName}/${this.#componentId}/definition-containers` })) {
125
- yield { id: row.id, modelId: row.modelId };
126
- }
138
+ SELECT
139
+ pdc.ECInstanceId,
140
+ pdc.Model.Id,
141
+ cdc.HasElements
142
+ FROM
143
+ ${DEFINITION_CONTAINERS_CTE} cdc
144
+ JOIN ${DEFINITION_CONTAINER_CLASS} pdc ON pdc.ECInstanceId = cdc.ModelId
145
+ WHERE NOT pdc.IsPrivate
146
+ )
147
+ `,
148
+ ];
149
+ const definitionsQuery = `
150
+ SELECT dc.ECInstanceId id, dc.ModelId modelId, MAX(dc.HasElements) hasElements FROM ${DEFINITION_CONTAINERS_CTE} dc GROUP BY dc.ECInstanceId
151
+ `;
152
+ return this.#queryExecutor.createQueryReader({ ctes, ecsql: definitionsQuery }, { rowFormat: "ECSqlPropertyNames", limit: "unbounded", restartToken: `${this.#componentName}/${this.#componentId}/definition-containers` });
153
+ }).pipe(map((row) => {
154
+ return { id: row.id, modelId: row.modelId, hasElements: !!row.hasElements };
155
+ }));
127
156
  }
128
- async *queryVisibleSubCategories(categoriesInfo) {
129
- const definitionsQuery = `
130
- SELECT
131
- sc.ECInstanceId id,
132
- sc.Parent.Id categoryId
133
- FROM
134
- ${SUB_CATEGORY_CLASS} sc
135
- WHERE
136
- NOT sc.IsPrivate
137
- AND sc.Parent.Id IN (${categoriesInfo.join(",")})
138
- `;
139
- for await (const row of this.#queryExecutor.createQueryReader({ ecsql: definitionsQuery }, { rowFormat: "ECSqlPropertyNames", limit: "unbounded", restartToken: `${this.#componentName}/${this.#componentId}/visible-sub-categories` })) {
140
- yield { id: row.id, parentId: row.categoryId };
141
- }
157
+ queryVisibleSubCategories(categoriesInfo) {
158
+ return defer(() => {
159
+ const definitionsQuery = `
160
+ SELECT
161
+ sc.ECInstanceId id,
162
+ sc.Parent.Id categoryId
163
+ FROM
164
+ ${SUB_CATEGORY_CLASS} sc
165
+ WHERE
166
+ NOT sc.IsPrivate
167
+ AND sc.Parent.Id IN (${categoriesInfo.join(",")})
168
+ `;
169
+ return this.#queryExecutor.createQueryReader({ ecsql: definitionsQuery }, { rowFormat: "ECSqlPropertyNames", limit: "unbounded", restartToken: `${this.#componentName}/${this.#componentId}/visible-sub-categories` });
170
+ }).pipe(map((row) => {
171
+ return { id: row.id, parentId: row.categoryId };
172
+ }));
142
173
  }
143
- async getModelsCategoriesInfo() {
144
- this.#modelsCategoriesInfo ??= (async () => {
145
- const allModelsCategories = new Map();
146
- for await (const queriedCategory of this.queryCategories()) {
147
- let modelCategories = allModelsCategories.get(queriedCategory.modelId);
148
- if (modelCategories === undefined) {
149
- modelCategories = { parentDefinitionContainerExists: queriedCategory.parentDefinitionContainerExists, childCategories: [] };
150
- allModelsCategories.set(queriedCategory.modelId, modelCategories);
151
- }
152
- modelCategories.childCategories.push({ id: queriedCategory.id, childCount: queriedCategory.childCount });
174
+ getModelsCategoriesInfo() {
175
+ this.#modelsCategoriesInfo ??= this.queryCategories()
176
+ .pipe(reduce((acc, queriedCategory) => {
177
+ let modelCategories = acc.get(queriedCategory.modelId);
178
+ if (modelCategories === undefined) {
179
+ modelCategories = { parentDefinitionContainerExists: queriedCategory.parentDefinitionContainerExists, childCategories: [] };
180
+ acc.set(queriedCategory.modelId, modelCategories);
153
181
  }
154
- return allModelsCategories;
155
- })();
182
+ modelCategories.childCategories.push({ id: queriedCategory.id, childCount: queriedCategory.childCount, hasElements: queriedCategory.hasElements });
183
+ return acc;
184
+ }, new Map()))
185
+ .pipe(shareReplay());
156
186
  return this.#modelsCategoriesInfo;
157
187
  }
158
- async getElementModelsCategories() {
159
- this.#elementModelsCategories ??= (async () => {
160
- const elementModelsCategories = new Map();
161
- for await (const queriedCategory of this.queryElementModelCategories()) {
162
- let modelEntry = elementModelsCategories.get(queriedCategory.modelId);
163
- if (modelEntry === undefined) {
164
- modelEntry = new Set();
165
- elementModelsCategories.set(queriedCategory.modelId, modelEntry);
166
- }
167
- modelEntry.add(queriedCategory.categoryId);
188
+ getElementModelsCategories() {
189
+ this.#elementModelsCategories ??= this.queryElementModelCategories()
190
+ .pipe(reduce((acc, queriedCategory) => {
191
+ let modelEntry = acc.get(queriedCategory.modelId);
192
+ if (modelEntry === undefined) {
193
+ modelEntry = new Set();
194
+ acc.set(queriedCategory.modelId, modelEntry);
168
195
  }
169
- return elementModelsCategories;
170
- })();
196
+ modelEntry.add(queriedCategory.categoryId);
197
+ return acc;
198
+ }, new Map()))
199
+ .pipe(shareReplay());
171
200
  return this.#elementModelsCategories;
172
201
  }
173
- async getSubCategoriesInfo() {
174
- this.#subCategoriesInfo ??= (async () => {
202
+ getSubCategoriesInfo() {
203
+ this.#subCategoriesInfo ??= this.getModelsCategoriesInfo()
204
+ .pipe(mergeMap((modelsCategoriesInfo) => from(modelsCategoriesInfo.values())), reduce((acc, modelCategoriesInfo) => {
205
+ acc.push(...modelCategoriesInfo.childCategories.filter((categoryInfo) => categoryInfo.childCount > 1).map((categoryInfo) => categoryInfo.id));
206
+ return acc;
207
+ }, new Array()), mergeMap((categoriesWithMoreThanOneSubCategory) => {
175
208
  const allSubCategories = new Map();
176
- const modelsCategoriesInfo = await this.getModelsCategoriesInfo();
177
- const categoriesWithMoreThanOneSubCategory = new Array();
178
- for (const modelCategoriesInfo of modelsCategoriesInfo.values()) {
179
- categoriesWithMoreThanOneSubCategory.push(...modelCategoriesInfo.childCategories.filter((categoryInfo) => categoryInfo.childCount > 1).map((categoryInfo) => categoryInfo.id));
180
- }
181
209
  if (categoriesWithMoreThanOneSubCategory.length === 0) {
182
- return allSubCategories;
210
+ return of(allSubCategories);
183
211
  }
184
- for await (const queriedSubCategory of this.queryVisibleSubCategories(categoriesWithMoreThanOneSubCategory)) {
185
- allSubCategories.set(queriedSubCategory.id, { categoryId: queriedSubCategory.parentId });
186
- }
187
- return allSubCategories;
188
- })();
212
+ return this.queryVisibleSubCategories(categoriesWithMoreThanOneSubCategory).pipe(reduce((acc, queriedSubCategory) => {
213
+ acc.set(queriedSubCategory.id, { categoryId: queriedSubCategory.parentId });
214
+ return acc;
215
+ }, allSubCategories));
216
+ }))
217
+ .pipe(shareReplay());
189
218
  return this.#subCategoriesInfo;
190
219
  }
191
- async getDefinitionContainersInfo() {
192
- this.#definitionContainersInfo ??= (async () => {
220
+ getDefinitionContainersInfo() {
221
+ this.#definitionContainersInfo ??= forkJoin({
222
+ isDefinitionContainerSupported: this.getIsDefinitionContainerSupported(),
223
+ modelsCategoriesInfo: this.getModelsCategoriesInfo(),
224
+ })
225
+ .pipe(mergeMap(({ isDefinitionContainerSupported, modelsCategoriesInfo }) => {
193
226
  const definitionContainersInfo = new Map();
194
- const [isDefinitionContainerSupported, modelsCategoriesInfo] = await Promise.all([
195
- this.getIsDefinitionContainerSupported(),
196
- this.getModelsCategoriesInfo(),
197
- ]);
198
227
  if (!isDefinitionContainerSupported || modelsCategoriesInfo.size === 0) {
199
- return definitionContainersInfo;
228
+ return of(definitionContainersInfo);
200
229
  }
201
- for await (const queriedDefinitionContainer of this.queryDefinitionContainers()) {
230
+ return this.queryDefinitionContainers().pipe(reduce((acc, queriedDefinitionContainer) => {
202
231
  const modelCategoriesInfo = modelsCategoriesInfo.get(queriedDefinitionContainer.id);
203
- definitionContainersInfo.set(queriedDefinitionContainer.id, {
232
+ acc.set(queriedDefinitionContainer.id, {
204
233
  childCategories: modelCategoriesInfo?.childCategories ?? [],
205
234
  modelId: queriedDefinitionContainer.modelId,
206
235
  childDefinitionContainers: [],
207
236
  parentDefinitionContainerExists: false,
237
+ hasElements: queriedDefinitionContainer.hasElements,
208
238
  });
209
- }
210
- for (const [definitionContainerId, definitionContainerInfo] of definitionContainersInfo) {
211
- const parentDefinitionContainer = definitionContainersInfo.get(definitionContainerInfo.modelId);
212
- if (parentDefinitionContainer !== undefined) {
213
- parentDefinitionContainer.childDefinitionContainers.push(definitionContainerId);
214
- definitionContainerInfo.parentDefinitionContainerExists = true;
239
+ return acc;
240
+ }, definitionContainersInfo), map((result) => {
241
+ for (const [definitionContainerId, definitionContainerInfo] of result) {
242
+ const parentDefinitionContainer = result.get(definitionContainerInfo.modelId);
243
+ if (parentDefinitionContainer !== undefined) {
244
+ parentDefinitionContainer.childDefinitionContainers.push({ id: definitionContainerId, hasElements: definitionContainerInfo.hasElements });
245
+ definitionContainerInfo.parentDefinitionContainerExists = true;
246
+ parentDefinitionContainer.hasElements = parentDefinitionContainer.hasElements || definitionContainerInfo.hasElements;
247
+ }
215
248
  }
216
- }
217
- return definitionContainersInfo;
218
- })();
249
+ return result;
250
+ }));
251
+ }))
252
+ .pipe(shareReplay());
219
253
  return this.#definitionContainersInfo;
220
254
  }
221
- async getDirectChildDefinitionContainersAndCategories(parentDefinitionContainerIds) {
222
- const definitionContainersInfo = await this.getDefinitionContainersInfo();
223
- const result = { definitionContainers: new Array(), categories: new Array() };
224
- parentDefinitionContainerIds.forEach((parentDefinitionContainerId) => {
255
+ getDirectChildDefinitionContainersAndCategories({ parentDefinitionContainerIds, includeEmpty, }) {
256
+ return this.getDefinitionContainersInfo().pipe(mergeMap((definitionContainersInfo) => from(parentDefinitionContainerIds).pipe(reduce((acc, parentDefinitionContainerId) => {
225
257
  const parentDefinitionContainerInfo = definitionContainersInfo.get(parentDefinitionContainerId);
226
258
  if (parentDefinitionContainerInfo !== undefined) {
227
- result.definitionContainers.push(...parentDefinitionContainerInfo.childDefinitionContainers);
228
- result.categories.push(...parentDefinitionContainerInfo.childCategories);
259
+ acc.definitionContainers.push(...applyElementsFilter(parentDefinitionContainerInfo.childDefinitionContainers, includeEmpty).map((dc) => dc.id));
260
+ acc.categories.push(...applyElementsFilter(parentDefinitionContainerInfo.childCategories, includeEmpty));
229
261
  }
230
- });
231
- return result;
262
+ return acc;
263
+ }, { definitionContainers: new Array(), categories: new Array() }))));
232
264
  }
233
- async getCategoriesElementModels(categoryIds) {
234
- const elementModelsCategories = await this.getElementModelsCategories();
235
- const result = new Map();
236
- for (const categoryId of categoryIds) {
265
+ getCategoriesElementModels(categoryIds) {
266
+ return this.getElementModelsCategories().pipe(mergeMap((elementModelsCategories) => from(categoryIds).pipe(reduce((acc, categoryId) => {
237
267
  for (const [modelId, categories] of elementModelsCategories) {
238
268
  if (categories.has(categoryId)) {
239
- let categoryModels = result.get(categoryId);
269
+ let categoryModels = acc.get(categoryId);
240
270
  if (!categoryModels) {
241
271
  categoryModels = new Array();
242
- result.set(categoryId, categoryModels);
272
+ acc.set(categoryId, categoryModels);
243
273
  }
244
274
  categoryModels.push(modelId);
245
275
  }
246
276
  }
247
- }
248
- return result;
277
+ return acc;
278
+ }, new Map()))));
249
279
  }
250
- async getAllContainedCategories(definitionContainerIds) {
251
- const result = new Array();
252
- const definitionContainersInfo = await this.getDefinitionContainersInfo();
253
- const indirectCategories = await Promise.all(definitionContainerIds.map(async (definitionContainerId) => {
280
+ getAllContainedCategories({ definitionContainerIds, includeEmptyCategories, }) {
281
+ return this.getDefinitionContainersInfo().pipe(mergeMap((definitionContainersInfo) => from(definitionContainerIds).pipe(mergeMap((definitionContainerId) => {
254
282
  const definitionContainerInfo = definitionContainersInfo.get(definitionContainerId);
255
283
  if (definitionContainerInfo === undefined) {
256
- return [];
284
+ return of({ directCategories: undefined, indirectCategories: undefined });
257
285
  }
258
- result.push(...definitionContainerInfo.childCategories.map((category) => category.id));
259
- return this.getAllContainedCategories(definitionContainerInfo.childDefinitionContainers);
260
- }));
261
- for (const categories of indirectCategories) {
262
- result.push(...categories);
263
- }
264
- return result;
286
+ const childDefinitionContainerIds = definitionContainerInfo.childDefinitionContainers.map(({ id }) => id);
287
+ return (childDefinitionContainerIds.length > 0
288
+ ? this.getAllContainedCategories({
289
+ definitionContainerIds: childDefinitionContainerIds,
290
+ includeEmptyCategories,
291
+ })
292
+ : of(new Set())).pipe(map((indirectCategories) => {
293
+ return {
294
+ directCategories: applyElementsFilter(definitionContainerInfo.childCategories, includeEmptyCategories).map((category) => category.id),
295
+ indirectCategories,
296
+ };
297
+ }));
298
+ }), reduce((acc, { directCategories, indirectCategories }) => {
299
+ directCategories?.forEach((categoryId) => acc.add(categoryId));
300
+ indirectCategories?.forEach((categoryId) => acc.add(categoryId));
301
+ return acc;
302
+ }, new Set()))));
265
303
  }
266
- async getInstanceKeyPaths(props) {
304
+ getInstanceKeyPaths(props) {
267
305
  if ("subCategoryId" in props) {
268
- const subCategoriesInfo = await this.getSubCategoriesInfo();
269
- const subCategoryInfo = subCategoriesInfo.get(props.subCategoryId);
270
- if (subCategoryInfo === undefined) {
271
- return [];
272
- }
273
- return [...(await this.getInstanceKeyPaths({ categoryId: subCategoryInfo.categoryId })), { id: props.subCategoryId, className: SUB_CATEGORY_CLASS }];
306
+ return this.getSubCategoriesInfo().pipe(mergeMap((subCategoriesInfo) => {
307
+ const subCategoryInfo = subCategoriesInfo.get(props.subCategoryId);
308
+ if (subCategoryInfo === undefined) {
309
+ return of([]);
310
+ }
311
+ return this.getInstanceKeyPaths({ categoryId: subCategoryInfo.categoryId }).pipe(map((pathToCategory) => [...pathToCategory, { id: props.subCategoryId, className: SUB_CATEGORY_CLASS }]));
312
+ }));
274
313
  }
275
314
  if ("categoryId" in props) {
276
- const modelsCategoriesInfo = await this.getModelsCategoriesInfo();
277
- for (const [modelId, modelCategoriesInfo] of modelsCategoriesInfo) {
278
- if (modelCategoriesInfo.childCategories.find((childCategory) => childCategory.id === props.categoryId)) {
279
- if (!modelCategoriesInfo.parentDefinitionContainerExists) {
280
- return [{ id: props.categoryId, className: this.#categoryClass }];
315
+ return this.getModelsCategoriesInfo().pipe(mergeMap((modelsCategoriesInfo) => {
316
+ for (const [modelId, modelCategoriesInfo] of modelsCategoriesInfo) {
317
+ if (modelCategoriesInfo.childCategories.find((childCategory) => childCategory.id === props.categoryId)) {
318
+ const instanceKey = { id: props.categoryId, className: this.#categoryClass };
319
+ if (!modelCategoriesInfo.parentDefinitionContainerExists) {
320
+ return of([instanceKey]);
321
+ }
322
+ return this.getInstanceKeyPaths({ definitionContainerId: modelId }).pipe(map((pathToDefinitionContainer) => [...pathToDefinitionContainer, instanceKey]));
281
323
  }
282
- return [...(await this.getInstanceKeyPaths({ definitionContainerId: modelId })), { id: props.categoryId, className: this.#categoryClass }];
283
324
  }
284
- }
285
- return [];
325
+ return of([]);
326
+ }));
286
327
  }
287
- const definitionContainersInfo = await this.getDefinitionContainersInfo();
288
- const definitionContainerInfo = definitionContainersInfo.get(props.definitionContainerId);
289
- if (definitionContainerInfo === undefined) {
290
- return [];
291
- }
292
- if (!definitionContainerInfo.parentDefinitionContainerExists) {
293
- return [{ id: props.definitionContainerId, className: DEFINITION_CONTAINER_CLASS }];
294
- }
295
- return [
296
- ...(await this.getInstanceKeyPaths({ definitionContainerId: definitionContainerInfo.modelId })),
297
- { id: props.definitionContainerId, className: DEFINITION_CONTAINER_CLASS },
298
- ];
299
- }
300
- async getAllDefinitionContainersAndCategories() {
301
- const [modelsCategoriesInfo, definitionContainersInfo] = await Promise.all([this.getModelsCategoriesInfo(), this.getDefinitionContainersInfo()]);
302
- const result = { definitionContainers: [...definitionContainersInfo.keys()], categories: new Array() };
303
- for (const modelCategoriesInfo of modelsCategoriesInfo.values()) {
304
- result.categories.push(...modelCategoriesInfo.childCategories.map((childCategory) => childCategory.id));
305
- }
306
- return result;
307
- }
308
- async getRootDefinitionContainersAndCategories() {
309
- const [modelsCategoriesInfo, definitionContainersInfo] = await Promise.all([this.getModelsCategoriesInfo(), this.getDefinitionContainersInfo()]);
310
- const result = { definitionContainers: new Array(), categories: new Array() };
311
- for (const modelCategoriesInfo of modelsCategoriesInfo.values()) {
312
- if (!modelCategoriesInfo.parentDefinitionContainerExists) {
313
- result.categories.push(...modelCategoriesInfo.childCategories);
328
+ return this.getDefinitionContainersInfo().pipe(mergeMap((definitionContainersInfo) => {
329
+ const definitionContainerInfo = definitionContainersInfo.get(props.definitionContainerId);
330
+ if (definitionContainerInfo === undefined) {
331
+ return of([]);
314
332
  }
315
- }
316
- for (const [definitionContainerId, definitionContainerInfo] of definitionContainersInfo) {
333
+ const instanceKey = { id: props.definitionContainerId, className: DEFINITION_CONTAINER_CLASS };
317
334
  if (!definitionContainerInfo.parentDefinitionContainerExists) {
318
- result.definitionContainers.push(definitionContainerId);
335
+ return of([instanceKey]);
319
336
  }
320
- }
321
- return result;
337
+ return this.getInstanceKeyPaths({ definitionContainerId: definitionContainerInfo.modelId }).pipe(map((pathToParentDefinitionContainer) => [...pathToParentDefinitionContainer, instanceKey]));
338
+ }));
339
+ }
340
+ getAllDefinitionContainersAndCategories(props) {
341
+ return forkJoin({
342
+ categories: this.getModelsCategoriesInfo().pipe(mergeMap((modelsCategoriesInfo) => modelsCategoriesInfo.values()), reduce((acc, modelCategoriesInfo) => {
343
+ applyElementsFilter(modelCategoriesInfo.childCategories, props?.includeEmpty).forEach((categoryInfo) => acc.push(categoryInfo.id));
344
+ return acc;
345
+ }, new Array())),
346
+ definitionContainers: this.getDefinitionContainersInfo().pipe(mergeMap((definitionContainersInfo) => definitionContainersInfo.entries()), reduce((acc, [definitionContainerId, definitionContainerInfo]) => {
347
+ if (definitionContainerInfo.hasElements || !!props?.includeEmpty) {
348
+ acc.push(definitionContainerId);
349
+ }
350
+ return acc;
351
+ }, new Array())),
352
+ });
353
+ }
354
+ getRootDefinitionContainersAndCategories(props) {
355
+ return forkJoin({
356
+ categories: this.getModelsCategoriesInfo().pipe(mergeMap((modelsCategoriesInfo) => modelsCategoriesInfo.values()), reduce((acc, modelCategoriesInfo) => {
357
+ if (!modelCategoriesInfo.parentDefinitionContainerExists) {
358
+ applyElementsFilter(modelCategoriesInfo.childCategories, props?.includeEmpty).forEach((categoryInfo) => acc.push(categoryInfo));
359
+ }
360
+ return acc;
361
+ }, new Array())),
362
+ definitionContainers: this.getDefinitionContainersInfo().pipe(mergeMap((definitionContainersInfo) => definitionContainersInfo.entries()), reduce((acc, [definitionContainerId, definitionContainerInfo]) => {
363
+ if (!definitionContainerInfo.parentDefinitionContainerExists && (definitionContainerInfo.hasElements || !!props?.includeEmpty)) {
364
+ acc.push(definitionContainerId);
365
+ }
366
+ return acc;
367
+ }, new Array())),
368
+ });
322
369
  }
323
- async getSubCategories(categoryId) {
324
- const subCategoriesInfo = await this.getSubCategoriesInfo();
325
- const result = new Array();
326
- for (const [subCategoryId, subCategoryInfo] of subCategoriesInfo) {
370
+ getSubCategories(categoryId) {
371
+ return this.getSubCategoriesInfo().pipe(mergeMap((subCategoriesInfo) => subCategoriesInfo.entries()), reduce((acc, [subCategoryId, subCategoryInfo]) => {
327
372
  if (subCategoryInfo.categoryId === categoryId) {
328
- result.push(subCategoryId);
373
+ acc.push(subCategoryId);
329
374
  }
330
- }
331
- return result;
375
+ return acc;
376
+ }, new Array()));
332
377
  }
333
- async getIsDefinitionContainerSupported() {
334
- this.#isDefinitionContainerSupported ??= this.queryIsDefinitionContainersSupported();
378
+ getIsDefinitionContainerSupported() {
379
+ this.#isDefinitionContainerSupported ??= this.queryIsDefinitionContainersSupported().pipe(shareReplay());
335
380
  return this.#isDefinitionContainerSupported;
336
381
  }
337
382
  }
@@ -341,4 +386,7 @@ export function getClassesByView(viewType) {
341
386
  ? { categoryClass: "BisCore.DrawingCategory", categoryElementClass: "BisCore.GeometricElement2d", categoryModelClass: "BisCore.GeometricModel2d" }
342
387
  : { categoryClass: "BisCore.SpatialCategory", categoryElementClass: "BisCore.GeometricElement3d", categoryModelClass: "BisCore.GeometricModel3d" };
343
388
  }
389
+ function applyElementsFilter(list, includeEmpty) {
390
+ return includeEmpty ? list : list.filter(({ hasElements }) => !!hasElements);
391
+ }
344
392
  //# sourceMappingURL=CategoriesTreeIdsCache.js.map