@itwin/unified-selection
Advanced tools
Comparing version 0.3.0 to 0.4.0
# @itwin/unified-selection | ||
## 0.4.0 | ||
### Minor Changes | ||
- [#558](https://github.com/iTwin/presentation/pull/558): Switched from `ECSchemaProvider` to `ECClassHierarchyInspector`, where appropriate. | ||
Some of the APIs were accepting `ECSchemaProvider` as a parameter and used it to only inspect class hierarchy. This change switches them to accept `ECClassHierarchyInspector` instead - this reduces the surface area of the API and makes it more clear that only class hierarchy is being inspected, while also possibly improving performance. | ||
This is a breaking change for the following APIs: | ||
- `createHiliteSetProvider` prop `imodelAccess`. | ||
- `createCachingHiliteSetProvider` prop `imodelProvider`. | ||
- `enableUnifiedSelectionSyncWithIModel` prop `imodelAccess`. | ||
Migration example: | ||
```ts | ||
import { | ||
createECSqlQueryExecutor, | ||
createECSchemaProvider, | ||
} from "@itwin/presentation-core-interop"; | ||
import { createCachingECClassHierarchyInspector } from "@itwin/presentation-shared"; | ||
import { createHiliteSetProvider } from "@itwin/unified-selection"; | ||
// before: | ||
const hiliteProvider = createHiliteSetProvider({ | ||
imodelAccess: { | ||
...createECSqlQueryExecutor(imodel), | ||
...createECSchemaProvider(MyAppFrontend.getSchemaContext(imodel)), | ||
}, | ||
}); | ||
// after: | ||
const hiliteProvider = createHiliteSetProvider({ | ||
imodelAccess: { | ||
...createECSqlQueryExecutor(imodel), | ||
...createCachingECClassHierarchyInspector({ | ||
schemaProvider: createECSchemaProvider( | ||
MyAppFrontend.getSchemaContext(imodel), | ||
), | ||
cacheSize: 100, | ||
}), | ||
}, | ||
}); | ||
``` | ||
### Patch Changes | ||
- [#557](https://github.com/iTwin/presentation/pull/557): Fixed `computeSelection` returning duplicate selectables when using `Functional` selection scope and non-3D elements. | ||
## 0.3.0 | ||
@@ -4,0 +54,0 @@ |
@@ -1,2 +0,2 @@ | ||
import { ECSchemaProvider, ECSqlQueryExecutor } from "@itwin/presentation-shared"; | ||
import { ECClassHierarchyInspector, ECSqlQueryExecutor } from "@itwin/presentation-shared"; | ||
import { HiliteSet } from "./HiliteSetProvider"; | ||
@@ -10,3 +10,3 @@ import { SelectionStorage } from "./SelectionStorage"; | ||
selectionStorage: SelectionStorage; | ||
imodelProvider: (imodelKey: string) => ECSchemaProvider & ECSqlQueryExecutor; | ||
imodelProvider: (imodelKey: string) => ECClassHierarchyInspector & ECSqlQueryExecutor; | ||
} | ||
@@ -13,0 +13,0 @@ /** |
@@ -1,2 +0,2 @@ | ||
import { ECSchemaProvider, ECSqlQueryExecutor } from "@itwin/presentation-shared"; | ||
import { ECClassHierarchyInspector, ECSqlQueryExecutor } from "@itwin/presentation-shared"; | ||
import { CachingHiliteSetProvider } from "./CachingHiliteSetProvider"; | ||
@@ -12,3 +12,3 @@ import { ComputeSelectionProps } from "./SelectionScope"; | ||
/** | ||
* Provides access to different iModel's features: query executing, metadata access, selection and hilite sets. | ||
* Provides access to different iModel's features: query executing, class hierarchy, selection and hilite sets. | ||
* It's recommended to use `@itwin/presentation-core-interop` to create `ECSqlQueryExecutor` and `ECSchemaProvider` from | ||
@@ -20,2 +20,3 @@ * [IModelConnection](https://www.itwinjs.org/reference/core-frontend/imodelconnection/imodelconnection/) and map its `key`, | ||
* import { createECSqlQueryExecutor, createECSchemaProvider } from "@itwin/presentation-core-interop"; | ||
* import { createCachingECClassHierarchyInspector } from "@itwin/presentation-shared"; | ||
* import { IModelConnection } from "@itwin/core-frontend"; | ||
@@ -26,3 +27,3 @@ * | ||
* ...createECSqlQueryExecutor(imodel), | ||
* ...createECSchemaProvider(MyAppFrontend.getSchemaContext(imodel)), | ||
* ...createCachingECClassHierarchyInspector({ schemaProvider: createECSchemaProvider(MyAppFrontend.getSchemaContext(imodel)) }), | ||
* key: imodel.key, | ||
@@ -34,3 +35,3 @@ * hiliteSet: imodel.hilited, | ||
*/ | ||
imodelAccess: ECSqlQueryExecutor & ECSchemaProvider & { | ||
imodelAccess: ECSqlQueryExecutor & ECClassHierarchyInspector & { | ||
/** Key of the iModel. Generally taken from `IModelConnection.key`. */ | ||
@@ -37,0 +38,0 @@ readonly key: string; |
@@ -1,2 +0,2 @@ | ||
import { ECSchemaProvider, ECSqlQueryExecutor } from "@itwin/presentation-shared"; | ||
import { ECClassHierarchyInspector, ECSqlQueryExecutor } from "@itwin/presentation-shared"; | ||
import { Selectables } from "./Selectable"; | ||
@@ -18,3 +18,3 @@ /** | ||
export interface HiliteSetProviderProps { | ||
imodelAccess: ECSchemaProvider & ECSqlQueryExecutor; | ||
imodelAccess: ECClassHierarchyInspector & ECSqlQueryExecutor; | ||
} | ||
@@ -21,0 +21,0 @@ /** |
@@ -10,3 +10,2 @@ "use strict"; | ||
const rxjs_for_await_1 = require("rxjs-for-await"); | ||
const presentation_shared_1 = require("@itwin/presentation-shared"); | ||
const Utils_1 = require("./Utils"); | ||
@@ -94,16 +93,26 @@ const HILITE_SET_EMIT_FREQUENCY = 20; | ||
async getTypeImpl(key) { | ||
const keyClass = await this.getClass(key.className); | ||
return ((keyClass && | ||
((await this.checkType(keyClass, "BisCore", "Subject", "subject")) ?? | ||
(await this.checkType(keyClass, "BisCore", "Model", "model")) ?? | ||
(await this.checkType(keyClass, "BisCore", "Category", "category")) ?? | ||
(await this.checkType(keyClass, "BisCore", "SubCategory", "subCategory")) ?? | ||
(await this.checkType(keyClass, "Functional", "FunctionalElement", "functionalElement")) ?? | ||
(await this.checkType(keyClass, "BisCore", "GroupInformationElement", "groupInformationElement")) ?? | ||
(await this.checkType(keyClass, "BisCore", "GeometricElement", "geometricElement")) ?? | ||
(await this.checkType(keyClass, "BisCore", "Element", "element")))) ?? | ||
return ((await this.checkType(key.className, "BisCore.Subject", "subject")) ?? | ||
(await this.checkType(key.className, "BisCore.Model", "model")) ?? | ||
(await this.checkType(key.className, "BisCore.Category", "category")) ?? | ||
(await this.checkType(key.className, "BisCore.SubCategory", "subCategory")) ?? | ||
(await this.checkType(key.className, "Functional.FunctionalElement", "functionalElement")) ?? | ||
(await this.checkType(key.className, "BisCore.GroupInformationElement", "groupInformationElement")) ?? | ||
(await this.checkType(key.className, "BisCore.GeometricElement", "geometricElement")) ?? | ||
(await this.checkType(key.className, "BisCore.Element", "element")) ?? | ||
"unknown"); | ||
} | ||
async checkType(keyClass, schemaName, className, type) { | ||
return (await keyClass.is(className, schemaName)) ? type : undefined; | ||
async checkType(keyClassName, checkClassName, type) { | ||
try { | ||
const res = this._imodelAccess.classDerivesFrom(keyClassName, checkClassName); | ||
const isOfType = typeof res === "boolean" ? res : await res; | ||
return isOfType ? type : undefined; | ||
} | ||
catch (e) { | ||
// we may be checking against a non-existing schema (e.g. Functional), in which case we should | ||
// return undefined instead of throwing an error | ||
if (e instanceof Error && e.message.match(/Schema "[\w\d_]+" not found/)) { | ||
return undefined; | ||
} | ||
throw e; | ||
} | ||
} | ||
@@ -309,14 +318,2 @@ getInstancesByType(selectables) { | ||
} | ||
async getClass(fullClassName) { | ||
const { schemaName, className } = (0, presentation_shared_1.parseFullClassName)(fullClassName); | ||
const schema = await this._imodelAccess.getSchema(schemaName); | ||
if (!schema) { | ||
return undefined; | ||
} | ||
const schemaClass = await schema.getClass(className); | ||
if (!schemaClass) { | ||
return undefined; | ||
} | ||
return schemaClass; | ||
} | ||
} | ||
@@ -323,0 +320,0 @@ const INSTANCE_TYPES = [ |
@@ -180,3 +180,3 @@ "use strict"; | ||
`, | ||
].join(" UNION ALL "); | ||
].join(" UNION "); | ||
yield* executeQuery(queryExecutor, { ctes, ecsql, bindings }); | ||
@@ -183,0 +183,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import { ECSchemaProvider, ECSqlQueryExecutor } from "@itwin/presentation-shared"; | ||
import { ECClassHierarchyInspector, ECSqlQueryExecutor } from "@itwin/presentation-shared"; | ||
import { HiliteSet } from "./HiliteSetProvider"; | ||
@@ -10,3 +10,3 @@ import { SelectionStorage } from "./SelectionStorage"; | ||
selectionStorage: SelectionStorage; | ||
imodelProvider: (imodelKey: string) => ECSchemaProvider & ECSqlQueryExecutor; | ||
imodelProvider: (imodelKey: string) => ECClassHierarchyInspector & ECSqlQueryExecutor; | ||
} | ||
@@ -13,0 +13,0 @@ /** |
@@ -1,2 +0,2 @@ | ||
import { ECSchemaProvider, ECSqlQueryExecutor } from "@itwin/presentation-shared"; | ||
import { ECClassHierarchyInspector, ECSqlQueryExecutor } from "@itwin/presentation-shared"; | ||
import { CachingHiliteSetProvider } from "./CachingHiliteSetProvider"; | ||
@@ -12,3 +12,3 @@ import { ComputeSelectionProps } from "./SelectionScope"; | ||
/** | ||
* Provides access to different iModel's features: query executing, metadata access, selection and hilite sets. | ||
* Provides access to different iModel's features: query executing, class hierarchy, selection and hilite sets. | ||
* It's recommended to use `@itwin/presentation-core-interop` to create `ECSqlQueryExecutor` and `ECSchemaProvider` from | ||
@@ -20,2 +20,3 @@ * [IModelConnection](https://www.itwinjs.org/reference/core-frontend/imodelconnection/imodelconnection/) and map its `key`, | ||
* import { createECSqlQueryExecutor, createECSchemaProvider } from "@itwin/presentation-core-interop"; | ||
* import { createCachingECClassHierarchyInspector } from "@itwin/presentation-shared"; | ||
* import { IModelConnection } from "@itwin/core-frontend"; | ||
@@ -26,3 +27,3 @@ * | ||
* ...createECSqlQueryExecutor(imodel), | ||
* ...createECSchemaProvider(MyAppFrontend.getSchemaContext(imodel)), | ||
* ...createCachingECClassHierarchyInspector({ schemaProvider: createECSchemaProvider(MyAppFrontend.getSchemaContext(imodel)) }), | ||
* key: imodel.key, | ||
@@ -34,3 +35,3 @@ * hiliteSet: imodel.hilited, | ||
*/ | ||
imodelAccess: ECSqlQueryExecutor & ECSchemaProvider & { | ||
imodelAccess: ECSqlQueryExecutor & ECClassHierarchyInspector & { | ||
/** Key of the iModel. Generally taken from `IModelConnection.key`. */ | ||
@@ -37,0 +38,0 @@ readonly key: string; |
@@ -1,2 +0,2 @@ | ||
import { ECSchemaProvider, ECSqlQueryExecutor } from "@itwin/presentation-shared"; | ||
import { ECClassHierarchyInspector, ECSqlQueryExecutor } from "@itwin/presentation-shared"; | ||
import { Selectables } from "./Selectable"; | ||
@@ -18,3 +18,3 @@ /** | ||
export interface HiliteSetProviderProps { | ||
imodelAccess: ECSchemaProvider & ECSqlQueryExecutor; | ||
imodelAccess: ECClassHierarchyInspector & ECSqlQueryExecutor; | ||
} | ||
@@ -21,0 +21,0 @@ /** |
@@ -7,3 +7,2 @@ /*--------------------------------------------------------------------------------------------- | ||
import { eachValueFrom } from "rxjs-for-await"; | ||
import { parseFullClassName } from "@itwin/presentation-shared"; | ||
import { formIdBindings } from "./Utils"; | ||
@@ -90,16 +89,26 @@ const HILITE_SET_EMIT_FREQUENCY = 20; | ||
async getTypeImpl(key) { | ||
const keyClass = await this.getClass(key.className); | ||
return ((keyClass && | ||
((await this.checkType(keyClass, "BisCore", "Subject", "subject")) ?? | ||
(await this.checkType(keyClass, "BisCore", "Model", "model")) ?? | ||
(await this.checkType(keyClass, "BisCore", "Category", "category")) ?? | ||
(await this.checkType(keyClass, "BisCore", "SubCategory", "subCategory")) ?? | ||
(await this.checkType(keyClass, "Functional", "FunctionalElement", "functionalElement")) ?? | ||
(await this.checkType(keyClass, "BisCore", "GroupInformationElement", "groupInformationElement")) ?? | ||
(await this.checkType(keyClass, "BisCore", "GeometricElement", "geometricElement")) ?? | ||
(await this.checkType(keyClass, "BisCore", "Element", "element")))) ?? | ||
return ((await this.checkType(key.className, "BisCore.Subject", "subject")) ?? | ||
(await this.checkType(key.className, "BisCore.Model", "model")) ?? | ||
(await this.checkType(key.className, "BisCore.Category", "category")) ?? | ||
(await this.checkType(key.className, "BisCore.SubCategory", "subCategory")) ?? | ||
(await this.checkType(key.className, "Functional.FunctionalElement", "functionalElement")) ?? | ||
(await this.checkType(key.className, "BisCore.GroupInformationElement", "groupInformationElement")) ?? | ||
(await this.checkType(key.className, "BisCore.GeometricElement", "geometricElement")) ?? | ||
(await this.checkType(key.className, "BisCore.Element", "element")) ?? | ||
"unknown"); | ||
} | ||
async checkType(keyClass, schemaName, className, type) { | ||
return (await keyClass.is(className, schemaName)) ? type : undefined; | ||
async checkType(keyClassName, checkClassName, type) { | ||
try { | ||
const res = this._imodelAccess.classDerivesFrom(keyClassName, checkClassName); | ||
const isOfType = typeof res === "boolean" ? res : await res; | ||
return isOfType ? type : undefined; | ||
} | ||
catch (e) { | ||
// we may be checking against a non-existing schema (e.g. Functional), in which case we should | ||
// return undefined instead of throwing an error | ||
if (e instanceof Error && e.message.match(/Schema "[\w\d_]+" not found/)) { | ||
return undefined; | ||
} | ||
throw e; | ||
} | ||
} | ||
@@ -305,14 +314,2 @@ getInstancesByType(selectables) { | ||
} | ||
async getClass(fullClassName) { | ||
const { schemaName, className } = parseFullClassName(fullClassName); | ||
const schema = await this._imodelAccess.getSchema(schemaName); | ||
if (!schema) { | ||
return undefined; | ||
} | ||
const schemaClass = await schema.getClass(className); | ||
if (!schemaClass) { | ||
return undefined; | ||
} | ||
return schemaClass; | ||
} | ||
} | ||
@@ -319,0 +316,0 @@ const INSTANCE_TYPES = [ |
@@ -176,3 +176,3 @@ /*--------------------------------------------------------------------------------------------- | ||
`, | ||
].join(" UNION ALL "); | ||
].join(" UNION "); | ||
yield* executeQuery(queryExecutor, { ctes, ecsql, bindings }); | ||
@@ -179,0 +179,0 @@ } |
{ | ||
"name": "@itwin/unified-selection", | ||
"version": "0.3.0", | ||
"version": "0.4.0", | ||
"description": "Package for managing unified selection in iTwin.js applications.", | ||
@@ -5,0 +5,0 @@ "license": "MIT", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
413969
3704