@itwin/presentation-frontend 4.0.0-dev.21 → 4.0.0-dev.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/presentation-frontend/ConnectivityInformationProvider.d.ts +29 -29
- package/lib/cjs/presentation-frontend/ConnectivityInformationProvider.js +47 -47
- package/lib/cjs/presentation-frontend/ConnectivityInformationProvider.js.map +1 -1
- package/lib/cjs/presentation-frontend/Diagnostics.d.ts +14 -14
- package/lib/cjs/presentation-frontend/Diagnostics.js +61 -61
- package/lib/cjs/presentation-frontend/Diagnostics.js.map +1 -1
- package/lib/cjs/presentation-frontend/FrontendLoggerCategory.d.ts +12 -12
- package/lib/cjs/presentation-frontend/FrontendLoggerCategory.js +20 -20
- package/lib/cjs/presentation-frontend/FrontendLoggerCategory.js.map +1 -1
- package/lib/cjs/presentation-frontend/IpcRequestsHandler.d.ts +10 -10
- package/lib/cjs/presentation-frontend/IpcRequestsHandler.js +41 -41
- package/lib/cjs/presentation-frontend/IpcRequestsHandler.js.map +1 -1
- package/lib/cjs/presentation-frontend/LocalizationHelper.d.ts +10 -10
- package/lib/cjs/presentation-frontend/LocalizationHelper.js +31 -31
- package/lib/cjs/presentation-frontend/LocalizationHelper.js.map +1 -1
- package/lib/cjs/presentation-frontend/Presentation.d.ts +73 -73
- package/lib/cjs/presentation-frontend/Presentation.js +160 -160
- package/lib/cjs/presentation-frontend/Presentation.js.map +1 -1
- package/lib/cjs/presentation-frontend/PresentationManager.d.ts +186 -186
- package/lib/cjs/presentation-frontend/PresentationManager.js +436 -436
- package/lib/cjs/presentation-frontend/PresentationManager.js.map +1 -1
- package/lib/cjs/presentation-frontend/RulesetManager.d.ts +63 -63
- package/lib/cjs/presentation-frontend/RulesetManager.js +85 -85
- package/lib/cjs/presentation-frontend/RulesetManager.js.map +1 -1
- package/lib/cjs/presentation-frontend/RulesetVariablesManager.d.ts +143 -143
- package/lib/cjs/presentation-frontend/RulesetVariablesManager.js +195 -195
- package/lib/cjs/presentation-frontend/RulesetVariablesManager.js.map +1 -1
- package/lib/cjs/presentation-frontend/StateTracker.d.ts +38 -38
- package/lib/cjs/presentation-frontend/StateTracker.js +129 -129
- package/lib/cjs/presentation-frontend/StateTracker.js.map +1 -1
- package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesManager.d.ts +132 -132
- package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesManager.js +525 -525
- package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesManager.js.map +1 -1
- package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesStorage.d.ts +111 -111
- package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesStorage.js +293 -293
- package/lib/cjs/presentation-frontend/favorite-properties/FavoritePropertiesStorage.js.map +1 -1
- package/lib/cjs/presentation-frontend/selection/HiliteRules.json +172 -172
- package/lib/cjs/presentation-frontend/selection/HiliteSetProvider.d.ts +52 -52
- package/lib/cjs/presentation-frontend/selection/HiliteSetProvider.js +97 -97
- package/lib/cjs/presentation-frontend/selection/HiliteSetProvider.js.map +1 -1
- package/lib/cjs/presentation-frontend/selection/ISelectionProvider.d.ts +19 -19
- package/lib/cjs/presentation-frontend/selection/ISelectionProvider.js +9 -9
- package/lib/cjs/presentation-frontend/selection/ISelectionProvider.js.map +1 -1
- package/lib/cjs/presentation-frontend/selection/SelectionChangeEvent.d.ts +52 -52
- package/lib/cjs/presentation-frontend/selection/SelectionChangeEvent.js +33 -33
- package/lib/cjs/presentation-frontend/selection/SelectionChangeEvent.js.map +1 -1
- package/lib/cjs/presentation-frontend/selection/SelectionHandler.d.ts +103 -103
- package/lib/cjs/presentation-frontend/selection/SelectionHandler.js +108 -108
- package/lib/cjs/presentation-frontend/selection/SelectionHandler.js.map +1 -1
- package/lib/cjs/presentation-frontend/selection/SelectionHelper.d.ts +17 -17
- package/lib/cjs/presentation-frontend/selection/SelectionHelper.js +40 -40
- package/lib/cjs/presentation-frontend/selection/SelectionHelper.js.map +1 -1
- package/lib/cjs/presentation-frontend/selection/SelectionManager.d.ts +139 -139
- package/lib/cjs/presentation-frontend/selection/SelectionManager.js +414 -414
- package/lib/cjs/presentation-frontend/selection/SelectionManager.js.map +1 -1
- package/lib/cjs/presentation-frontend/selection/SelectionScopesManager.d.ts +59 -59
- package/lib/cjs/presentation-frontend/selection/SelectionScopesManager.js +91 -91
- package/lib/cjs/presentation-frontend/selection/SelectionScopesManager.js.map +1 -1
- package/lib/cjs/presentation-frontend.d.ts +34 -34
- package/lib/cjs/presentation-frontend.js +50 -50
- package/lib/cjs/presentation-frontend.js.map +1 -1
- package/lib/esm/presentation-frontend/ConnectivityInformationProvider.d.ts +29 -29
- package/lib/esm/presentation-frontend/ConnectivityInformationProvider.js +43 -43
- package/lib/esm/presentation-frontend/ConnectivityInformationProvider.js.map +1 -1
- package/lib/esm/presentation-frontend/Diagnostics.d.ts +14 -14
- package/lib/esm/presentation-frontend/Diagnostics.js +56 -56
- package/lib/esm/presentation-frontend/Diagnostics.js.map +1 -1
- package/lib/esm/presentation-frontend/FrontendLoggerCategory.d.ts +12 -12
- package/lib/esm/presentation-frontend/FrontendLoggerCategory.js +17 -17
- package/lib/esm/presentation-frontend/FrontendLoggerCategory.js.map +1 -1
- package/lib/esm/presentation-frontend/IpcRequestsHandler.d.ts +10 -10
- package/lib/esm/presentation-frontend/IpcRequestsHandler.js +37 -37
- package/lib/esm/presentation-frontend/IpcRequestsHandler.js.map +1 -1
- package/lib/esm/presentation-frontend/LocalizationHelper.d.ts +10 -10
- package/lib/esm/presentation-frontend/LocalizationHelper.js +27 -27
- package/lib/esm/presentation-frontend/LocalizationHelper.js.map +1 -1
- package/lib/esm/presentation-frontend/Presentation.d.ts +73 -73
- package/lib/esm/presentation-frontend/Presentation.js +156 -156
- package/lib/esm/presentation-frontend/Presentation.js.map +1 -1
- package/lib/esm/presentation-frontend/PresentationManager.d.ts +186 -186
- package/lib/esm/presentation-frontend/PresentationManager.js +431 -431
- package/lib/esm/presentation-frontend/PresentationManager.js.map +1 -1
- package/lib/esm/presentation-frontend/RulesetManager.d.ts +63 -63
- package/lib/esm/presentation-frontend/RulesetManager.js +81 -81
- package/lib/esm/presentation-frontend/RulesetManager.js.map +1 -1
- package/lib/esm/presentation-frontend/RulesetVariablesManager.d.ts +143 -143
- package/lib/esm/presentation-frontend/RulesetVariablesManager.js +191 -191
- package/lib/esm/presentation-frontend/RulesetVariablesManager.js.map +1 -1
- package/lib/esm/presentation-frontend/StateTracker.d.ts +38 -38
- package/lib/esm/presentation-frontend/StateTracker.js +125 -125
- package/lib/esm/presentation-frontend/StateTracker.js.map +1 -1
- package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesManager.d.ts +132 -132
- package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesManager.js +519 -519
- package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesManager.js.map +1 -1
- package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesStorage.d.ts +111 -111
- package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesStorage.js +285 -285
- package/lib/esm/presentation-frontend/favorite-properties/FavoritePropertiesStorage.js.map +1 -1
- package/lib/esm/presentation-frontend/selection/HiliteRules.json +172 -172
- package/lib/esm/presentation-frontend/selection/HiliteSetProvider.d.ts +52 -52
- package/lib/esm/presentation-frontend/selection/HiliteSetProvider.js +93 -93
- package/lib/esm/presentation-frontend/selection/HiliteSetProvider.js.map +1 -1
- package/lib/esm/presentation-frontend/selection/ISelectionProvider.d.ts +19 -19
- package/lib/esm/presentation-frontend/selection/ISelectionProvider.js +8 -8
- package/lib/esm/presentation-frontend/selection/ISelectionProvider.js.map +1 -1
- package/lib/esm/presentation-frontend/selection/SelectionChangeEvent.d.ts +52 -52
- package/lib/esm/presentation-frontend/selection/SelectionChangeEvent.js +29 -29
- package/lib/esm/presentation-frontend/selection/SelectionChangeEvent.js.map +1 -1
- package/lib/esm/presentation-frontend/selection/SelectionHandler.d.ts +103 -103
- package/lib/esm/presentation-frontend/selection/SelectionHandler.js +104 -104
- package/lib/esm/presentation-frontend/selection/SelectionHandler.js.map +1 -1
- package/lib/esm/presentation-frontend/selection/SelectionHelper.d.ts +17 -17
- package/lib/esm/presentation-frontend/selection/SelectionHelper.js +36 -36
- package/lib/esm/presentation-frontend/selection/SelectionHelper.js.map +1 -1
- package/lib/esm/presentation-frontend/selection/SelectionManager.d.ts +139 -139
- package/lib/esm/presentation-frontend/selection/SelectionManager.js +409 -409
- package/lib/esm/presentation-frontend/selection/SelectionManager.js.map +1 -1
- package/lib/esm/presentation-frontend/selection/SelectionScopesManager.d.ts +59 -59
- package/lib/esm/presentation-frontend/selection/SelectionScopesManager.js +85 -85
- package/lib/esm/presentation-frontend/selection/SelectionScopesManager.js.map +1 -1
- package/lib/esm/presentation-frontend.d.ts +34 -34
- package/lib/esm/presentation-frontend.js +38 -38
- package/lib/esm/presentation-frontend.js.map +1 -1
- package/package.json +14 -14
|
@@ -1,432 +1,432 @@
|
|
|
1
|
-
/*---------------------------------------------------------------------------------------------
|
|
2
|
-
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
3
|
-
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
|
-
*--------------------------------------------------------------------------------------------*/
|
|
5
|
-
/** @packageDocumentation
|
|
6
|
-
* @module Core
|
|
7
|
-
*/
|
|
8
|
-
import { BeEvent, CompressedId64Set, OrderedId64Iterable } from "@itwin/core-bentley";
|
|
9
|
-
import { IpcApp } from "@itwin/core-frontend";
|
|
10
|
-
import { Content, Descriptor, DisplayValueGroup, Item, Key, KeySet, Node, NodePathElement, PresentationIpcEvents, RpcRequestsHandler, RulesetVariable, SelectClassInfo, UpdateInfo, VariableValueTypes, } from "@itwin/presentation-common";
|
|
11
|
-
import { IpcRequestsHandler } from "./IpcRequestsHandler";
|
|
12
|
-
import { FrontendLocalizationHelper } from "./LocalizationHelper";
|
|
13
|
-
import { RulesetManagerImpl } from "./RulesetManager";
|
|
14
|
-
import { RulesetVariablesManagerImpl } from "./RulesetVariablesManager";
|
|
15
|
-
import { TRANSIENT_ELEMENT_CLASSNAME } from "./selection/SelectionManager";
|
|
16
|
-
import { StateTracker } from "./StateTracker";
|
|
17
|
-
/**
|
|
18
|
-
* Frontend Presentation manager which basically just forwards all calls to
|
|
19
|
-
* the backend implementation.
|
|
20
|
-
*
|
|
21
|
-
* @public
|
|
22
|
-
*/
|
|
23
|
-
export class PresentationManager {
|
|
24
|
-
constructor(props) {
|
|
25
|
-
var _a, _b, _c;
|
|
26
|
-
/**
|
|
27
|
-
* An event raised when hierarchies created using specific ruleset change
|
|
28
|
-
* @alpha
|
|
29
|
-
*/
|
|
30
|
-
this.onIModelHierarchyChanged = new BeEvent();
|
|
31
|
-
/**
|
|
32
|
-
* An event raised when content created using specific ruleset changes
|
|
33
|
-
* @alpha
|
|
34
|
-
*/
|
|
35
|
-
this.onIModelContentChanged = new BeEvent();
|
|
36
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
37
|
-
this.onUpdate = (_evt, report) => {
|
|
38
|
-
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
39
|
-
this.handleUpdateAsync(UpdateInfo.fromJSON(report));
|
|
40
|
-
};
|
|
41
|
-
if (props) {
|
|
42
|
-
this.activeUnitSystem = props.activeUnitSystem;
|
|
43
|
-
}
|
|
44
|
-
this._requestsHandler = (_a = props === null || props === void 0 ? void 0 : props.rpcRequestsHandler) !== null && _a !== void 0 ? _a : new RpcRequestsHandler(props ? { clientId: props.clientId } : undefined);
|
|
45
|
-
this._rulesetVars = new Map();
|
|
46
|
-
this._rulesets = RulesetManagerImpl.create();
|
|
47
|
-
this._localizationHelper = new FrontendLocalizationHelper(props === null || props === void 0 ? void 0 : props.activeLocale);
|
|
48
|
-
this._connections = new Map();
|
|
49
|
-
if (IpcApp.isValid) {
|
|
50
|
-
// Ipc only works in ipc apps, so the `onUpdate` callback will only be called there.
|
|
51
|
-
this._clearEventListener = IpcApp.addListener(PresentationIpcEvents.Update, this.onUpdate);
|
|
52
|
-
this._ipcRequestsHandler = (_b = props === null || props === void 0 ? void 0 : props.ipcRequestsHandler) !== null && _b !== void 0 ? _b : new IpcRequestsHandler(this._requestsHandler.clientId);
|
|
53
|
-
this._stateTracker = (_c = props === null || props === void 0 ? void 0 : props.stateTracker) !== null && _c !== void 0 ? _c : new StateTracker(this._ipcRequestsHandler);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
/** Get / set active locale used for localizing presentation data */
|
|
57
|
-
get activeLocale() { return this._localizationHelper.locale; }
|
|
58
|
-
set activeLocale(locale) { this._localizationHelper.locale = locale; }
|
|
59
|
-
dispose() {
|
|
60
|
-
this._requestsHandler.dispose();
|
|
61
|
-
if (this._clearEventListener) {
|
|
62
|
-
this._clearEventListener();
|
|
63
|
-
this._clearEventListener = undefined;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
async onConnection(imodel) {
|
|
67
|
-
if (!this._connections.has(imodel))
|
|
68
|
-
this._connections.set(imodel, this.initializeIModel(imodel));
|
|
69
|
-
await this._connections.get(imodel);
|
|
70
|
-
}
|
|
71
|
-
async initializeIModel(imodel) {
|
|
72
|
-
imodel.onClose.addOnce(() => {
|
|
73
|
-
this._connections.delete(imodel);
|
|
74
|
-
});
|
|
75
|
-
await this.onNewiModelConnection(imodel);
|
|
76
|
-
}
|
|
77
|
-
/** @note This is only called in native apps after changes in iModels */
|
|
78
|
-
async handleUpdateAsync(report) {
|
|
79
|
-
for (const imodelKey in report) {
|
|
80
|
-
// istanbul ignore if
|
|
81
|
-
if (!report.hasOwnProperty(imodelKey))
|
|
82
|
-
continue;
|
|
83
|
-
const imodelReport = report[imodelKey];
|
|
84
|
-
for (const rulesetId in imodelReport) {
|
|
85
|
-
// istanbul ignore if
|
|
86
|
-
if (!imodelReport.hasOwnProperty(rulesetId))
|
|
87
|
-
continue;
|
|
88
|
-
const updateInfo = imodelReport[rulesetId];
|
|
89
|
-
if (updateInfo.content)
|
|
90
|
-
this.onIModelContentChanged.raiseEvent({ rulesetId, updateInfo: updateInfo.content, imodelKey });
|
|
91
|
-
if (updateInfo.hierarchy)
|
|
92
|
-
this.onIModelHierarchyChanged.raiseEvent({ rulesetId, updateInfo: updateInfo.hierarchy, imodelKey });
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
/** Function that is called when a new IModelConnection is used to retrieve data.
|
|
97
|
-
* @internal
|
|
98
|
-
*/
|
|
99
|
-
async onNewiModelConnection(_) { }
|
|
100
|
-
/**
|
|
101
|
-
* Create a new PresentationManager instance
|
|
102
|
-
* @param props Optional properties used to configure the manager
|
|
103
|
-
*/
|
|
104
|
-
static create(props) {
|
|
105
|
-
return new PresentationManager(props);
|
|
106
|
-
}
|
|
107
|
-
/** @internal */
|
|
108
|
-
get rpcRequestsHandler() { return this._requestsHandler; }
|
|
109
|
-
/** @internal */
|
|
110
|
-
get ipcRequestsHandler() { return this._ipcRequestsHandler; }
|
|
111
|
-
/** @internal */
|
|
112
|
-
get stateTracker() { return this._stateTracker; }
|
|
113
|
-
/**
|
|
114
|
-
* Get rulesets manager
|
|
115
|
-
*/
|
|
116
|
-
rulesets() { return this._rulesets; }
|
|
117
|
-
/**
|
|
118
|
-
* Get ruleset variables manager for specific ruleset
|
|
119
|
-
* @param rulesetId Id of the ruleset to get the vars manager for
|
|
120
|
-
*/
|
|
121
|
-
vars(rulesetId) {
|
|
122
|
-
if (!this._rulesetVars.has(rulesetId)) {
|
|
123
|
-
const varsManager = new RulesetVariablesManagerImpl(rulesetId, this._ipcRequestsHandler);
|
|
124
|
-
this._rulesetVars.set(rulesetId, varsManager);
|
|
125
|
-
}
|
|
126
|
-
return this._rulesetVars.get(rulesetId);
|
|
127
|
-
}
|
|
128
|
-
toRpcTokenOptions(requestOptions) {
|
|
129
|
-
// 1. put default `locale` and `unitSystem`
|
|
130
|
-
// 2. put all `requestOptions` members (if `locale` or `unitSystem` are set, they'll override the defaults put at #1)
|
|
131
|
-
// 3. put `imodel` of type `IModelRpcProps` which overwrites the `imodel` from `requestOptions` put at #2
|
|
132
|
-
const defaultOptions = {};
|
|
133
|
-
if (this.activeLocale)
|
|
134
|
-
defaultOptions.locale = this.activeLocale;
|
|
135
|
-
if (this.activeUnitSystem)
|
|
136
|
-
defaultOptions.unitSystem = this.activeUnitSystem;
|
|
137
|
-
const { imodel, rulesetVariables, ...rpcRequestOptions } = requestOptions;
|
|
138
|
-
return {
|
|
139
|
-
...defaultOptions,
|
|
140
|
-
...rpcRequestOptions,
|
|
141
|
-
...(rulesetVariables ? { rulesetVariables: rulesetVariables.map(RulesetVariable.toJSON) } : {}),
|
|
142
|
-
imodel: imodel.getRpcProps(),
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
async addRulesetAndVariablesToOptions(options) {
|
|
146
|
-
const { rulesetOrId, rulesetVariables } = options;
|
|
147
|
-
let foundRulesetOrId;
|
|
148
|
-
if (typeof rulesetOrId === "object") {
|
|
149
|
-
foundRulesetOrId = rulesetOrId;
|
|
150
|
-
}
|
|
151
|
-
else {
|
|
152
|
-
const foundRuleset = await this._rulesets.get(rulesetOrId);
|
|
153
|
-
foundRulesetOrId = foundRuleset ? foundRuleset.toJSON() : rulesetOrId;
|
|
154
|
-
}
|
|
155
|
-
const rulesetId = (typeof foundRulesetOrId === "object") ? foundRulesetOrId.id : foundRulesetOrId;
|
|
156
|
-
// All Id64Array variable values must be sorted for serialization to JSON to work. RulesetVariablesManager
|
|
157
|
-
// sorts them before storing, so that part is taken care of, but we need to ensure that variables coming from
|
|
158
|
-
// request options are also sorted.
|
|
159
|
-
const variables = (rulesetVariables !== null && rulesetVariables !== void 0 ? rulesetVariables : []).map((variable) => {
|
|
160
|
-
if (variable.type === VariableValueTypes.Id64Array)
|
|
161
|
-
return { ...variable, value: OrderedId64Iterable.sortArray(variable.value) };
|
|
162
|
-
return variable;
|
|
163
|
-
});
|
|
164
|
-
if (!this._ipcRequestsHandler) {
|
|
165
|
-
// only need to add variables from variables manager if there's no IPC
|
|
166
|
-
// handler - if there is one, the variables are already known by the backend
|
|
167
|
-
variables.push(...this.vars(rulesetId).getAllVariables());
|
|
168
|
-
}
|
|
169
|
-
return { ...options, rulesetOrId: foundRulesetOrId, rulesetVariables: variables };
|
|
170
|
-
}
|
|
171
|
-
/** Retrieves nodes */
|
|
172
|
-
async getNodes(requestOptions) {
|
|
173
|
-
await this.onConnection(requestOptions.imodel);
|
|
174
|
-
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
|
|
175
|
-
const rpcOptions = this.toRpcTokenOptions({ ...options });
|
|
176
|
-
const result = await buildPagedArrayResponse(options.paging, async (partialPageOptions) => this._requestsHandler.getPagedNodes({ ...rpcOptions, paging: partialPageOptions }));
|
|
177
|
-
// eslint-disable-next-line deprecation/deprecation
|
|
178
|
-
return this._localizationHelper.getLocalizedNodes(result.items.map(Node.fromJSON));
|
|
179
|
-
}
|
|
180
|
-
/** Retrieves nodes count. */
|
|
181
|
-
async getNodesCount(requestOptions) {
|
|
182
|
-
await this.onConnection(requestOptions.imodel);
|
|
183
|
-
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
|
|
184
|
-
const rpcOptions = this.toRpcTokenOptions({ ...options });
|
|
185
|
-
return this._requestsHandler.getNodesCount(rpcOptions);
|
|
186
|
-
}
|
|
187
|
-
/** Retrieves total nodes count and a single page of nodes. */
|
|
188
|
-
async getNodesAndCount(requestOptions) {
|
|
189
|
-
await this.onConnection(requestOptions.imodel);
|
|
190
|
-
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
|
|
191
|
-
const rpcOptions = this.toRpcTokenOptions({ ...options });
|
|
192
|
-
const result = await buildPagedArrayResponse(options.paging, async (partialPageOptions) => this._requestsHandler.getPagedNodes({ ...rpcOptions, paging: partialPageOptions }));
|
|
193
|
-
return {
|
|
194
|
-
count: result.total,
|
|
195
|
-
// eslint-disable-next-line deprecation/deprecation
|
|
196
|
-
nodes: this._localizationHelper.getLocalizedNodes(result.items.map(Node.fromJSON)),
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
/**
|
|
200
|
-
* Retrieves hierarchy level descriptor.
|
|
201
|
-
* @beta
|
|
202
|
-
*/
|
|
203
|
-
async getNodesDescriptor(requestOptions) {
|
|
204
|
-
await this.onConnection(requestOptions.imodel);
|
|
205
|
-
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
|
|
206
|
-
const rpcOptions = this.toRpcTokenOptions({ ...options });
|
|
207
|
-
const result = await this._requestsHandler.getNodesDescriptor(rpcOptions);
|
|
208
|
-
return Descriptor.fromJSON(result);
|
|
209
|
-
}
|
|
210
|
-
/** Retrieves paths from root nodes to children nodes according to specified keys. Intersecting paths will be merged. */
|
|
211
|
-
async getNodePaths(requestOptions) {
|
|
212
|
-
await this.onConnection(requestOptions.imodel);
|
|
213
|
-
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
|
|
214
|
-
const rpcOptions = this.toRpcTokenOptions({ ...options });
|
|
215
|
-
const result = await this._requestsHandler.getNodePaths(rpcOptions);
|
|
216
|
-
// eslint-disable-next-line deprecation/deprecation
|
|
217
|
-
return result.map(NodePathElement.fromJSON);
|
|
218
|
-
}
|
|
219
|
-
/** Retrieves paths from root nodes to nodes containing filter text in their label. */
|
|
220
|
-
async getFilteredNodePaths(requestOptions) {
|
|
221
|
-
await this.onConnection(requestOptions.imodel);
|
|
222
|
-
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
|
|
223
|
-
const result = await this._requestsHandler.getFilteredNodePaths(this.toRpcTokenOptions(options));
|
|
224
|
-
// eslint-disable-next-line deprecation/deprecation
|
|
225
|
-
return result.map(NodePathElement.fromJSON);
|
|
226
|
-
}
|
|
227
|
-
/**
|
|
228
|
-
* Get information about the sources of content when building it for specific ECClasses. Sources involve classes of the primary select instance,
|
|
229
|
-
* its related instances for loading related and navigation properties.
|
|
230
|
-
* @public
|
|
231
|
-
*/
|
|
232
|
-
async getContentSources(requestOptions) {
|
|
233
|
-
await this.onConnection(requestOptions.imodel);
|
|
234
|
-
const rpcOptions = this.toRpcTokenOptions(requestOptions);
|
|
235
|
-
const result = await this._requestsHandler.getContentSources(rpcOptions);
|
|
236
|
-
return SelectClassInfo.listFromCompressedJSON(result.sources, result.classesMap);
|
|
237
|
-
}
|
|
238
|
-
/** Retrieves the content descriptor which describes the content and can be used to customize it. */
|
|
239
|
-
async getContentDescriptor(requestOptions) {
|
|
240
|
-
await this.onConnection(requestOptions.imodel);
|
|
241
|
-
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
|
|
242
|
-
const rpcOptions = this.toRpcTokenOptions({
|
|
243
|
-
...options,
|
|
244
|
-
keys: stripTransientElementKeys(options.keys).toJSON(),
|
|
245
|
-
});
|
|
246
|
-
const result = await this._requestsHandler.getContentDescriptor(rpcOptions);
|
|
247
|
-
return Descriptor.fromJSON(result);
|
|
248
|
-
}
|
|
249
|
-
/** Retrieves overall content set size. */
|
|
250
|
-
async getContentSetSize(requestOptions) {
|
|
251
|
-
await this.onConnection(requestOptions.imodel);
|
|
252
|
-
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
|
|
253
|
-
const rpcOptions = this.toRpcTokenOptions({
|
|
254
|
-
...options,
|
|
255
|
-
descriptor: getDescriptorOverrides(requestOptions.descriptor),
|
|
256
|
-
keys: stripTransientElementKeys(requestOptions.keys).toJSON(),
|
|
257
|
-
});
|
|
258
|
-
return this._requestsHandler.getContentSetSize(rpcOptions);
|
|
259
|
-
}
|
|
260
|
-
/** Retrieves content which consists of a content descriptor and a page of records. */
|
|
261
|
-
async getContent(requestOptions) {
|
|
262
|
-
var _a;
|
|
263
|
-
return (_a = (await this.getContentAndSize(requestOptions))) === null || _a === void 0 ? void 0 : _a.content;
|
|
264
|
-
}
|
|
265
|
-
/** Retrieves content set size and content which consists of a content descriptor and a page of records. */
|
|
266
|
-
async getContentAndSize(requestOptions) {
|
|
267
|
-
await this.onConnection(requestOptions.imodel);
|
|
268
|
-
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
|
|
269
|
-
const rpcOptions = this.toRpcTokenOptions({
|
|
270
|
-
...options,
|
|
271
|
-
descriptor: getDescriptorOverrides(requestOptions.descriptor),
|
|
272
|
-
keys: stripTransientElementKeys(requestOptions.keys).toJSON(),
|
|
273
|
-
});
|
|
274
|
-
let descriptor = (requestOptions.descriptor instanceof Descriptor) ? requestOptions.descriptor : undefined;
|
|
275
|
-
const result = await buildPagedArrayResponse(options.paging, async (partialPageOptions, requestIndex) => {
|
|
276
|
-
if (0 === requestIndex && !descriptor) {
|
|
277
|
-
const content = await this._requestsHandler.getPagedContent({ ...rpcOptions, paging: partialPageOptions });
|
|
278
|
-
if (content) {
|
|
279
|
-
descriptor = Descriptor.fromJSON(content.descriptor);
|
|
280
|
-
return content.contentSet;
|
|
281
|
-
}
|
|
282
|
-
return { total: 0, items: [] };
|
|
283
|
-
}
|
|
284
|
-
return this._requestsHandler.getPagedContentSet({ ...rpcOptions, paging: partialPageOptions });
|
|
285
|
-
});
|
|
286
|
-
if (!descriptor)
|
|
287
|
-
return undefined;
|
|
288
|
-
const items = result.items.map((itemJson) => Item.fromJSON(itemJson)).filter((item) => (item !== undefined));
|
|
289
|
-
return {
|
|
290
|
-
size: result.total,
|
|
291
|
-
content: this._localizationHelper.getLocalizedContent(new Content(descriptor, items)),
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
|
-
/** Retrieves distinct values of specific field from the content. */
|
|
295
|
-
async getPagedDistinctValues(requestOptions) {
|
|
296
|
-
await this.onConnection(requestOptions.imodel);
|
|
297
|
-
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
|
|
298
|
-
const rpcOptions = {
|
|
299
|
-
...this.toRpcTokenOptions(options),
|
|
300
|
-
descriptor: getDescriptorOverrides(options.descriptor),
|
|
301
|
-
keys: stripTransientElementKeys(options.keys).toJSON(),
|
|
302
|
-
};
|
|
303
|
-
const result = await buildPagedArrayResponse(requestOptions.paging, async (partialPageOptions) => this._requestsHandler.getPagedDistinctValues({ ...rpcOptions, paging: partialPageOptions }));
|
|
304
|
-
return {
|
|
305
|
-
...result,
|
|
306
|
-
// eslint-disable-next-line deprecation/deprecation
|
|
307
|
-
items: result.items.map(DisplayValueGroup.fromJSON),
|
|
308
|
-
};
|
|
309
|
-
}
|
|
310
|
-
/**
|
|
311
|
-
* Retrieves property data in a simplified format for a single element specified by ID.
|
|
312
|
-
* @public
|
|
313
|
-
*/
|
|
314
|
-
async getElementProperties(requestOptions) {
|
|
315
|
-
await this.onConnection(requestOptions.imodel);
|
|
316
|
-
const results = await this._requestsHandler.getElementProperties(this.toRpcTokenOptions(requestOptions));
|
|
317
|
-
// istanbul ignore if
|
|
318
|
-
if (!results)
|
|
319
|
-
return undefined;
|
|
320
|
-
return this._localizationHelper.getLocalizedElementProperties(results);
|
|
321
|
-
}
|
|
322
|
-
/**
|
|
323
|
-
* Retrieves content item instance keys.
|
|
324
|
-
* @public
|
|
325
|
-
*/
|
|
326
|
-
async getContentInstanceKeys(requestOptions) {
|
|
327
|
-
await this.onConnection(requestOptions.imodel);
|
|
328
|
-
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
|
|
329
|
-
const rpcOptions = {
|
|
330
|
-
...this.toRpcTokenOptions(options),
|
|
331
|
-
keys: stripTransientElementKeys(options.keys).toJSON(),
|
|
332
|
-
};
|
|
333
|
-
const props = {
|
|
334
|
-
page: requestOptions.paging,
|
|
335
|
-
get: async (page) => {
|
|
336
|
-
const keys = await this._requestsHandler.getContentInstanceKeys({ ...rpcOptions, paging: page });
|
|
337
|
-
return {
|
|
338
|
-
total: keys.total,
|
|
339
|
-
items: keys.items.instanceKeys.reduce((instanceKeys, entry) => {
|
|
340
|
-
for (const id of CompressedId64Set.iterable(entry[1])) {
|
|
341
|
-
instanceKeys.push({ className: entry[0], id });
|
|
342
|
-
}
|
|
343
|
-
return instanceKeys;
|
|
344
|
-
}, new Array()),
|
|
345
|
-
};
|
|
346
|
-
},
|
|
347
|
-
};
|
|
348
|
-
return createPagedGeneratorResponse(props);
|
|
349
|
-
}
|
|
350
|
-
/** Retrieves display label definition of specific item. */
|
|
351
|
-
async getDisplayLabelDefinition(requestOptions) {
|
|
352
|
-
await this.onConnection(requestOptions.imodel);
|
|
353
|
-
const rpcOptions = this.toRpcTokenOptions({ ...requestOptions });
|
|
354
|
-
const result = await this._requestsHandler.getDisplayLabelDefinition(rpcOptions);
|
|
355
|
-
return this._localizationHelper.getLocalizedLabelDefinition(result);
|
|
356
|
-
}
|
|
357
|
-
/** Retrieves display label definition of specific items. */
|
|
358
|
-
async getDisplayLabelDefinitions(requestOptions) {
|
|
359
|
-
await this.onConnection(requestOptions.imodel);
|
|
360
|
-
const rpcOptions = this.toRpcTokenOptions({ ...requestOptions });
|
|
361
|
-
const result = await buildPagedArrayResponse(undefined, async (partialPageOptions) => {
|
|
362
|
-
const partialKeys = (!partialPageOptions.start) ? rpcOptions.keys : rpcOptions.keys.slice(partialPageOptions.start);
|
|
363
|
-
return this._requestsHandler.getPagedDisplayLabelDefinitions({ ...rpcOptions, keys: partialKeys });
|
|
364
|
-
});
|
|
365
|
-
return this._localizationHelper.getLocalizedLabelDefinitions(result.items);
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
const getDescriptorOverrides = (descriptorOrOverrides) => {
|
|
369
|
-
if (descriptorOrOverrides instanceof Descriptor)
|
|
370
|
-
return descriptorOrOverrides.createDescriptorOverrides();
|
|
371
|
-
return descriptorOrOverrides;
|
|
372
|
-
};
|
|
373
|
-
async function createPagedGeneratorResponse(props) {
|
|
374
|
-
var _a, _b, _c, _d;
|
|
375
|
-
let pageStart = (_b = (_a = props.page) === null || _a === void 0 ? void 0 : _a.start) !== null && _b !== void 0 ? _b : 0;
|
|
376
|
-
let pageSize = (_d = (_c = props.page) === null || _c === void 0 ? void 0 : _c.size) !== null && _d !== void 0 ? _d : 0;
|
|
377
|
-
let requestIndex = 0;
|
|
378
|
-
const firstPage = await props.get({ start: pageStart, size: pageSize }, requestIndex++);
|
|
379
|
-
return {
|
|
380
|
-
total: firstPage.total,
|
|
381
|
-
async *items() {
|
|
382
|
-
let partialResult = firstPage;
|
|
383
|
-
while (true) {
|
|
384
|
-
for (const item of partialResult.items) {
|
|
385
|
-
yield item;
|
|
386
|
-
}
|
|
387
|
-
const receivedItemsCount = partialResult.items.length;
|
|
388
|
-
if (partialResult.total !== 0 && receivedItemsCount === 0) {
|
|
389
|
-
if (pageStart >= partialResult.total)
|
|
390
|
-
throw new Error(`Requested page with start index ${pageStart} is out of bounds. Total number of items: ${partialResult.total}`);
|
|
391
|
-
throw new Error("Paged request returned non zero total count but no items");
|
|
392
|
-
}
|
|
393
|
-
if (pageSize !== 0 && receivedItemsCount >= pageSize || receivedItemsCount >= (partialResult.total - pageStart))
|
|
394
|
-
break;
|
|
395
|
-
if (pageSize !== 0)
|
|
396
|
-
pageSize -= receivedItemsCount;
|
|
397
|
-
pageStart += receivedItemsCount;
|
|
398
|
-
partialResult = await props.get({ start: pageStart, size: pageSize }, requestIndex++);
|
|
399
|
-
}
|
|
400
|
-
},
|
|
401
|
-
};
|
|
402
|
-
}
|
|
403
|
-
/** @internal */
|
|
404
|
-
export const buildPagedArrayResponse = async (requestedPage, getter) => {
|
|
405
|
-
try {
|
|
406
|
-
const items = new Array();
|
|
407
|
-
const gen = await createPagedGeneratorResponse({ page: requestedPage, get: getter });
|
|
408
|
-
for await (const item of gen.items()) {
|
|
409
|
-
items.push(item);
|
|
410
|
-
}
|
|
411
|
-
return { total: gen.total, items };
|
|
412
|
-
}
|
|
413
|
-
catch {
|
|
414
|
-
// FIXME: we should propagate the error...
|
|
415
|
-
return { total: 0, items: [] };
|
|
416
|
-
}
|
|
417
|
-
};
|
|
418
|
-
const stripTransientElementKeys = (keys) => {
|
|
419
|
-
if (!keys.some((key) => Key.isInstanceKey(key) && key.className === TRANSIENT_ELEMENT_CLASSNAME))
|
|
420
|
-
return keys;
|
|
421
|
-
const copy = new KeySet();
|
|
422
|
-
copy.add(keys, (key) => {
|
|
423
|
-
// the callback is not going to be called with EntityProps as KeySet converts them
|
|
424
|
-
// to InstanceKeys, but we want to keep the EntityProps case for correctness
|
|
425
|
-
// istanbul ignore next
|
|
426
|
-
const isTransient = Key.isInstanceKey(key) && key.className === TRANSIENT_ELEMENT_CLASSNAME
|
|
427
|
-
|| Key.isEntityProps(key) && key.classFullName === TRANSIENT_ELEMENT_CLASSNAME;
|
|
428
|
-
return !isTransient;
|
|
429
|
-
});
|
|
430
|
-
return copy;
|
|
431
|
-
};
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
3
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
|
5
|
+
/** @packageDocumentation
|
|
6
|
+
* @module Core
|
|
7
|
+
*/
|
|
8
|
+
import { BeEvent, CompressedId64Set, OrderedId64Iterable } from "@itwin/core-bentley";
|
|
9
|
+
import { IpcApp } from "@itwin/core-frontend";
|
|
10
|
+
import { Content, Descriptor, DisplayValueGroup, Item, Key, KeySet, Node, NodePathElement, PresentationIpcEvents, RpcRequestsHandler, RulesetVariable, SelectClassInfo, UpdateInfo, VariableValueTypes, } from "@itwin/presentation-common";
|
|
11
|
+
import { IpcRequestsHandler } from "./IpcRequestsHandler";
|
|
12
|
+
import { FrontendLocalizationHelper } from "./LocalizationHelper";
|
|
13
|
+
import { RulesetManagerImpl } from "./RulesetManager";
|
|
14
|
+
import { RulesetVariablesManagerImpl } from "./RulesetVariablesManager";
|
|
15
|
+
import { TRANSIENT_ELEMENT_CLASSNAME } from "./selection/SelectionManager";
|
|
16
|
+
import { StateTracker } from "./StateTracker";
|
|
17
|
+
/**
|
|
18
|
+
* Frontend Presentation manager which basically just forwards all calls to
|
|
19
|
+
* the backend implementation.
|
|
20
|
+
*
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
23
|
+
export class PresentationManager {
|
|
24
|
+
constructor(props) {
|
|
25
|
+
var _a, _b, _c;
|
|
26
|
+
/**
|
|
27
|
+
* An event raised when hierarchies created using specific ruleset change
|
|
28
|
+
* @alpha
|
|
29
|
+
*/
|
|
30
|
+
this.onIModelHierarchyChanged = new BeEvent();
|
|
31
|
+
/**
|
|
32
|
+
* An event raised when content created using specific ruleset changes
|
|
33
|
+
* @alpha
|
|
34
|
+
*/
|
|
35
|
+
this.onIModelContentChanged = new BeEvent();
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
37
|
+
this.onUpdate = (_evt, report) => {
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
39
|
+
this.handleUpdateAsync(UpdateInfo.fromJSON(report));
|
|
40
|
+
};
|
|
41
|
+
if (props) {
|
|
42
|
+
this.activeUnitSystem = props.activeUnitSystem;
|
|
43
|
+
}
|
|
44
|
+
this._requestsHandler = (_a = props === null || props === void 0 ? void 0 : props.rpcRequestsHandler) !== null && _a !== void 0 ? _a : new RpcRequestsHandler(props ? { clientId: props.clientId } : undefined);
|
|
45
|
+
this._rulesetVars = new Map();
|
|
46
|
+
this._rulesets = RulesetManagerImpl.create();
|
|
47
|
+
this._localizationHelper = new FrontendLocalizationHelper(props === null || props === void 0 ? void 0 : props.activeLocale);
|
|
48
|
+
this._connections = new Map();
|
|
49
|
+
if (IpcApp.isValid) {
|
|
50
|
+
// Ipc only works in ipc apps, so the `onUpdate` callback will only be called there.
|
|
51
|
+
this._clearEventListener = IpcApp.addListener(PresentationIpcEvents.Update, this.onUpdate);
|
|
52
|
+
this._ipcRequestsHandler = (_b = props === null || props === void 0 ? void 0 : props.ipcRequestsHandler) !== null && _b !== void 0 ? _b : new IpcRequestsHandler(this._requestsHandler.clientId);
|
|
53
|
+
this._stateTracker = (_c = props === null || props === void 0 ? void 0 : props.stateTracker) !== null && _c !== void 0 ? _c : new StateTracker(this._ipcRequestsHandler);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** Get / set active locale used for localizing presentation data */
|
|
57
|
+
get activeLocale() { return this._localizationHelper.locale; }
|
|
58
|
+
set activeLocale(locale) { this._localizationHelper.locale = locale; }
|
|
59
|
+
dispose() {
|
|
60
|
+
this._requestsHandler.dispose();
|
|
61
|
+
if (this._clearEventListener) {
|
|
62
|
+
this._clearEventListener();
|
|
63
|
+
this._clearEventListener = undefined;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async onConnection(imodel) {
|
|
67
|
+
if (!this._connections.has(imodel))
|
|
68
|
+
this._connections.set(imodel, this.initializeIModel(imodel));
|
|
69
|
+
await this._connections.get(imodel);
|
|
70
|
+
}
|
|
71
|
+
async initializeIModel(imodel) {
|
|
72
|
+
imodel.onClose.addOnce(() => {
|
|
73
|
+
this._connections.delete(imodel);
|
|
74
|
+
});
|
|
75
|
+
await this.onNewiModelConnection(imodel);
|
|
76
|
+
}
|
|
77
|
+
/** @note This is only called in native apps after changes in iModels */
|
|
78
|
+
async handleUpdateAsync(report) {
|
|
79
|
+
for (const imodelKey in report) {
|
|
80
|
+
// istanbul ignore if
|
|
81
|
+
if (!report.hasOwnProperty(imodelKey))
|
|
82
|
+
continue;
|
|
83
|
+
const imodelReport = report[imodelKey];
|
|
84
|
+
for (const rulesetId in imodelReport) {
|
|
85
|
+
// istanbul ignore if
|
|
86
|
+
if (!imodelReport.hasOwnProperty(rulesetId))
|
|
87
|
+
continue;
|
|
88
|
+
const updateInfo = imodelReport[rulesetId];
|
|
89
|
+
if (updateInfo.content)
|
|
90
|
+
this.onIModelContentChanged.raiseEvent({ rulesetId, updateInfo: updateInfo.content, imodelKey });
|
|
91
|
+
if (updateInfo.hierarchy)
|
|
92
|
+
this.onIModelHierarchyChanged.raiseEvent({ rulesetId, updateInfo: updateInfo.hierarchy, imodelKey });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/** Function that is called when a new IModelConnection is used to retrieve data.
|
|
97
|
+
* @internal
|
|
98
|
+
*/
|
|
99
|
+
async onNewiModelConnection(_) { }
|
|
100
|
+
/**
|
|
101
|
+
* Create a new PresentationManager instance
|
|
102
|
+
* @param props Optional properties used to configure the manager
|
|
103
|
+
*/
|
|
104
|
+
static create(props) {
|
|
105
|
+
return new PresentationManager(props);
|
|
106
|
+
}
|
|
107
|
+
/** @internal */
|
|
108
|
+
get rpcRequestsHandler() { return this._requestsHandler; }
|
|
109
|
+
/** @internal */
|
|
110
|
+
get ipcRequestsHandler() { return this._ipcRequestsHandler; }
|
|
111
|
+
/** @internal */
|
|
112
|
+
get stateTracker() { return this._stateTracker; }
|
|
113
|
+
/**
|
|
114
|
+
* Get rulesets manager
|
|
115
|
+
*/
|
|
116
|
+
rulesets() { return this._rulesets; }
|
|
117
|
+
/**
|
|
118
|
+
* Get ruleset variables manager for specific ruleset
|
|
119
|
+
* @param rulesetId Id of the ruleset to get the vars manager for
|
|
120
|
+
*/
|
|
121
|
+
vars(rulesetId) {
|
|
122
|
+
if (!this._rulesetVars.has(rulesetId)) {
|
|
123
|
+
const varsManager = new RulesetVariablesManagerImpl(rulesetId, this._ipcRequestsHandler);
|
|
124
|
+
this._rulesetVars.set(rulesetId, varsManager);
|
|
125
|
+
}
|
|
126
|
+
return this._rulesetVars.get(rulesetId);
|
|
127
|
+
}
|
|
128
|
+
toRpcTokenOptions(requestOptions) {
|
|
129
|
+
// 1. put default `locale` and `unitSystem`
|
|
130
|
+
// 2. put all `requestOptions` members (if `locale` or `unitSystem` are set, they'll override the defaults put at #1)
|
|
131
|
+
// 3. put `imodel` of type `IModelRpcProps` which overwrites the `imodel` from `requestOptions` put at #2
|
|
132
|
+
const defaultOptions = {};
|
|
133
|
+
if (this.activeLocale)
|
|
134
|
+
defaultOptions.locale = this.activeLocale;
|
|
135
|
+
if (this.activeUnitSystem)
|
|
136
|
+
defaultOptions.unitSystem = this.activeUnitSystem;
|
|
137
|
+
const { imodel, rulesetVariables, ...rpcRequestOptions } = requestOptions;
|
|
138
|
+
return {
|
|
139
|
+
...defaultOptions,
|
|
140
|
+
...rpcRequestOptions,
|
|
141
|
+
...(rulesetVariables ? { rulesetVariables: rulesetVariables.map(RulesetVariable.toJSON) } : {}),
|
|
142
|
+
imodel: imodel.getRpcProps(),
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
async addRulesetAndVariablesToOptions(options) {
|
|
146
|
+
const { rulesetOrId, rulesetVariables } = options;
|
|
147
|
+
let foundRulesetOrId;
|
|
148
|
+
if (typeof rulesetOrId === "object") {
|
|
149
|
+
foundRulesetOrId = rulesetOrId;
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
const foundRuleset = await this._rulesets.get(rulesetOrId);
|
|
153
|
+
foundRulesetOrId = foundRuleset ? foundRuleset.toJSON() : rulesetOrId;
|
|
154
|
+
}
|
|
155
|
+
const rulesetId = (typeof foundRulesetOrId === "object") ? foundRulesetOrId.id : foundRulesetOrId;
|
|
156
|
+
// All Id64Array variable values must be sorted for serialization to JSON to work. RulesetVariablesManager
|
|
157
|
+
// sorts them before storing, so that part is taken care of, but we need to ensure that variables coming from
|
|
158
|
+
// request options are also sorted.
|
|
159
|
+
const variables = (rulesetVariables !== null && rulesetVariables !== void 0 ? rulesetVariables : []).map((variable) => {
|
|
160
|
+
if (variable.type === VariableValueTypes.Id64Array)
|
|
161
|
+
return { ...variable, value: OrderedId64Iterable.sortArray(variable.value) };
|
|
162
|
+
return variable;
|
|
163
|
+
});
|
|
164
|
+
if (!this._ipcRequestsHandler) {
|
|
165
|
+
// only need to add variables from variables manager if there's no IPC
|
|
166
|
+
// handler - if there is one, the variables are already known by the backend
|
|
167
|
+
variables.push(...this.vars(rulesetId).getAllVariables());
|
|
168
|
+
}
|
|
169
|
+
return { ...options, rulesetOrId: foundRulesetOrId, rulesetVariables: variables };
|
|
170
|
+
}
|
|
171
|
+
/** Retrieves nodes */
|
|
172
|
+
async getNodes(requestOptions) {
|
|
173
|
+
await this.onConnection(requestOptions.imodel);
|
|
174
|
+
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
|
|
175
|
+
const rpcOptions = this.toRpcTokenOptions({ ...options });
|
|
176
|
+
const result = await buildPagedArrayResponse(options.paging, async (partialPageOptions) => this._requestsHandler.getPagedNodes({ ...rpcOptions, paging: partialPageOptions }));
|
|
177
|
+
// eslint-disable-next-line deprecation/deprecation
|
|
178
|
+
return this._localizationHelper.getLocalizedNodes(result.items.map(Node.fromJSON));
|
|
179
|
+
}
|
|
180
|
+
/** Retrieves nodes count. */
|
|
181
|
+
async getNodesCount(requestOptions) {
|
|
182
|
+
await this.onConnection(requestOptions.imodel);
|
|
183
|
+
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
|
|
184
|
+
const rpcOptions = this.toRpcTokenOptions({ ...options });
|
|
185
|
+
return this._requestsHandler.getNodesCount(rpcOptions);
|
|
186
|
+
}
|
|
187
|
+
/** Retrieves total nodes count and a single page of nodes. */
|
|
188
|
+
async getNodesAndCount(requestOptions) {
|
|
189
|
+
await this.onConnection(requestOptions.imodel);
|
|
190
|
+
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
|
|
191
|
+
const rpcOptions = this.toRpcTokenOptions({ ...options });
|
|
192
|
+
const result = await buildPagedArrayResponse(options.paging, async (partialPageOptions) => this._requestsHandler.getPagedNodes({ ...rpcOptions, paging: partialPageOptions }));
|
|
193
|
+
return {
|
|
194
|
+
count: result.total,
|
|
195
|
+
// eslint-disable-next-line deprecation/deprecation
|
|
196
|
+
nodes: this._localizationHelper.getLocalizedNodes(result.items.map(Node.fromJSON)),
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Retrieves hierarchy level descriptor.
|
|
201
|
+
* @beta
|
|
202
|
+
*/
|
|
203
|
+
async getNodesDescriptor(requestOptions) {
|
|
204
|
+
await this.onConnection(requestOptions.imodel);
|
|
205
|
+
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
|
|
206
|
+
const rpcOptions = this.toRpcTokenOptions({ ...options });
|
|
207
|
+
const result = await this._requestsHandler.getNodesDescriptor(rpcOptions);
|
|
208
|
+
return Descriptor.fromJSON(result);
|
|
209
|
+
}
|
|
210
|
+
/** Retrieves paths from root nodes to children nodes according to specified keys. Intersecting paths will be merged. */
|
|
211
|
+
async getNodePaths(requestOptions) {
|
|
212
|
+
await this.onConnection(requestOptions.imodel);
|
|
213
|
+
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
|
|
214
|
+
const rpcOptions = this.toRpcTokenOptions({ ...options });
|
|
215
|
+
const result = await this._requestsHandler.getNodePaths(rpcOptions);
|
|
216
|
+
// eslint-disable-next-line deprecation/deprecation
|
|
217
|
+
return result.map(NodePathElement.fromJSON);
|
|
218
|
+
}
|
|
219
|
+
/** Retrieves paths from root nodes to nodes containing filter text in their label. */
|
|
220
|
+
async getFilteredNodePaths(requestOptions) {
|
|
221
|
+
await this.onConnection(requestOptions.imodel);
|
|
222
|
+
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
|
|
223
|
+
const result = await this._requestsHandler.getFilteredNodePaths(this.toRpcTokenOptions(options));
|
|
224
|
+
// eslint-disable-next-line deprecation/deprecation
|
|
225
|
+
return result.map(NodePathElement.fromJSON);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Get information about the sources of content when building it for specific ECClasses. Sources involve classes of the primary select instance,
|
|
229
|
+
* its related instances for loading related and navigation properties.
|
|
230
|
+
* @public
|
|
231
|
+
*/
|
|
232
|
+
async getContentSources(requestOptions) {
|
|
233
|
+
await this.onConnection(requestOptions.imodel);
|
|
234
|
+
const rpcOptions = this.toRpcTokenOptions(requestOptions);
|
|
235
|
+
const result = await this._requestsHandler.getContentSources(rpcOptions);
|
|
236
|
+
return SelectClassInfo.listFromCompressedJSON(result.sources, result.classesMap);
|
|
237
|
+
}
|
|
238
|
+
/** Retrieves the content descriptor which describes the content and can be used to customize it. */
|
|
239
|
+
async getContentDescriptor(requestOptions) {
|
|
240
|
+
await this.onConnection(requestOptions.imodel);
|
|
241
|
+
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
|
|
242
|
+
const rpcOptions = this.toRpcTokenOptions({
|
|
243
|
+
...options,
|
|
244
|
+
keys: stripTransientElementKeys(options.keys).toJSON(),
|
|
245
|
+
});
|
|
246
|
+
const result = await this._requestsHandler.getContentDescriptor(rpcOptions);
|
|
247
|
+
return Descriptor.fromJSON(result);
|
|
248
|
+
}
|
|
249
|
+
/** Retrieves overall content set size. */
|
|
250
|
+
async getContentSetSize(requestOptions) {
|
|
251
|
+
await this.onConnection(requestOptions.imodel);
|
|
252
|
+
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
|
|
253
|
+
const rpcOptions = this.toRpcTokenOptions({
|
|
254
|
+
...options,
|
|
255
|
+
descriptor: getDescriptorOverrides(requestOptions.descriptor),
|
|
256
|
+
keys: stripTransientElementKeys(requestOptions.keys).toJSON(),
|
|
257
|
+
});
|
|
258
|
+
return this._requestsHandler.getContentSetSize(rpcOptions);
|
|
259
|
+
}
|
|
260
|
+
/** Retrieves content which consists of a content descriptor and a page of records. */
|
|
261
|
+
async getContent(requestOptions) {
|
|
262
|
+
var _a;
|
|
263
|
+
return (_a = (await this.getContentAndSize(requestOptions))) === null || _a === void 0 ? void 0 : _a.content;
|
|
264
|
+
}
|
|
265
|
+
/** Retrieves content set size and content which consists of a content descriptor and a page of records. */
|
|
266
|
+
async getContentAndSize(requestOptions) {
|
|
267
|
+
await this.onConnection(requestOptions.imodel);
|
|
268
|
+
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
|
|
269
|
+
const rpcOptions = this.toRpcTokenOptions({
|
|
270
|
+
...options,
|
|
271
|
+
descriptor: getDescriptorOverrides(requestOptions.descriptor),
|
|
272
|
+
keys: stripTransientElementKeys(requestOptions.keys).toJSON(),
|
|
273
|
+
});
|
|
274
|
+
let descriptor = (requestOptions.descriptor instanceof Descriptor) ? requestOptions.descriptor : undefined;
|
|
275
|
+
const result = await buildPagedArrayResponse(options.paging, async (partialPageOptions, requestIndex) => {
|
|
276
|
+
if (0 === requestIndex && !descriptor) {
|
|
277
|
+
const content = await this._requestsHandler.getPagedContent({ ...rpcOptions, paging: partialPageOptions });
|
|
278
|
+
if (content) {
|
|
279
|
+
descriptor = Descriptor.fromJSON(content.descriptor);
|
|
280
|
+
return content.contentSet;
|
|
281
|
+
}
|
|
282
|
+
return { total: 0, items: [] };
|
|
283
|
+
}
|
|
284
|
+
return this._requestsHandler.getPagedContentSet({ ...rpcOptions, paging: partialPageOptions });
|
|
285
|
+
});
|
|
286
|
+
if (!descriptor)
|
|
287
|
+
return undefined;
|
|
288
|
+
const items = result.items.map((itemJson) => Item.fromJSON(itemJson)).filter((item) => (item !== undefined));
|
|
289
|
+
return {
|
|
290
|
+
size: result.total,
|
|
291
|
+
content: this._localizationHelper.getLocalizedContent(new Content(descriptor, items)),
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
/** Retrieves distinct values of specific field from the content. */
|
|
295
|
+
async getPagedDistinctValues(requestOptions) {
|
|
296
|
+
await this.onConnection(requestOptions.imodel);
|
|
297
|
+
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
|
|
298
|
+
const rpcOptions = {
|
|
299
|
+
...this.toRpcTokenOptions(options),
|
|
300
|
+
descriptor: getDescriptorOverrides(options.descriptor),
|
|
301
|
+
keys: stripTransientElementKeys(options.keys).toJSON(),
|
|
302
|
+
};
|
|
303
|
+
const result = await buildPagedArrayResponse(requestOptions.paging, async (partialPageOptions) => this._requestsHandler.getPagedDistinctValues({ ...rpcOptions, paging: partialPageOptions }));
|
|
304
|
+
return {
|
|
305
|
+
...result,
|
|
306
|
+
// eslint-disable-next-line deprecation/deprecation
|
|
307
|
+
items: result.items.map(DisplayValueGroup.fromJSON),
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Retrieves property data in a simplified format for a single element specified by ID.
|
|
312
|
+
* @public
|
|
313
|
+
*/
|
|
314
|
+
async getElementProperties(requestOptions) {
|
|
315
|
+
await this.onConnection(requestOptions.imodel);
|
|
316
|
+
const results = await this._requestsHandler.getElementProperties(this.toRpcTokenOptions(requestOptions));
|
|
317
|
+
// istanbul ignore if
|
|
318
|
+
if (!results)
|
|
319
|
+
return undefined;
|
|
320
|
+
return this._localizationHelper.getLocalizedElementProperties(results);
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Retrieves content item instance keys.
|
|
324
|
+
* @public
|
|
325
|
+
*/
|
|
326
|
+
async getContentInstanceKeys(requestOptions) {
|
|
327
|
+
await this.onConnection(requestOptions.imodel);
|
|
328
|
+
const options = await this.addRulesetAndVariablesToOptions(requestOptions);
|
|
329
|
+
const rpcOptions = {
|
|
330
|
+
...this.toRpcTokenOptions(options),
|
|
331
|
+
keys: stripTransientElementKeys(options.keys).toJSON(),
|
|
332
|
+
};
|
|
333
|
+
const props = {
|
|
334
|
+
page: requestOptions.paging,
|
|
335
|
+
get: async (page) => {
|
|
336
|
+
const keys = await this._requestsHandler.getContentInstanceKeys({ ...rpcOptions, paging: page });
|
|
337
|
+
return {
|
|
338
|
+
total: keys.total,
|
|
339
|
+
items: keys.items.instanceKeys.reduce((instanceKeys, entry) => {
|
|
340
|
+
for (const id of CompressedId64Set.iterable(entry[1])) {
|
|
341
|
+
instanceKeys.push({ className: entry[0], id });
|
|
342
|
+
}
|
|
343
|
+
return instanceKeys;
|
|
344
|
+
}, new Array()),
|
|
345
|
+
};
|
|
346
|
+
},
|
|
347
|
+
};
|
|
348
|
+
return createPagedGeneratorResponse(props);
|
|
349
|
+
}
|
|
350
|
+
/** Retrieves display label definition of specific item. */
|
|
351
|
+
async getDisplayLabelDefinition(requestOptions) {
|
|
352
|
+
await this.onConnection(requestOptions.imodel);
|
|
353
|
+
const rpcOptions = this.toRpcTokenOptions({ ...requestOptions });
|
|
354
|
+
const result = await this._requestsHandler.getDisplayLabelDefinition(rpcOptions);
|
|
355
|
+
return this._localizationHelper.getLocalizedLabelDefinition(result);
|
|
356
|
+
}
|
|
357
|
+
/** Retrieves display label definition of specific items. */
|
|
358
|
+
async getDisplayLabelDefinitions(requestOptions) {
|
|
359
|
+
await this.onConnection(requestOptions.imodel);
|
|
360
|
+
const rpcOptions = this.toRpcTokenOptions({ ...requestOptions });
|
|
361
|
+
const result = await buildPagedArrayResponse(undefined, async (partialPageOptions) => {
|
|
362
|
+
const partialKeys = (!partialPageOptions.start) ? rpcOptions.keys : rpcOptions.keys.slice(partialPageOptions.start);
|
|
363
|
+
return this._requestsHandler.getPagedDisplayLabelDefinitions({ ...rpcOptions, keys: partialKeys });
|
|
364
|
+
});
|
|
365
|
+
return this._localizationHelper.getLocalizedLabelDefinitions(result.items);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
const getDescriptorOverrides = (descriptorOrOverrides) => {
|
|
369
|
+
if (descriptorOrOverrides instanceof Descriptor)
|
|
370
|
+
return descriptorOrOverrides.createDescriptorOverrides();
|
|
371
|
+
return descriptorOrOverrides;
|
|
372
|
+
};
|
|
373
|
+
async function createPagedGeneratorResponse(props) {
|
|
374
|
+
var _a, _b, _c, _d;
|
|
375
|
+
let pageStart = (_b = (_a = props.page) === null || _a === void 0 ? void 0 : _a.start) !== null && _b !== void 0 ? _b : 0;
|
|
376
|
+
let pageSize = (_d = (_c = props.page) === null || _c === void 0 ? void 0 : _c.size) !== null && _d !== void 0 ? _d : 0;
|
|
377
|
+
let requestIndex = 0;
|
|
378
|
+
const firstPage = await props.get({ start: pageStart, size: pageSize }, requestIndex++);
|
|
379
|
+
return {
|
|
380
|
+
total: firstPage.total,
|
|
381
|
+
async *items() {
|
|
382
|
+
let partialResult = firstPage;
|
|
383
|
+
while (true) {
|
|
384
|
+
for (const item of partialResult.items) {
|
|
385
|
+
yield item;
|
|
386
|
+
}
|
|
387
|
+
const receivedItemsCount = partialResult.items.length;
|
|
388
|
+
if (partialResult.total !== 0 && receivedItemsCount === 0) {
|
|
389
|
+
if (pageStart >= partialResult.total)
|
|
390
|
+
throw new Error(`Requested page with start index ${pageStart} is out of bounds. Total number of items: ${partialResult.total}`);
|
|
391
|
+
throw new Error("Paged request returned non zero total count but no items");
|
|
392
|
+
}
|
|
393
|
+
if (pageSize !== 0 && receivedItemsCount >= pageSize || receivedItemsCount >= (partialResult.total - pageStart))
|
|
394
|
+
break;
|
|
395
|
+
if (pageSize !== 0)
|
|
396
|
+
pageSize -= receivedItemsCount;
|
|
397
|
+
pageStart += receivedItemsCount;
|
|
398
|
+
partialResult = await props.get({ start: pageStart, size: pageSize }, requestIndex++);
|
|
399
|
+
}
|
|
400
|
+
},
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
/** @internal */
|
|
404
|
+
export const buildPagedArrayResponse = async (requestedPage, getter) => {
|
|
405
|
+
try {
|
|
406
|
+
const items = new Array();
|
|
407
|
+
const gen = await createPagedGeneratorResponse({ page: requestedPage, get: getter });
|
|
408
|
+
for await (const item of gen.items()) {
|
|
409
|
+
items.push(item);
|
|
410
|
+
}
|
|
411
|
+
return { total: gen.total, items };
|
|
412
|
+
}
|
|
413
|
+
catch {
|
|
414
|
+
// FIXME: we should propagate the error...
|
|
415
|
+
return { total: 0, items: [] };
|
|
416
|
+
}
|
|
417
|
+
};
|
|
418
|
+
const stripTransientElementKeys = (keys) => {
|
|
419
|
+
if (!keys.some((key) => Key.isInstanceKey(key) && key.className === TRANSIENT_ELEMENT_CLASSNAME))
|
|
420
|
+
return keys;
|
|
421
|
+
const copy = new KeySet();
|
|
422
|
+
copy.add(keys, (key) => {
|
|
423
|
+
// the callback is not going to be called with EntityProps as KeySet converts them
|
|
424
|
+
// to InstanceKeys, but we want to keep the EntityProps case for correctness
|
|
425
|
+
// istanbul ignore next
|
|
426
|
+
const isTransient = Key.isInstanceKey(key) && key.className === TRANSIENT_ELEMENT_CLASSNAME
|
|
427
|
+
|| Key.isEntityProps(key) && key.classFullName === TRANSIENT_ELEMENT_CLASSNAME;
|
|
428
|
+
return !isTransient;
|
|
429
|
+
});
|
|
430
|
+
return copy;
|
|
431
|
+
};
|
|
432
432
|
//# sourceMappingURL=PresentationManager.js.map
|