@masterportal/masterportalapi 2.47.0 → 2.49.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 CHANGED
@@ -19,6 +19,30 @@
19
19
 
20
20
  ---
21
21
 
22
+ ## 2.49.0 - 2025-04-294
23
+
24
+ ### Added
25
+ - Add new parameters polygonStrokeDash, polygonStrokeDashOffset in styleObject of drawInteraction.
26
+
27
+ ### Changed
28
+ - The following packages have been updated:
29
+ - dependencies:
30
+ - ol-mapbox-style: 12.4.0 to 12.5.0
31
+
32
+ ### Fixed
33
+ - wms: Fix passing layerParams from layerBuilder.
34
+ - wms-time: layers that are updated daily don't run into errors due to late promise-resolving anymore.
35
+ - Issue #1386: handle label creation if values are empty.
36
+
37
+ ---
38
+
39
+ ## 2.48.0 - 2025-04-01
40
+
41
+ ### Fixed
42
+ - olcsMap: fixed function setCameraParameter.
43
+
44
+ ---
45
+
22
46
  ## 2.47.0 - 2025-03-20
23
47
 
24
48
  ### Added
package/babel.config.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "presets": [],
2
+ "presets": [],
3
3
  "plugins": [
4
4
  "@babel/plugin-transform-modules-commonjs"
5
5
  ]
package/jest.config.js CHANGED
@@ -6,7 +6,7 @@ module.exports = {
6
6
  /** ol prints errors without HTMLCanvasElement being available in test environment */
7
7
  "setupFiles": ["jest-canvas-mock"],
8
8
  /** node_modules are usually ignored by babel-jest, but ol is published in ES6 */
9
- "transformIgnorePatterns": ["/node_modules/(?!(ol|olcs|ol-mapbox-style|geotiff|quick-lru|color-space|color-rgba|color-parse|color-name|rbush|quickselect|earcut|pbf)/).*/"],
9
+ "transformIgnorePatterns": ["/node_modules/(?!(ol|olcs|ol-mapbox-style|mapbox-to-css-font|geotiff|quick-lru|color-space|color-rgba|color-parse|color-name|rbush|quickselect|earcut|pbf)/).*/"],
10
10
  /** only consider files in src/ for coverage */
11
11
  "collectCoverageFrom": ["src/**/*.js"],
12
12
  /** coverage reporters */
@@ -14,7 +14,8 @@ module.exports = {
14
14
  /** mapping svg to string representation since jest can't handle svg and mapping olcs paths*/
15
15
  "moduleNameMapper": {
16
16
  "marker.svg": "<rootDir>/public/stringMarker.js",
17
- "olcs/lib/olcs/(.*)$": "<rootDir>/node_modules/olcs/lib/olcs/$1"
17
+ "olcs/lib/olcs/(.*)$": "<rootDir>/node_modules/olcs/lib/olcs/$1",
18
+ "ol-mapbox-style$": "<rootDir>/node_modules/ol-mapbox-style/src/$1"
18
19
  },
19
20
  "testEnvironment": "jsdom",
20
21
  "setupFilesAfterEnv": ["./jest.setup.js"],
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@masterportal/masterportalapi",
3
3
  "author": "Implementierungspartnerschaft Masterportal <info@masterportal.org> (https://www.masterportal.org)",
4
- "version": "2.47.0",
4
+ "version": "2.49.0",
5
5
  "license": "MIT",
6
6
  "description": "Basic functions of the Masterportal as api",
7
7
  "repository": {
@@ -22,7 +22,7 @@
22
22
  "core-js": "^3.33.1",
23
23
  "dayjs": "^1.11.10",
24
24
  "ol": "^10.4.0",
25
- "ol-mapbox-style": "12.4.0",
25
+ "ol-mapbox-style": "12.5.0",
26
26
  "olcs": "^2.22.1",
27
27
  "proj4": "^2.10.0",
28
28
  "xml2js": "^0.6.2"
@@ -4,11 +4,11 @@ import VectorTileSource from "ol/source/VectorTile";
4
4
  import OpenLayersTileGrid from "ol/tilegrid/TileGrid";
5
5
  import {extentFromProjection} from "ol/tilegrid";
6
6
  import * as webgl from "../renderer/webgl";
7
-
8
- import {stylefunction, apply} from "ol-mapbox-style";
7
+ import {apply, stylefunction} from "ol-mapbox-style";
9
8
 
10
9
  import defaults from "../defaults";
11
10
 
11
+
12
12
  const OL_DEFAULT_VECTOR_TILE_GRID_CRS = "EPSG:3857";
13
13
 
14
14
  /**
package/src/layer/wms.js CHANGED
@@ -112,6 +112,14 @@ export function createLayerSource (rawLayer, options) {
112
112
  projection = rawLayer.crs ? getProjection(rawLayer.crs) : undefined;
113
113
  let tileGrid = null;
114
114
 
115
+
116
+ // Fix for daily updated WMS-Time Layer, which use 'current' as the default value of the time-Extent in their getCapabilities
117
+ // The promise isn't resolved quickly enough for the continued work with the layer.
118
+ // Its resolved value would be the current date, so it is hardcoded here.
119
+ if (rawLayer.TIME && rawLayer.TIME.toString() === "[object Promise]") {
120
+ params.TIME = new Date().toISOString();
121
+ }
122
+
115
123
  if (rawLayer.singleTile) {
116
124
  return new ImageWMS({
117
125
  url: rawLayer.url,
@@ -154,13 +162,15 @@ export function createLayerSource (rawLayer, options) {
154
162
  * @param {function} [rawLayer.olAttribution] - optional function that takes a module:ol/Map~FrameState and returns a string or an array of strings representing source attributions
155
163
  * @param {string|number} [rawLayer.tilesize] - optional needed to create the tileGrid
156
164
  * @param {string|"anonymous"} [rawLayer.crossOrigin] - optional needed for CORS requests of image data, to enable canvas export
157
- * @param {object} layerParams - additional layer params
165
+ * @param {object} [optionalParams] - optional params
166
+ * @param {object} [optionalParams.layerParams] - additional layer params
167
+ * @param {options} [optionalParams.options] - additional options
158
168
  * @param {object} options - optional resolutions and origin to create the TileGrid
159
169
  * @param {Array} [options.resolutions] - optional resolutions to create the TileGrid, must be in descending order
160
170
  * @param {Array} [options.origin] - optional origin to create the TileGrid
161
171
  * @returns {ol.Layer} Layer that can be added to map.
162
172
  */
163
- export function createLayer (rawLayer, layerParams = {}, options) {
173
+ export function createLayer (rawLayer = {}, {layerParams = {}, options = {}} = {}) {
164
174
  const source = createLayerSource(rawLayer, options),
165
175
  Layer = rawLayer.singleTile ? ImageLayer : TileLayer;
166
176
 
@@ -169,6 +169,8 @@ function setStyleObject (currentLayout, outerCircle = false) {
169
169
  lineStrokeWidth: currentLayout.strokeWidth,
170
170
  polygonFillColor: fillColorRgba,
171
171
  polygonStrokeColor: currentLayout.strokeColor,
172
+ polygonStrokeDash: currentLayout.polygonDash,
173
+ polygonStrokeDashOffset: currentLayout.polygonStrokeDashOffset,
172
174
  polygonStrokeWidth: currentLayout.strokeWidth
173
175
  }
174
176
  }
@@ -9,91 +9,84 @@ import defaults from "../../defaults";
9
9
  let mapIdCounter = 0;
10
10
 
11
11
  /**
12
- * Recursive function.
13
- * Sets the cesium default scene params.
14
- * @param {Cesium.scene} scene The cesium scene.
15
- * @param {Object} params Optional configuration parameters.
12
+ * Recursively sets parameters on the Cesium scene.
13
+ *
14
+ * Certain keys are excluded from being set directly on the scene object:
15
+ * - "0", "1", "2": These is placeholder keys or indices from certain configurations that should not be interpreted as scene properties.
16
+ * - "heading", "tilt", "altitude": These are camera-related properties and should be handled separately via specific camera functions.
17
+ *
18
+ * @param {Cesium.Scene} scene - The Cesium scene instance.
19
+ * @param {Object} params - Configuration parameters.
16
20
  * @returns {void}
17
21
  */
18
22
  export function setCesiumSceneParams (scene, params) {
19
- Object.keys(params).forEach(paramKey => {
20
- const paramValue = params[paramKey];
21
-
22
- if (typeof paramValue === "object") {
23
- Object.keys(paramValue).forEach(paramSubKey => {
24
- if (paramSubKey !== "heading" && paramSubKey !== "tilt" && paramSubKey !== "altitude") {
25
- setCesiumSceneParams(scene[paramKey], paramValue);
26
- }
27
- });
23
+ if (!scene || !params || typeof params !== "object") {
24
+ console.warn("setCesiumSceneParams: Invalid scene or params.");
25
+ return;
26
+ }
27
+
28
+ Object.entries(params).forEach(([key, value]) => {
29
+ if (["0", "1", "2", "heading", "tilt", "altitude"].includes(key)) {
30
+ return;
31
+ }
32
+
33
+ if (typeof value === "object" && scene[key]) {
34
+ setCesiumSceneParams(scene[key], value);
28
35
  }
29
36
  else {
30
- scene[paramKey] = paramValue;
37
+ scene[key] = value;
31
38
  }
32
39
  });
33
40
  }
34
41
  /**
35
42
  * Sets the camera parameters either from config or from an trigger.
36
- * @param {Object} params Params.
37
- * @param {Object} map3D olcs map.
38
- * @param {Cesium} cesium cesium.
43
+ * @param {Object} params - Parameters for setting the camera.
44
+ * @param {Object} map3D - olcs map instance.
45
+ * @param {Cesium} cesium - Cesium instance.
39
46
  * @returns {void}
40
47
  */
41
48
  export function setCameraParameter (params, map3D, cesium) {
42
- let camera,
43
- destination,
44
- orientation,
45
- heading;
46
-
47
- if (params && map3D) {
48
- if (typeof params.heading !== "undefined") {
49
- heading = parseFloat(params.heading);
50
- }
51
- else if (typeof params.camera?.heading !== "undefined") {
52
- heading = parseFloat(params.camera?.heading);
53
- }
54
- // if the cameraPosition is given, directly set the cesium camera position, otherwise use olcesium Camera
55
- if (params.cameraPosition) {
56
- camera = map3D.getCesiumScene().camera;
57
- destination = cesium.Cartesian3.fromDegrees(params.cameraPosition[0], params.cameraPosition[1], params.cameraPosition[2]);
49
+ if (!params || !map3D) {
50
+ console.warn("setCameraParameter: Missing parameters or map3D instance.");
51
+ return;
52
+ }
53
+
54
+ let camera = map3D.getCesiumScene()?.camera;
55
+ const heading = parseFloat(params.heading ?? params.camera?.heading ?? 0),
56
+ pitch = parseFloat(params.pitch ?? params.camera?.pitch ?? 0),
57
+ roll = parseFloat(params.roll ?? 0),
58
+ tilt = parseFloat(params.tilt ?? params.camera?.tilt ?? 0),
59
+ altitude = parseFloat(params.altitude ?? params.camera?.altitude ?? 0);
60
+
61
+ if (params.cameraPosition || params.camera?.cameraPosition) {
62
+ const cameraPosition = params.cameraPosition ?? params.camera.cameraPosition,
63
+ destination = cesium.Cartesian3.fromDegrees(cameraPosition[0], cameraPosition[1], cameraPosition[2]),
58
64
  orientation = {
59
65
  heading: cesium.Math.toRadians(heading),
60
- pitch: cesium.Math.toRadians(parseFloat(params.pitch)),
61
- roll: cesium.Math.toRadians(parseFloat(params.roll))
66
+ pitch: cesium.Math.toRadians(pitch),
67
+ roll: cesium.Math.toRadians(roll)
62
68
  };
63
69
 
64
- camera.setView({
65
- destination,
66
- orientation
67
- });
70
+ if (params.cameraPosition) {
71
+ camera.setView({destination, orientation});
68
72
  }
69
73
  else {
70
- let tilt,
71
- altitude;
74
+ camera.flyTo({destination, orientation});
75
+ }
72
76
 
73
- if (typeof params.tilt !== "undefined") {
74
- tilt = parseFloat(params.tilt);
75
- }
76
- else if (typeof params.camera?.tilt !== "undefined") {
77
- tilt = parseFloat(params.camera?.tilt);
78
- }
79
- if (typeof params.altitude !== "undefined") {
80
- altitude = parseFloat(params.altitude);
81
- }
82
- else if (typeof params.camera?.altitude !== "undefined") {
83
- altitude = parseFloat(params.camera?.altitude);
84
- }
85
- camera = map3D.getCamera();
77
+ return;
78
+ }
86
79
 
87
- if (tilt) {
88
- camera.setTilt(tilt);
89
- }
90
- if (heading) {
91
- camera.setHeading(heading);
92
- }
93
- if (altitude) {
94
- camera.setAltitude(altitude);
95
- }
96
- }
80
+ camera = map3D.getCamera();
81
+
82
+ if (tilt) {
83
+ camera.setTilt(tilt);
84
+ }
85
+ if (heading) {
86
+ camera.setHeading(heading);
87
+ }
88
+ if (altitude) {
89
+ camera.setAltitude(altitude);
97
90
  }
98
91
  }
99
92
 
@@ -120,7 +120,7 @@ class TextStyle extends StyleClass {
120
120
  const feature = this.feature,
121
121
  featureProperties = feature.getProperties(),
122
122
  textSuffix = this.attributes.textSuffix;
123
- let text = mapAttributes(featureProperties, this.attributes.labelField, false);
123
+ let text = mapAttributes(featureProperties, this.attributes.labelField, false) ?? "";
124
124
 
125
125
  if (textSuffix !== "") {
126
126
  text = text + " " + textSuffix;
@@ -250,7 +250,7 @@ describe("wms.js", function () {
250
250
  name: "name",
251
251
  layers: "layer1, layer2"
252
252
  },
253
- layer = wms.createLayer({singleTile: false, tilesize: "10", extent: [10, 20, 11, 22]}, layerParams, options);
253
+ layer = wms.createLayer({singleTile: false, tilesize: "10", extent: [10, 20, 11, 22]}, {layerParams, options});
254
254
 
255
255
  expect(layer).toBeInstanceOf(TileLayer);
256
256
  expect(layer.get("name")).toEqual("name");
@@ -266,7 +266,7 @@ describe("wms.js", function () {
266
266
  name: "name",
267
267
  layers: "layer1, layer2"
268
268
  },
269
- layer = wms.createLayer({singleTile: true}, layerParams);
269
+ layer = wms.createLayer({singleTile: true}, {layerParams});
270
270
 
271
271
  expect(layer).toBeInstanceOf(ImageLayer);
272
272
  expect(layer.get("name")).toEqual("name");
package/test/map.test.js CHANGED
@@ -72,7 +72,7 @@ describe("map.js", function () {
72
72
  };
73
73
  }
74
74
  },
75
- cesiumLib: "https://lib.virtualcitymap.de/v3.6.x/lib/Cesium/Cesium.js"
75
+ cesiumLib: "https://geoportal-hamburg.de/mastercode/cesium/latest/Cesium.js"
76
76
  };
77
77
 
78
78
  load3DScriptModule.load3DScript(config.cesiumLib, function Loaded3DCallback () {
@@ -165,7 +165,7 @@ describe("map.js", function () {
165
165
  heading: -0.30858728378862876,
166
166
  tilt: 0.9321791580603296
167
167
  },
168
- cesiumLib: "https://lib.virtualcitymap.de/v3.6.x/lib/Cesium/Cesium.js"
168
+ cesiumLib: "https://geoportal-hamburg.de/mastercode/cesium/latest/Cesium.js"
169
169
  };
170
170
 
171
171
  load3DScriptModule.load3DScript(config.cesiumLib, function Loaded3DCallback () {
@@ -200,7 +200,7 @@ describe("map.js", function () {
200
200
  tilt: 0.9321791580603296
201
201
  }
202
202
  },
203
- cesiumLib: "https://lib.virtualcitymap.de/v3.6.x/lib/Cesium/Cesium.js"
203
+ cesiumLib: "https://geoportal-hamburg.de/mastercode/cesium/latest/Cesium.js"
204
204
  };
205
205
 
206
206
  load3DScriptModule.load3DScript(config.cesiumLib, function Loaded3DCallback () {
@@ -213,48 +213,108 @@ describe("map.js", function () {
213
213
  });
214
214
  });
215
215
  it("set the camera from viewpoint parameter", function () {
216
- const config = {
217
- map2D: {
218
- getView: () => {
219
- return {
220
- getProjection: () => {
221
- return {getCode: () => "code"};
222
- }
223
- };
216
+ const mockFlyTo = jest.fn(),
217
+ config = {
218
+ map2D: {
219
+ getView: () => {
220
+ return {
221
+ getProjection: () => {
222
+ return {getCode: () => "code"};
223
+ }
224
+ };
225
+ },
226
+ getViewport: () => {
227
+ return {
228
+ appendChild: jest.fn()
229
+ };
230
+ }
224
231
  },
225
- getViewport: () => {
226
- return {
227
- appendChild: jest.fn()
228
- };
229
- }
230
- },
231
- viewpoint: [{"distance": 1660.0290142521517,
232
- "cameraPosition": [
233
- 9.982163927085617,
234
- 53.532817572762475,
235
- 1180.9805498821436
236
- ],
237
- "groundPosition": [
238
- 9.983171185370468,
239
- 53.54328139366739,
240
- -0.00449886760542777
241
- ],
242
- "heading": 3.281512334248587,
243
- "pitch": -45.35612834848329,
244
- "roll": 0.015054499334397243,
245
- "animate": false,
246
- "duration": 6.006336273348537
247
- }],
248
- cesiumLib: "https://lib.virtualcitymap.de/v3.6.x/lib/Cesium/Cesium.js"
249
- };
232
+ viewpoint: [{
233
+ "distance": 1660.0290142521517,
234
+ "cameraPosition": [
235
+ 9.982163927085617,
236
+ 53.532817572762475,
237
+ 1180.9805498821436
238
+ ],
239
+ "heading": 3.281512334248587,
240
+ "pitch": -45.35612834848329,
241
+ "roll": 0.015054499334397243
242
+ }],
243
+ cesiumLib: "https://geoportal-hamburg.de/mastercode/cesium/latest/Cesium.js"
244
+ };
250
245
 
251
246
  load3DScriptModule.load3DScript(config.cesiumLib, function Loaded3DCallback () {
252
- const map3D = map.createMap(config, "3D");
247
+ const mockMap3D = {
248
+ mapMode: "3D",
249
+ getCesiumScene: () => ({
250
+ camera: {
251
+ flyTo: mockFlyTo
252
+ }
253
+ })
254
+ };
253
255
 
254
- expect(map3D.mapMode).toBe("3D");
255
- map.setCameraParameter(config.viewpoint, map3D, config.cesiumLib);
256
+ map.setCameraParameter(config.viewpoint, mockMap3D, config.cesiumLib);
256
257
 
257
- // missing test, if the passed parameters are also in the 3D map
258
+ expect(mockFlyTo).toHaveBeenCalledWith(expect.objectContaining({
259
+ destination: expect.any(Object),
260
+ orientation: {
261
+ heading: expect.any(Number),
262
+ pitch: expect.any(Number),
263
+ roll: expect.any(Number)
264
+ },
265
+ duration: config.viewpoint[0].duration
266
+ }));
267
+ });
268
+ });
269
+
270
+ it("sets the camera parameters when cameraPosition is not provided", function () {
271
+ const mockFlyTo = jest.fn(),
272
+ config = {
273
+ map2D: {
274
+ getView: () => {
275
+ return {
276
+ getProjection: () => {
277
+ return {getCode: () => "code"};
278
+ }
279
+ };
280
+ },
281
+ getViewport: () => {
282
+ return {
283
+ appendChild: jest.fn()
284
+ };
285
+ }
286
+ },
287
+ viewpoint: [{
288
+ "distance": 1660.0290142521517,
289
+ "heading": 3.281512334248587,
290
+ "pitch": -45.35612834848329,
291
+ "roll": 0.015054499334397243,
292
+ "tilt": 10,
293
+ "altitude": 1500
294
+ }],
295
+ cesiumLib: "https://geoportal-hamburg.de/mastercode/cesium/latest/Cesium.js"
296
+ };
297
+
298
+ load3DScriptModule.load3DScript(config.cesiumLib, function Loaded3DCallback () {
299
+ const mockMap3D = {
300
+ mapMode: "3D",
301
+ getCesiumScene: () => ({
302
+ camera: {
303
+ flyTo: mockFlyTo,
304
+ setTilt: jest.fn(),
305
+ setHeading: jest.fn(),
306
+ setAltitude: jest.fn()
307
+ }
308
+ })
309
+ };
310
+
311
+ map.setCameraParameter(config.viewpoint[0], mockMap3D, config.cesiumLib);
312
+
313
+ expect(mockFlyTo).not.toHaveBeenCalled();
314
+
315
+ expect(mockMap3D.getCesiumScene().camera.setTilt).toHaveBeenCalledWith(10);
316
+ expect(mockMap3D.getCesiumScene().camera.setHeading).toHaveBeenCalledWith(3.281512334248587);
317
+ expect(mockMap3D.getCesiumScene().camera.setAltitude).toHaveBeenCalledWith(1500);
258
318
  });
259
319
  });
260
320
  });
@@ -281,7 +341,7 @@ describe("map.js", function () {
281
341
  heading: -0.30858728378862876,
282
342
  tilt: 0.9321791580603296
283
343
  },
284
- cesiumLib: "https://lib.virtualcitymap.de/v3.6.x/lib/Cesium/Cesium.js"
344
+ cesiumLib: "https://geoportal-hamburg.de/mastercode/cesium/latest/Cesium.js"
285
345
  };
286
346
 
287
347
  load3DScriptModule.load3DScript(config.cesiumLib, function Loaded3DCallback () {
@@ -339,7 +399,7 @@ describe("map.js", function () {
339
399
  undergroundColor: undefined
340
400
  }
341
401
  },
342
- cesiumLib: "https://lib.virtualcitymap.de/v3.6.x/lib/Cesium/Cesium.js"
402
+ cesiumLib: "https://geoportal-hamburg.de/mastercode/cesium/latest/Cesium.js"
343
403
  };
344
404
 
345
405
  load3DScriptModule.load3DScript(config.cesiumLib, function Loaded3DCallback () {
@@ -355,5 +415,4 @@ describe("map.js", function () {
355
415
  });
356
416
  });
357
417
  });
358
-
359
418
  });
@@ -86,7 +86,8 @@ describe("src/maps/interactions/drawInteraction.js", () => {
86
86
  fillColor: [55, 126, 184],
87
87
  fillTransparency: 0,
88
88
  strokeColor: [0, 0, 0],
89
- strokeWidth: 1
89
+ strokeWidth: 1,
90
+ polygonDash: [4]
90
91
  };
91
92
 
92
93
  drawInteractions.setStyleObject(currentLayout);
@@ -124,6 +125,8 @@ describe("src/maps/interactions/drawInteraction.js", () => {
124
125
  0,
125
126
  0
126
127
  ],
128
+ polygonStrokeDash: [4],
129
+ polygonStrokeDashOffset: undefined,
127
130
  polygonStrokeWidth: 1
128
131
  }
129
132
  }