@masterportal/masterportalapi 2.18.0 → 2.19.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 CHANGED
@@ -3,6 +3,41 @@
3
3
 
4
4
  The [Semantic Versioning](https://semver.org/spec/v2.0.0.html) is used.
5
5
 
6
+ ## Unreleased - in development
7
+ ### Added
8
+ ### Changed
9
+ ### Deprecated
10
+ ### Removed
11
+ ### Fixed
12
+
13
+ ---
14
+ ## 2.19.1 - 2023-06-02
15
+ ### Added
16
+ ### Changed
17
+ - Exports in src/layer/wmts.js changed to export default {} to provide ES-Syntax.
18
+ ### Deprecated
19
+ ### Removed
20
+ ### Fixed
21
+
22
+ ---
23
+
24
+ ## 2.19.0 - 2023-05-26
25
+ ### Added
26
+ - The following package has been added:
27
+ - dependencies:
28
+ - dayjs: "^1.11.7"
29
+
30
+ ### Changed
31
+ - AttributeMapper: Object keys are supported with dot notation.
32
+ - WFS: hardcoded URL changed to dynamic url creation.
33
+ - Issue Masterportal #1021: extend vectorStyle in order to handle geometryCollections.
34
+ - Issue Masterportal #1022: attributeMapper supports additional time formats.
35
+
36
+ ### Fixed
37
+ - Issue Masterportal # 1028: set cesium scene parameter recursively.
38
+
39
+ ---
40
+
6
41
  ## 2.18.0 - 2023-05-10
7
42
  ### Changed
8
43
  - The following packages have been updated:
@@ -18,7 +53,7 @@
18
53
  - jest-canvas-mock: 2.4.0 to 2.5.0
19
54
  - parcel: 2.6.0 to 2.8.3
20
55
  - sass: 1.59.3 to 1.62.1
21
- - The devDependency `buffer` ist downgrade from 6.0.3 to 5.7.1 because parcel requires a version 5
56
+ - The devDependency `buffer` ist downgrade from 6.0.3 to 5.7.1 because parcel requires a version 5.
22
57
 
23
58
  ---
24
59
 
package/package.json CHANGED
@@ -1,64 +1,64 @@
1
- {
2
- "name": "@masterportal/masterportalapi",
3
- "author": "Implementierungspartnerschaft Masterportal <info@masterportal.org> (https://www.masterportal.org)",
4
- "version": "2.18.0",
5
- "license": "MIT",
6
- "description": "Basic functions of the Masterportal as api",
7
- "repository": {
8
- "type": "git",
9
- "url": "git+https://bitbucket.org/geowerkstatt-hamburg/masterportalapi.git"
10
- },
11
- "main": "src/index.js",
12
- "scripts": {
13
- "test": "jest .test.js --config ./jest.config.js --collectCoverage",
14
- "test:trace": "node --trace-warnings node_modules/jest/bin/jest.js ./test/layer/wfs.test.js --config ./jest.config.js",
15
- "test:watch": "jest .test.js --config ./jest.config.js --watch",
16
- "example": "parcel example/index.html",
17
- "generate-jsdoc": "jsdoc ./src -r -d ./docs/ -R ./README.md -c jsdoc.json",
18
- "prePushHook": "eslint --max-warnings 0 \"./**/*.js\" && npm run test",
19
- "prepare": "husky install"
20
- },
21
- "dependencies": {
22
- "core-js": "^3.30.2",
23
- "ol": "7.3.0",
24
- "olcs": "^2.14.0",
25
- "proj4": "^2.9.0",
26
- "xml2js": "^0.5.0"
27
- },
28
- "devDependencies": {
29
- "@babel/core": "^7.21.8",
30
- "@babel/plugin-transform-modules-commonjs": "^7.21.5",
31
- "@parcel/transformer-sass": "^2.8.3",
32
- "buffer": "^5.7.1",
33
- "canvas": "^2.11.2",
34
- "eslint": "^8.40.0",
35
- "events": "^3.3.0",
36
- "husky": "^8.0.3",
37
- "jest": "^29.5.0",
38
- "jest-canvas-mock": "^2.5.0",
39
- "jest-environment-jsdom": "^29.5.0",
40
- "jsdoc": "^4.0.2",
41
- "parcel": "^2.8.3",
42
- "process": "^0.11.10",
43
- "sass": "^1.62.1",
44
- "stream-browserify": "^3.0.0",
45
- "timers-browserify": "^2.0.12",
46
- "use-resize-observer": "^9.1.0"
47
- },
48
- "peerDependencies": {
49
- "cesium": "^1.95.0"
50
- },
51
- "engines": {
52
- "node": "^16.13.2 || ^18.12.0",
53
- "npm": "^8.1.2 || ^9.3.1"
54
- },
55
- "homepage": "https://bitbucket.org/geowerkstatt-hamburg/masterportalapi#readme",
56
- "directories": {
57
- "doc": "docs",
58
- "example": "example",
59
- "test": "test"
60
- },
61
- "bugs": {
62
- "url": "https://bitbucket.org/geowerkstatt-hamburg/masterportalapi/issues"
63
- }
64
- }
1
+ {
2
+ "name": "@masterportal/masterportalapi",
3
+ "author": "Implementierungspartnerschaft Masterportal <info@masterportal.org> (https://www.masterportal.org)",
4
+ "version": "2.19.1",
5
+ "license": "MIT",
6
+ "description": "Basic functions of the Masterportal as api",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://bitbucket.org/geowerkstatt-hamburg/masterportalapi.git"
10
+ },
11
+ "main": "src/index.js",
12
+ "scripts": {
13
+ "test": "jest .test.js --config ./jest.config.js --collectCoverage",
14
+ "test:trace": "node --trace-warnings node_modules/jest/bin/jest.js ./test/layer/wfs.test.js --config ./jest.config.js",
15
+ "test:watch": "jest .test.js --config ./jest.config.js --watch",
16
+ "example": "parcel example/index.html",
17
+ "generate-jsdoc": "jsdoc ./src -r -d ./docs/ -R ./README.md -c jsdoc.json",
18
+ "prePushHook": "eslint --max-warnings 0 \"./**/*.js\" && npm run test",
19
+ "prepare": "husky install"
20
+ },
21
+ "dependencies": {
22
+ "core-js": "^3.30.2",
23
+ "dayjs": "^1.11.7",
24
+ "ol": "7.3.0",
25
+ "olcs": "^2.14.0",
26
+ "proj4": "^2.9.0",
27
+ "xml2js": "^0.5.0"
28
+ },
29
+ "devDependencies": {
30
+ "@babel/core": "^7.21.8",
31
+ "@babel/plugin-transform-modules-commonjs": "^7.21.5",
32
+ "@parcel/transformer-sass": "^2.8.3",
33
+ "buffer": "^5.7.1",
34
+ "canvas": "^2.11.2",
35
+ "eslint": "^8.40.0",
36
+ "events": "^3.3.0",
37
+ "husky": "^8.0.3",
38
+ "jest": "^29.5.0",
39
+ "jest-canvas-mock": "^2.5.0",
40
+ "jest-environment-jsdom": "^29.5.0",
41
+ "jsdoc": "^4.0.2",
42
+ "parcel": "^2.8.3",
43
+ "process": "^0.11.10",
44
+ "sass": "^1.62.1",
45
+ "stream-browserify": "^3.0.0",
46
+ "timers-browserify": "^2.0.12",
47
+ "use-resize-observer": "^9.1.0"
48
+ },
49
+ "peerDependencies": {
50
+ "cesium": "^1.95.0"
51
+ },
52
+ "engines": {
53
+ "node": "^16.13.2 || ^18.12.0",
54
+ "npm": "^8.1.2 || ^9.3.1"
55
+ },
56
+ "homepage": "https://bitbucket.org/geowerkstatt-hamburg/masterportalapi#readme",
57
+ "directories": {
58
+ "example": "example",
59
+ "test": "test"
60
+ },
61
+ "bugs": {
62
+ "url": "https://bitbucket.org/geowerkstatt-hamburg/masterportalapi/issues"
63
+ }
64
+ }
package/src/index.js CHANGED
@@ -2,7 +2,7 @@ import {createMapView} from "./maps/mapView";
2
2
  import crs from "./crs";
3
3
  import rawLayerList from "./rawLayerList";
4
4
  import * as wms from "./layer/wms";
5
- import * as wmts from "./layer/wmts";
5
+ import wmts from "./layer/wmts";
6
6
  import * as wfs from "./layer/wfs";
7
7
  import * as geojson from "./layer/geojson";
8
8
  import * as vectorBase from "./layer/vectorBase";
package/src/layer/wfs.js CHANGED
@@ -126,16 +126,21 @@ function loadWFSFilter (filter, url, source, {onErrorFn, success, failure}, opti
126
126
  * @returns {string} the url
127
127
  */
128
128
  function createUrl (rawLayer, version, projection, bboxParam) {
129
- let url = `${rawLayer.url}?service=WFS&version=${version}&request=GetFeature&srsName=${projection.getCode()}${bboxParam}`;
129
+ const url = new URL(rawLayer.url);
130
+
131
+ url.searchParams.set("service", "WFS");
132
+ url.searchParams.set("version", version);
133
+ url.searchParams.set("request", "GetFeature");
134
+ url.searchParams.set("srsName", projection.getCode());
130
135
 
131
136
  if (version === "1.0.0" || version === "1.1.0") {
132
- url = `${url}&typeName=${rawLayer.featureType}`;
137
+ url.searchParams.set("typeName", rawLayer.featureType);
133
138
  }
134
139
  else if (version === "2.0.0") {
135
- url = `${url}&typeNames=${rawLayer.featureType}`;
140
+ url.searchParams.set("typeNames", rawLayer.featureType);
136
141
  }
137
142
 
138
- return url;
143
+ return `${url.toString()}${bboxParam}`;
139
144
  }
140
145
 
141
146
  /**
package/src/layer/wmts.js CHANGED
@@ -12,7 +12,7 @@ import {get as getProjection} from "ol/proj";
12
12
  * @param {String} layerName layerName
13
13
  * @returns {void}
14
14
  */
15
- export function showErrorMessage (errorMessage, layerName) {
15
+ function showErrorMessage (errorMessage, layerName) {
16
16
  console.error("content: Layer " + layerName + ": " + errorMessage);
17
17
  }
18
18
 
@@ -24,7 +24,7 @@ export function showErrorMessage (errorMessage, layerName) {
24
24
  * @param {Number} size The tileSize depending on the extent.
25
25
  * @returns {void}
26
26
  */
27
- export function generateArrays (resolutions, matrixIds, length, size) {
27
+ function generateArrays (resolutions, matrixIds, length, size) {
28
28
  for (let i = 0; i < length; ++i) {
29
29
  resolutions[i] = size / Math.pow(2, i);
30
30
  matrixIds[i] = i;
@@ -37,7 +37,7 @@ export function generateArrays (resolutions, matrixIds, length, size) {
37
37
  * @throws {Error} on unexpected return
38
38
  * @returns {promise} promise resolves to parsed WMTS-GetCapabilities object
39
39
  */
40
- export function getWMTSCapabilities (url) {
40
+ function getWMTSCapabilities (url) {
41
41
  return fetch(url)
42
42
  .then(response => {
43
43
  if (response && response.status === 200) {
@@ -55,7 +55,7 @@ export function getWMTSCapabilities (url) {
55
55
  * @param {WMTS} tileLayer layer object
56
56
  * @returns {void}
57
57
  */
58
- export function createLayerSourceByDefinitions (attrs, tileLayer) {
58
+ function createLayerSourceByDefinitions (attrs, tileLayer) {
59
59
  const projection = getProjection(attrs.coordinateSystem),
60
60
  extent = projection.getExtent(),
61
61
  style = attrs.style,
@@ -108,7 +108,7 @@ export function createLayerSourceByDefinitions (attrs, tileLayer) {
108
108
  * @param {WMTS} tileLayer layer object
109
109
  * @returns {void}
110
110
  */
111
- export function createLayerSourceByCapabilities (attrs, tileLayer) {
111
+ function createLayerSourceByCapabilities (attrs, tileLayer) {
112
112
  const layerIdentifier = attrs.layers,
113
113
  url = attrs.capabilitiesUrl,
114
114
  matrixSet = attrs.tileMatrixSet,
@@ -169,7 +169,7 @@ export function createLayerSourceByCapabilities (attrs, tileLayer) {
169
169
  * @param {object} layerParams - additional layer params
170
170
  * @returns {void}
171
171
  */
172
- export function createLayer (rawLayer, layerParams = {}) {
172
+ function createLayer (rawLayer, layerParams = {}) {
173
173
  const tileLayer = new TileLayer(Object.assign({
174
174
  id: rawLayer.id,
175
175
  source: new WMTS({}),
@@ -193,3 +193,12 @@ export function createLayer (rawLayer, layerParams = {}) {
193
193
 
194
194
  return tileLayer;
195
195
  }
196
+
197
+ export default {
198
+ createLayer,
199
+ createLayerSourceByCapabilities,
200
+ createLayerSourceByDefinitions,
201
+ getWMTSCapabilities,
202
+ generateArrays,
203
+ showErrorMessage
204
+ };
@@ -1,5 +1,6 @@
1
1
  import {getValueFromObjectByPath} from "./getValueFromObjectByPath.js";
2
2
  import thousandsSeparator from "./thousandsSeparator";
3
+ import dayjs from "dayjs";
3
4
  /**
4
5
  * checks if value starts with special prefix to determine if value is a object path
5
6
  * @param {string} value string to check
@@ -11,16 +12,25 @@ function isObjectPath (value) {
11
12
  /**
12
13
  * Returns the value of the given key. Also considers, that the key may be an object path.
13
14
  * @param {Object} properties properties.
14
- * @param {String} key Key to derive value from.
15
+ * @param {String} propertyKey Key to derive value from.
15
16
  * @returns {*} - Value from key.
16
17
  */
17
- function prepareValue (properties, key) {
18
- const isPath = isObjectPath(key);
19
- let value = properties[Object.keys(properties).find(propertiesKey => propertiesKey.toLowerCase() === key.toLowerCase())];
18
+ function prepareValue (properties, propertyKey) {
19
+ Object.keys(properties).forEach((parentKey) => {
20
+ if (properties[parentKey] && typeof properties[parentKey] === "object") {
21
+ Object.keys(properties[parentKey]).forEach((key) => {
22
+ properties[parentKey + "." + key] = properties[parentKey][key];
23
+ });
24
+ }
25
+ });
26
+
27
+ const isPath = isObjectPath(propertyKey);
28
+ let value = properties[Object.keys(properties).find(propertiesKey => propertiesKey.toLowerCase() === propertyKey.toLowerCase())];
20
29
 
21
30
  if (isPath) {
22
- value = getValueFromObjectByPath(properties, key);
31
+ value = getValueFromObjectByPath(properties, propertyKey);
23
32
  }
33
+
24
34
  return value;
25
35
  }
26
36
 
@@ -128,30 +138,21 @@ function prepareValueFromObject (key, mappingObj, properties) {
128
138
  switch (type) {
129
139
  case "date": {
130
140
  date = new Date(String(preparedValue));
131
- if (!isNaN(date.getTime())) {
132
- const year = date.getFullYear(),
133
- month = ("0" + (date.getMonth() + 1)).slice(-2),
134
- day = ("0" + date.getDate()).slice(-2);
135
-
136
- if (format === "YYYY-MM-DDTHH:mm:ss.SSSZ") {
137
- const offset = date.getTimezoneOffset();
138
-
139
- let offsetHours = (offset / 60) % 24,
140
- offsetMinutes = offset % 60;
141
-
142
- offsetHours = offsetHours < 0 ? "+" + ("0" + Math.abs(offsetHours)).slice(-2) : "-" + ("0" + Math.abs(offsetHours)).slice(-2);
143
- offsetMinutes = offsetMinutes < 0 ? ":" + ("0" + Math.abs(offsetMinutes)).slice(-2) : ":" + ("0" + offsetMinutes).slice(-2);
144
- preparedValue = date.toISOString().slice(0, -1) + offsetHours + offsetMinutes;
145
- }
146
- else if (format === "YYYY-MM-DD") {
147
- preparedValue = year + "-" + month + "-" + day;
148
- }
149
- else if (format === "DD-MM-YYYY") {
150
- preparedValue = day + "-" + month + "-" + year;
151
- }
152
- else {
153
- console.error("The format must be 'YYYY-MM-DD' or 'DD-MM-YYYY', if the attribute is missing, ISO 8601 is used.");
154
- }
141
+ if (format === "YYYY-MM-DDTHH:mm:ss.SSSZ") {
142
+ const offset = date.getTimezoneOffset();
143
+
144
+ let offsetHours = (offset / 60) % 24,
145
+ offsetMinutes = offset % 60;
146
+
147
+ offsetHours = offsetHours < 0 ? "+" + ("0" + Math.abs(offsetHours)).slice(-2) : "-" + ("0" + Math.abs(offsetHours)).slice(-2);
148
+ offsetMinutes = offsetMinutes < 0 ? ":" + ("0" + Math.abs(offsetMinutes)).slice(-2) : ":" + ("0" + offsetMinutes).slice(-2);
149
+ preparedValue = date.toISOString().slice(0, -1) + offsetHours + offsetMinutes;
150
+ }
151
+ else if (!isNaN(date.getDay())) {
152
+ preparedValue = dayjs(String(preparedValue)).format(format);
153
+ }
154
+ else {
155
+ console.warn("If the attribute is missing, ISO 8601 is used.");
155
156
  }
156
157
  break;
157
158
  }
@@ -9,6 +9,7 @@ import defaults from "../../defaults";
9
9
  let mapIdCounter = 0;
10
10
 
11
11
  /**
12
+ * Recursive function.
12
13
  * Sets the cesium default scene params.
13
14
  * @param {Cesium.scene} scene The cesium scene.
14
15
  * @param {Object} params Optional configuration parameters.
@@ -21,7 +22,7 @@ export function setCesiumSceneParams (scene, params) {
21
22
  if (typeof paramValue === "object") {
22
23
  Object.keys(paramValue).forEach(paramSubKey => {
23
24
  if (paramSubKey !== "heading" && paramSubKey !== "tilt" && paramSubKey !== "altitude") {
24
- scene[paramKey][paramSubKey] = paramValue[paramSubKey];
25
+ setCesiumSceneParams(scene[paramKey], paramValue);
25
26
  }
26
27
  });
27
28
  }
@@ -228,9 +228,16 @@ function createStyle (styleObject, feature, isClustered, wfsImgPathFromConfig) {
228
228
  hasLabelField = style?.labelField,
229
229
  geometryStyle = getGeometryStyle(feature, rules, isClustered, wfsImgPathFromConfig),
230
230
  legendInformation = Array.isArray(geometryStyle) ? geometryStyle[0].legendInfos : geometryStyle.legendInfos,
231
- styleObjectGeometry = Array.isArray(geometryStyle) ? geometryStyle[0].getStyle() : geometryStyle.getStyle();
231
+ styleObjectGeometry = Array.isArray(geometryStyle) ? geometryStyle.map(styleItem => styleItem.getStyle()) : geometryStyle.getStyle();
232
232
 
233
- captureLegendFromFeature(styleObject.styleId, legendInformation);
233
+ if (geometryStyle.length > 1) {
234
+ for (const i in geometryStyle) {
235
+ captureLegendFromFeature(styleObject.styleId, geometryStyle[i].legendInfos);
236
+ }
237
+ }
238
+ else {
239
+ captureLegendFromFeature(styleObject.styleId, legendInformation);
240
+ }
234
241
 
235
242
  // label style is optional and depends on some fields
236
243
  if (isClustered || hasLabelField) {
@@ -1,7 +1,7 @@
1
1
  import {get as getProjection} from "ol/proj";
2
2
  import {getWidth} from "ol/extent";
3
3
 
4
- import * as wmts from "../../src/layer/wmts";
4
+ import wmts from "../../src/layer/wmts";
5
5
 
6
6
  describe("wmts.js", function () {
7
7
  describe("generateArrays", function () {
@@ -1,4 +1,4 @@
1
- import {mapAttributes, isObjectPath} from "../../src/lib/attributeMapper";
1
+ import {mapAttributes, isObjectPath, prepareValue} from "../../src/lib/attributeMapper";
2
2
 
3
3
  const props = {
4
4
  random_text: "foobar",
@@ -287,4 +287,26 @@ describe("src/utils/attributeMapper.js", () => {
287
287
  expect(isObjectPath(true)).toBe(false);
288
288
  });
289
289
  });
290
+ describe("prepareValue", () => {
291
+ it("returns value from object by dot notation key", () => {
292
+ const properties = {
293
+ address: {
294
+ street: "Platz"
295
+ }
296
+ },
297
+ testkey = "Address.Street";
298
+
299
+ expect(prepareValue(properties, testkey)).toEqual("Platz");
300
+ });
301
+ it("returns undefined from object by dot notation key if parentkey is not found", () => {
302
+ const properties = {
303
+ address: {
304
+ street: "Platz"
305
+ }
306
+ },
307
+ testkey = "Location.Street";
308
+
309
+ expect(prepareValue(properties, testkey)).toBeUndefined();
310
+ });
311
+ });
290
312
  });
package/test/map.test.js CHANGED
@@ -292,5 +292,68 @@ describe("map.js", function () {
292
292
  });
293
293
  });
294
294
  });
295
+ describe("setCesiumSceneParams", function () {
296
+ it("set the cesium scene parameter from config", function () {
297
+ global.Cesium = {};
298
+ global.Cesium.Color = {};
299
+ global.Cesium.Rectangle = {};
300
+ global.Cesium.Color.WHITE = {
301
+ "red": 1,
302
+ "green": 1,
303
+ "blue": 1,
304
+ "alpha": 1
305
+ };
306
+ global.Cesium.Rectangle.fromDegrees = function fromDegrees () {
307
+ return {
308
+ "west": 0.18151424220741028,
309
+ "south": 0.9107128036906411,
310
+ "east": 0.1858775653373961,
311
+ "north": 0.9138543963442309
312
+ };
313
+ };
314
+
315
+ const config = {
316
+ map2D: {
317
+ getView: () => {
318
+ return {
319
+ getProjection: () => {
320
+ return {getCode: () => "code"};
321
+ }
322
+ };
323
+ },
324
+ getViewport: () => {
325
+ return {
326
+ appendChild: jest.fn()
327
+ };
328
+ }
329
+ },
330
+ cesiumParameter: {
331
+ globe: {
332
+ showGroundAtmosphere: true,
333
+ baseColor: global.Cesium.Color.WHITE,
334
+ translucency: {
335
+ frontFaceAlpha: 0.50,
336
+ enabled: true,
337
+ rectangle: global.Cesium.Rectangle.fromDegrees(10.40, 52.18, 10.65, 52.36)
338
+ },
339
+ undergroundColor: undefined
340
+ }
341
+ },
342
+ cesiumLib: "https://lib.virtualcitymap.de/v3.6.x/lib/Cesium/Cesium.js"
343
+ };
344
+
345
+ load3DScriptModule.load3DScript(config.cesiumLib, function Loaded3DCallback () {
346
+ const map3D = map.createMap(config, "3D");
347
+
348
+ expect(map3D.mapMode).toBe("3D");
349
+ expect(map3D.getCesiumScene().globe.showGroundAtmosphere).toBe(config.cameraParameter.globe.showGroundAtmosphere);
350
+ expect(map3D.getCesiumScene().globe.baseColor).toBe(config.cameraParameter.globe.baseColor);
351
+ expect(map3D.getCesiumScene().globe.translucency.frontFaceAlpha).toBe(config.cameraParameter.globe.translucency.frontFaceAlpha);
352
+ expect(map3D.getCesiumScene().globe.translucency.enabled).toBe(config.cameraParameter.globe.translucency.enabled);
353
+ expect(map3D.getCesiumScene().globe.translucency.rectangle).toBe(config.cameraParameter.globe.translucency.rectangle);
354
+ expect(map3D.getCesiumScene().globe.undergroundColor()).toBe(config.cameraParameter.globe.undergroundColor);
355
+ });
356
+ });
357
+ });
295
358
 
296
359
  });