@masterportal/masterportalapi 2.62.0 → 2.63.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 +25 -0
- package/package.json +14 -14
- package/publiccode.yml +2 -2
- package/src/vectorStyle/createStyle.js +37 -5
- package/src/vectorStyle/styles/style.js +4 -2
- package/test/vectorStyle/styles/style.test.js +70 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,31 @@
|
|
|
2
2
|
All important changes in this project are stored in this file.
|
|
3
3
|
|
|
4
4
|
The [Semantic Versioning](https://semver.org/spec/v2.0.0.html) is used.
|
|
5
|
+
|
|
6
|
+
## 2.63.0 - 2026-07-17
|
|
7
|
+
|
|
8
|
+
### Changed
|
|
9
|
+
- The following packages have been updated:
|
|
10
|
+
- dependencies:
|
|
11
|
+
- core-js: 3.33.1 to 3.49.0
|
|
12
|
+
- dayjs: 1.11.10 to 1.11.21
|
|
13
|
+
- proj4: 2.10.0 to 2.20.9
|
|
14
|
+
- devDependencies:
|
|
15
|
+
- @parcel/config-default: 2.15.4 to 2.16.4
|
|
16
|
+
- @parcel/transformer-sass: 2.15.4 to 2.16.4
|
|
17
|
+
- canvas: 3.2.0 to 3.2.3
|
|
18
|
+
- jest: 30.1.3 to 30.4.2
|
|
19
|
+
- jest-environment-jsdom: 30.1.2 to 30.4.1
|
|
20
|
+
- jsdoc: 4.0.2 to 4.0.5
|
|
21
|
+
- parcel: 2.15.4 to 2.16.4
|
|
22
|
+
- sass: 1.69.4 to 1.101.0
|
|
23
|
+
- url: 0.11.3 to 0.11.4
|
|
24
|
+
- @cesium/engine: 23.0.0 to 26.0.0
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
- Issue \#1623: fix label for configuration of style properties as array of objects.
|
|
28
|
+
|
|
29
|
+
---
|
|
5
30
|
|
|
6
31
|
## 2.62.0 - 2026-06-11
|
|
7
32
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@masterportal/masterportalapi",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.63.0",
|
|
4
4
|
"description": "Basic functions of the Masterportal as api",
|
|
5
5
|
"homepage": "https://bitbucket.org/geowerkstatt-hamburg/masterportalapi#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -33,42 +33,42 @@
|
|
|
33
33
|
"prepare": "husky install"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"core-js": "^3.
|
|
37
|
-
"dayjs": "^1.11.
|
|
36
|
+
"core-js": "^3.49.0",
|
|
37
|
+
"dayjs": "^1.11.21",
|
|
38
38
|
"ol": "10.9.0",
|
|
39
39
|
"ol-mapbox-style": "13.3.0",
|
|
40
40
|
"olcs": "^2.23.0",
|
|
41
|
-
"proj4": "^2.
|
|
41
|
+
"proj4": "^2.20.9"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@parcel/config-default": "^2.
|
|
45
|
-
"@parcel/transformer-sass": "^2.
|
|
44
|
+
"@parcel/config-default": "^2.16.4",
|
|
45
|
+
"@parcel/transformer-sass": "^2.16.4",
|
|
46
46
|
"@swc/jest": "^0.2.39",
|
|
47
47
|
"assert": "^2.1.0",
|
|
48
48
|
"browserify-zlib": "^0.2.0",
|
|
49
49
|
"buffer": "^6.0.3",
|
|
50
|
-
"canvas": "3.2.
|
|
50
|
+
"canvas": "3.2.3",
|
|
51
51
|
"eslint": "8.57.1",
|
|
52
52
|
"events": "^3.3.0",
|
|
53
53
|
"https-browserify": "^1.0.0",
|
|
54
54
|
"husky": "8.0.3",
|
|
55
|
-
"jest": "30.
|
|
55
|
+
"jest": "30.4.2",
|
|
56
56
|
"jest-canvas-mock": "2.5.2",
|
|
57
|
-
"jest-environment-jsdom": "30.1
|
|
57
|
+
"jest-environment-jsdom": "30.4.1",
|
|
58
58
|
"jest-fetch-mock": "^3.0.3",
|
|
59
|
-
"jsdoc": "4.0.
|
|
60
|
-
"parcel": "^2.
|
|
59
|
+
"jsdoc": "4.0.5",
|
|
60
|
+
"parcel": "^2.16.4",
|
|
61
61
|
"process": "^0.11.10",
|
|
62
|
-
"sass": "1.
|
|
62
|
+
"sass": "1.101.0",
|
|
63
63
|
"stream-browserify": "^3.0.0",
|
|
64
64
|
"stream-http": "^3.2.0",
|
|
65
65
|
"timers-browserify": "^2.0.12",
|
|
66
|
-
"url": "^0.11.
|
|
66
|
+
"url": "^0.11.4",
|
|
67
67
|
"use-resize-observer": "^9.1.0",
|
|
68
68
|
"util": "^0.12.5"
|
|
69
69
|
},
|
|
70
70
|
"peerDependencies": {
|
|
71
|
-
"@cesium/engine": "^
|
|
71
|
+
"@cesium/engine": "^26.0.0"
|
|
72
72
|
},
|
|
73
73
|
"engines": {
|
|
74
74
|
"node": "^22.19.0 || ^24.11.1",
|
package/publiccode.yml
CHANGED
|
@@ -81,8 +81,8 @@ maintenance:
|
|
|
81
81
|
name: Masterportal
|
|
82
82
|
platforms:
|
|
83
83
|
- web
|
|
84
|
-
releaseDate: '2026-
|
|
84
|
+
releaseDate: '2026-07-17'
|
|
85
85
|
roadmap: 'https://bitbucket.org/geowerkstatt-hamburg/masterportalapi/src/master/'
|
|
86
86
|
softwareType: api
|
|
87
|
-
softwareVersion: 2.
|
|
87
|
+
softwareVersion: 2.63.0
|
|
88
88
|
url: 'https://bitbucket.org/geowerkstatt-hamburg/masterportalapi.git'
|
|
@@ -9,6 +9,35 @@ import {getRuleForIndex, getRulesForFeature} from "./lib/getRuleForIndex";
|
|
|
9
9
|
|
|
10
10
|
const legendsOfAllStyles = [];
|
|
11
11
|
let legendInformationLength = 0;
|
|
12
|
+
const warnedLayerIdsWithDefaultStyleFallback = new Set();
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Warns once per layer when no styling rule matches and default styles are used.
|
|
16
|
+
* @param {object} [warningContext={}] context for the warning
|
|
17
|
+
* @param {string} [warningContext.layerId] id of the affected layer
|
|
18
|
+
* @returns {void}
|
|
19
|
+
*/
|
|
20
|
+
function warnAboutDefaultStyleFallback (warningContext = {}) {
|
|
21
|
+
const {layerId} = warningContext;
|
|
22
|
+
|
|
23
|
+
if (typeof layerId === "string" && layerId.length > 0) {
|
|
24
|
+
if (warnedLayerIdsWithDefaultStyleFallback.has(layerId)) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
warnedLayerIdsWithDefaultStyleFallback.add(layerId);
|
|
28
|
+
console.warn(`No valid styling rule found for layer "${layerId}". Falling back to defaults.`);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
console.warn("No valid styling rule found. Falling back to defaults");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Clears cached default-style fallback warnings.
|
|
36
|
+
* @returns {void}
|
|
37
|
+
*/
|
|
38
|
+
function clearDefaultStyleFallbackWarnings () {
|
|
39
|
+
warnedLayerIdsWithDefaultStyleFallback.clear();
|
|
40
|
+
}
|
|
12
41
|
|
|
13
42
|
/**
|
|
14
43
|
* Returns true if feature contains some kind of MultiGeometry
|
|
@@ -152,9 +181,10 @@ function getMultiGeometryStyle (geometryType, feature, rules, isClustered, wfsIm
|
|
|
152
181
|
* @param {object[]} rules styling rules to check. Array can be empty.
|
|
153
182
|
* @param {Boolean} isClustered Flag to show if feature is clustered.
|
|
154
183
|
* @param {String} wfsImgPathFromConfig path to wfsImg from Config
|
|
184
|
+
* @param {object} [warningContext={}] context for warning deduplication
|
|
155
185
|
* @returns {ol/style/Style} style is always returned
|
|
156
186
|
*/
|
|
157
|
-
function getGeometryStyle (feature, rules, isClustered, wfsImgPathFromConfig) {
|
|
187
|
+
function getGeometryStyle (feature, rules, isClustered, wfsImgPathFromConfig, warningContext = {}) {
|
|
158
188
|
const geometryType = feature ? feature.getGeometry().getType() : "cesium";
|
|
159
189
|
|
|
160
190
|
// For simple geometries the first styling rule is used.
|
|
@@ -168,7 +198,7 @@ function getGeometryStyle (feature, rules, isClustered, wfsImgPathFromConfig) {
|
|
|
168
198
|
}
|
|
169
199
|
|
|
170
200
|
// fall back to default styles as configured in geomType specific styles, if no rule is matched
|
|
171
|
-
|
|
201
|
+
warnAboutDefaultStyleFallback(warningContext);
|
|
172
202
|
return isMultiGeometry(geometryType)
|
|
173
203
|
? getMultiGeometryStyle(geometryType, feature, undefined, isClustered, wfsImgPathFromConfig)
|
|
174
204
|
: getSimpleGeometryStyle(geometryType, feature, undefined, isClustered, wfsImgPathFromConfig);
|
|
@@ -224,14 +254,15 @@ function captureLegendFromFeature (styleId, legendInformation) {
|
|
|
224
254
|
* @param {ol/feature} feature the feature to style
|
|
225
255
|
* @param {Boolean} isClustered is feature clustered
|
|
226
256
|
* @param {String} wfsImgPathFromConfig path to wfsImg from Config
|
|
227
|
-
|
|
257
|
+
* @param {object} [warningContext={}] context for warning deduplication
|
|
258
|
+
* @returns {ol/style/Style} style used in layer model
|
|
228
259
|
*/
|
|
229
|
-
function createStyle (styleObject, feature, isClustered, wfsImgPathFromConfig) {
|
|
260
|
+
function createStyle (styleObject, feature, isClustered, wfsImgPathFromConfig, warningContext = {}) {
|
|
230
261
|
const rules = getRulesForFeature(styleObject, feature),
|
|
231
262
|
// Takes first rule in array for labeling so that is giving precedence to the order in the style.json
|
|
232
263
|
style = Array.isArray(rules) && rules.length > 0 ? rules[0].style : null,
|
|
233
264
|
hasLabelField = style?.labelField,
|
|
234
|
-
geometryStyle = getGeometryStyle(feature, rules, isClustered, wfsImgPathFromConfig),
|
|
265
|
+
geometryStyle = getGeometryStyle(feature, rules, isClustered, wfsImgPathFromConfig, warningContext),
|
|
235
266
|
legendInformation = Array.isArray(geometryStyle) ? geometryStyle[0].legendInfos : geometryStyle.legendInfos;
|
|
236
267
|
let styleObjectGeometry = null;
|
|
237
268
|
|
|
@@ -327,5 +358,6 @@ export default {
|
|
|
327
358
|
getGeometryStyle,
|
|
328
359
|
getLabelStyle,
|
|
329
360
|
createStyle,
|
|
361
|
+
clearDefaultStyleFallbackWarnings,
|
|
330
362
|
returnLegendByStyleId
|
|
331
363
|
};
|
|
@@ -106,9 +106,12 @@ class StyleClass {
|
|
|
106
106
|
else if (rule?.conditions) {
|
|
107
107
|
let label = "";
|
|
108
108
|
|
|
109
|
-
if (rule.conditions?.properties) {
|
|
109
|
+
if (rule.conditions?.properties && !Array.isArray(rule.conditions.properties)) {
|
|
110
110
|
label = Object.values(rule.conditions.properties).join(", ");
|
|
111
111
|
}
|
|
112
|
+
if (Array.isArray(rule.conditions?.properties)) {
|
|
113
|
+
label = rule.conditions.properties.map(prop => prop.value).join(", ");
|
|
114
|
+
}
|
|
112
115
|
|
|
113
116
|
if (rule.conditions?.sequence
|
|
114
117
|
&& Array.isArray(rule.conditions.sequence)
|
|
@@ -117,7 +120,6 @@ class StyleClass {
|
|
|
117
120
|
&& rule.conditions.sequence[1] >= rule.conditions.sequence[0]) {
|
|
118
121
|
label = label + " (" + rule.conditions.sequence.join("-") + ")";
|
|
119
122
|
}
|
|
120
|
-
|
|
121
123
|
return label;
|
|
122
124
|
}
|
|
123
125
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import StyleClass from "../../../src/vectorStyle/styles/style";
|
|
2
|
+
|
|
3
|
+
describe("StyleClass", () => {
|
|
4
|
+
describe("createLegendLabel", () => {
|
|
5
|
+
it("returns legendValue with highest precedence", () => {
|
|
6
|
+
const style = new StyleClass(),
|
|
7
|
+
label = style.createLegendLabel({
|
|
8
|
+
conditions: {
|
|
9
|
+
properties: {
|
|
10
|
+
category: "Rule Label"
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
attributes: {
|
|
16
|
+
legendValue: 123
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
expect(label).toBe("123");
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("creates label from properties configured as array of objects", () => {
|
|
24
|
+
const style = new StyleClass(),
|
|
25
|
+
label = style.createLegendLabel({
|
|
26
|
+
conditions: {
|
|
27
|
+
properties: [
|
|
28
|
+
{
|
|
29
|
+
key: "category",
|
|
30
|
+
value: "A"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
key: "category",
|
|
34
|
+
value: "B"
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
attributes: {}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
expect(label).toBe("A, B");
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("appends valid sequence to created label", () => {
|
|
47
|
+
const style = new StyleClass(),
|
|
48
|
+
label = style.createLegendLabel({
|
|
49
|
+
conditions: {
|
|
50
|
+
properties: {
|
|
51
|
+
category: "A"
|
|
52
|
+
},
|
|
53
|
+
sequence: [10, 20]
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
attributes: {}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
expect(label).toBe("A (10-20)");
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("returns null if no legendValue and no rule conditions exist", () => {
|
|
64
|
+
const style = new StyleClass(),
|
|
65
|
+
label = style.createLegendLabel(undefined, {attributes: {}});
|
|
66
|
+
|
|
67
|
+
expect(label).toBeNull();
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
});
|