@disy/cadenza.js 2.2.3 β 2.3.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.
- package/CHANGELOG.md +15 -4
- package/README.md +1 -322
- package/apidoc/assets/highlight.css +0 -7
- package/apidoc/assets/main.js +2 -2
- package/apidoc/assets/navigation.js +1 -1
- package/apidoc/assets/search.js +1 -1
- package/apidoc/assets/style.css +46 -15
- package/apidoc/classes/AbortError.html +3 -3
- package/apidoc/classes/CadenzaClient.html +68 -89
- package/apidoc/classes/CadenzaError.html +8 -6
- package/apidoc/functions/cadenza.html +4 -4
- package/apidoc/index.html +152 -9
- package/apidoc/interfaces/CadenzaEvent.html +6 -6
- package/apidoc/interfaces/ExternalLinkKey.html +6 -3
- package/apidoc/interfaces/Geometry.html +2 -2
- package/apidoc/interfaces/PageSource.html +2 -2
- package/apidoc/modules.html +14 -2
- package/apidoc/types/CadenzaChangeSelectionEvent.html +2 -0
- package/apidoc/types/CadenzaDrillThroughEvent.html +7 -0
- package/apidoc/types/CadenzaEditGeometryCancelEvent.html +2 -0
- package/apidoc/types/CadenzaEditGeometryOkEvent.html +2 -0
- package/apidoc/types/CadenzaEditGeometryUpdateEvent.html +2 -0
- package/apidoc/types/CadenzaErrorEvent.html +2 -2
- package/apidoc/types/CadenzaEventByType.html +1 -0
- package/apidoc/types/CadenzaEventType.html +2 -0
- package/apidoc/types/CadenzaObjectInfoEvent.html +2 -0
- package/apidoc/types/CadenzaSelectObjectsCancelEvent.html +2 -0
- package/apidoc/types/CadenzaSelectObjectsOkEvent.html +2 -0
- package/apidoc/types/DataType.html +3 -2
- package/apidoc/types/EmbeddingTargetId.html +9 -2
- package/apidoc/types/Extent.html +1 -1
- package/apidoc/types/FilterVariables.html +5 -2
- package/apidoc/types/GeometryType.html +1 -1
- package/apidoc/types/GlobalId.html +2 -2
- package/apidoc/types/OpaqueString.html +6 -0
- package/apidoc/types/OperationMode.html +1 -1
- package/apidoc/types/TablePart.html +1 -1
- package/apidoc/types/UiFeature.html +3 -3
- package/apidoc/types/WorkbookLayerPath.html +3 -0
- package/cadenza.d.ts +320 -56
- package/cadenza.js +344 -69
- package/package.json +6 -6
- package/sandbox.html +197 -31
package/cadenza.js
CHANGED
|
@@ -24,13 +24,42 @@ globalThis.cadenza = Object.assign((/** @type Parameters<cadenza> */ ...args) =>
|
|
|
24
24
|
return cadenza;
|
|
25
25
|
},
|
|
26
26
|
});
|
|
27
|
-
/**
|
|
28
|
-
|
|
27
|
+
/**
|
|
28
|
+
* @template {string} T
|
|
29
|
+
* @typedef {string & {__type: T}} OpaqueString - A specific `string` type that is not assignable from another string
|
|
30
|
+
*
|
|
31
|
+
* The idea is to have a specific type e.g. for the {@link EmbeddingTargetId} instead of a plain `string`.
|
|
32
|
+
* You don't need to _actually_ add that `__type` property. In TS code, just use a
|
|
33
|
+
* [type assertion](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-assertions)
|
|
34
|
+
* (e.g. `cadenzaClient.show('{embeddingTargetId}' as EmbeddingTargetId)`).
|
|
35
|
+
*/
|
|
36
|
+
/**
|
|
37
|
+
* @typedef {OpaqueString<'EmbeddingTargetId'>} EmbeddingTargetId - The ID of a Cadenza embedding target
|
|
38
|
+
*
|
|
39
|
+
* Embedding targets are called π©πͺ "Einbettbarer Inhalt" / πΊπΈ "Embeddable content" throughout the Cadenza UI and help.
|
|
40
|
+
* They're managed within the respective workbook:
|
|
41
|
+
*
|
|
42
|
+
* - π©πͺ "Mehr" > "Arbeitsmappe verwalten" > "Einbettung"
|
|
43
|
+
* - πΊπΈ "More" > "Manage workbook" > "Embedding"
|
|
44
|
+
*
|
|
45
|
+
* The name of an embedding target (as entered in the UI) is its ID.
|
|
46
|
+
*/
|
|
47
|
+
/** @typedef {OpaqueString<'GlobalId'>} GlobalId - The ID of a navigator item */
|
|
29
48
|
/**
|
|
30
49
|
* @typedef ExternalLinkKey - A tuple qualifying a Cadenza external link
|
|
50
|
+
*
|
|
51
|
+
* You get the `repositoryName` and `externalLinkId` from the URL of the external link's page in the Cadenza management center:
|
|
52
|
+
* ```
|
|
53
|
+
* {baseUrl}/admin/repositories/{repositoryName}/external-links/{externalLinkId}?...
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
31
56
|
* @property {string} repositoryName - The name of the link's repository
|
|
32
57
|
* @property {string} externalLinkId - The ID of the external link
|
|
33
58
|
*/
|
|
59
|
+
/**
|
|
60
|
+
* @typedef {string[]} WorkbookLayerPath - Identifies a layer within a workbook map view
|
|
61
|
+
* using the print names of the layer and - if the layer is grouped - its ancestors
|
|
62
|
+
*/
|
|
34
63
|
/**
|
|
35
64
|
* @typedef PageSource - A well-known Cadenza page
|
|
36
65
|
* @property {'welcome'} page - The name of the page (Only `"welcome"` is currently supported.)
|
|
@@ -40,8 +69,8 @@ globalThis.cadenza = Object.assign((/** @type Parameters<cadenza> */ ...args) =>
|
|
|
40
69
|
* @typedef {'workbook-design'|'workbook-view-management'} UiFeature - The name of a Cadenza UI feature
|
|
41
70
|
*
|
|
42
71
|
* _Note:_ Supported features are:
|
|
43
|
-
* *
|
|
44
|
-
* *
|
|
72
|
+
* * `"workbook-design"` - The workbook designer
|
|
73
|
+
* * `"workbook-view-management"` - Add/Edit/Remove workbook views (Is included in 'workbook-design'.)
|
|
45
74
|
* */
|
|
46
75
|
/**
|
|
47
76
|
* @typedef Geometry - A [GeoJSON](https://geojson.org/) geometry object
|
|
@@ -53,9 +82,20 @@ globalThis.cadenza = Object.assign((/** @type Parameters<cadenza> */ ...args) =>
|
|
|
53
82
|
* _Note:_ The GeoJSON geometry type "GeometryCollection" is currently not supported.
|
|
54
83
|
*/
|
|
55
84
|
/** @typedef {[number,number,number,number]} Extent - An array of numbers representing an extent: [minx, miny, maxx, maxy] */
|
|
56
|
-
/**
|
|
85
|
+
/**
|
|
86
|
+
* @typedef {'csv' | 'excel' | 'json' | 'pdf' | 'png'} DataType - A data type
|
|
87
|
+
*
|
|
88
|
+
* See [JSON Representation of Cadenza Object Data](../index.html#md:json-representation-of-cadenza-object-data) for JSON data.
|
|
89
|
+
*/
|
|
57
90
|
/** @typedef {'columns' | 'values' | 'totals'} TablePart - A part of a table to export */
|
|
58
|
-
/**
|
|
91
|
+
/**
|
|
92
|
+
* @typedef {Record<string, string | string[] | number | Date | null>} FilterVariables - Filter variable names and values
|
|
93
|
+
*
|
|
94
|
+
* Variables of type String, Integer, Long, Double and Date can be set.
|
|
95
|
+
*
|
|
96
|
+
* _Note:_ Since numbers in JavaScript are Double values ([more info on MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number#number_encoding)),
|
|
97
|
+
* for Long variables, the API is currently limited to the Double value range.
|
|
98
|
+
*/
|
|
59
99
|
/**
|
|
60
100
|
* _Notes:_
|
|
61
101
|
* * Most public methods can be aborted using an [AbortSignal](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal).
|
|
@@ -78,7 +118,7 @@ export class CadenzaClient {
|
|
|
78
118
|
#iframeElement;
|
|
79
119
|
/** @readonly */
|
|
80
120
|
#debug;
|
|
81
|
-
/** @type {[ string, (event: CadenzaEvent<never>) => void ][]} */
|
|
121
|
+
/** @type {[ CadenzaEventType | string, (event: CadenzaEvent<never>) => void ][]} */
|
|
82
122
|
#subscriptions = [];
|
|
83
123
|
/**
|
|
84
124
|
* @hidden
|
|
@@ -142,15 +182,12 @@ export class CadenzaClient {
|
|
|
142
182
|
* @param {String} [options.labelSet] - The name of a label set defined in the `basicweb-config.xml` (only supported for the welcome page)
|
|
143
183
|
* @param {OperationMode} [options.operationMode] - The mode in which a workbook should be operated
|
|
144
184
|
* @param {AbortSignal} [options.signal] - A signal to abort the iframe loading
|
|
145
|
-
* @return {Promise<void>} A Promise for when the iframe is loaded
|
|
185
|
+
* @return {Promise<void>} A `Promise` for when the iframe is loaded
|
|
146
186
|
* @throws For invalid arguments
|
|
147
|
-
* @fires
|
|
148
|
-
* The event includes a row of values for each row in the workbook selection, each row consisting of the values of
|
|
149
|
-
* the attributes that were selected for the POST message content. If the drill-through was executed from a map
|
|
150
|
-
* view, each row includes the geometry of the select object as the last value.
|
|
187
|
+
* @fires {@link CadenzaDrillThroughEvent}
|
|
151
188
|
*/
|
|
152
189
|
show(source, { dataType, disabledUiFeatures, expandNavigator, filter, hideMainHeaderAndFooter, hideWorkbookToolBar, highlightGlobalId, labelSet, operationMode, signal, } = {}) {
|
|
153
|
-
this.#log('CadenzaClient#show',
|
|
190
|
+
this.#log('CadenzaClient#show', ...arguments);
|
|
154
191
|
if (dataType) {
|
|
155
192
|
assertSupportedDataType(dataType, ['pdf']);
|
|
156
193
|
}
|
|
@@ -169,7 +206,6 @@ export class CadenzaClient {
|
|
|
169
206
|
labelSet,
|
|
170
207
|
dataType,
|
|
171
208
|
operationMode,
|
|
172
|
-
webApplication: this.#webApplication,
|
|
173
209
|
});
|
|
174
210
|
return this.#show(resolvePath(source), params, signal);
|
|
175
211
|
}
|
|
@@ -190,14 +226,12 @@ export class CadenzaClient {
|
|
|
190
226
|
* @param {OperationMode} [options.operationMode] - The mode in which a workbook should be operated
|
|
191
227
|
* @param {boolean} [options.useMapSrs] - Whether the geometry and the extent are in the map's SRS (otherwise EPSG:4326 is assumed)
|
|
192
228
|
* @param {AbortSignal} [options.signal] - A signal to abort the iframe loading
|
|
193
|
-
* @return {Promise<void>} A Promise for when the iframe is loaded
|
|
229
|
+
* @return {Promise<void>} A `Promise` for when the iframe is loaded
|
|
194
230
|
* @throws For invalid arguments
|
|
195
|
-
* @fires
|
|
196
|
-
* The event includes a row of values for each row in the workbook selection, each row consisting of the values of
|
|
197
|
-
* the attributes that were selected for the POST message content plus the geometry of the select object as the last value.
|
|
231
|
+
* @fires {@link CadenzaDrillThroughEvent}
|
|
198
232
|
*/
|
|
199
233
|
async showMap(mapView, { disabledUiFeatures, expandNavigator, filter, geometry, hideMainHeaderAndFooter, hideWorkbookToolBar, highlightGlobalId, locationFinder, mapExtent, operationMode, useMapSrs, signal, } = {}) {
|
|
200
|
-
this.#log('CadenzaClient#showMap',
|
|
234
|
+
this.#log('CadenzaClient#showMap', ...arguments);
|
|
201
235
|
if (geometry) {
|
|
202
236
|
assertValidGeometryType(geometry.type);
|
|
203
237
|
}
|
|
@@ -211,11 +245,13 @@ export class CadenzaClient {
|
|
|
211
245
|
locationFinder,
|
|
212
246
|
mapExtent,
|
|
213
247
|
operationMode,
|
|
248
|
+
targetType: 'MAP',
|
|
214
249
|
useMapSrs,
|
|
215
|
-
webApplication: this.#webApplication,
|
|
216
250
|
});
|
|
217
251
|
await this.#show(resolvePath(mapView), params, signal);
|
|
218
|
-
|
|
252
|
+
if (geometry) {
|
|
253
|
+
this.#postEvent('setGeometry', { geometry });
|
|
254
|
+
}
|
|
219
255
|
}
|
|
220
256
|
/**
|
|
221
257
|
* Expand/collapse the navigator.
|
|
@@ -223,9 +259,93 @@ export class CadenzaClient {
|
|
|
223
259
|
* @param {boolean} expanded - The expansion state of the navigator
|
|
224
260
|
*/
|
|
225
261
|
expandNavigator(expanded = true) {
|
|
226
|
-
this.#log('CadenzaClient#expandNavigator',
|
|
262
|
+
this.#log('CadenzaClient#expandNavigator', ...arguments);
|
|
227
263
|
this.#postEvent('expandNavigator', { expandNavigator: Boolean(expanded) });
|
|
228
264
|
}
|
|
265
|
+
/**
|
|
266
|
+
* Get data from the currently shown workbook view.
|
|
267
|
+
*
|
|
268
|
+
* Currently, only map views are supported.
|
|
269
|
+
*
|
|
270
|
+
* @hidden
|
|
271
|
+
* @template {DataType} T
|
|
272
|
+
* @param {T} dataType - The requested data type. Currently, only `"png"` is supported.
|
|
273
|
+
* @return {Promise<T extends 'png' ? Blob : never>}
|
|
274
|
+
*/
|
|
275
|
+
async getData(dataType) {
|
|
276
|
+
this.#log('CadenzaClient#getData', ...arguments);
|
|
277
|
+
assertSupportedDataType(dataType, ['png']);
|
|
278
|
+
return this.#postRequest('getData', { dataType });
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Set filter variables in the currently shown workbook.
|
|
282
|
+
*
|
|
283
|
+
* @hidden
|
|
284
|
+
* @param {FilterVariables} filter - The variable values
|
|
285
|
+
* @return {Promise<void>} A `Promise` for when the filter variables were set.
|
|
286
|
+
*/
|
|
287
|
+
setFilter(filter) {
|
|
288
|
+
this.#log('CadenzaClient#setFilter', ...arguments);
|
|
289
|
+
return this.#postRequest('setFilter', { filter });
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Set the visibility of a layer in the currently shown workbook map view.
|
|
293
|
+
*
|
|
294
|
+
* When making a layer visible, its ancestors will be made visible, too.
|
|
295
|
+
* When hiding a layer, the ancestors are not affected.
|
|
296
|
+
*
|
|
297
|
+
* @hidden
|
|
298
|
+
* @param {WorkbookLayerPath | string} layer - The layer to show or hide
|
|
299
|
+
* (identified using a layer path or a print name)
|
|
300
|
+
* @param {boolean} visible - The visibility state of the layer
|
|
301
|
+
* @return {Promise<void>} A `Promise` for when the layer visibility was set.
|
|
302
|
+
*/
|
|
303
|
+
setLayerVisibility(layer, visible) {
|
|
304
|
+
this.#log('CadenzaClient#setLayerVisibility', ...arguments);
|
|
305
|
+
return this.#postRequest('setLayerVisibility', {
|
|
306
|
+
layer: array(layer),
|
|
307
|
+
visible,
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Set the selection in the currently shown workbook map view.
|
|
312
|
+
*
|
|
313
|
+
* @hidden
|
|
314
|
+
* @param {WorkbookLayerPath | string} layer - The data view layer to set the selection in
|
|
315
|
+
* @param {unknown[]} values - The IDs of the objects to select
|
|
316
|
+
* @return {Promise<void>} A `Promise` for when the selection was set.
|
|
317
|
+
*/
|
|
318
|
+
setSelection(layer, values) {
|
|
319
|
+
this.#log('CadenzaClient#setSelection', ...arguments);
|
|
320
|
+
return this.#postRequest('setSelection', { layer: array(layer), values });
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Add to the selection in the currently shown workbook map view.
|
|
324
|
+
*
|
|
325
|
+
* @hidden
|
|
326
|
+
* @param {WorkbookLayerPath | string} layer - The data view layer to change the selection in
|
|
327
|
+
* @param {unknown[]} values - The IDs of the objects to select
|
|
328
|
+
* @return {Promise<void>} A `Promise` for when the selection was changed.
|
|
329
|
+
*/
|
|
330
|
+
addSelection(layer, values) {
|
|
331
|
+
this.#log('CadenzaClient#addSelection', ...arguments);
|
|
332
|
+
return this.#postRequest('addSelection', { layer: array(layer), values });
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Remove from the selection in the currently shown workbook map view.
|
|
336
|
+
*
|
|
337
|
+
* @hidden
|
|
338
|
+
* @param {WorkbookLayerPath | string} layer - The data view layer to change the selection in
|
|
339
|
+
* @param {unknown[]} values - The IDs of the objects to unselect
|
|
340
|
+
* @return {Promise<void>} A `Promise` for when the selection was changed.
|
|
341
|
+
*/
|
|
342
|
+
removeSelection(layer, values) {
|
|
343
|
+
this.#log('CadenzaClient#removeSelection', ...arguments);
|
|
344
|
+
return this.#postRequest('removeSelection', {
|
|
345
|
+
layer: array(layer),
|
|
346
|
+
values,
|
|
347
|
+
});
|
|
348
|
+
}
|
|
229
349
|
/**
|
|
230
350
|
* Create a geometry.
|
|
231
351
|
*
|
|
@@ -240,14 +360,15 @@ export class CadenzaClient {
|
|
|
240
360
|
* @param {number} [options.minScale] - The minimum scale where the user should work on. A warning is shown when the map is zoomed out above the threshold.
|
|
241
361
|
* @param {boolean} [options.useMapSrs] - Whether the created geometry should use the map's SRS (otherwise EPSG:4326 will be used)
|
|
242
362
|
* @param {AbortSignal} [options.signal] - A signal to abort the iframe loading
|
|
243
|
-
* @return {Promise<void>} A Promise for when the iframe is loaded
|
|
363
|
+
* @return {Promise<void>} A `Promise` for when the iframe is loaded
|
|
244
364
|
* @throws For invalid arguments
|
|
245
|
-
* @fires
|
|
246
|
-
*
|
|
247
|
-
*
|
|
365
|
+
* @fires
|
|
366
|
+
* - {@link CadenzaEditGeometryUpdateEvent}
|
|
367
|
+
* - {@link CadenzaEditGeometryOkEvent}
|
|
368
|
+
* - {@link CadenzaEditGeometryCancelEvent}
|
|
248
369
|
*/
|
|
249
370
|
createGeometry(backgroundMapView, geometryType, { locationFinder, mapExtent, minScale, useMapSrs, signal } = {}) {
|
|
250
|
-
this.#log('CadenzaClient#createGeometry',
|
|
371
|
+
this.#log('CadenzaClient#createGeometry', ...arguments);
|
|
251
372
|
const params = createParams({
|
|
252
373
|
action: 'editGeometry',
|
|
253
374
|
geometryType,
|
|
@@ -255,7 +376,6 @@ export class CadenzaClient {
|
|
|
255
376
|
mapExtent,
|
|
256
377
|
minScale,
|
|
257
378
|
useMapSrs,
|
|
258
|
-
webApplication: this.#webApplication,
|
|
259
379
|
});
|
|
260
380
|
return this.#show(resolvePath(backgroundMapView), params, signal);
|
|
261
381
|
}
|
|
@@ -270,14 +390,15 @@ export class CadenzaClient {
|
|
|
270
390
|
* @param {number} [options.minScale] - The minimum scale where the user should work on. A warning is shown when the map is zoomed out above the threshold.
|
|
271
391
|
* @param {boolean} [options.useMapSrs] - Whether the geometry is in the map's SRS (otherwise EPSG:4326 is assumed)
|
|
272
392
|
* @param {AbortSignal} [options.signal] - A signal to abort the iframe loading
|
|
273
|
-
* @return {Promise<void>} A Promise for when the iframe is loaded
|
|
393
|
+
* @return {Promise<void>} A `Promise` for when the iframe is loaded
|
|
274
394
|
* @throws For invalid arguments
|
|
275
|
-
* @fires
|
|
276
|
-
*
|
|
277
|
-
*
|
|
395
|
+
* @fires
|
|
396
|
+
* - {@link CadenzaEditGeometryUpdateEvent}
|
|
397
|
+
* - {@link CadenzaEditGeometryOkEvent}
|
|
398
|
+
* - {@link CadenzaEditGeometryCancelEvent}
|
|
278
399
|
*/
|
|
279
400
|
async editGeometry(backgroundMapView, geometry, { locationFinder, mapExtent, minScale, useMapSrs, signal } = {}) {
|
|
280
|
-
this.#log('CadenzaClient#editGeometry',
|
|
401
|
+
this.#log('CadenzaClient#editGeometry', ...arguments);
|
|
281
402
|
assertValidGeometryType(geometry.type);
|
|
282
403
|
const params = createParams({
|
|
283
404
|
action: 'editGeometry',
|
|
@@ -285,15 +406,51 @@ export class CadenzaClient {
|
|
|
285
406
|
mapExtent,
|
|
286
407
|
minScale,
|
|
287
408
|
useMapSrs,
|
|
288
|
-
webApplication: this.#webApplication,
|
|
289
409
|
});
|
|
290
410
|
await this.#show(resolvePath(backgroundMapView), params, signal);
|
|
291
|
-
|
|
411
|
+
if (geometry) {
|
|
412
|
+
this.#postEvent('setGeometry', { geometry });
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Select objects in a workbook map.
|
|
417
|
+
*
|
|
418
|
+
* @param {EmbeddingTargetId} backgroundMapView - The workbook map view
|
|
419
|
+
* @param {object} [options] - Options
|
|
420
|
+
* @param {(WorkbookLayerPath | string)[]} [options.layers] - Layers to restrict the selection to
|
|
421
|
+
* (identified using layer paths or print names)
|
|
422
|
+
* @param {string} [options.locationFinder] - A search query for the location finder
|
|
423
|
+
* @param {Extent} [options.mapExtent] - A map extent to set
|
|
424
|
+
* @param {boolean} [options.useMapSrs] - Whether the geometry is in the map's SRS (otherwise EPSG:4326 is assumed)
|
|
425
|
+
* @param {AbortSignal} [options.signal] - A signal to abort the iframe loading
|
|
426
|
+
* @return {Promise<void>} A `Promise` for when the iframe is loaded
|
|
427
|
+
* @throws For invalid arguments
|
|
428
|
+
* @fires
|
|
429
|
+
* - {@link CadenzaChangeSelectionEvent}
|
|
430
|
+
* - {@link CadenzaObjectInfoEvent}
|
|
431
|
+
* - {@link CadenzaSelectObjectsOkEvent}
|
|
432
|
+
* - {@link CadenzaSelectObjectsCancelEvent}
|
|
433
|
+
*/
|
|
434
|
+
selectObjects(backgroundMapView, { layers, locationFinder, mapExtent, useMapSrs, signal } = {}) {
|
|
435
|
+
this.#log('CadenzaClient#selectObjects', ...arguments);
|
|
436
|
+
const params = createParams({
|
|
437
|
+
action: 'selectObjects',
|
|
438
|
+
layers: layers?.map(array),
|
|
439
|
+
locationFinder,
|
|
440
|
+
mapExtent,
|
|
441
|
+
useMapSrs,
|
|
442
|
+
});
|
|
443
|
+
return this.#show(resolvePath(backgroundMapView), params, signal);
|
|
292
444
|
}
|
|
293
445
|
#show(
|
|
294
446
|
/** @type string */ path,
|
|
295
447
|
/** @type URLSearchParams */ params,
|
|
296
448
|
/** @type AbortSignal | undefined */ signal) {
|
|
449
|
+
const webApplication = this.#webApplication;
|
|
450
|
+
if (webApplication) {
|
|
451
|
+
params.set('webApplicationLink', webApplication.externalLinkId);
|
|
452
|
+
params.set('webApplicationLinkRepository', webApplication.repositoryName);
|
|
453
|
+
}
|
|
297
454
|
const url = this.#createUrl(path, params);
|
|
298
455
|
this.#log('Load iframe', url.toString());
|
|
299
456
|
this.#requiredIframe.src = url.toString();
|
|
@@ -301,14 +458,14 @@ export class CadenzaClient {
|
|
|
301
458
|
}
|
|
302
459
|
#getIframePromise(/** @type AbortSignal | undefined */ signal) {
|
|
303
460
|
const iframe = this.#requiredIframe;
|
|
304
|
-
/** @type {
|
|
461
|
+
/** @type {EventListener} */
|
|
305
462
|
let onerror;
|
|
306
|
-
/** @type {
|
|
463
|
+
/** @type {EventListener} */
|
|
307
464
|
let onabort;
|
|
308
465
|
/** @type {(() => void)[]} */
|
|
309
466
|
let unsubscribes;
|
|
310
467
|
/** @type {Promise<void>} */
|
|
311
|
-
|
|
468
|
+
const promise = new Promise((resolve, reject) => {
|
|
312
469
|
onerror = () => reject(new CadenzaError('loading-error', 'Loading failed'));
|
|
313
470
|
iframe.addEventListener('error', onerror);
|
|
314
471
|
if (signal) {
|
|
@@ -319,8 +476,8 @@ export class CadenzaClient {
|
|
|
319
476
|
signal.addEventListener('abort', onabort);
|
|
320
477
|
}
|
|
321
478
|
unsubscribes = [
|
|
322
|
-
this
|
|
323
|
-
this
|
|
479
|
+
this.#on('ready', () => resolve()),
|
|
480
|
+
this.#on('error', (/** @type {CadenzaErrorEvent} */ event) => {
|
|
324
481
|
const { type, message } = event.detail;
|
|
325
482
|
reject(new CadenzaError(type, message ?? 'Loading failed'));
|
|
326
483
|
}),
|
|
@@ -338,17 +495,30 @@ export class CadenzaClient {
|
|
|
338
495
|
/**
|
|
339
496
|
* Subscribe to a `postMessage()` event.
|
|
340
497
|
*
|
|
341
|
-
* @template
|
|
342
|
-
* @param {
|
|
343
|
-
* @param {(event: CadenzaEvent<
|
|
498
|
+
* @template {CadenzaEventType} TYPE
|
|
499
|
+
* @param {TYPE} type - The event type
|
|
500
|
+
* @param {(event: CadenzaEvent<TYPE, CadenzaEventByType<TYPE>['detail']>) => void} subscriber - The subscriber function
|
|
344
501
|
* @return {() => void} An unsubscribe function
|
|
345
502
|
*/
|
|
346
503
|
on(type, subscriber) {
|
|
504
|
+
return this.#on(type, subscriber);
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* @template {CadenzaEventType | string} TYPE
|
|
508
|
+
* @template [DETAIL=unknown]
|
|
509
|
+
* @param {TYPE} type
|
|
510
|
+
* @param {(event: CadenzaEvent<TYPE, DETAIL>) => void} subscriber
|
|
511
|
+
* @return {() => void} An unsubscribe function
|
|
512
|
+
*/
|
|
513
|
+
#on(type, subscriber) {
|
|
347
514
|
const subscriptions = this.#subscriptions;
|
|
348
515
|
if (subscriptions.length === 0) {
|
|
349
516
|
window.addEventListener('message', this.#onMessage);
|
|
350
517
|
}
|
|
351
|
-
subscriptions.push([
|
|
518
|
+
subscriptions.push([
|
|
519
|
+
type,
|
|
520
|
+
/** @type {(event: CadenzaEvent<never>) => void} */ (subscriber),
|
|
521
|
+
]);
|
|
352
522
|
return () => {
|
|
353
523
|
subscriptions.forEach(([subscriptionType, subscriptionSubscriber], i) => {
|
|
354
524
|
if (subscriptionType === type &&
|
|
@@ -362,7 +532,8 @@ export class CadenzaClient {
|
|
|
362
532
|
};
|
|
363
533
|
}
|
|
364
534
|
// Use arrow function so that it's bound to this.
|
|
365
|
-
#onMessage = (
|
|
535
|
+
#onMessage = (
|
|
536
|
+
/** @type MessageEvent<CadenzaEvent<never, never>> */ event) => {
|
|
366
537
|
if (event.origin !== this.#origin ||
|
|
367
538
|
event.source !== this.#requiredIframe.contentWindow) {
|
|
368
539
|
return;
|
|
@@ -375,26 +546,63 @@ export class CadenzaClient {
|
|
|
375
546
|
}
|
|
376
547
|
});
|
|
377
548
|
};
|
|
378
|
-
|
|
549
|
+
/**
|
|
550
|
+
* Posts an event to Cadenza and returns a `Promise` for the response.
|
|
551
|
+
*
|
|
552
|
+
* It is guaranteed that a response refers to a specific request,
|
|
553
|
+
* even if multiple request are executed in parallel.
|
|
554
|
+
* @template [T=void]
|
|
555
|
+
* @param {string} type
|
|
556
|
+
* @param {unknown} [detail]
|
|
557
|
+
* @returns {Promise<T>}
|
|
558
|
+
*/
|
|
559
|
+
#postRequest(type, detail) {
|
|
560
|
+
const { port1, port2 } = new MessageChannel();
|
|
561
|
+
const promise = new Promise((resolve, reject) => {
|
|
562
|
+
port1.onmessage = (
|
|
563
|
+
/** @type MessageEvent<CadenzaEvent<never, never>> */ event) => {
|
|
564
|
+
const cadenzaEvent = event.data;
|
|
565
|
+
if (cadenzaEvent.type === `${type}:success`) {
|
|
566
|
+
resolve(cadenzaEvent.detail);
|
|
567
|
+
}
|
|
568
|
+
else if (cadenzaEvent.type === `${type}:error`) {
|
|
569
|
+
reject();
|
|
570
|
+
}
|
|
571
|
+
};
|
|
572
|
+
});
|
|
573
|
+
this.#postEvent(type, detail, [port2]);
|
|
574
|
+
return promise;
|
|
575
|
+
}
|
|
576
|
+
/**
|
|
577
|
+
* @param {string} type
|
|
578
|
+
* @param {unknown} [detail]
|
|
579
|
+
* @param {Transferable[]} [transfer]
|
|
580
|
+
*/
|
|
581
|
+
#postEvent(type, detail, transfer) {
|
|
379
582
|
const cadenzaEvent = { type, detail };
|
|
380
583
|
this.#log('postMessage', cadenzaEvent);
|
|
381
584
|
const contentWindow = /** @type {WindowProxy} */ (this.#requiredIframe.contentWindow);
|
|
382
|
-
contentWindow.postMessage(cadenzaEvent, {
|
|
585
|
+
contentWindow.postMessage(cadenzaEvent, {
|
|
586
|
+
targetOrigin: this.#origin,
|
|
587
|
+
transfer,
|
|
588
|
+
});
|
|
383
589
|
}
|
|
384
590
|
/**
|
|
385
591
|
* Fetch data from a workbook view.
|
|
386
592
|
*
|
|
387
|
-
* @param {EmbeddingTargetId} source - The workbook view to fetch data from
|
|
388
|
-
*
|
|
593
|
+
* @param {EmbeddingTargetId} source - The workbook view to fetch data from.
|
|
594
|
+
* Currently only table and indicator views are supported.
|
|
595
|
+
* @param {DataType} dataType - The data type you want to get back from the server.
|
|
596
|
+
* Currently, `"csv"`, `"excel"` and `"json"` are supported.
|
|
389
597
|
* @param {object} options - Options
|
|
390
598
|
* @param {TablePart[]} [options.parts] - Table parts to export; If not specified, all parts are exported.
|
|
391
599
|
* @param {AbortSignal} [options.signal] - A signal to abort the data fetching
|
|
392
|
-
* @return {Promise<Response>} A Promise for the fetch response
|
|
600
|
+
* @return {Promise<Response>} A `Promise` for the fetch response
|
|
393
601
|
* @throws For invalid arguments
|
|
394
602
|
*/
|
|
395
603
|
fetchData(source, dataType, { parts, signal } = {}) {
|
|
396
|
-
this.#log('CadenzaClient#fetchData',
|
|
397
|
-
assertSupportedDataType(dataType);
|
|
604
|
+
this.#log('CadenzaClient#fetchData', ...arguments);
|
|
605
|
+
assertSupportedDataType(dataType, ['csv', 'excel', 'json']);
|
|
398
606
|
const params = createParams({ dataType, parts });
|
|
399
607
|
return this.#fetch(resolvePath(source), params, signal);
|
|
400
608
|
}
|
|
@@ -420,16 +628,18 @@ export class CadenzaClient {
|
|
|
420
628
|
*
|
|
421
629
|
* _Note:_ The file name, if not provided, is generated from the name of the workbook view and the current date.
|
|
422
630
|
*
|
|
423
|
-
* @param {EmbeddingTargetId} source - The workbook view to download data from
|
|
424
|
-
*
|
|
631
|
+
* @param {EmbeddingTargetId} source - The workbook view to download data from.
|
|
632
|
+
* Currently only table and indicator views are supported.
|
|
633
|
+
* @param {DataType} dataType - The data type you want to get back from the server.
|
|
634
|
+
* Currently, `"csv"`, `"excel"` and `"json"` are supported.
|
|
425
635
|
* @param {object} options - Options
|
|
426
636
|
* @param {string} [options.fileName] - The file name to use; The file extension is appended by Cadenza.
|
|
427
637
|
* @param {TablePart[]} [options.parts] - Table parts to export; If not specified, all parts are exported.
|
|
428
638
|
* @throws For invalid arguments
|
|
429
639
|
*/
|
|
430
640
|
downloadData(source, dataType, { fileName, parts }) {
|
|
431
|
-
this.#log('CadenzaClient#downloadData',
|
|
432
|
-
assertSupportedDataType(dataType);
|
|
641
|
+
this.#log('CadenzaClient#downloadData', ...arguments);
|
|
642
|
+
assertSupportedDataType(dataType, ['csv', 'excel', 'json']);
|
|
433
643
|
const params = createParams({ dataType, fileName, parts });
|
|
434
644
|
this.#download(resolvePath(source), params);
|
|
435
645
|
}
|
|
@@ -455,7 +665,20 @@ export class CadenzaClient {
|
|
|
455
665
|
}
|
|
456
666
|
#log(/** @type unknown[] */ ...args) {
|
|
457
667
|
if (this.#debug) {
|
|
458
|
-
|
|
668
|
+
/** @type {unknown[]} */
|
|
669
|
+
const redundantValues = [undefined, '', false];
|
|
670
|
+
/** @type {(value: unknown) => value is object} */
|
|
671
|
+
const isObject = (/** @type {unknown} */ value) => value != null && typeof value === 'object';
|
|
672
|
+
const sanitizedArgs = args
|
|
673
|
+
.map((arg) => {
|
|
674
|
+
if (isObject(arg)) {
|
|
675
|
+
return Object.fromEntries(Object.entries(arg).filter(([, value]) => !redundantValues.includes(value)));
|
|
676
|
+
}
|
|
677
|
+
return arg;
|
|
678
|
+
})
|
|
679
|
+
.filter((arg) => !redundantValues.includes(arg) &&
|
|
680
|
+
!(isObject(arg) && Object.keys(arg).length === 0));
|
|
681
|
+
console.log(...sanitizedArgs);
|
|
459
682
|
}
|
|
460
683
|
}
|
|
461
684
|
}
|
|
@@ -532,11 +755,11 @@ function validUiFeature(/** @type string */ value) {
|
|
|
532
755
|
}
|
|
533
756
|
function assertSupportedDataType(
|
|
534
757
|
/** @type DataType */ type,
|
|
535
|
-
/** @type DataType[] */ supportedTypes
|
|
758
|
+
/** @type DataType[] */ supportedTypes) {
|
|
536
759
|
assert(supportedTypes.includes(type), `Invalid data type: ${type}`);
|
|
537
760
|
}
|
|
538
761
|
/**
|
|
539
|
-
* @param {object} params
|
|
762
|
+
* @param {object} params
|
|
540
763
|
* @param {string} [params.action]
|
|
541
764
|
* @param {DataType} [params.dataType]
|
|
542
765
|
* @param {UiFeature[]} [params.disabledUiFeatures]
|
|
@@ -548,16 +771,17 @@ function assertSupportedDataType(
|
|
|
548
771
|
* @param {boolean} [params.hideWorkbookToolBar]
|
|
549
772
|
* @param {GlobalId} [params.highlightGlobalId]
|
|
550
773
|
* @param {string} [params.labelSet]
|
|
774
|
+
* @param {WorkbookLayerPath[]} [params.layers]
|
|
551
775
|
* @param {string} [params.locationFinder]
|
|
552
776
|
* @param {Extent} [params.mapExtent]
|
|
553
777
|
* @param {number} [params.minScale]
|
|
554
778
|
* @param {OperationMode} [params.operationMode]
|
|
555
779
|
* @param {TablePart[]} [params.parts]
|
|
780
|
+
* @param {'MAP'} [params.targetType]
|
|
556
781
|
* @param {boolean} [params.useMapSrs]
|
|
557
|
-
* @param {ExternalLinkKey} [params.webApplication]
|
|
558
782
|
* @return {URLSearchParams}
|
|
559
783
|
*/
|
|
560
|
-
function createParams({ action, dataType, disabledUiFeatures, expandNavigator, fileName, filter, geometryType, hideMainHeaderAndFooter, hideWorkbookToolBar, highlightGlobalId, labelSet, locationFinder, mapExtent, minScale,
|
|
784
|
+
function createParams({ action, dataType, disabledUiFeatures, expandNavigator, fileName, filter, geometryType, hideMainHeaderAndFooter, hideWorkbookToolBar, highlightGlobalId, labelSet, layers, locationFinder, mapExtent, minScale, operationMode, parts, targetType, useMapSrs, }) {
|
|
561
785
|
if (disabledUiFeatures) {
|
|
562
786
|
disabledUiFeatures.forEach((feature) => assert(validUiFeature(feature), `Invalid UI feature: ${feature}`));
|
|
563
787
|
}
|
|
@@ -591,25 +815,76 @@ function createParams({ action, dataType, disabledUiFeatures, expandNavigator, f
|
|
|
591
815
|
...(hideWorkbookToolBar && { hideWorkbookToolBar: 'true' }),
|
|
592
816
|
...(highlightGlobalId && { highlightGlobalId }),
|
|
593
817
|
...(labelSet && { labelSet }),
|
|
818
|
+
...(layers &&
|
|
819
|
+
layers.length && {
|
|
820
|
+
layers: JSON.stringify(layers),
|
|
821
|
+
}),
|
|
594
822
|
...(locationFinder && { locationFinder }),
|
|
595
823
|
...(mapExtent && { mapExtent: mapExtent.join() }),
|
|
596
824
|
...(minScale && { minScale: String(minScale) }),
|
|
597
825
|
...(operationMode && operationMode !== 'normal' && { operationMode }),
|
|
598
826
|
...(parts && { parts: parts.join() }),
|
|
827
|
+
...(targetType && { targetType }),
|
|
599
828
|
...(useMapSrs && { useMapSrs: 'true' }),
|
|
600
|
-
...(webApplication && {
|
|
601
|
-
webApplicationLink: webApplication.externalLinkId,
|
|
602
|
-
webApplicationLinkRepository: webApplication.repositoryName,
|
|
603
|
-
}),
|
|
604
829
|
});
|
|
605
830
|
}
|
|
831
|
+
function array(/** @type unknown */ value) {
|
|
832
|
+
return Array.isArray(value) ? value : [value];
|
|
833
|
+
}
|
|
834
|
+
// Please do not add internal event types like 'ready' here.
|
|
835
|
+
/**
|
|
836
|
+
* @typedef {'change:selection'
|
|
837
|
+
* | 'drillThrough'
|
|
838
|
+
* | 'editGeometry:ok'
|
|
839
|
+
* | 'editGeometry:update'
|
|
840
|
+
* | 'editGeometry:cancel'
|
|
841
|
+
* | 'objectInfo'
|
|
842
|
+
* | 'selectObjects:ok'
|
|
843
|
+
* | 'selectObjects:cancel'
|
|
844
|
+
* } CadenzaEventType - An event type to subscribe to using {@link CadenzaClient#on}
|
|
845
|
+
*/
|
|
846
|
+
/**
|
|
847
|
+
* @template {CadenzaEventType} T
|
|
848
|
+
* @typedef {T extends 'change:selection' ? CadenzaChangeSelectionEvent
|
|
849
|
+
* : T extends 'drillThrough' ? CadenzaDrillThroughEvent
|
|
850
|
+
* : T extends 'editGeometry:update' ? CadenzaEditGeometryUpdateEvent
|
|
851
|
+
* : T extends 'editGeometry:ok' ? CadenzaEditGeometryOkEvent
|
|
852
|
+
* : T extends 'editGeometry:cancel' ? CadenzaEditGeometryCancelEvent
|
|
853
|
+
* : T extends 'objectInfo' ? CadenzaObjectInfoEvent
|
|
854
|
+
* : T extends 'selectObjects:ok' ? CadenzaSelectObjectsOkEvent
|
|
855
|
+
* : T extends 'selectObjects:cancel' ? CadenzaSelectObjectsCancelEvent
|
|
856
|
+
* : never
|
|
857
|
+
* } CadenzaEventByType
|
|
858
|
+
*/
|
|
606
859
|
/**
|
|
607
|
-
* @template
|
|
860
|
+
* @template {CadenzaEventType | string} TYPE
|
|
861
|
+
* @template [DETAIL=unknown]
|
|
608
862
|
* @typedef CadenzaEvent - A Cadenza `postMessage()` event
|
|
609
|
-
* @property {
|
|
610
|
-
* @property {
|
|
863
|
+
* @property {TYPE} type - The event type
|
|
864
|
+
* @property {DETAIL} detail - Optional event details (depending on the event type)
|
|
865
|
+
*/
|
|
866
|
+
/*
|
|
867
|
+
* @hidden
|
|
868
|
+
* @typedef {CadenzaEvent<'change:extent', {extent: Extent}>} CadenzaChangeExtentEvent - When the user moved the map.
|
|
869
|
+
* The extent is transformed according to the `useMapSrs` option.
|
|
870
|
+
*/
|
|
871
|
+
/** @typedef {CadenzaEvent<'change:selection', undefined | {layer: WorkbookLayerPath, values: unknown[][]}>} CadenzaChangeSelectionEvent - When the user changed the selection. */
|
|
872
|
+
/**
|
|
873
|
+
* @typedef {CadenzaEvent<'drillThrough', {values: unknown[][]}>} CadenzaDrillThroughEvent - When the user executed a POST message drill-through.
|
|
874
|
+
* <p>
|
|
875
|
+
* The event includes a data row for every item in the workbook selection, each row consisting of the values of
|
|
876
|
+
* the attributes that were selected for the POST message content. If the drill-through was executed from a map
|
|
877
|
+
* view, each row includes the geometry of the selected object as the last value.
|
|
878
|
+
* <p>
|
|
879
|
+
* See also: <a href="../index.html#md:json-representation-of-cadenza-object-data">JSON Representation of Cadenza Object Data</a>
|
|
611
880
|
*/
|
|
612
|
-
/** @typedef {CadenzaEvent<
|
|
881
|
+
/** @typedef {CadenzaEvent<'editGeometry:update', {geometry: Geometry}>} CadenzaEditGeometryUpdateEvent - When the user changed the geometry. */
|
|
882
|
+
/** @typedef {CadenzaEvent<'editGeometry:ok', {geometry: Geometry}>} CadenzaEditGeometryOkEvent - When the user submitted the geometry. */
|
|
883
|
+
/** @typedef {CadenzaEvent<'editGeometry:cancel'>} CadenzaEditGeometryCancelEvent - When the user cancelled the geometry editing. */
|
|
884
|
+
/** @typedef {CadenzaEvent<'error', {type: string, message?: string}>} CadenzaErrorEvent - An error event that is mapped to a {@link CadenzaError} */
|
|
885
|
+
/** @typedef {CadenzaEvent<'objectInfo', {layer: WorkbookLayerPath, objectInfos: {selectionIndex: number, formattedValues: Record<string, string>}[]}>} CadenzaObjectInfoEvent - When the user opened the object info flyout. */
|
|
886
|
+
/** @typedef {CadenzaEvent<'selectObjects:ok', {layer: WorkbookLayerPath, values: unknown[][]}>} CadenzaSelectObjectsOkEvent - When the user submitted the selection. */
|
|
887
|
+
/** @typedef {CadenzaEvent<'selectObjects:cancel'>} CadenzaSelectObjectsCancelEvent - When the user cancelled the selection. */
|
|
613
888
|
export class AbortError extends DOMException {
|
|
614
889
|
constructor() {
|
|
615
890
|
super('Aborted', 'AbortError');
|