@disy/cadenza.js 2.2.4 β 2.3.1
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 +16 -5
- 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 +65 -86
- 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 +274 -50
- package/cadenza.js +339 -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
|
let hasCadenzaSession = false;
|
|
60
100
|
/** @type {Promise<void> | undefined} */
|
|
61
101
|
let firstEmbeddingTargetShown;
|
|
@@ -81,7 +121,7 @@ export class CadenzaClient {
|
|
|
81
121
|
#iframeElement;
|
|
82
122
|
/** @readonly */
|
|
83
123
|
#debug;
|
|
84
|
-
/** @type {[ string, (event: CadenzaEvent<never>) => void ][]} */
|
|
124
|
+
/** @type {[ CadenzaEventType | string, (event: CadenzaEvent<never>) => void ][]} */
|
|
85
125
|
#subscriptions = [];
|
|
86
126
|
/**
|
|
87
127
|
* @hidden
|
|
@@ -145,15 +185,12 @@ export class CadenzaClient {
|
|
|
145
185
|
* @param {String} [options.labelSet] - The name of a label set defined in the `basicweb-config.xml` (only supported for the welcome page)
|
|
146
186
|
* @param {OperationMode} [options.operationMode] - The mode in which a workbook should be operated
|
|
147
187
|
* @param {AbortSignal} [options.signal] - A signal to abort the iframe loading
|
|
148
|
-
* @return {Promise<void>} A Promise for when the iframe is loaded
|
|
188
|
+
* @return {Promise<void>} A `Promise` for when the iframe is loaded
|
|
149
189
|
* @throws For invalid arguments
|
|
150
|
-
* @fires
|
|
151
|
-
* The event includes a row of values for each row in the workbook selection, each row consisting of the values of
|
|
152
|
-
* the attributes that were selected for the POST message content. If the drill-through was executed from a map
|
|
153
|
-
* view, each row includes the geometry of the select object as the last value.
|
|
190
|
+
* @fires {@link CadenzaDrillThroughEvent}
|
|
154
191
|
*/
|
|
155
192
|
show(source, { dataType, disabledUiFeatures, expandNavigator, filter, hideMainHeaderAndFooter, hideWorkbookToolBar, highlightGlobalId, labelSet, operationMode, signal, } = {}) {
|
|
156
|
-
this.#log('CadenzaClient#show',
|
|
193
|
+
this.#log('CadenzaClient#show', ...arguments);
|
|
157
194
|
if (dataType) {
|
|
158
195
|
assertSupportedDataType(dataType, ['pdf']);
|
|
159
196
|
}
|
|
@@ -172,7 +209,6 @@ export class CadenzaClient {
|
|
|
172
209
|
labelSet,
|
|
173
210
|
dataType,
|
|
174
211
|
operationMode,
|
|
175
|
-
webApplication: this.#webApplication,
|
|
176
212
|
});
|
|
177
213
|
return this.#show(resolvePath(source), params, signal);
|
|
178
214
|
}
|
|
@@ -193,14 +229,12 @@ export class CadenzaClient {
|
|
|
193
229
|
* @param {OperationMode} [options.operationMode] - The mode in which a workbook should be operated
|
|
194
230
|
* @param {boolean} [options.useMapSrs] - Whether the geometry and the extent are in the map's SRS (otherwise EPSG:4326 is assumed)
|
|
195
231
|
* @param {AbortSignal} [options.signal] - A signal to abort the iframe loading
|
|
196
|
-
* @return {Promise<void>} A Promise for when the iframe is loaded
|
|
232
|
+
* @return {Promise<void>} A `Promise` for when the iframe is loaded
|
|
197
233
|
* @throws For invalid arguments
|
|
198
|
-
* @fires
|
|
199
|
-
* The event includes a row of values for each row in the workbook selection, each row consisting of the values of
|
|
200
|
-
* the attributes that were selected for the POST message content plus the geometry of the select object as the last value.
|
|
234
|
+
* @fires {@link CadenzaDrillThroughEvent}
|
|
201
235
|
*/
|
|
202
236
|
async showMap(mapView, { disabledUiFeatures, expandNavigator, filter, geometry, hideMainHeaderAndFooter, hideWorkbookToolBar, highlightGlobalId, locationFinder, mapExtent, operationMode, useMapSrs, signal, } = {}) {
|
|
203
|
-
this.#log('CadenzaClient#showMap',
|
|
237
|
+
this.#log('CadenzaClient#showMap', ...arguments);
|
|
204
238
|
if (geometry) {
|
|
205
239
|
assertValidGeometryType(geometry.type);
|
|
206
240
|
}
|
|
@@ -214,11 +248,13 @@ export class CadenzaClient {
|
|
|
214
248
|
locationFinder,
|
|
215
249
|
mapExtent,
|
|
216
250
|
operationMode,
|
|
251
|
+
targetType: 'MAP',
|
|
217
252
|
useMapSrs,
|
|
218
|
-
webApplication: this.#webApplication,
|
|
219
253
|
});
|
|
220
254
|
await this.#show(resolvePath(mapView), params, signal);
|
|
221
|
-
|
|
255
|
+
if (geometry) {
|
|
256
|
+
this.#postEvent('setGeometry', { geometry });
|
|
257
|
+
}
|
|
222
258
|
}
|
|
223
259
|
/**
|
|
224
260
|
* Expand/collapse the navigator.
|
|
@@ -226,9 +262,93 @@ export class CadenzaClient {
|
|
|
226
262
|
* @param {boolean} expanded - The expansion state of the navigator
|
|
227
263
|
*/
|
|
228
264
|
expandNavigator(expanded = true) {
|
|
229
|
-
this.#log('CadenzaClient#expandNavigator',
|
|
265
|
+
this.#log('CadenzaClient#expandNavigator', ...arguments);
|
|
230
266
|
this.#postEvent('expandNavigator', { expandNavigator: Boolean(expanded) });
|
|
231
267
|
}
|
|
268
|
+
/**
|
|
269
|
+
* Get data from the currently shown workbook view.
|
|
270
|
+
*
|
|
271
|
+
* Currently, only map views are supported.
|
|
272
|
+
*
|
|
273
|
+
* @hidden
|
|
274
|
+
* @template {DataType} T
|
|
275
|
+
* @param {T} dataType - The requested data type. Currently, only `"png"` is supported.
|
|
276
|
+
* @return {Promise<T extends 'png' ? Blob : never>}
|
|
277
|
+
*/
|
|
278
|
+
async getData(dataType) {
|
|
279
|
+
this.#log('CadenzaClient#getData', ...arguments);
|
|
280
|
+
assertSupportedDataType(dataType, ['png']);
|
|
281
|
+
return this.#postRequest('getData', { dataType });
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Set filter variables in the currently shown workbook.
|
|
285
|
+
*
|
|
286
|
+
* @hidden
|
|
287
|
+
* @param {FilterVariables} filter - The variable values
|
|
288
|
+
* @return {Promise<void>} A `Promise` for when the filter variables were set.
|
|
289
|
+
*/
|
|
290
|
+
setFilter(filter) {
|
|
291
|
+
this.#log('CadenzaClient#setFilter', ...arguments);
|
|
292
|
+
return this.#postRequest('setFilter', { filter });
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Set the visibility of a layer in the currently shown workbook map view.
|
|
296
|
+
*
|
|
297
|
+
* When making a layer visible, its ancestors will be made visible, too.
|
|
298
|
+
* When hiding a layer, the ancestors are not affected.
|
|
299
|
+
*
|
|
300
|
+
* @hidden
|
|
301
|
+
* @param {WorkbookLayerPath | string} layer - The layer to show or hide
|
|
302
|
+
* (identified using a layer path or a print name)
|
|
303
|
+
* @param {boolean} visible - The visibility state of the layer
|
|
304
|
+
* @return {Promise<void>} A `Promise` for when the layer visibility was set.
|
|
305
|
+
*/
|
|
306
|
+
setLayerVisibility(layer, visible) {
|
|
307
|
+
this.#log('CadenzaClient#setLayerVisibility', ...arguments);
|
|
308
|
+
return this.#postRequest('setLayerVisibility', {
|
|
309
|
+
layer: array(layer),
|
|
310
|
+
visible,
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Set the selection in the currently shown workbook map view.
|
|
315
|
+
*
|
|
316
|
+
* @hidden
|
|
317
|
+
* @param {WorkbookLayerPath | string} layer - The data view layer to set the selection in
|
|
318
|
+
* @param {unknown[]} values - The IDs of the objects to select
|
|
319
|
+
* @return {Promise<void>} A `Promise` for when the selection was set.
|
|
320
|
+
*/
|
|
321
|
+
setSelection(layer, values) {
|
|
322
|
+
this.#log('CadenzaClient#setSelection', ...arguments);
|
|
323
|
+
return this.#postRequest('setSelection', { layer: array(layer), values });
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Add to the selection in the currently shown workbook map view.
|
|
327
|
+
*
|
|
328
|
+
* @hidden
|
|
329
|
+
* @param {WorkbookLayerPath | string} layer - The data view layer to change the selection in
|
|
330
|
+
* @param {unknown[]} values - The IDs of the objects to select
|
|
331
|
+
* @return {Promise<void>} A `Promise` for when the selection was changed.
|
|
332
|
+
*/
|
|
333
|
+
addSelection(layer, values) {
|
|
334
|
+
this.#log('CadenzaClient#addSelection', ...arguments);
|
|
335
|
+
return this.#postRequest('addSelection', { layer: array(layer), values });
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Remove from the selection in the currently shown workbook map view.
|
|
339
|
+
*
|
|
340
|
+
* @hidden
|
|
341
|
+
* @param {WorkbookLayerPath | string} layer - The data view layer to change the selection in
|
|
342
|
+
* @param {unknown[]} values - The IDs of the objects to unselect
|
|
343
|
+
* @return {Promise<void>} A `Promise` for when the selection was changed.
|
|
344
|
+
*/
|
|
345
|
+
removeSelection(layer, values) {
|
|
346
|
+
this.#log('CadenzaClient#removeSelection', ...arguments);
|
|
347
|
+
return this.#postRequest('removeSelection', {
|
|
348
|
+
layer: array(layer),
|
|
349
|
+
values,
|
|
350
|
+
});
|
|
351
|
+
}
|
|
232
352
|
/**
|
|
233
353
|
* Create a geometry.
|
|
234
354
|
*
|
|
@@ -243,14 +363,15 @@ export class CadenzaClient {
|
|
|
243
363
|
* @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.
|
|
244
364
|
* @param {boolean} [options.useMapSrs] - Whether the created geometry should use the map's SRS (otherwise EPSG:4326 will be used)
|
|
245
365
|
* @param {AbortSignal} [options.signal] - A signal to abort the iframe loading
|
|
246
|
-
* @return {Promise<void>} A Promise for when the iframe is loaded
|
|
366
|
+
* @return {Promise<void>} A `Promise` for when the iframe is loaded
|
|
247
367
|
* @throws For invalid arguments
|
|
248
|
-
* @fires
|
|
249
|
-
*
|
|
250
|
-
*
|
|
368
|
+
* @fires
|
|
369
|
+
* - {@link CadenzaEditGeometryUpdateEvent}
|
|
370
|
+
* - {@link CadenzaEditGeometryOkEvent}
|
|
371
|
+
* - {@link CadenzaEditGeometryCancelEvent}
|
|
251
372
|
*/
|
|
252
373
|
createGeometry(backgroundMapView, geometryType, { locationFinder, mapExtent, minScale, useMapSrs, signal } = {}) {
|
|
253
|
-
this.#log('CadenzaClient#createGeometry',
|
|
374
|
+
this.#log('CadenzaClient#createGeometry', ...arguments);
|
|
254
375
|
const params = createParams({
|
|
255
376
|
action: 'editGeometry',
|
|
256
377
|
geometryType,
|
|
@@ -258,7 +379,6 @@ export class CadenzaClient {
|
|
|
258
379
|
mapExtent,
|
|
259
380
|
minScale,
|
|
260
381
|
useMapSrs,
|
|
261
|
-
webApplication: this.#webApplication,
|
|
262
382
|
});
|
|
263
383
|
return this.#show(resolvePath(backgroundMapView), params, signal);
|
|
264
384
|
}
|
|
@@ -273,14 +393,15 @@ export class CadenzaClient {
|
|
|
273
393
|
* @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.
|
|
274
394
|
* @param {boolean} [options.useMapSrs] - Whether the geometry is in the map's SRS (otherwise EPSG:4326 is assumed)
|
|
275
395
|
* @param {AbortSignal} [options.signal] - A signal to abort the iframe loading
|
|
276
|
-
* @return {Promise<void>} A Promise for when the iframe is loaded
|
|
396
|
+
* @return {Promise<void>} A `Promise` for when the iframe is loaded
|
|
277
397
|
* @throws For invalid arguments
|
|
278
|
-
* @fires
|
|
279
|
-
*
|
|
280
|
-
*
|
|
398
|
+
* @fires
|
|
399
|
+
* - {@link CadenzaEditGeometryUpdateEvent}
|
|
400
|
+
* - {@link CadenzaEditGeometryOkEvent}
|
|
401
|
+
* - {@link CadenzaEditGeometryCancelEvent}
|
|
281
402
|
*/
|
|
282
403
|
async editGeometry(backgroundMapView, geometry, { locationFinder, mapExtent, minScale, useMapSrs, signal } = {}) {
|
|
283
|
-
this.#log('CadenzaClient#editGeometry',
|
|
404
|
+
this.#log('CadenzaClient#editGeometry', ...arguments);
|
|
284
405
|
assertValidGeometryType(geometry.type);
|
|
285
406
|
const params = createParams({
|
|
286
407
|
action: 'editGeometry',
|
|
@@ -288,10 +409,41 @@ export class CadenzaClient {
|
|
|
288
409
|
mapExtent,
|
|
289
410
|
minScale,
|
|
290
411
|
useMapSrs,
|
|
291
|
-
webApplication: this.#webApplication,
|
|
292
412
|
});
|
|
293
413
|
await this.#show(resolvePath(backgroundMapView), params, signal);
|
|
294
|
-
|
|
414
|
+
if (geometry) {
|
|
415
|
+
this.#postEvent('setGeometry', { geometry });
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Select objects in a workbook map.
|
|
420
|
+
*
|
|
421
|
+
* @param {EmbeddingTargetId} backgroundMapView - The workbook map view
|
|
422
|
+
* @param {object} [options] - Options
|
|
423
|
+
* @param {(WorkbookLayerPath | string)[]} [options.layers] - Layers to restrict the selection to
|
|
424
|
+
* (identified using layer paths or print names)
|
|
425
|
+
* @param {string} [options.locationFinder] - A search query for the location finder
|
|
426
|
+
* @param {Extent} [options.mapExtent] - A map extent to set
|
|
427
|
+
* @param {boolean} [options.useMapSrs] - Whether the geometry is in the map's SRS (otherwise EPSG:4326 is assumed)
|
|
428
|
+
* @param {AbortSignal} [options.signal] - A signal to abort the iframe loading
|
|
429
|
+
* @return {Promise<void>} A `Promise` for when the iframe is loaded
|
|
430
|
+
* @throws For invalid arguments
|
|
431
|
+
* @fires
|
|
432
|
+
* - {@link CadenzaChangeSelectionEvent}
|
|
433
|
+
* - {@link CadenzaObjectInfoEvent}
|
|
434
|
+
* - {@link CadenzaSelectObjectsOkEvent}
|
|
435
|
+
* - {@link CadenzaSelectObjectsCancelEvent}
|
|
436
|
+
*/
|
|
437
|
+
selectObjects(backgroundMapView, { layers, locationFinder, mapExtent, useMapSrs, signal } = {}) {
|
|
438
|
+
this.#log('CadenzaClient#selectObjects', ...arguments);
|
|
439
|
+
const params = createParams({
|
|
440
|
+
action: 'selectObjects',
|
|
441
|
+
layers: layers?.map(array),
|
|
442
|
+
locationFinder,
|
|
443
|
+
mapExtent,
|
|
444
|
+
useMapSrs,
|
|
445
|
+
});
|
|
446
|
+
return this.#show(resolvePath(backgroundMapView), params, signal);
|
|
295
447
|
}
|
|
296
448
|
/**
|
|
297
449
|
* @param {string} path
|
|
@@ -331,14 +483,14 @@ export class CadenzaClient {
|
|
|
331
483
|
}
|
|
332
484
|
#getIframePromise(/** @type AbortSignal | undefined */ signal) {
|
|
333
485
|
const iframe = this.#requiredIframe;
|
|
334
|
-
/** @type {
|
|
486
|
+
/** @type {EventListener} */
|
|
335
487
|
let onerror;
|
|
336
|
-
/** @type {
|
|
488
|
+
/** @type {EventListener} */
|
|
337
489
|
let onabort;
|
|
338
490
|
/** @type {(() => void)[]} */
|
|
339
491
|
let unsubscribes;
|
|
340
492
|
/** @type {Promise<void>} */
|
|
341
|
-
|
|
493
|
+
const promise = new Promise((resolve, reject) => {
|
|
342
494
|
onerror = () => reject(new CadenzaError('loading-error', 'Loading failed'));
|
|
343
495
|
iframe.addEventListener('error', onerror);
|
|
344
496
|
if (signal) {
|
|
@@ -349,8 +501,8 @@ export class CadenzaClient {
|
|
|
349
501
|
signal.addEventListener('abort', onabort);
|
|
350
502
|
}
|
|
351
503
|
unsubscribes = [
|
|
352
|
-
this
|
|
353
|
-
this
|
|
504
|
+
this.#on('ready', () => resolve()),
|
|
505
|
+
this.#on('error', (/** @type {CadenzaErrorEvent} */ event) => {
|
|
354
506
|
const { type, message } = event.detail;
|
|
355
507
|
reject(new CadenzaError(type, message ?? 'Loading failed'));
|
|
356
508
|
}),
|
|
@@ -368,17 +520,30 @@ export class CadenzaClient {
|
|
|
368
520
|
/**
|
|
369
521
|
* Subscribe to a `postMessage()` event.
|
|
370
522
|
*
|
|
371
|
-
* @template
|
|
372
|
-
* @param {
|
|
373
|
-
* @param {(event: CadenzaEvent<
|
|
523
|
+
* @template {CadenzaEventType} TYPE
|
|
524
|
+
* @param {TYPE} type - The event type
|
|
525
|
+
* @param {(event: CadenzaEvent<TYPE, CadenzaEventByType<TYPE>['detail']>) => void} subscriber - The subscriber function
|
|
374
526
|
* @return {() => void} An unsubscribe function
|
|
375
527
|
*/
|
|
376
528
|
on(type, subscriber) {
|
|
529
|
+
return this.#on(type, subscriber);
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* @template {CadenzaEventType | string} TYPE
|
|
533
|
+
* @template [DETAIL=unknown]
|
|
534
|
+
* @param {TYPE} type
|
|
535
|
+
* @param {(event: CadenzaEvent<TYPE, DETAIL>) => void} subscriber
|
|
536
|
+
* @return {() => void} An unsubscribe function
|
|
537
|
+
*/
|
|
538
|
+
#on(type, subscriber) {
|
|
377
539
|
const subscriptions = this.#subscriptions;
|
|
378
540
|
if (subscriptions.length === 0) {
|
|
379
541
|
window.addEventListener('message', this.#onMessage);
|
|
380
542
|
}
|
|
381
|
-
subscriptions.push([
|
|
543
|
+
subscriptions.push([
|
|
544
|
+
type,
|
|
545
|
+
/** @type {(event: CadenzaEvent<never>) => void} */ (subscriber),
|
|
546
|
+
]);
|
|
382
547
|
return () => {
|
|
383
548
|
subscriptions.forEach(([subscriptionType, subscriptionSubscriber], i) => {
|
|
384
549
|
if (subscriptionType === type &&
|
|
@@ -392,7 +557,8 @@ export class CadenzaClient {
|
|
|
392
557
|
};
|
|
393
558
|
}
|
|
394
559
|
// Use arrow function so that it's bound to this.
|
|
395
|
-
#onMessage = (
|
|
560
|
+
#onMessage = (
|
|
561
|
+
/** @type MessageEvent<CadenzaEvent<never, never>> */ event) => {
|
|
396
562
|
if (event.origin !== this.#origin ||
|
|
397
563
|
event.source !== this.#requiredIframe.contentWindow) {
|
|
398
564
|
return;
|
|
@@ -405,26 +571,63 @@ export class CadenzaClient {
|
|
|
405
571
|
}
|
|
406
572
|
});
|
|
407
573
|
};
|
|
408
|
-
|
|
574
|
+
/**
|
|
575
|
+
* Posts an event to Cadenza and returns a `Promise` for the response.
|
|
576
|
+
*
|
|
577
|
+
* It is guaranteed that a response refers to a specific request,
|
|
578
|
+
* even if multiple request are executed in parallel.
|
|
579
|
+
* @template [T=void]
|
|
580
|
+
* @param {string} type
|
|
581
|
+
* @param {unknown} [detail]
|
|
582
|
+
* @returns {Promise<T>}
|
|
583
|
+
*/
|
|
584
|
+
#postRequest(type, detail) {
|
|
585
|
+
const { port1, port2 } = new MessageChannel();
|
|
586
|
+
const promise = new Promise((resolve, reject) => {
|
|
587
|
+
port1.onmessage = (
|
|
588
|
+
/** @type MessageEvent<CadenzaEvent<never, never>> */ event) => {
|
|
589
|
+
const cadenzaEvent = event.data;
|
|
590
|
+
if (cadenzaEvent.type === `${type}:success`) {
|
|
591
|
+
resolve(cadenzaEvent.detail);
|
|
592
|
+
}
|
|
593
|
+
else if (cadenzaEvent.type === `${type}:error`) {
|
|
594
|
+
reject();
|
|
595
|
+
}
|
|
596
|
+
};
|
|
597
|
+
});
|
|
598
|
+
this.#postEvent(type, detail, [port2]);
|
|
599
|
+
return promise;
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* @param {string} type
|
|
603
|
+
* @param {unknown} [detail]
|
|
604
|
+
* @param {Transferable[]} [transfer]
|
|
605
|
+
*/
|
|
606
|
+
#postEvent(type, detail, transfer) {
|
|
409
607
|
const cadenzaEvent = { type, detail };
|
|
410
608
|
this.#log('postMessage', cadenzaEvent);
|
|
411
609
|
const contentWindow = /** @type {WindowProxy} */ (this.#requiredIframe.contentWindow);
|
|
412
|
-
contentWindow.postMessage(cadenzaEvent, {
|
|
610
|
+
contentWindow.postMessage(cadenzaEvent, {
|
|
611
|
+
targetOrigin: this.#origin,
|
|
612
|
+
transfer,
|
|
613
|
+
});
|
|
413
614
|
}
|
|
414
615
|
/**
|
|
415
616
|
* Fetch data from a workbook view.
|
|
416
617
|
*
|
|
417
|
-
* @param {EmbeddingTargetId} source - The workbook view to fetch data from
|
|
418
|
-
*
|
|
618
|
+
* @param {EmbeddingTargetId} source - The workbook view to fetch data from.
|
|
619
|
+
* Currently only table and indicator views are supported.
|
|
620
|
+
* @param {DataType} dataType - The data type you want to get back from the server.
|
|
621
|
+
* Currently, `"csv"`, `"excel"` and `"json"` are supported.
|
|
419
622
|
* @param {object} options - Options
|
|
420
623
|
* @param {TablePart[]} [options.parts] - Table parts to export; If not specified, all parts are exported.
|
|
421
624
|
* @param {AbortSignal} [options.signal] - A signal to abort the data fetching
|
|
422
|
-
* @return {Promise<Response>} A Promise for the fetch response
|
|
625
|
+
* @return {Promise<Response>} A `Promise` for the fetch response
|
|
423
626
|
* @throws For invalid arguments
|
|
424
627
|
*/
|
|
425
628
|
fetchData(source, dataType, { parts, signal } = {}) {
|
|
426
|
-
this.#log('CadenzaClient#fetchData',
|
|
427
|
-
assertSupportedDataType(dataType);
|
|
629
|
+
this.#log('CadenzaClient#fetchData', ...arguments);
|
|
630
|
+
assertSupportedDataType(dataType, ['csv', 'excel', 'json']);
|
|
428
631
|
const params = createParams({ dataType, parts });
|
|
429
632
|
return this.#fetch(resolvePath(source), params, signal);
|
|
430
633
|
}
|
|
@@ -450,16 +653,18 @@ export class CadenzaClient {
|
|
|
450
653
|
*
|
|
451
654
|
* _Note:_ The file name, if not provided, is generated from the name of the workbook view and the current date.
|
|
452
655
|
*
|
|
453
|
-
* @param {EmbeddingTargetId} source - The workbook view to download data from
|
|
454
|
-
*
|
|
656
|
+
* @param {EmbeddingTargetId} source - The workbook view to download data from.
|
|
657
|
+
* Currently only table and indicator views are supported.
|
|
658
|
+
* @param {DataType} dataType - The data type you want to get back from the server.
|
|
659
|
+
* Currently, `"csv"`, `"excel"` and `"json"` are supported.
|
|
455
660
|
* @param {object} options - Options
|
|
456
661
|
* @param {string} [options.fileName] - The file name to use; The file extension is appended by Cadenza.
|
|
457
662
|
* @param {TablePart[]} [options.parts] - Table parts to export; If not specified, all parts are exported.
|
|
458
663
|
* @throws For invalid arguments
|
|
459
664
|
*/
|
|
460
665
|
downloadData(source, dataType, { fileName, parts }) {
|
|
461
|
-
this.#log('CadenzaClient#downloadData',
|
|
462
|
-
assertSupportedDataType(dataType);
|
|
666
|
+
this.#log('CadenzaClient#downloadData', ...arguments);
|
|
667
|
+
assertSupportedDataType(dataType, ['csv', 'excel', 'json']);
|
|
463
668
|
const params = createParams({ dataType, fileName, parts });
|
|
464
669
|
this.#download(resolvePath(source), params);
|
|
465
670
|
}
|
|
@@ -485,7 +690,20 @@ export class CadenzaClient {
|
|
|
485
690
|
}
|
|
486
691
|
#log(/** @type unknown[] */ ...args) {
|
|
487
692
|
if (this.#debug) {
|
|
488
|
-
|
|
693
|
+
/** @type {unknown[]} */
|
|
694
|
+
const redundantValues = [undefined, '', false];
|
|
695
|
+
/** @type {(value: unknown) => value is object} */
|
|
696
|
+
const isObject = (/** @type {unknown} */ value) => value != null && typeof value === 'object';
|
|
697
|
+
const sanitizedArgs = args
|
|
698
|
+
.map((arg) => {
|
|
699
|
+
if (isObject(arg)) {
|
|
700
|
+
return Object.fromEntries(Object.entries(arg).filter(([, value]) => !redundantValues.includes(value)));
|
|
701
|
+
}
|
|
702
|
+
return arg;
|
|
703
|
+
})
|
|
704
|
+
.filter((arg) => !redundantValues.includes(arg) &&
|
|
705
|
+
!(isObject(arg) && Object.keys(arg).length === 0));
|
|
706
|
+
console.log(...sanitizedArgs);
|
|
489
707
|
}
|
|
490
708
|
}
|
|
491
709
|
}
|
|
@@ -562,11 +780,11 @@ function validUiFeature(/** @type string */ value) {
|
|
|
562
780
|
}
|
|
563
781
|
function assertSupportedDataType(
|
|
564
782
|
/** @type DataType */ type,
|
|
565
|
-
/** @type DataType[] */ supportedTypes
|
|
783
|
+
/** @type DataType[] */ supportedTypes) {
|
|
566
784
|
assert(supportedTypes.includes(type), `Invalid data type: ${type}`);
|
|
567
785
|
}
|
|
568
786
|
/**
|
|
569
|
-
* @param {object} params
|
|
787
|
+
* @param {object} params
|
|
570
788
|
* @param {string} [params.action]
|
|
571
789
|
* @param {DataType} [params.dataType]
|
|
572
790
|
* @param {UiFeature[]} [params.disabledUiFeatures]
|
|
@@ -578,16 +796,17 @@ function assertSupportedDataType(
|
|
|
578
796
|
* @param {boolean} [params.hideWorkbookToolBar]
|
|
579
797
|
* @param {GlobalId} [params.highlightGlobalId]
|
|
580
798
|
* @param {string} [params.labelSet]
|
|
799
|
+
* @param {WorkbookLayerPath[]} [params.layers]
|
|
581
800
|
* @param {string} [params.locationFinder]
|
|
582
801
|
* @param {Extent} [params.mapExtent]
|
|
583
802
|
* @param {number} [params.minScale]
|
|
584
803
|
* @param {OperationMode} [params.operationMode]
|
|
585
804
|
* @param {TablePart[]} [params.parts]
|
|
805
|
+
* @param {'MAP'} [params.targetType]
|
|
586
806
|
* @param {boolean} [params.useMapSrs]
|
|
587
|
-
* @param {ExternalLinkKey} [params.webApplication]
|
|
588
807
|
* @return {URLSearchParams}
|
|
589
808
|
*/
|
|
590
|
-
function createParams({ action, dataType, disabledUiFeatures, expandNavigator, fileName, filter, geometryType, hideMainHeaderAndFooter, hideWorkbookToolBar, highlightGlobalId, labelSet, locationFinder, mapExtent, minScale,
|
|
809
|
+
function createParams({ action, dataType, disabledUiFeatures, expandNavigator, fileName, filter, geometryType, hideMainHeaderAndFooter, hideWorkbookToolBar, highlightGlobalId, labelSet, layers, locationFinder, mapExtent, minScale, operationMode, parts, targetType, useMapSrs, }) {
|
|
591
810
|
if (disabledUiFeatures) {
|
|
592
811
|
disabledUiFeatures.forEach((feature) => assert(validUiFeature(feature), `Invalid UI feature: ${feature}`));
|
|
593
812
|
}
|
|
@@ -621,25 +840,76 @@ function createParams({ action, dataType, disabledUiFeatures, expandNavigator, f
|
|
|
621
840
|
...(hideWorkbookToolBar && { hideWorkbookToolBar: 'true' }),
|
|
622
841
|
...(highlightGlobalId && { highlightGlobalId }),
|
|
623
842
|
...(labelSet && { labelSet }),
|
|
843
|
+
...(layers &&
|
|
844
|
+
layers.length && {
|
|
845
|
+
layers: JSON.stringify(layers),
|
|
846
|
+
}),
|
|
624
847
|
...(locationFinder && { locationFinder }),
|
|
625
848
|
...(mapExtent && { mapExtent: mapExtent.join() }),
|
|
626
849
|
...(minScale && { minScale: String(minScale) }),
|
|
627
850
|
...(operationMode && operationMode !== 'normal' && { operationMode }),
|
|
628
851
|
...(parts && { parts: parts.join() }),
|
|
852
|
+
...(targetType && { targetType }),
|
|
629
853
|
...(useMapSrs && { useMapSrs: 'true' }),
|
|
630
|
-
...(webApplication && {
|
|
631
|
-
webApplicationLink: webApplication.externalLinkId,
|
|
632
|
-
webApplicationLinkRepository: webApplication.repositoryName,
|
|
633
|
-
}),
|
|
634
854
|
});
|
|
635
855
|
}
|
|
856
|
+
function array(/** @type unknown */ value) {
|
|
857
|
+
return Array.isArray(value) ? value : [value];
|
|
858
|
+
}
|
|
859
|
+
// Please do not add internal event types like 'ready' here.
|
|
860
|
+
/**
|
|
861
|
+
* @typedef {'change:selection'
|
|
862
|
+
* | 'drillThrough'
|
|
863
|
+
* | 'editGeometry:ok'
|
|
864
|
+
* | 'editGeometry:update'
|
|
865
|
+
* | 'editGeometry:cancel'
|
|
866
|
+
* | 'objectInfo'
|
|
867
|
+
* | 'selectObjects:ok'
|
|
868
|
+
* | 'selectObjects:cancel'
|
|
869
|
+
* } CadenzaEventType - An event type to subscribe to using {@link CadenzaClient#on}
|
|
870
|
+
*/
|
|
871
|
+
/**
|
|
872
|
+
* @template {CadenzaEventType} T
|
|
873
|
+
* @typedef {T extends 'change:selection' ? CadenzaChangeSelectionEvent
|
|
874
|
+
* : T extends 'drillThrough' ? CadenzaDrillThroughEvent
|
|
875
|
+
* : T extends 'editGeometry:update' ? CadenzaEditGeometryUpdateEvent
|
|
876
|
+
* : T extends 'editGeometry:ok' ? CadenzaEditGeometryOkEvent
|
|
877
|
+
* : T extends 'editGeometry:cancel' ? CadenzaEditGeometryCancelEvent
|
|
878
|
+
* : T extends 'objectInfo' ? CadenzaObjectInfoEvent
|
|
879
|
+
* : T extends 'selectObjects:ok' ? CadenzaSelectObjectsOkEvent
|
|
880
|
+
* : T extends 'selectObjects:cancel' ? CadenzaSelectObjectsCancelEvent
|
|
881
|
+
* : never
|
|
882
|
+
* } CadenzaEventByType
|
|
883
|
+
*/
|
|
636
884
|
/**
|
|
637
|
-
* @template
|
|
885
|
+
* @template {CadenzaEventType | string} TYPE
|
|
886
|
+
* @template [DETAIL=unknown]
|
|
638
887
|
* @typedef CadenzaEvent - A Cadenza `postMessage()` event
|
|
639
|
-
* @property {
|
|
640
|
-
* @property {
|
|
888
|
+
* @property {TYPE} type - The event type
|
|
889
|
+
* @property {DETAIL} detail - Optional event details (depending on the event type)
|
|
890
|
+
*/
|
|
891
|
+
/*
|
|
892
|
+
* @hidden
|
|
893
|
+
* @typedef {CadenzaEvent<'change:extent', {extent: Extent}>} CadenzaChangeExtentEvent - When the user moved the map.
|
|
894
|
+
* The extent is transformed according to the `useMapSrs` option.
|
|
895
|
+
*/
|
|
896
|
+
/** @typedef {CadenzaEvent<'change:selection', undefined | {layer: WorkbookLayerPath, values: unknown[][]}>} CadenzaChangeSelectionEvent - When the user changed the selection. */
|
|
897
|
+
/**
|
|
898
|
+
* @typedef {CadenzaEvent<'drillThrough', {values: unknown[][]}>} CadenzaDrillThroughEvent - When the user executed a POST message drill-through.
|
|
899
|
+
* <p>
|
|
900
|
+
* The event includes a data row for every item in the workbook selection, each row consisting of the values of
|
|
901
|
+
* the attributes that were selected for the POST message content. If the drill-through was executed from a map
|
|
902
|
+
* view, each row includes the geometry of the selected object as the last value.
|
|
903
|
+
* <p>
|
|
904
|
+
* See also: <a href="../index.html#md:json-representation-of-cadenza-object-data">JSON Representation of Cadenza Object Data</a>
|
|
641
905
|
*/
|
|
642
|
-
/** @typedef {CadenzaEvent<
|
|
906
|
+
/** @typedef {CadenzaEvent<'editGeometry:update', {geometry: Geometry}>} CadenzaEditGeometryUpdateEvent - When the user changed the geometry. */
|
|
907
|
+
/** @typedef {CadenzaEvent<'editGeometry:ok', {geometry: Geometry}>} CadenzaEditGeometryOkEvent - When the user submitted the geometry. */
|
|
908
|
+
/** @typedef {CadenzaEvent<'editGeometry:cancel'>} CadenzaEditGeometryCancelEvent - When the user cancelled the geometry editing. */
|
|
909
|
+
/** @typedef {CadenzaEvent<'error', {type: string, message?: string}>} CadenzaErrorEvent - An error event that is mapped to a {@link CadenzaError} */
|
|
910
|
+
/** @typedef {CadenzaEvent<'objectInfo', {layer: WorkbookLayerPath, objectInfos: {selectionIndex: number, formattedValues: Record<string, string>}[]}>} CadenzaObjectInfoEvent - When the user opened the object info flyout. */
|
|
911
|
+
/** @typedef {CadenzaEvent<'selectObjects:ok', {layer: WorkbookLayerPath, values: unknown[][]}>} CadenzaSelectObjectsOkEvent - When the user submitted the selection. */
|
|
912
|
+
/** @typedef {CadenzaEvent<'selectObjects:cancel'>} CadenzaSelectObjectsCancelEvent - When the user cancelled the selection. */
|
|
643
913
|
export class AbortError extends DOMException {
|
|
644
914
|
constructor() {
|
|
645
915
|
super('Aborted', 'AbortError');
|