@masterportal/masterportalapi 2.12.0 → 2.14.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.
Files changed (50) hide show
  1. package/.eslintrc +2 -1
  2. package/CHANGELOG.md +19 -1
  3. package/example/config/portal.json +8 -1
  4. package/example/config/services.json +10 -0
  5. package/example/index.js +34 -2
  6. package/jest.config.js +1 -1
  7. package/jest.setup.js +9 -1
  8. package/package.json +63 -63
  9. package/src/layer/geojson/index.js +3 -3
  10. package/src/lib/attributeMapper.js +231 -0
  11. package/src/lib/getValueFromObjectByPath.js +73 -0
  12. package/src/lib/thousandsSeparator.js +23 -0
  13. package/src/maps/olcs/3dUtils/wmsRasterSynchronizer.js +3 -0
  14. package/src/vectorStyle/createStyle.js +259 -0
  15. package/src/vectorStyle/lib/colorConvertions.js +97 -0
  16. package/src/vectorStyle/lib/createLegendInfo.js +28 -0
  17. package/src/vectorStyle/lib/getGeometryTypeFromService.js +153 -0
  18. package/src/vectorStyle/lib/getRuleForIndex.js +62 -0
  19. package/src/vectorStyle/lib/valueOperations.js +172 -0
  20. package/src/vectorStyle/styleList.js +281 -0
  21. package/src/vectorStyle/styles/defaultStyles.js +177 -0
  22. package/src/vectorStyle/styles/point/stylePoint.js +108 -0
  23. package/src/vectorStyle/styles/point/stylePointCircle.js +29 -0
  24. package/src/vectorStyle/styles/point/stylePointIcon.js +79 -0
  25. package/src/vectorStyle/styles/point/stylePointInterval.js +124 -0
  26. package/src/vectorStyle/styles/point/stylePointNominal.js +232 -0
  27. package/src/vectorStyle/styles/point/stylePointRegularShape.js +39 -0
  28. package/src/vectorStyle/styles/polygon/polygonStyleHatch.js +160 -0
  29. package/src/vectorStyle/styles/polygon/stylePolygon.js +125 -0
  30. package/src/vectorStyle/styles/style.js +161 -0
  31. package/src/vectorStyle/styles/styleCesium.js +106 -0
  32. package/src/vectorStyle/styles/styleLine.js +51 -0
  33. package/src/vectorStyle/styles/styleText.js +143 -0
  34. package/test/lib/attributeMapper.test.js +290 -0
  35. package/test/lib/getValueFromObjectByPath.test.js +61 -0
  36. package/test/lib/thousandsSeparator.test.js +58 -0
  37. package/test/vectorStyle/createStyle.test.js +335 -0
  38. package/test/vectorStyle/lib/colorConvertions.test.js +42 -0
  39. package/test/vectorStyle/lib/getRuleForIndex.test.js +132 -0
  40. package/test/vectorStyle/lib/valueOperations.test.js +191 -0
  41. package/test/vectorStyle/styles/point/stylePoint.test.js +28 -0
  42. package/test/vectorStyle/styles/point/stylePointCircle.test.js +30 -0
  43. package/test/vectorStyle/styles/point/stylePointIcon.test.js +83 -0
  44. package/test/vectorStyle/styles/point/stylePointInterval.test.js +57 -0
  45. package/test/vectorStyle/styles/point/stylePointNominal.test.js +84 -0
  46. package/test/vectorStyle/styles/point/stylePointRegularShape.test.js +24 -0
  47. package/test/vectorStyle/styles/polygon/polygonStyleHatch.test.js +95 -0
  48. package/test/vectorStyle/styles/polygon/stylePolygon.test.js +61 -0
  49. package/test/vectorStyle/styles/styleLine.test.js +29 -0
  50. package/test/vectorStyle/styles/styleText.test.js +49 -0
package/.eslintrc CHANGED
@@ -3,7 +3,8 @@
3
3
  // browser global variables
4
4
  "browser": true,
5
5
  "node": true,
6
- "es6": true
6
+ "es6": true,
7
+ "jest": true
7
8
  },
8
9
  "globals": {
9
10
  "Cesium": true
package/CHANGELOG.md CHANGED
@@ -3,8 +3,26 @@
3
3
 
4
4
  The [Semantic Versioning](https://semver.org/spec/v2.0.0.html) is used.
5
5
 
6
+ ## 2.14.0 - 2023-02-22
7
+ ### Added
8
+ - VectorStyle is now part of the masterportalApi.
9
+ - The following packages have been installed:
10
+ - use-resize-observer: 9.1.0
11
+
12
+ ### Changed
13
+ - The following packages have been updated:
14
+ - dependencies:
15
+ - ol: 7.1.0 to 7.2.2
16
+
17
+ ---
18
+
19
+ ## 2.13.0 - 2023-02-16
20
+ ### Changed
21
+ - GeoJSON now also register a featuresloadend function if the source is a cluster.
22
+
23
+ ---
6
24
 
7
- ## 2.12.0 - 2022-01-24
25
+ ## 2.12.0 - 2023-01-24
8
26
  ### Added
9
27
  - Added support for Node LTS version 18.
10
28
  - Add possibility to specify additional layerparams for a wmts layer, like opacity for example.
@@ -29,7 +29,14 @@
29
29
  "layers": [
30
30
  {
31
31
  "id": "1001"
32
+ },
33
+ {
34
+ "id": "8712",
35
+ "name": "Schulinfosystem",
36
+ "styleId": "8712",
37
+ "typ": "WFS"
32
38
  }
33
39
  ],
34
- "cesiumLib":"https://geoportal-hamburg.de/mastercode/cesium/1_99/Cesium.js"
40
+ "cesiumLib":"https://geoportal-hamburg.de/mastercode/cesium/1_99/Cesium.js",
41
+ "wfsImgPath": "https://geodienste.hamburg.de/lgv-config/img/"
35
42
  }
@@ -113,6 +113,16 @@
113
113
  "anzahl_schueler": ">1000"
114
114
  }
115
115
  },
116
+ {
117
+ "id": "8712",
118
+ "name": "de.hh.up:staatliche schulen",
119
+ "url": "https://geodienste.hamburg.de/HH_WFS_Schulen",
120
+ "typ": "WFS",
121
+ "featureType": "staatliche_schulen",
122
+ "outputFormat": "XML",
123
+ "version": "1.1.0",
124
+ "featureNS": "https://registry.gdi-de.org/id/de.hh.up"
125
+ },
116
126
  {
117
127
  "id": "6001",
118
128
  "name": "ADV (EPSG:25832)",
package/example/index.js CHANGED
@@ -5,6 +5,8 @@ import {Style, Stroke, Fill, Icon} from "ol/style.js";
5
5
  import * as mpapi from "../src";
6
6
  import mapsAPI from "../src/maps/api.js";
7
7
  import rawLayerList from "../src/rawLayerList";
8
+ import styleList from "../src/vectorStyle/styleList";
9
+ import createStyle from "../src/vectorStyle/createStyle";
8
10
 
9
11
  import services from "./config/services.json";
10
12
  import portalConfig from "./config/portal.json";
@@ -31,7 +33,25 @@ const hamburgServicesUrl = "https://geodienste.hamburg.de/services-internet.json
31
33
  },
32
34
  config = {
33
35
  ...portalConfig,
34
- layerConf: services
36
+ layerConf: services,
37
+ styleConf: "https://geodienste.hamburg.de/lgv-config/style_v3.json"
38
+ },
39
+ // eslint-disable-next-line func-style
40
+ getWfsStyleFunction = function () {
41
+ const styleId = "8712",
42
+ olLayer = window.mpapi.map.getLayers().getArray().find((element) => element.get("id") === "8712"),
43
+ source = olLayer.getSource(),
44
+ styleObject = styleList.returnStyleObject(styleId);
45
+ let isClusterFeature = false;
46
+
47
+ if (styleObject !== undefined) {
48
+ source.on("featuresloadend", event => {
49
+ event.features.forEach(element => {
50
+ isClusterFeature = false;
51
+ element.setStyle(createStyle.createStyle(styleObject, element, isClusterFeature, config.wfsImgPath));
52
+ });
53
+ });
54
+ }
35
55
  };
36
56
  let map2D = null;
37
57
 
@@ -237,4 +257,16 @@ map2D.getLayers().forEach(layer => {
237
257
  window.mpapi.map.addLayer("7001");
238
258
  window.mpapi.map.addLayer("7002");
239
259
  window.mpapi.map.addLayer("7003");
240
- // */
260
+ */
261
+
262
+ /* VectorStyle example */
263
+ // Example for using the vectorStyle that is now implemented in the masterportalAPI.
264
+ // Hardcoded to show the school layer "8712" as a wfs.
265
+ // For better visibility adding of the other layers, especially "5001", should be commented out.
266
+ styleList.initializeStyleList({}, config, config.layers, undefined, (initializedStyleList, error) => {
267
+ if (error) {
268
+ console.error("Die Datei " + config.styleConf + " konnte nicht geladen werden!");
269
+ }
270
+ return initializedStyleList;
271
+ });
272
+ getWfsStyleFunction();
package/jest.config.js CHANGED
@@ -3,7 +3,7 @@ module.exports = {
3
3
  /** ol prints errors without HTMLCanvasElement being available in test environment */
4
4
  "setupFiles": ["jest-canvas-mock"],
5
5
  /** node_modules are usually ignored by babel-jest, but ol is published in ES6 */
6
- "transformIgnorePatterns": ["/node_modules/(?!(ol|olcs|ol-mapbox-style|geotiff)/).*/"],
6
+ "transformIgnorePatterns": ["/node_modules/(?!(ol|olcs|ol-mapbox-style|geotiff|quick-lru)/).*/"],
7
7
  /** only consider files in src/ for coverage */
8
8
  "collectCoverageFrom": ["src/**/*.js"],
9
9
  /** coverage reporters */
package/jest.setup.js CHANGED
@@ -2,4 +2,12 @@ import "regenerator-runtime/runtime";
2
2
 
3
3
  window.URL.createObjectURL = function () {
4
4
  // empty
5
- };
5
+ };
6
+
7
+ window.ResizeObserver =
8
+ window.ResizeObserver ||
9
+ jest.fn().mockImplementation(() => ({
10
+ disconnect: jest.fn(),
11
+ observe: jest.fn(),
12
+ unobserve: jest.fn()
13
+ }));
package/package.json CHANGED
@@ -1,63 +1,63 @@
1
- {
2
- "name": "@masterportal/masterportalapi",
3
- "author": "Implementierungspartnerschaft Masterportal <info@masterportal.org> (https://www.masterportal.org)",
4
- "version": "2.12.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.27.1",
23
- "ol": "7.1.0",
24
- "olcs": "^2.13.1",
25
- "proj4": "^2.8.1",
26
- "xml2js": "^0.4.23"
27
- },
28
- "devDependencies": {
29
- "@babel/core": "^7.20.12",
30
- "@babel/plugin-transform-modules-commonjs": "^7.20.11",
31
- "@parcel/transformer-sass": "^2.6.0",
32
- "buffer": "^6.0.3",
33
- "canvas": "^2.11.0",
34
- "eslint": "^8.31.0",
35
- "events": "^3.3.0",
36
- "husky": "^8.0.3",
37
- "jest": "^29.3.1",
38
- "jest-canvas-mock": "^2.4.0",
39
- "jest-environment-jsdom": "^29.3.1",
40
- "jsdoc": "^4.0.0",
41
- "parcel": "^2.6.0",
42
- "process": "^0.11.10",
43
- "sass": "^1.57.1",
44
- "stream-browserify": "^3.0.0",
45
- "timers-browserify": "^2.0.12"
46
- },
47
- "peerDependencies": {
48
- "cesium": "^1.95.0"
49
- },
50
- "engines": {
51
- "node": "^16.13.2 || ^18.12.0",
52
- "npm": "^8.1.2"
53
- },
54
- "homepage": "https://bitbucket.org/geowerkstatt-hamburg/masterportalapi#readme",
55
- "directories": {
56
- "doc": "docs",
57
- "example": "example",
58
- "test": "test"
59
- },
60
- "bugs": {
61
- "url": "https://bitbucket.org/geowerkstatt-hamburg/masterportalapi/issues"
62
- }
63
- }
1
+ {
2
+ "name": "@masterportal/masterportalapi",
3
+ "author": "Implementierungspartnerschaft Masterportal <info@masterportal.org> (https://www.masterportal.org)",
4
+ "version": "2.14.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.27.1",
23
+ "ol": "7.2.2",
24
+ "olcs": "^2.13.1",
25
+ "proj4": "^2.8.1",
26
+ "xml2js": "^0.4.23"
27
+ },
28
+ "devDependencies": {
29
+ "@babel/core": "^7.20.12",
30
+ "@babel/plugin-transform-modules-commonjs": "^7.20.11",
31
+ "@parcel/transformer-sass": "^2.6.0",
32
+ "buffer": "^6.0.3",
33
+ "canvas": "^2.11.0",
34
+ "eslint": "^8.31.0",
35
+ "events": "^3.3.0",
36
+ "husky": "^8.0.3",
37
+ "jest": "^29.3.1",
38
+ "jest-canvas-mock": "^2.4.0",
39
+ "jest-environment-jsdom": "^29.3.1",
40
+ "jsdoc": "^4.0.0",
41
+ "parcel": "^2.6.0",
42
+ "process": "^0.11.10",
43
+ "sass": "^1.57.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"
54
+ },
55
+ "homepage": "https://bitbucket.org/geowerkstatt-hamburg/masterportalapi#readme",
56
+ "directories": {
57
+ "example": "example",
58
+ "test": "test"
59
+ },
60
+ "bugs": {
61
+ "url": "https://bitbucket.org/geowerkstatt-hamburg/masterportalapi/issues"
62
+ }
63
+ }
@@ -22,11 +22,11 @@ export function createLayerSource ({url, features, clusterDistance}, options) {
22
22
 
23
23
  source = createVectorSource(url || features, options.loadingStrategy, format);
24
24
 
25
- if (clusterDistance) {
26
- return createClusterVectorSource(source, clusterDistance, options.clusterGeometryFunction);
25
+ if (typeof clusterDistance === "number") {
26
+ source = createClusterVectorSource(source, clusterDistance, options.clusterGeometryFunction);
27
27
  }
28
28
 
29
- source.once("featuresloadend", event => {
29
+ (typeof clusterDistance === "number" ? source.getSource() : source).once("featuresloadend", event => {
30
30
  if (typeof options.afterLoading === "function") {
31
31
  options.afterLoading(event?.features);
32
32
  }
@@ -0,0 +1,231 @@
1
+ import {getValueFromObjectByPath} from "./getValueFromObjectByPath.js";
2
+ import thousandsSeparator from "./thousandsSeparator";
3
+ /**
4
+ * checks if value starts with special prefix to determine if value is a object path
5
+ * @param {string} value string to check
6
+ * @returns {Boolean} true is value is an object path
7
+ */
8
+ function isObjectPath (value) {
9
+ return typeof value === "string" && value.startsWith("@");
10
+ }
11
+ /**
12
+ * Returns the value of the given key. Also considers, that the key may be an object path.
13
+ * @param {Object} properties properties.
14
+ * @param {String} key Key to derive value from.
15
+ * @returns {*} - Value from key.
16
+ */
17
+ function prepareValue (properties, key) {
18
+ const isPath = isObjectPath(key);
19
+ let value = properties[Object.keys(properties).find(propertiesKey => propertiesKey.toLowerCase() === key.toLowerCase())];
20
+
21
+ if (isPath) {
22
+ value = getValueFromObjectByPath(properties, key);
23
+ }
24
+ return value;
25
+ }
26
+
27
+ /**
28
+ * Parsing the boolean value
29
+ * @param {String} value default value
30
+ * @param {String|Object} format the format of boolean value
31
+ * @returns {String} - original value or parsed value
32
+ */
33
+ function getBooleanValue (value, format) {
34
+ let parsedValue = String(value);
35
+
36
+ if (Object.prototype.hasOwnProperty.call(format, value)) {
37
+ // TODO: check if true -> translation is dismissed because i18next does not exist in masterportalApi
38
+ parsedValue = format[value];
39
+
40
+ }
41
+ return parsedValue;
42
+ }
43
+
44
+ /**
45
+ * Appends a suffix if available.
46
+ * @param {*} value Value to append suffix.
47
+ * @param {String} suffix Suffix
48
+ * @returns {String} - Value with suffix.
49
+ */
50
+ function appendSuffix (value, suffix) {
51
+ let valueWithSuffix = value;
52
+
53
+ if (suffix) {
54
+ valueWithSuffix = String(valueWithSuffix) + " " + suffix;
55
+ }
56
+ return valueWithSuffix;
57
+ }
58
+
59
+ /**
60
+ * Prepend a prefix if available.
61
+ * @param {*} value Value to prepend prefix.
62
+ * @param {String} prefix Prefix
63
+ * @returns {String} - Value with prefix.
64
+ */
65
+ function prependPrefix (value, prefix) {
66
+ let valueWithPrefix = value;
67
+
68
+ if (prefix) {
69
+ valueWithPrefix = prefix + String(valueWithPrefix);
70
+ }
71
+ return valueWithPrefix;
72
+ }
73
+
74
+ /**
75
+ * Derives the value from the given condition.
76
+ * @param {String} key Key.
77
+ * @param {String} condition Condition to filter.
78
+ * @param {Object} properties Properties.
79
+ * @returns {*} - Value that matches the given condition.
80
+ */
81
+ function getValueFromCondition (key, condition, properties) {
82
+ let valueFromCondition,
83
+ match;
84
+
85
+ if (condition === "contains") {
86
+ match = Object.keys(properties).filter(key2 => {
87
+ return key2.includes(key);
88
+ })[0];
89
+ valueFromCondition = properties[match];
90
+ }
91
+ else if (condition === "startsWith") {
92
+ match = Object.keys(properties).filter(key2 => {
93
+ return key2.startsWith(key);
94
+ })[0];
95
+ valueFromCondition = properties[match];
96
+ }
97
+ else if (condition === "endsWith") {
98
+ match = Object.keys(properties).filter(key2 => {
99
+ return key2.endsWith(key);
100
+ })[0];
101
+ valueFromCondition = properties[match];
102
+ }
103
+ else {
104
+ valueFromCondition = properties[key];
105
+ }
106
+
107
+ return valueFromCondition;
108
+
109
+ }
110
+
111
+ /**
112
+ * Derives the gfi value if the value is an object.
113
+ * @param {*} key Key of Attribute.
114
+ * @param {Object} mappingObj Value of attribute.
115
+ * @param {Object} properties object.
116
+ * @returns {*} - Prepared Value
117
+ */
118
+ function prepareValueFromObject (key, mappingObj, properties) {
119
+ const type = mappingObj?.type ? mappingObj.type : "string",
120
+ condition = mappingObj?.condition ? mappingObj.condition : null;
121
+ let preparedValue = prepareValue(properties, key),
122
+ format = mappingObj?.format ? mappingObj.format : "YYYY-MM-DDTHH:mm:ss.SSSZ",
123
+ date;
124
+
125
+ if (condition) {
126
+ preparedValue = getValueFromCondition(key, condition, properties);
127
+ }
128
+ switch (type) {
129
+ case "date": {
130
+ 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
+ }
155
+ }
156
+ break;
157
+ }
158
+ case "number": {
159
+ preparedValue = thousandsSeparator(preparedValue);
160
+ break;
161
+ }
162
+ case "linechart": {
163
+ preparedValue = Object.assign({
164
+ name: key,
165
+ staObject: preparedValue
166
+ }, mappingObj);
167
+ break;
168
+ }
169
+ case "boolean": {
170
+ format = format === "DD.MM.YYYY HH:mm:ss" ? {true: "true", false: "false"} : format;
171
+ preparedValue = getBooleanValue(preparedValue, format);
172
+ break;
173
+ }
174
+ // default equals to mappingObj.type === "string"
175
+ default: {
176
+ preparedValue = String(preparedValue);
177
+ }
178
+ }
179
+ if (preparedValue && mappingObj.suffix && preparedValue !== "undefined") {
180
+ preparedValue = appendSuffix(preparedValue, mappingObj.suffix);
181
+ }
182
+ if (preparedValue && mappingObj.prefix && preparedValue !== "undefined") {
183
+ preparedValue = prependPrefix(preparedValue, mappingObj.prefix);
184
+ }
185
+ return preparedValue;
186
+ }
187
+
188
+ /**
189
+ * Maps the feature properties by the given object.
190
+ * @param {Object} properties The feature properties.
191
+ * @param {Object} mappingObject Object to me mapped.
192
+ * @param {Boolean} [isNested=true] Flag if Object is nested, like "gfiAttributes".
193
+ * @returns {Object} The mapped properties.
194
+ */
195
+ function mapAttributes (properties, mappingObject, isNested = true) {
196
+ let mappedProperties;
197
+
198
+ if (!mappingObject) {
199
+ return false;
200
+ }
201
+ if (!isNested) {
202
+ if (typeof mappingObject === "string") {
203
+ mappedProperties = prepareValue(properties, mappingObject);
204
+ }
205
+ else {
206
+ mappedProperties = prepareValueFromObject(mappingObject.name, mappingObject, properties);
207
+ }
208
+ }
209
+ else {
210
+ mappedProperties = {};
211
+ Object.keys(mappingObject).forEach(key => {
212
+ let newKey = mappingObject[key],
213
+ value = prepareValue(properties, key);
214
+
215
+ if (typeof newKey === "object") {
216
+ value = prepareValueFromObject(key, newKey, properties);
217
+ newKey = newKey.name;
218
+ }
219
+ if (value && value !== "undefined") {
220
+ mappedProperties[newKey] = value;
221
+ }
222
+ });
223
+ }
224
+ return mappedProperties;
225
+ }
226
+
227
+ export {
228
+ mapAttributes,
229
+ isObjectPath,
230
+ prepareValue
231
+ };
@@ -0,0 +1,73 @@
1
+ /**
2
+ * gets the parts of the given path splitted by ".", ignoring escaped "."
3
+ * @param {String} path the path to split
4
+ * @param {String} [delimitor="."] the delimitor to use
5
+ * @returns {String[]} the resulting parts of the path
6
+ */
7
+ function getPathPartsFromPath (path, delimitor = ".") {
8
+ const len = path.length,
9
+ result = [];
10
+ let letter = "",
11
+ word = "";
12
+
13
+ for (let i = 0; i < len; i++) {
14
+ letter = path[i];
15
+
16
+ if (letter === "\\") {
17
+ i++;
18
+ letter = path[i];
19
+ }
20
+ else if (letter === delimitor) {
21
+ result.push(word);
22
+ word = "";
23
+ continue;
24
+ }
25
+ word += letter;
26
+ }
27
+
28
+ if (word) {
29
+ result.push(word);
30
+ }
31
+ return result;
32
+ }
33
+ /**
34
+ * uses the given path to go into the given object and returns the value found at the end
35
+ * @info arrays can be accessed by using a number as index (e.g. "@Test.0.test")
36
+ * @param {Object} obj an object or array to search through
37
+ * @param {String} path the path to follow through the given object
38
+ * @param {String} [prefix="@"] the prefix to use to recognize the string as path to follow
39
+ * @param {String} [delimitor="."] the delimitor to use
40
+ * @param {Number} [depthBarrier=20] the depth barrier to avoid infinit recurtions
41
+ * @returns {*} any value found at the end or undefined if nothing was found
42
+ */
43
+ function getValueFromObjectByPath (obj, path, prefix = "@", delimitor = ".", depthBarrier = 20) {
44
+ if (
45
+ typeof obj !== "object"
46
+ || obj === null
47
+ || typeof path !== "string"
48
+ || (
49
+ typeof prefix === "string"
50
+ && path.substr(0, prefix.length) !== prefix
51
+ )
52
+ ) {
53
+ return undefined;
54
+ }
55
+ const pathParts = getPathPartsFromPath(typeof prefix === "string" ? path.substring(prefix.length) : path, delimitor),
56
+ len = pathParts.length;
57
+ let value = obj,
58
+ depth = 0;
59
+
60
+ for (let i = 0; i < len; i++) {
61
+ if (typeof value !== "object" || value === null) {
62
+ return undefined;
63
+ }
64
+ value = value[pathParts[i]];
65
+ depth++;
66
+ if (typeof value === "undefined" || depth > depthBarrier) {
67
+ return undefined;
68
+ }
69
+ }
70
+ return value;
71
+ }
72
+
73
+ export {getValueFromObjectByPath, getPathPartsFromPath};
@@ -0,0 +1,23 @@
1
+
2
+ /**
3
+ * adds thousands seperators into a number and changes the decimal point
4
+ * @param {(Number|String)} num the number as number or string
5
+ * @param {String} [delimAbs="."] the letter(s) to use as thousand point
6
+ * @param {String} [delimDec=","] the letter(s) to use as decimal point
7
+ * @returns {String} the given number with thousands seperators or an empty string if any invalid num was given
8
+ */
9
+ function thousandsSeparator (num, delimAbs = ".", delimDec = ",") {
10
+ if (typeof num !== "number" && typeof num !== "string") {
11
+ return "";
12
+ }
13
+
14
+ const value = typeof num !== "string" ? num.toString() : num,
15
+ decPointPos = value.indexOf("."),
16
+ abs = decPointPos > -1 ? value.substring(0, decPointPos) : value,
17
+ result = abs.replace(/\B(?=(\d{3})+(?!\d),?.*)/g, delimAbs),
18
+ dec = decPointPos > -1 ? value.substring(decPointPos + 1) : false;
19
+
20
+ return dec ? result + delimDec + dec : result;
21
+ }
22
+
23
+ export default thousandsSeparator;
@@ -118,6 +118,9 @@ class WMSRasterSynchronizer extends olcsAbstractSynchronizer {
118
118
  provider = this.createProviderForStaticImageSource(source);
119
119
  }
120
120
  else if (source instanceof WMTS) {
121
+ if (typeof source.getUrls !== "function" || !Array.isArray(source.getUrls())) {
122
+ return null;
123
+ }
121
124
  provider = new Cesium.WebMapTileServiceImageryProvider({
122
125
  url: source.getUrls()[0],
123
126
  format: source.getFormat(),