@masterportal/masterportalapi 2.27.0 → 2.29.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
@@ -5,20 +5,75 @@
5
5
 
6
6
  ### Unreleased - in development
7
7
  ## Added
8
+
8
9
  ## Changed
10
+
9
11
  ## Deprecated
12
+
10
13
  ## Removed
14
+
11
15
  ## Fixed
12
16
 
13
17
  ---
14
18
 
15
- ### 2.27.0 - 2023-08-31
19
+ ### 2.29.0 - 2023-10-27
16
20
  ## Added
21
+ - The following packages from parcel automatic were installed for node builtin:
22
+ - dependencies:
23
+ - assert": 2.1.0,
24
+ - browserify-zlib: 0.2.0,
25
+ - https-browserify: 1.0.0
26
+ - stream-http: 3.2.0
27
+ - url: 0.11.3
28
+ - util: 0.12.5
29
+ - The following packages have been added:
30
+ - dependencies:
31
+ - ol-mapbox-style: 12.0.0
32
+
17
33
  ## Changed
18
- - VectorStyle: 'initializeStyleList' is asynchron, waits for loading finished and returns the loaded styles.
19
- ## Deprecated
20
- ## Removed
34
+ - The following packages have been updated:
35
+ - dependencies:
36
+ - core-js: 3.32.0 to 3.33.1
37
+ - dayjs: 1.11.9 to 1.11.10
38
+ - ol: 7.5.2 to 8.1.0 (includes the change of the symbol style format in ol/layer/WebGLPointsLayer)
39
+ - olcs: 2.15.0 to 2.16.0
40
+ - proj4: 2.9.0 to 2.9.1
41
+ - devDependencies:
42
+ - @babel/core: 7.22.9 to 7.23.2
43
+ - @babel/plugin-transform-modules-commonjs: 7.22.5 to 7.23.2
44
+ - @parcel/transformer-sass: 2.9.3 to 2.10.0
45
+ - @swc/jest: 0.2.27 to 0.2.29
46
+ - eslint: 8.46.0 to 8.52.0
47
+ - jest: 29.6.2 to 29.7.0
48
+ - jest-environment-jsdom: 29.6.2 to 29.7.0
49
+ - parcel: 2.9.3 to 2.10.0
50
+ - sass: 1.64.2 to 1.69.4
51
+ - Revert Cesium.Cesium3DTileset.fromUrl(url, options) adaptions in tileset.js for Cesium v1.107 deprecated warnings
52
+
21
53
  ## Fixed
54
+ - styleList: styles of type oaf are now also added to the stylelist
55
+ - Issue Masterportal #1052 VectorStyle: path to an icon in the map or in the legend in style.json may be an icon name, a relative path to icon, a complete url or an svg.
56
+
57
+ ---
58
+
59
+ ### 2.28.0 - 2023-09-27
60
+ ## Added
61
+ - GfiAttributes: GFI Attributes can now be configured as HTML tags, e.g <a>, <img> or <iframe>
62
+
63
+ ## Changed
64
+ - The following packages have been updated:
65
+ - dependencies:
66
+ - ol: 7.5.1 to 7.5.2 (This version fix a bug for vectorTiles with declutter: true)
67
+ ## Fixed
68
+ - Issue Masterportal #1067 VectorStyle: if there is a ? in the services URL, no further one is added
69
+ - Cesium tileset: set visibility and set opacity was fixed.
70
+ - Webgl: set default style for feature and fix the opacity problem
71
+
72
+ ---
73
+
74
+ ### 2.27.0 - 2023-08-31
75
+ ## Changed
76
+ - VectorStyle: 'initializeStyleList' is asynchron, waits for loading finished and returns the loaded styles.
22
77
 
23
78
  ---
24
79
 
@@ -31,7 +86,6 @@
31
86
  ---
32
87
 
33
88
  ## 2.25.0 - 2023-08-21
34
-
35
89
  ### Changed
36
90
  - WebGL: method "afterLoading" catches MultiPoint geometries and parses them to a single point feature for proper rendering
37
91
  - WebGL Render-Pipeline for VectorLayer of type VectorTile can be called using {"renderer": "webgl"} in config.json.
@@ -56,30 +56,11 @@
56
56
  "renderer": "webgl",
57
57
  "hitTolerance": 20,
58
58
  "isPointLayer": true,
59
- "style": {
60
- "symbol": {
61
- "symbolType": "circle",
62
- "size": [
63
- "interpolate",
64
- ["linear"],
65
- ["get", "Total_votes"],
66
- 0,
67
- 6,
68
- 18,
69
- 24
70
- ],
71
- "color": [
72
- "interpolate",
73
- ["linear"],
74
- ["get", "compound"],
75
- -1,
76
- [240, 40, 30],
77
- 1,
78
- [0, 200, 60]
79
- ],
80
- "opacity": 0.8,
81
- "rotateWithView": true
82
- }
59
+ "style":{
60
+ "circle-radius": [ "interpolate", ["linear"], ["get", "Total_votes"], 0, 3, 18, 12 ],
61
+ "circle-fill-color": [ "interpolate", ["linear"], ["get", "compound"], -1, [240, 40, 30], 1, [0, 200, 60] ],
62
+ "circle-rotate-with-view": true,
63
+ "circle-opacity": 0.8
83
64
  }
84
65
  }
85
66
  ],
@@ -32,7 +32,7 @@
32
32
  "id": "2001",
33
33
  "typ": "GeoJSON",
34
34
  "name": "Landesgrenze Hamburg",
35
- "url": "https://geoportal-hamburg.de/lgv-config/landesgrenze_hh.json"
35
+ "url": "https://geodienste.hamburg.de/lgv-config/landesgrenze_hh.json"
36
36
  },
37
37
  {
38
38
  "id": "3001",
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.27.0",
4
+ "version": "2.29.0",
5
5
  "license": "MIT",
6
6
  "description": "Basic functions of the Masterportal as api",
7
7
  "repository": {
@@ -19,34 +19,41 @@
19
19
  "prepare": "husky install"
20
20
  },
21
21
  "dependencies": {
22
- "core-js": "^3.32.0",
23
- "dayjs": "^1.11.9",
24
- "ol": "7.5.1",
25
- "olcs": "^2.15.0",
26
- "proj4": "^2.9.0",
22
+ "core-js": "^3.33.1",
23
+ "dayjs": "^1.11.10",
24
+ "ol": "8.1.0",
25
+ "ol-mapbox-style": "12.0.0",
26
+ "olcs": "2.16.0",
27
+ "proj4": "^2.9.1",
27
28
  "xml2js": "^0.6.2"
28
29
  },
29
30
  "devDependencies": {
30
- "@babel/core": "^7.22.9",
31
- "@babel/plugin-transform-modules-commonjs": "^7.22.5",
32
- "@parcel/transformer-sass": "^2.9.3",
33
- "@swc/jest": "^0.2.27",
31
+ "@babel/core": "^7.23.2",
32
+ "@babel/plugin-transform-modules-commonjs": "^7.23.0",
33
+ "@parcel/transformer-sass": "^2.10.0",
34
+ "@swc/jest": "^0.2.29",
35
+ "assert": "^2.1.0",
36
+ "browserify-zlib": "^0.2.0",
34
37
  "buffer": "^6.0.3",
35
38
  "canvas": "^2.11.2",
36
- "eslint": "^8.46.0",
39
+ "eslint": "^8.52.0",
37
40
  "events": "^3.3.0",
41
+ "https-browserify": "^1.0.0",
38
42
  "husky": "^8.0.3",
39
- "jest": "^29.6.2",
43
+ "jest": "^29.7.0",
40
44
  "jest-canvas-mock": "^2.5.2",
41
- "jest-environment-jsdom": "^29.6.2",
45
+ "jest-environment-jsdom": "^29.7.0",
42
46
  "jest-fetch-mock": "^3.0.3",
43
47
  "jsdoc": "^4.0.2",
44
- "parcel": "^2.9.3",
48
+ "parcel": "^2.10.0",
45
49
  "process": "^0.11.10",
46
- "sass": "^1.64.2",
50
+ "sass": "^1.69.4",
47
51
  "stream-browserify": "^3.0.0",
52
+ "stream-http": "^3.2.0",
48
53
  "timers-browserify": "^2.0.12",
49
- "use-resize-observer": "^9.1.0"
54
+ "url": "^0.11.3",
55
+ "use-resize-observer": "^9.1.0",
56
+ "util": "^0.12.5"
50
57
  },
51
58
  "peerDependencies": {
52
59
  "@cesium/engine": "^2.4.1"
@@ -13,8 +13,8 @@ function createTileSet (rawLayer) {
13
13
  if (rawLayer.cesium3DTilesetOptions) {
14
14
  Object.assign(options, rawLayer.cesium3DTilesetOptions);
15
15
  }
16
-
17
- return Promise.resolve(Cesium.Cesium3DTileset.fromUrl(url, options));
16
+ options.url = url;
17
+ return new Cesium.Cesium3DTileset(options);
18
18
  }
19
19
 
20
20
  /**
@@ -33,13 +33,8 @@ export default function Tileset (rawLayer) {
33
33
  typ: rawLayer.typ
34
34
  };
35
35
  if (Cesium) {
36
- this.tileset = Promise.resolve(createTileSet(rawLayer));
37
- this.tileset.then(function (tileset) {
38
- if (tileset) {
39
- tileset.layerReferenceId = rawLayer.id;
40
- }
41
- });
42
-
36
+ this.tileset = createTileSet(rawLayer);
37
+ this.tileset.layerReferenceId = rawLayer.id;
43
38
  }
44
39
  }
45
40
 
@@ -76,15 +71,10 @@ Tileset.prototype.setVisible = function (value, map) {
76
71
  if (map && typeof map.getCesiumScene === "function") {
77
72
  if (value) {
78
73
  if (!map.getCesiumScene().primitives.contains(this.tileset)) {
79
- this.tileset.then(function (tileset) {
80
- map.getCesiumScene().primitives.add(tileset);
81
- });
74
+ map.getCesiumScene().primitives.add(this.tileset);
82
75
  }
83
- this.tileset.show = true;
84
- }
85
- else {
86
- this.tileset.show = false;
87
76
  }
77
+ this.tileset.show = value;
88
78
  }
89
79
  };
90
80
 
@@ -118,6 +118,29 @@ function getValueFromCondition (key, condition, properties) {
118
118
 
119
119
  }
120
120
 
121
+ /**
122
+ * Maps the feature properties by the given object. if the value is the wildcard '%value%' then the prepared value is taken.
123
+ * @param {HTML} htmltag The html tag.
124
+ * @param {Object} properties The properties for the htmltag.
125
+ * @param {String} preparedValue The prepared value.
126
+ * @returns {HTML} The html tag with mapped properties.
127
+ */
128
+ function addPropertiesToHtmlTag (htmltag, properties, preparedValue) {
129
+ const htmltagWithproperties = htmltag;
130
+
131
+ if (properties) {
132
+ Object.keys(properties).forEach(prop => {
133
+ if (properties[prop] === "%value%") {
134
+ htmltagWithproperties.setAttribute(prop, preparedValue);
135
+ }
136
+ else {
137
+ htmltagWithproperties.setAttribute(prop, properties[prop]);
138
+ }
139
+ });
140
+ }
141
+ return htmltagWithproperties;
142
+ }
143
+
121
144
  /**
122
145
  * Derives the gfi value if the value is an object.
123
146
  * @param {*} key Key of Attribute.
@@ -127,10 +150,12 @@ function getValueFromCondition (key, condition, properties) {
127
150
  */
128
151
  function prepareValueFromObject (key, mappingObj, properties) {
129
152
  const type = mappingObj?.type ? mappingObj.type : "string",
130
- condition = mappingObj?.condition ? mappingObj.condition : null;
153
+ condition = mappingObj?.condition ? mappingObj.condition : null,
154
+ serializer = new XMLSerializer();
131
155
  let preparedValue = prepareValue(properties, key),
132
156
  format = mappingObj?.format ? mappingObj.format : "YYYY-MM-DDTHH:mm:ss.SSSZ",
133
- date;
157
+ date,
158
+ htmltag;
134
159
 
135
160
  if (condition) {
136
161
  preparedValue = getValueFromCondition(key, condition, properties);
@@ -172,6 +197,32 @@ function prepareValueFromObject (key, mappingObj, properties) {
172
197
  preparedValue = getBooleanValue(preparedValue, format);
173
198
  break;
174
199
  }
200
+ case "html": {
201
+ // create tag
202
+ if (mappingObj?.html?.tag) {
203
+ htmltag = document.createElement(mappingObj?.html?.tag);
204
+ }
205
+ // create innerHTML
206
+ if (mappingObj?.html?.innerHTML === "%value%") {
207
+ htmltag.innerHTML = preparedValue;
208
+ }
209
+ else if (mappingObj?.html?.innerHTML) {
210
+ htmltag.innerHTML = mappingObj?.html?.innerHTML;
211
+ }
212
+
213
+
214
+ if (htmltag) {
215
+ if (mappingObj?.html?.properties) {
216
+ htmltag = addPropertiesToHtmlTag(htmltag, mappingObj?.html?.properties, preparedValue);
217
+ }
218
+ preparedValue = serializer.serializeToString(htmltag);
219
+ // remove xmlns
220
+ preparedValue = preparedValue.replace(/ xmlns="(.*?)"/g, "");
221
+
222
+ }
223
+
224
+ break;
225
+ }
175
226
  // default equals to mappingObj.type === "string"
176
227
  default: {
177
228
  preparedValue = String(preparedValue);
@@ -6,8 +6,8 @@ import {getUid} from "olcs/util.js";
6
6
  import TileWMS from "ol/source/TileWMS.js";
7
7
  import ImageWMS from "ol/source/ImageWMS.js";
8
8
  import WMTS from "ol/source/WMTS.js";
9
- import olcsAbstractSynchronizer from "olcs/AbstractSynchronizer.ts";
10
- import {extentToRectangle, tileLayerToImageryLayer, updateCesiumLayerProperties} from "olcs/core.ts";
9
+ import olcsAbstractSynchronizer from "olcs/AbstractSynchronizer.js";
10
+ import {extentToRectangle, tileLayerToImageryLayer, updateCesiumLayerProperties} from "olcs/core.js";
11
11
  import {Tile, Image as ImageLayer} from "ol/layer.js";
12
12
  import {stableSort} from "ol/array.js";
13
13
  import {getBottomLeft, getBottomRight, getTopRight, getTopLeft} from "ol/extent.js";
@@ -1,6 +1,6 @@
1
- import OLCesium from "olcs/OLCesium.ts";
1
+ import OLCesium from "olcs/OLCesium.js";
2
2
  import {transform, get} from "ol/proj.js";
3
- import VectorSynchronizer from "olcs/VectorSynchronizer.ts";
3
+ import VectorSynchronizer from "olcs/VectorSynchronizer.js";
4
4
 
5
5
  import FixedOverlaySynchronizer from "./3dUtils/fixedOverlaySynchronizer.js";
6
6
  import WMSRasterSynchronizer from "./3dUtils/wmsRasterSynchronizer.js";
@@ -14,26 +14,29 @@ import {packColor, parseLiteralStyle} from "ol/webgl/styleparser.js";
14
14
  * @see https://openlayers.org/en/latest/examples/webgl-points-layer.html
15
15
  * @private
16
16
  */
17
- const defaultStyle = {
18
- symbol: {
19
- symbolType: "circle",
20
- size: 20,
21
- color: "#006688",
22
- rotateWithView: false,
23
- offset: [0, 0],
24
- opacity: 0.6
25
- }
17
+ const defaultPointStyle = {
18
+ "circle-radius": 10,
19
+ "circle-fill-color": "#006688",
20
+ "circle-rotate-with-view": false,
21
+ "circle-displacement": [0, 0],
22
+ "circle-opacity": 0.6
23
+ },
24
+
25
+ defaultPolygonStyle = {
26
+ fillColor: "#006688",
27
+ strokeColor: "#006688",
28
+ strokeWidth: 1,
29
+ opacity: 1
26
30
  },
27
31
 
28
32
  /** @type {import('ol/style/literal.js').LiteralStyle} */
29
- style = {
33
+ style = Object.assign({
30
34
  "stroke-color": ["get", "strokeColor"],
31
35
  "stroke-width": ["get", "strokeWidth", "number"],
32
36
  "fill-color": ["get", "fillColor"],
33
37
  "opacity": ["get", "opacity", "number"],
34
- "size": ["get", "circleSize", "number"],
35
- symbol: defaultStyle.symbol
36
- };
38
+ "size": ["get", "circleSize", "number"]
39
+ }, defaultPointStyle);
37
40
 
38
41
  /**
39
42
  * Creates a vector layer with custom renderer.
@@ -165,29 +168,36 @@ export function createVectorTileLayerRenderer () {
165
168
  * @returns {void}
166
169
  */
167
170
  export function formatFeatureStyles (feature, styleObject) {
168
- if (!styleObject) {
169
- return;
170
- }
171
+ let rule;
171
172
 
172
- // extract first matching rule only
173
- const rule = getRulesForFeature(styleObject, feature)[0];
173
+ if (styleObject) {
174
+ // extract first matching rule only
175
+ rule = getRulesForFeature(styleObject, feature)[0];
176
+ }
174
177
 
175
- // undefined if no match
176
- feature.styleRule = rule;
178
+ if (rule?.style) {
179
+ feature.styleRule = rule;
177
180
 
178
- if (rule && rule.style) {
179
- const polygonFillColor = returnColor(rule.style.polygonFillColor, "hex"),
181
+ const polygonFillColor = returnColor(rule.style.polygonFillColor, "rgba"),
180
182
  circleFillColor = returnColor(rule.style.circleFillColor, "hex"),
183
+
181
184
  fillColor = polygonFillColor ? polygonFillColor : circleFillColor,
182
185
  strokeColor = returnColor(rule.style.polygonStrokeColor || rule.style.lineStrokeColor, "hex"),
183
186
  strokeWidth = rule.style.polygonStrokeWidth || rule.style.lineStrokeWidth,
184
187
  size = rule.style.circleRadius;
185
188
 
186
- feature.set("fillColor", fillColor ? fillColor : "#006688");
187
- feature.set("strokeColor", strokeColor ? strokeColor : "#006688");
188
- feature.set("strokeWidth", strokeWidth ? strokeWidth : 1);
189
- feature.set("opacity", fillColor ? (rule.style.polygonFillColor || rule.style.circleFillColor)[3] : 1);
190
- feature.set("circleSize", size ? size : 20);
189
+ feature.set("fillColor", fillColor || defaultPolygonStyle.fillColor);
190
+ feature.set("strokeColor", strokeColor || defaultPolygonStyle.strokeColor);
191
+ feature.set("strokeWidth", strokeWidth || defaultPolygonStyle.strokeWidth);
192
+ feature.set("opacity", fillColor ? (rule.style.polygonFillColor || rule.style.circleFillColor)[3] : defaultPolygonStyle.opacity);
193
+ feature.set("circleSize", size || defaultPointStyle["circle-radius"] * 2);
194
+ }
195
+ else {
196
+ feature.set("fillColor", defaultPolygonStyle.fillColor);
197
+ feature.set("strokeColor", defaultPolygonStyle.strokeColor);
198
+ feature.set("strokeWidth", defaultPolygonStyle.strokeWidth);
199
+ feature.set("opacity", defaultPolygonStyle.opacity);
200
+ feature.set("circleSize", defaultPointStyle["circle-radius"] * 2);
191
201
  }
192
202
  }
193
203
 
@@ -217,7 +227,7 @@ export function formatFeatureData (feature, excludeTypes = ["boolean"]) {
217
227
  valueIsTrue = typeof feature.get(key) === "string" && feature.get(key).toLowerCase() === "true" ? true : undefined,
218
228
  valueIsFalse = typeof feature.get(key) === "string" && feature.get(key).toLowerCase() === "false" ? false : undefined;
219
229
 
220
- if (!isNaN(parseFloat(feature.get(key))) && !excludeTypes.includes("number")) {
230
+ if (!isNaN(parseFloat(feature.get(key))) && !excludeTypes?.includes("number")) {
221
231
  feature.set(key, valueAsNumber);
222
232
  }
223
233
  if (valueIsTrue === true && !excludeTypes.includes("boolean")) {
@@ -288,14 +298,14 @@ export function createLayer (attrs) {
288
298
  * If the layer consists only of points, use WebGLPointsLayer
289
299
  * For advanced styling options
290
300
  * @see https://openlayers.org/en/latest/examples/webgl-points-layer.html
291
- */
301
+ */
292
302
  if (attrs.isPointLayer) {
293
303
  /**
294
304
  * @deprecated
295
305
  * @todo will be replaced in the next OL release and incorporated in the WebGLVectorLayerRenderer
296
306
  */
297
307
  return new LayerConstructor({
298
- style: attrs.style || defaultStyle,
308
+ style: attrs.style || defaultPointStyle,
299
309
  disableHitDetection: false,
300
310
  ...options,
301
311
  isPointLayer: true
@@ -323,3 +333,12 @@ export function createLayer (attrs) {
323
333
  isPointLayer: false
324
334
  });
325
335
  }
336
+
337
+ export default {
338
+ afterLoading,
339
+ createLayer,
340
+ createVectorLayerRenderer,
341
+ formatFeatureData,
342
+ formatFeatureGeometry,
343
+ formatFeatureStyles
344
+ };
@@ -90,6 +90,9 @@ export function returnColor (color, dest) {
90
90
  else if (src === "rgb" && dest === "hex") {
91
91
  newColor = rgbToHex(newColor[0], newColor[1], newColor[2]);
92
92
  }
93
+ else if (src === "rgb" && dest === "rgba") {
94
+ newColor = "rgba(" + newColor[0] + ", " + newColor[1] + ", " + newColor[2] + ", " + newColor[3] + ")";
95
+ }
93
96
 
94
97
  newColor = dest === "rgb" ? normalizeRgbColor(newColor) : newColor;
95
98
 
@@ -99,7 +99,14 @@ function getGeometryTypeFromWFS (rules, wfsURL, version, featureType, styleGeome
99
99
  "VERSION": version,
100
100
  "REQUEST": "DescribeFeatureType"
101
101
  };
102
- let url = wfsURL + "?";
102
+ let url = wfsURL;
103
+
104
+ if (url && url.includes("?")) {
105
+ url += "&";
106
+ }
107
+ else {
108
+ url += "?";
109
+ }
103
110
 
104
111
  Object.keys(params).forEach(key => {
105
112
  url += key + "=" + params[key] + "&";
@@ -30,7 +30,7 @@ function getStyleIdsFromLayers () {
30
30
 
31
31
  if (configuredLayers) {
32
32
  configuredLayers.forEach(layer => {
33
- if (layer.typ === "WFS" || layer.typ === "GeoJSON" || layer.typ === "SensorThings" || layer.typ === "TileSet3D") {
33
+ if (layer.typ === "WFS" || layer.typ === "GeoJSON" || layer.typ === "SensorThings" || layer.typ === "TileSet3D" || layer.typ === "OAF") {
34
34
  if (layer?.styleId) {
35
35
  styleIds.push(layer.styleId);
36
36
  }
@@ -1,6 +1,5 @@
1
1
  import {Style, Icon} from "ol/style.js";
2
2
  import {prepareValue, isObjectPath} from "../../../lib/attributeMapper";
3
- import PointStyle from "./stylePoint";
4
3
 
5
4
  /**
6
5
  * Returns the rotation value and its corresponding value according to style.json.
@@ -33,21 +32,23 @@ export function getRotationValue (rotation, featureValues) {
33
32
  */
34
33
  export function createIconStyle (attributes, feature, isClustered) {
35
34
  const showCluster = isClustered && feature.get("features")?.length > 1,
36
-
37
- height = showCluster ? attributes.clusterImageHeight : attributes.imageHeight,
38
35
  imageName = showCluster ? attributes.clusterImageName : attributes.imageName,
39
36
  imageOffsetX = showCluster ? attributes.clusterImageOffsetY : attributes.imageOffsetX,
40
37
  imageOffsetY = showCluster ? attributes.clusterImageOffsetX : attributes.imageOffsetY,
41
38
  scale = showCluster ? attributes.clusterImageScale : attributes.imageScale,
42
- src = imageName.indexOf("/") === -1 ? attributes.imagePath + imageName : imageName,
43
- width = showCluster ? attributes.clusterImageWidth : attributes.imageWidth,
44
- iconOptions = {
45
- crossOrigin: "anonymous",
46
- src: src.startsWith("<svg") ? "data:image/svg+xml;charset=utf-8," + encodeURIComponent(src) : src,
47
- scale,
48
- anchor: [parseFloat(imageOffsetX), parseFloat(imageOffsetY)],
49
- imgSize: src.indexOf(".svg") > -1 ? [width, height] : ""
50
- };
39
+ wfsImgPath = attributes.imagePath;
40
+ let iconOptions = {},
41
+ src = imageName;
42
+
43
+ if (!imageName.startsWith("https:") && !imageName.startsWith("<svg")) {
44
+ src = wfsImgPath + imageName;
45
+ }
46
+ iconOptions = {
47
+ crossOrigin: "anonymous",
48
+ src: src.startsWith("<svg") ? "data:image/svg+xml;charset=utf-8," + encodeURIComponent(src) : src,
49
+ scale,
50
+ anchor: [parseFloat(imageOffsetX), parseFloat(imageOffsetY)]
51
+ };
51
52
 
52
53
  if (!showCluster) {
53
54
  iconOptions.anchorXUnits = attributes.imageOffsetXUnit;
@@ -67,13 +68,10 @@ export function createIconStyle (attributes, feature, isClustered) {
67
68
  * @return {ol.Style} style
68
69
  */
69
70
  export function createSVGStyle (svgPath) {
70
- const size = PointStyle.prototype.getSize();
71
-
72
71
  return new Style({
73
72
  image: new Icon({
74
73
  crossOrigin: "anonymous",
75
- src: "data:image/svg+xml;charset=utf-8," + encodeURIComponent(svgPath),
76
- imgSize: [size, size]
74
+ src: "data:image/svg+xml;charset=utf-8," + encodeURIComponent(svgPath)
77
75
  })
78
76
  });
79
77
  }
@@ -6,12 +6,11 @@ describe("tileset.js", function () {
6
6
 
7
7
  beforeEach(() => {
8
8
  global.Cesium = {};
9
- global.Cesium.Cesium3DTileset = {};
10
- global.Cesium.Cesium3DTileset.fromUrl = jest.fn();
9
+ global.Cesium.Cesium3DTileset = jest.fn();
11
10
  global.Cesium.Cesium3DTileStyle = jest.fn(color => color);
12
11
  attr = {
13
12
  id: "4002",
14
- name: "Gebäude LoD2",
13
+ name: "Gebäude LoD2",
15
14
  url: "https://geoportal-hamburg.de/gdi3d/datasource-data/LoD2",
16
15
  typ: "TileSet3D",
17
16
  cesium3DTilesetOptions: {
@@ -29,9 +28,7 @@ describe("tileset.js", function () {
29
28
  };
30
29
  }
31
30
  };
32
- cesium3DTilesetSpy = jest.spyOn(global.Cesium.Cesium3DTileset, "fromUrl").mockImplementation(() => {
33
- return Promise.resolve({});
34
- });
31
+ cesium3DTilesetSpy = jest.spyOn(global.Cesium, "Cesium3DTileset");
35
32
  console.warn = jest.fn();
36
33
  });
37
34
 
@@ -41,23 +38,21 @@ describe("tileset.js", function () {
41
38
  console.warn = consoleWarn;
42
39
  });
43
40
 
44
- async function checkAttributes (layer, attrs) {
45
- const tileset = await layer.tileset;
46
-
41
+ function checkAttributes (layer, attrs) {
47
42
  expect(layer.get("name")).toEqual(attrs.name);
48
43
  expect(layer.get("typ")).toEqual(attrs.typ);
49
44
  expect(layer.get("id")).toEqual(attrs.id);
50
- expect(tileset.layerReferenceId).toEqual(attrs.id);
45
+ expect(layer.tileset.layerReferenceId).toEqual(attrs.id);
51
46
  }
52
47
 
53
48
  describe("createLayer", function () {
54
49
  it("creates tileset layer without map", function () {
55
50
  const layer = new Tileset(attr);
56
51
 
52
+ checkAttributes(layer, attr);
57
53
  expect(layer.tileSet).toEqual(undefined);
58
54
  expect(layer.tileset.show).toEqual(undefined);
59
55
  expect(cesium3DTilesetSpy).toHaveBeenCalledTimes(1);
60
- checkAttributes(layer, attr);
61
56
  });
62
57
  it("creates 2 tileset layers with map and checks attributes", function () {
63
58
  const attr2 = {
@@ -21,7 +21,8 @@ const props = {
21
21
  }
22
22
  ]
23
23
  }
24
- ]
24
+ ],
25
+ random_url: "http://random.url.de"
25
26
  };
26
27
 
27
28
  describe("src/utils/attributeMapper.js", () => {
@@ -272,6 +273,168 @@ describe("src/utils/attributeMapper.js", () => {
272
273
  int: "12345"
273
274
  });
274
275
  });
276
+ it("should map object with mapping object and type:html", () => {
277
+ const mappingObj = {
278
+ random_url: {
279
+ name: "url",
280
+ type: "html"
281
+ }
282
+ };
283
+
284
+ expect(mapAttributes(props, mappingObj)).toEqual({
285
+ url: "http://random.url.de"
286
+ });
287
+ });
288
+ it("should map object with mapping object and type:html and tag a", () => {
289
+ const mappingObj = {
290
+ random_url: {
291
+ name: "url",
292
+ type: "html",
293
+ html: {
294
+ tag: "a",
295
+ properties: {
296
+ href: "%value%"
297
+ }
298
+ }
299
+ }
300
+ };
301
+
302
+ expect(mapAttributes(props, mappingObj)).toEqual({
303
+ url: "<a href=\"http://random.url.de\"></a>"
304
+ });
305
+ });
306
+ it("should map object with mapping object and type:html and tag a", () => {
307
+ const mappingObj = {
308
+ random_url: {
309
+ name: "url",
310
+ type: "html",
311
+ html: {
312
+ tag: "a",
313
+ innerHTML: "%value%",
314
+ properties: {
315
+ href: "%value%"
316
+ }
317
+ }
318
+ }
319
+ };
320
+
321
+ expect(mapAttributes(props, mappingObj)).toEqual({
322
+ url: "<a href=\"http://random.url.de\">http://random.url.de</a>"
323
+ });
324
+ });
325
+ it("should map object with mapping object and type:html and tag a without innerHTML and properties", () => {
326
+ const mappingObj = {
327
+ random_url: {
328
+ name: "url",
329
+ type: "html",
330
+ html: {
331
+ tag: "a"
332
+ }
333
+ }
334
+ };
335
+
336
+ expect(mapAttributes(props, mappingObj)).toEqual({
337
+ url: "<a></a>"
338
+ });
339
+ });
340
+ it("should map object with mapping object and type:html and tag a and innerHTML", () => {
341
+ const mappingObj = {
342
+ random_url: {
343
+ name: "url",
344
+ type: "html",
345
+ html: {
346
+ tag: "a",
347
+ innerHTML: "myURL",
348
+ properties: {
349
+ href: "%value%"
350
+ }
351
+ }
352
+ }
353
+ };
354
+
355
+ expect(mapAttributes(props, mappingObj)).toEqual({
356
+ url: "<a href=\"http://random.url.de\">myURL</a>"
357
+ });
358
+ });
359
+ it("should map object with mapping object and type:html and tag a and properties", () => {
360
+ const mappingObj = {
361
+ random_url: {
362
+ name: "url",
363
+ type: "html",
364
+ html: {
365
+ tag: "a",
366
+ innerHTML: "myURL",
367
+ properties: {
368
+ href: "%value%",
369
+ target: "_blank"
370
+ }
371
+ }
372
+ }
373
+ };
374
+
375
+ expect(mapAttributes(props, mappingObj)).toEqual({
376
+ url: "<a href=\"http://random.url.de\" target=\"_blank\">myURL</a>"
377
+ });
378
+ });
379
+ it("should map object with mapping object and type:html and tag a and properties", () => {
380
+ const mappingObj = {
381
+ random_url: {
382
+ name: "url",
383
+ type: "html",
384
+ html: {
385
+ tag: "a",
386
+ innerHTML: "%value%",
387
+ properties: {
388
+ href: "%value%",
389
+ target: "_blank"
390
+ }
391
+ }
392
+ }
393
+ };
394
+
395
+ expect(mapAttributes(props, mappingObj)).toEqual({
396
+ url: "<a href=\"http://random.url.de\" target=\"_blank\">http://random.url.de</a>"
397
+ });
398
+ });
399
+ it("should map object with mapping object and type:html and tag img and properties", () => {
400
+ const mappingObj = {
401
+ random_url: {
402
+ name: "url",
403
+ type: "html",
404
+ html: {
405
+ tag: "img",
406
+ properties: {
407
+ src: "%value%",
408
+ style: "width:150px"
409
+ }
410
+ }
411
+ }
412
+ };
413
+
414
+ expect(mapAttributes(props, mappingObj)).toEqual({
415
+ url: "<img src=\"http://random.url.de\" style=\"width:150px\" />"
416
+ });
417
+ });
418
+ it("should map object with mapping object and type:html and tag iframe and properties", () => {
419
+ const mappingObj = {
420
+ random_url: {
421
+ name: "url",
422
+ type: "html",
423
+ html: {
424
+ tag: "iframe",
425
+ properties: {
426
+ src: "%value%",
427
+ foo: "bar",
428
+ bar: "foo"
429
+ }
430
+ }
431
+ }
432
+ };
433
+
434
+ expect(mapAttributes(props, mappingObj)).toEqual({
435
+ url: "<iframe src=\"http://random.url.de\" foo=\"bar\" bar=\"foo\"></iframe>"
436
+ });
437
+ });
275
438
  });
276
439
  describe("isObjectPath", () => {
277
440
  it("should return true for \"@foobar\"", () => {
@@ -18,7 +18,7 @@ jest.mock("../../src/vectorStyle/styleList.js", () => {
18
18
  });
19
19
 
20
20
  describe("webgl.js", () => {
21
- let layerParams, layerParamsVectorTile, rawLayer, rawLayerVectorTile, styleRule, styleObject;
21
+ let layerParams, layerParamsVectorTile, rawLayer, rawLayerVectorTile, styleRule, styleObject, defaultStyle;
22
22
 
23
23
  beforeEach(() => {
24
24
  layerParams = {
@@ -68,6 +68,13 @@ describe("webgl.js", () => {
68
68
  styleObject = {
69
69
  rules: [styleRule]
70
70
  };
71
+ defaultStyle = {
72
+ fillColor: "#006688",
73
+ strokeColor: "#006688",
74
+ strokeWidth: 1,
75
+ opacity: 1,
76
+ size: 20
77
+ };
71
78
  });
72
79
 
73
80
  describe("createLayer", () => {
@@ -156,7 +163,7 @@ describe("webgl.js", () => {
156
163
  it("set the necessary style attributes on the feature for literal style syntax", () => {
157
164
  $feature = feature.clone();
158
165
  webgl.formatFeatureStyles($feature, styleObject);
159
- expect($feature.get("fillColor")).toEqual(returnColor(styleRule.style.polygonFillColor, "hex"));
166
+ expect($feature.get("fillColor")).toEqual(returnColor(styleRule.style.polygonFillColor, "rgba"));
160
167
  expect($feature.get("strokeColor")).toEqual(returnColor(styleRule.style.polygonStrokeColor, "hex"));
161
168
  expect($feature.get("strokeWidth")).toEqual(styleRule.style.polygonStrokeWidth);
162
169
  expect($feature.get("opacity")).toEqual(styleRule.style.polygonFillColor[3]);
@@ -173,6 +180,19 @@ describe("webgl.js", () => {
173
180
  expect($feature.get("opacity")).toEqual(styleRule.style.circleFillColor[3]);
174
181
  expect($feature.get("circleSize")).toEqual(styleRule.style.circleRadius);
175
182
  });
183
+ it("set the necessary style attributes on the feature with default style", () => {
184
+ $feature = feature.clone();
185
+ styleRule = null;
186
+ styleObject = {
187
+ rules: [styleRule]
188
+ };
189
+ webgl.formatFeatureStyles($feature, styleObject);
190
+ expect($feature.get("fillColor")).toEqual(defaultStyle.fillColor);
191
+ expect($feature.get("strokeColor")).toEqual(defaultStyle.strokeColor);
192
+ expect($feature.get("strokeWidth")).toEqual(defaultStyle.strokeWidth);
193
+ expect($feature.get("opacity")).toEqual(defaultStyle.opacity);
194
+ expect($feature.get("circleSize")).toEqual(defaultStyle.size);
195
+ });
176
196
  });
177
197
  });
178
- });
198
+ });
@@ -1,4 +1,10 @@
1
- import {normalizeRgbColor, componentToHex, rgbToHex, hexToRgb} from "../../../src/vectorStyle/lib/colorConvertions";
1
+ import {
2
+ normalizeRgbColor,
3
+ componentToHex,
4
+ rgbToHex,
5
+ hexToRgb,
6
+ returnColor
7
+ } from "../../../src/vectorStyle/lib/colorConvertions";
2
8
 
3
9
  describe("normalizeRgbColor", function () {
4
10
  it("should be extend the given array with length 3 by value 1", function () {
@@ -39,4 +45,26 @@ describe("hexToRgb", function () {
39
45
  it("should return null", function () {
40
46
  expect(hexToRgb("")).toEqual(null);
41
47
  });
42
- });
48
+ });
49
+
50
+ describe("returnColor", function () {
51
+ it("should return the parsed rgb value", function () {
52
+ expect(returnColor([255, 0, 0])).toEqual([255, 0, 0]);
53
+ });
54
+ it("should return the parsed rgb value with hex format", function () {
55
+ expect(returnColor([255, 0, 0, 0.5], "hex")).toEqual("#ff0000");
56
+ });
57
+ it("should return the parsed rgb value with rgba format", function () {
58
+ expect(returnColor([255, 0, 0, 0.5], "rgba")).toEqual("rgba(255, 0, 0, 0.5)");
59
+ });
60
+
61
+ it("should return the parsed rgb value with hex format", function () {
62
+ expect(returnColor("#ff0000")).toEqual("#ff0000");
63
+ });
64
+ it("should return the parsed rgb value with array in string", function () {
65
+ expect(returnColor("[255, 0, 0, 0.5]")).toEqual(["255", "0", "0", "0.5"]);
66
+ });
67
+ it("should return the parsed rgb value with array in string and hex format as destination format", function () {
68
+ expect(returnColor("[255, 0, 0, 0.5]", "hex")).toEqual("#ff0000");
69
+ });
70
+ });
@@ -34,7 +34,7 @@ describe("stylePointIcon.js", () => {
34
34
  clusterAttributes = {
35
35
  clusterImageName: "bild.svg",
36
36
  clusterImageWidth: 10,
37
- clusterImagePath: "/imagePath",
37
+ imagePath: "/imagePath",
38
38
  clusterImageHeight: 20,
39
39
  clusterImageScale: 1
40
40
  },
@@ -61,12 +61,87 @@ describe("stylePointIcon.js", () => {
61
61
  }
62
62
  };
63
63
 
64
- it("should create icon point style", () => {
64
+ it("should create icon point style with imageName without path", () => {
65
65
  expect(stylePointIcon.createIconStyle(attributes, feature, false)).toBeInstanceOf(Style);
66
66
  expect(stylePointIcon.createIconStyle(clusterAttributes, clusteredFeature, true)).toBeInstanceOf(Style);
67
67
  expect(stylePointIcon.createIconStyle(attributes, feature, false).getImage()).toBeInstanceOf(Icon);
68
68
  expect(stylePointIcon.createIconStyle(attributes, feature, false).getImage().getScale()).toEqual(1);
69
69
  });
70
+ it("should create icon point style with pure imageName and wfsImgPath exists", () => {
71
+ let style = null;
72
+
73
+ attributes.imageName = "Rathaus.svg";
74
+ attributes.imagePath = "./geodaten/icons/";
75
+ style = stylePointIcon.createIconStyle(attributes, feature, false);
76
+
77
+ expect(style).toBeInstanceOf(Style);
78
+ expect(style.getImage()).toBeInstanceOf(Icon);
79
+ expect(style.getImage().getSrc()).toEqual(attributes.imagePath + attributes.imageName);
80
+ });
81
+ it("should create clustered icon point style with pure imageName and wfsImgPath exists", () => {
82
+ let style = null;
83
+
84
+ clusterAttributes.clusterImageName = "Rathaus.svg";
85
+ clusterAttributes.imagePath = "./geodaten/icons/";
86
+ style = stylePointIcon.createIconStyle(clusterAttributes, clusteredFeature, true);
87
+
88
+ expect(style).toBeInstanceOf(Style);
89
+ expect(style.getImage()).toBeInstanceOf(Icon);
90
+ expect(style.getImage().getSrc()).toEqual(clusterAttributes.imagePath + clusterAttributes.clusterImageName);
91
+ });
92
+ it("should create icon point style with path in imageName and wfsImgPath exists", () => {
93
+ let style = null;
94
+
95
+ attributes.imageName = "/svg/poi/Rathaus.svg";
96
+ attributes.imagePath = "https://localhost:9001/portal/basic/geodaten/icons/";
97
+ style = stylePointIcon.createIconStyle(attributes, feature, false);
98
+
99
+ expect(style).toBeInstanceOf(Style);
100
+ expect(style.getImage()).toBeInstanceOf(Icon);
101
+ expect(style.getImage().getSrc()).toEqual(attributes.imagePath + attributes.imageName);
102
+ });
103
+ it("should create clustered icon point style with path in imageName and wfsImgPath exists", () => {
104
+ let style = null;
105
+
106
+ clusterAttributes.clusterImageName = "/svg/poi/Rathaus.svg";
107
+ clusterAttributes.imagePath = "https://localhost:9001/portal/basic/geodaten/icons/";
108
+ style = stylePointIcon.createIconStyle(clusterAttributes, clusteredFeature, true);
109
+
110
+ expect(style).toBeInstanceOf(Style);
111
+ expect(style.getImage()).toBeInstanceOf(Icon);
112
+ expect(style.getImage().getSrc()).toEqual(clusterAttributes.imagePath + clusterAttributes.clusterImageName);
113
+ });
114
+ it("should create icon point style with whole path in imageName and wfsImgPath is empty", () => {
115
+ let style = null;
116
+
117
+ attributes.imageName = "https://localhost:9001/portal/basic/geodaten/icons/svg/poi/Rathaus.svg";
118
+ style = stylePointIcon.createIconStyle(attributes, feature, false);
119
+
120
+ expect(style).toBeInstanceOf(Style);
121
+ expect(style.getImage()).toBeInstanceOf(Icon);
122
+ expect(style.getImage().getSrc()).toEqual(attributes.imageName);
123
+ });
124
+ it("should create clustered icon point style with whole path in imageName and wfsImgPath is empty", () => {
125
+ let style = null;
126
+
127
+ clusterAttributes.clusterImageName = "https://localhost:9001/portal/basic/geodaten/icons/svg/poi/Rathaus.svg";
128
+ clusterAttributes.imagePath = "";
129
+ style = stylePointIcon.createIconStyle(clusterAttributes, clusteredFeature, true);
130
+
131
+ expect(style).toBeInstanceOf(Style);
132
+ expect(style.getImage()).toBeInstanceOf(Icon);
133
+ expect(style.getImage().getSrc()).toEqual(clusterAttributes.clusterImageName);
134
+ });
135
+ it("should create icon point style with svg", () => {
136
+ let style = null;
137
+
138
+ attributes.imageName = "<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='#E10019' class='bi bi-geo-fill' viewBox='0 0 16 16'><path fill-rule='evenodd' d='M4 4a4 4 0 1 1 4.5 3.969V13.5a.5.5 0 0 1-1 0V7.97A4 4 0 0 1 4 3.999zm2.493 8.574a.5.5 0 0 1-.411.575c-.712.118-1.28.295-1.655.493a1.319 1.319 0 0 0-.37.265.301.301 0 0 0-.057.09V14l.002.008a.147.147 0 0 0 .016.033.617.617 0 0 0 .145.15c.165.13.435.27.813.395.751.25 1.82.414 3.024.414s2.273-.163 3.024-.414c.378-.126.648-.265.813-.395a.619.619 0 0 0 .146-.15.148.148 0 0 0 .015-.033L12 14v-.004a.301.301 0 0 0-.057-.09 1.318 1.318 0 0 0-.37-.264c-.376-.198-.943-.375-1.655-.493a.5.5 0 1 1 .164-.986c.77.127 1.452.328 1.957.594C12.5 13 13 13.4 13 14c0 .426-.26.752-.544.977-.29.228-.68.413-1.116.558-.878.293-2.059.465-3.34.465-1.281 0-2.462-.172-3.34-.465-.436-.145-.826-.33-1.116-.558C3.26 14.752 3 14.426 3 14c0-.599.5-1 .961-1.243.505-.266 1.187-.467 1.957-.594a.5.5 0 0 1 .575.411z'/></svg>";
139
+ style = stylePointIcon.createIconStyle(attributes, feature, false);
140
+
141
+ expect(style).toBeInstanceOf(Style);
142
+ expect(style.getImage()).toBeInstanceOf(Icon);
143
+ expect(style.getImage().getSrc()).toEqual("data:image/svg+xml;charset=utf-8," + encodeURIComponent(attributes.imageName));
144
+ });
70
145
  it("should create cluster icon point style", () => {
71
146
  expect(stylePointIcon.createIconStyle(clusterAttributes, clusteredFeature, true)).toBeInstanceOf(Style);
72
147
  expect(stylePointIcon.createIconStyle(clusterAttributes, clusteredFeature, true).getImage()).toBeInstanceOf(Icon);