qwc2 2025.10.30 → 2025.11.12

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 (55) hide show
  1. package/actions/layers.js +6 -29
  2. package/components/AttributeForm.js +106 -77
  3. package/components/AttributeTableWidget.js +89 -88
  4. package/components/IdentifyViewer.js +4 -2
  5. package/components/LinkFeatureForm.js +17 -9
  6. package/components/LocationRecorder.js +1 -1
  7. package/components/PickFeature.js +45 -33
  8. package/components/QtDesignerForm.js +20 -18
  9. package/components/StandardApp.js +4 -0
  10. package/components/ThemeList.js +9 -10
  11. package/components/map3d/Map3D.js +6 -3
  12. package/package.json +2 -1
  13. package/plugins/Cyclomedia.js +5 -4
  14. package/plugins/Editing.js +307 -72
  15. package/plugins/FeatureForm.js +103 -111
  16. package/plugins/LayerTree.js +4 -1
  17. package/plugins/NewsPopup.js +2 -2
  18. package/plugins/Portal.js +3 -1
  19. package/plugins/Print.js +4 -4
  20. package/plugins/Redlining.js +9 -0
  21. package/plugins/ThemeSwitcher.js +3 -0
  22. package/plugins/map/EditingSupport.js +2 -2
  23. package/plugins/map/RedliningSupport.js +63 -13
  24. package/plugins/style/Editing.css +34 -0
  25. package/reducers/editing.js +12 -7
  26. package/reducers/layers.js +27 -5
  27. package/static/translations/bg-BG.json +10 -0
  28. package/static/translations/ca-ES.json +10 -0
  29. package/static/translations/cs-CZ.json +10 -0
  30. package/static/translations/de-CH.json +10 -0
  31. package/static/translations/de-DE.json +10 -0
  32. package/static/translations/en-US.json +11 -1
  33. package/static/translations/es-ES.json +10 -0
  34. package/static/translations/fi-FI.json +10 -0
  35. package/static/translations/fr-FR.json +10 -0
  36. package/static/translations/hu-HU.json +10 -0
  37. package/static/translations/it-IT.json +10 -0
  38. package/static/translations/ja-JP.json +10 -0
  39. package/static/translations/nl-NL.json +10 -0
  40. package/static/translations/no-NO.json +10 -0
  41. package/static/translations/pl-PL.json +10 -0
  42. package/static/translations/pt-BR.json +10 -0
  43. package/static/translations/pt-PT.json +10 -0
  44. package/static/translations/ro-RO.json +10 -0
  45. package/static/translations/ru-RU.json +10 -0
  46. package/static/translations/sv-SE.json +10 -0
  47. package/static/translations/tr-TR.json +10 -0
  48. package/static/translations/tsconfig.json +10 -0
  49. package/static/translations/uk-UA.json +10 -0
  50. package/utils/EditingUtils.js +15 -13
  51. package/utils/ElevationInterface.js +1 -2
  52. package/utils/LayerUtils.js +5 -3
  53. package/utils/MapUtils.js +2 -11
  54. package/utils/ServiceLayerUtils.js +53 -2
  55. package/utils/ThemeUtils.js +3 -1
@@ -1,6 +1,10 @@
1
1
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
2
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
3
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
+ function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
5
+ function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
6
+ function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
7
+ function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
4
8
  function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
5
9
  function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
6
10
  function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
@@ -74,18 +78,26 @@ var PickFeature = /*#__PURE__*/function (_React$Component) {
74
78
  }
75
79
  _this.setState(function (state) {
76
80
  var newState = {
77
- pickResults: _objectSpread(_objectSpread({}, state.pickResults), result),
81
+ pickResults: [].concat(_toConsumableArray(state.pickResults), _toConsumableArray(Object.entries(result).map(function (_ref5) {
82
+ var _ref6 = _slicedToArray(_ref5, 2),
83
+ layername = _ref6[0],
84
+ features = _ref6[1];
85
+ return features.map(function (feature) {
86
+ return {
87
+ layer: layername,
88
+ feature: feature,
89
+ mapName: layer.wms_name
90
+ };
91
+ });
92
+ }).flat())),
78
93
  pendingQueries: state.pendingQueries - 1
79
94
  };
80
95
  if (newState.pendingQueries === 0) {
81
- var entries = Object.entries(newState.pickResults);
82
- if (entries.length === 1 && entries[0][1].length === 1) {
83
- _this.props.featurePicked(entries[0][0], entries[0][1][0]);
96
+ if (newState.pickResults.length === 1) {
97
+ _this.props.featurePicked(newState.pickResults[0].layer, newState.pickResults[0].feature, newState.pickResults[0].mapName);
84
98
  newState.pickResults = null;
85
99
  newState.pickGeom = null;
86
- } else if (entries.reduce(function (sum, entry) {
87
- return sum + entry[1].length;
88
- }, 0) === 0) {
100
+ } else if (newState.pickResults.length === 0) {
89
101
  newState.pickResults = null;
90
102
  newState.pickGeom = null;
91
103
  }
@@ -100,11 +112,11 @@ var PickFeature = /*#__PURE__*/function (_React$Component) {
100
112
  };
101
113
  _this.props.addLayerFeatures(layer, [feature], true);
102
114
  _this.setState({
103
- highlightedFeature: key + ":" + feature.id
115
+ highlightedFeature: key
104
116
  });
105
117
  });
106
118
  _defineProperty(_this, "clearHighlight", function (key, feature) {
107
- if (_this.state.highlightedFeature === key + ":" + feature.id) {
119
+ if (_this.state.highlightedFeature === key) {
108
120
  _this.setState({
109
121
  highlightFeature: null
110
122
  });
@@ -174,7 +186,7 @@ var PickFeature = /*#__PURE__*/function (_React$Component) {
174
186
  });
175
187
  });
176
188
  }
177
- var pickResults = {};
189
+ var pickResults = [];
178
190
  if (!isEmpty(queryVectorLayers)) {
179
191
  var olMap = MapUtils.getHook(MapUtils.GET_MAP);
180
192
  var layerMap = queryVectorLayers.reduce(function (res, layer) {
@@ -188,8 +200,10 @@ var PickFeature = /*#__PURE__*/function (_React$Component) {
188
200
  if (layerid in layerMap) {
189
201
  var featureObj = format.writeFeatureObject(feature);
190
202
  var layername = layerMap[layerid].name;
191
- pickResults[layername] = pickResults[layername] || [];
192
- pickResults[layername].push(featureObj);
203
+ pickResults.push({
204
+ layer: layername,
205
+ feature: featureObj
206
+ });
193
207
  }
194
208
  });
195
209
  } else if (_this2.props.pickGeomType === 'Polygon') {
@@ -212,8 +226,10 @@ var PickFeature = /*#__PURE__*/function (_React$Component) {
212
226
  }
213
227
  var featureObj = format.writeFeatureObject(feature);
214
228
  var layername = layerMap[layer.get('id')].name;
215
- pickResults[layername] = pickResults[layername] || [];
216
- pickResults[layername].push(featureObj);
229
+ pickResults.push({
230
+ layer: layername,
231
+ feature: featureObj
232
+ });
217
233
  });
218
234
  });
219
235
  }
@@ -239,25 +255,21 @@ var PickFeature = /*#__PURE__*/function (_React$Component) {
239
255
  onClose: this.onClose,
240
256
  x: this.state.clickPos[0],
241
257
  y: this.state.clickPos[1]
242
- }, this.state.pendingQueries === 0 ? Object.entries(this.state.pickResults).map(function (_ref5) {
243
- var _ref6 = _slicedToArray(_ref5, 2),
244
- layername = _ref6[0],
245
- features = _ref6[1];
246
- return features.map(function (feature) {
247
- var _feature$displayname;
248
- return /*#__PURE__*/React.createElement("div", {
249
- key: layername + ":" + feature.id,
250
- onClickCapture: function onClickCapture() {
251
- return _this3.props.featurePicked(layername, feature);
252
- },
253
- onMouseOut: function onMouseOut() {
254
- return _this3.clearHighlight(layername, feature);
255
- },
256
- onMouseOver: function onMouseOver() {
257
- return _this3.highlightFeature(layername, feature);
258
- }
259
- }, layername + ": " + ((_feature$displayname = feature.displayname) !== null && _feature$displayname !== void 0 ? _feature$displayname : feature.id));
260
- });
258
+ }, this.state.pendingQueries === 0 ? this.state.pickResults.map(function (entry) {
259
+ var _entry$feature$displa;
260
+ var key = (entry.mapName || "") + "." + entry.layer + ":" + entry.feature.id;
261
+ return /*#__PURE__*/React.createElement("div", {
262
+ key: key,
263
+ onClickCapture: function onClickCapture() {
264
+ return _this3.props.featurePicked(entry.layer, entry.feature, entry.mapName);
265
+ },
266
+ onMouseOut: function onMouseOut() {
267
+ return _this3.clearHighlight(key, entry.feature);
268
+ },
269
+ onMouseOver: function onMouseOver() {
270
+ return _this3.highlightFeature(key, entry.feature);
271
+ }
272
+ }, entry.layer + ": " + ((_entry$feature$displa = entry.feature.displayname) !== null && _entry$feature$displa !== void 0 ? _entry$feature$displa : entry.feature.id));
261
273
  }) : /*#__PURE__*/React.createElement("div", {
262
274
  className: "pick-feature-menu-querying"
263
275
  }, /*#__PURE__*/React.createElement(Spinner, null), LocaleUtils.tr("pickfeature.querying")));
@@ -226,13 +226,13 @@ var QtDesignerForm = /*#__PURE__*/function (_React$Component) {
226
226
  return rows;
227
227
  });
228
228
  _defineProperty(_this, "renderWidget", function (widget, feature, editConfig, fields, updateField) {
229
- var _widget$name;
229
+ var _feature$properties$w, _feature$properties;
230
230
  var nametransform = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : function (name) {
231
231
  return name;
232
232
  };
233
233
  var isRelWidget = arguments.length > 6 ? arguments[6] : undefined;
234
234
  var disabled = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : false;
235
- var value = (_widget$name = (feature.properties || {})[widget.name]) !== null && _widget$name !== void 0 ? _widget$name : "";
235
+ var value = (_feature$properties$w = (_feature$properties = feature.properties) === null || _feature$properties === void 0 ? void 0 : _feature$properties[widget.name]) !== null && _feature$properties$w !== void 0 ? _feature$properties$w : "";
236
236
  var prop = widget.property || {};
237
237
  if (String(prop.visible) === "false") {
238
238
  return null;
@@ -270,8 +270,8 @@ var QtDesignerForm = /*#__PURE__*/function (_React$Component) {
270
270
  }
271
271
  if (widget["class"] === "QLabel") {
272
272
  if (widget.name.startsWith("img__")) {
273
- var _widget$name$split$;
274
- value = (_widget$name$split$ = (feature.properties || [])[widget.name.split("__")[1]]) !== null && _widget$name$split$ !== void 0 ? _widget$name$split$ : widget.property.text;
273
+ var _feature$properties$w2, _feature$properties2;
274
+ value = (_feature$properties$w2 = (_feature$properties2 = feature.properties) === null || _feature$properties2 === void 0 ? void 0 : _feature$properties2[widget.name.split("__")[1]]) !== null && _feature$properties$w2 !== void 0 ? _feature$properties$w2 : widget.property.text;
275
275
  return /*#__PURE__*/React.createElement("div", {
276
276
  className: "qt-designer-form-image"
277
277
  }, /*#__PURE__*/React.createElement("a", {
@@ -372,8 +372,8 @@ var QtDesignerForm = /*#__PURE__*/function (_React$Component) {
372
372
  return _this.renderLayout(child.layout, feature, editConfig, updateField, nametransform, child.name === activetab);
373
373
  })));
374
374
  } else if (widget["class"] === "QTextEdit" || widget["class"] === "QTextBrowser" || widget["class"] === "QPlainTextEdit") {
375
- var _feature$properties$w, _feature$properties;
376
- if (((_feature$properties$w = (_feature$properties = feature.properties) === null || _feature$properties === void 0 ? void 0 : _feature$properties[widget.name]) !== null && _feature$properties$w !== void 0 ? _feature$properties$w : null) === null) {
375
+ var _feature$properties$w3, _feature$properties3;
376
+ if (((_feature$properties$w3 = (_feature$properties3 = feature.properties) === null || _feature$properties3 === void 0 ? void 0 : _feature$properties3[widget.name]) !== null && _feature$properties$w3 !== void 0 ? _feature$properties$w3 : null) === null) {
377
377
  var _ConfigUtils$getConfi;
378
378
  value = (_ConfigUtils$getConfi = ConfigUtils.getConfigProp("editTextNullValue")) !== null && _ConfigUtils$getConfi !== void 0 ? _ConfigUtils$getConfi : "";
379
379
  }
@@ -397,9 +397,9 @@ var QtDesignerForm = /*#__PURE__*/function (_React$Component) {
397
397
  }
398
398
  } else if (widget["class"] === "QLineEdit") {
399
399
  if (widget.name.endsWith("__upload")) {
400
- var _feature$properties2;
400
+ var _feature$properties4;
401
401
  var fieldId = widget.name.replace(/__upload/, '');
402
- var uploadValue = ((_feature$properties2 = feature.properties) === null || _feature$properties2 === void 0 ? void 0 : _feature$properties2[fieldId]) || "";
402
+ var uploadValue = ((_feature$properties4 = feature.properties) === null || _feature$properties4 === void 0 ? void 0 : _feature$properties4[fieldId]) || "";
403
403
  var uploadElName = elname.replace(/__upload/, '');
404
404
  var constraints = {
405
405
  accept: prop.text || "",
@@ -417,10 +417,10 @@ var QtDesignerForm = /*#__PURE__*/function (_React$Component) {
417
417
  value: uploadValue
418
418
  });
419
419
  } else {
420
- var _feature$properties$w2, _feature$properties3;
420
+ var _feature$properties$w4, _feature$properties5;
421
421
  if (fieldConstraints.prec !== undefined && typeof value === 'number') {
422
422
  value = value.toFixed(fieldConstraints.prec);
423
- } else if (((_feature$properties$w2 = (_feature$properties3 = feature.properties) === null || _feature$properties3 === void 0 ? void 0 : _feature$properties3[widget.name]) !== null && _feature$properties$w2 !== void 0 ? _feature$properties$w2 : null) === null) {
423
+ } else if (((_feature$properties$w4 = (_feature$properties5 = feature.properties) === null || _feature$properties5 === void 0 ? void 0 : _feature$properties5[widget.name]) !== null && _feature$properties$w4 !== void 0 ? _feature$properties$w4 : null) === null) {
424
424
  var _ConfigUtils$getConfi2;
425
425
  value = (_ConfigUtils$getConfi2 = ConfigUtils.getConfigProp("editTextNullValue")) !== null && _ConfigUtils$getConfi2 !== void 0 ? _ConfigUtils$getConfi2 : "";
426
426
  }
@@ -471,7 +471,7 @@ var QtDesignerForm = /*#__PURE__*/function (_React$Component) {
471
471
  var count = parts.length;
472
472
  var _fieldId = parts.slice(1, count - 3).join("__");
473
473
  value = (_fieldId2 = (feature.properties || [])[_fieldId]) !== null && _fieldId2 !== void 0 ? _fieldId2 : "";
474
- var keyvalrel = _this.props.mapPrefix + parts[count - 3] + ":" + parts[count - 2] + ":" + parts[count - 1];
474
+ var keyvalrel = _this.props.mapPrefix + "." + parts[count - 3] + ":" + parts[count - 2] + ":" + parts[count - 1];
475
475
  var filterExpr = null;
476
476
  if (field !== null && field !== void 0 && field.filterExpression) {
477
477
  filterExpr = parseExpression(field.filterExpression, feature, editConfig, _this.props.iface, _this.props.mapPrefix, _this.props.mapCrs, function () {
@@ -543,6 +543,7 @@ var QtDesignerForm = /*#__PURE__*/function (_React$Component) {
543
543
  value: value
544
544
  }));
545
545
  } else {
546
+ var _feature$properties6;
546
547
  return /*#__PURE__*/React.createElement(NumberInput, _extends({
547
548
  decimals: precision,
548
549
  max: max,
@@ -554,7 +555,7 @@ var QtDesignerForm = /*#__PURE__*/function (_React$Component) {
554
555
  }, inputConstraints, {
555
556
  step: step,
556
557
  style: fontStyle,
557
- value: value
558
+ value: (_feature$properties6 = feature.properties) === null || _feature$properties6 === void 0 ? void 0 : _feature$properties6[widget.name]
558
559
  }));
559
560
  }
560
561
  } else if (widget["class"] === "QDateEdit") {
@@ -621,14 +622,14 @@ var QtDesignerForm = /*#__PURE__*/function (_React$Component) {
621
622
  // featurelink__layer__attrname
622
623
  // featurelink__layer__reltable__attrname
623
624
  if (_parts.length === 3 || _parts.length === 4) {
624
- var _feature$properties4;
625
+ var _feature$properties7;
625
626
  var layer = _parts[1];
626
627
  var reltable = _parts.length === 4 ? _parts[2] : "";
627
628
  var attrname = _parts.slice(2).join("__");
628
- value = (_feature$properties4 = feature.properties) === null || _feature$properties4 === void 0 ? void 0 : _feature$properties4[attrname];
629
+ value = (_feature$properties7 = feature.properties) === null || _feature$properties7 === void 0 ? void 0 : _feature$properties7[attrname];
629
630
  if (layer === reltable) {
630
631
  var index = parseInt(nametransform("").split("__")[1], 10); // Ugh..
631
- var reldataset = _this.props.mapPrefix + reltable;
632
+ var reldataset = _this.props.mapPrefix + "." + reltable;
632
633
  var displayField = attrname.split("__")[1];
633
634
  if (feature.__status__ !== "empty") {
634
635
  var featurebuttons = [{
@@ -745,7 +746,7 @@ var QtDesignerForm = /*#__PURE__*/function (_React$Component) {
745
746
  width: '1px'
746
747
  } : {};
747
748
  });
748
- var editConfig = _this.props.editConfigs[tablename];
749
+ var editConfig = _this.props.editConfigs[_this.props.mapPrefix][tablename];
749
750
  if (!editConfig) {
750
751
  // Relation dataset not permitted / no edit config available
751
752
  return null;
@@ -991,7 +992,7 @@ var QtDesignerForm = /*#__PURE__*/function (_React$Component) {
991
992
  }
992
993
  var parts = widget.name.split("__");
993
994
  if (parts.length >= 3 && parts[0] === "nrel") {
994
- relationTables[_this.props.mapPrefix + parts[1]] = {
995
+ relationTables[_this.props.mapPrefix + "." + parts[1]] = {
995
996
  fk: parts[2],
996
997
  sortcol: parts[3] || null,
997
998
  noreorder: parts[4] || false
@@ -1145,6 +1146,7 @@ _defineProperty(QtDesignerForm, "defaultState", {
1145
1146
  });
1146
1147
  export default connect(function (state) {
1147
1148
  return {
1148
- locale: state.locale.current
1149
+ locale: state.locale.current,
1150
+ editConfigs: state.layers.editConfigs
1149
1151
  };
1150
1152
  }, {})(QtDesignerForm);
@@ -101,6 +101,10 @@ var AppContainerComponent = /*#__PURE__*/function (_React$Component) {
101
101
  if (params.t) {
102
102
  _this.props.showNotification("missingtheme", LocaleUtils.tr("app.missingtheme", params.t), NotificationType.WARN, true);
103
103
  params.l = undefined;
104
+ params.bl = undefined;
105
+ params.c = undefined;
106
+ params.e = undefined;
107
+ params.s = undefined;
104
108
  }
105
109
  var userDefaultTheme = Object.fromEntries(_this.props.defaultUrlParams.split("&").map(function (x) {
106
110
  return x.split("=");
@@ -1,11 +1,9 @@
1
1
  function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
2
  function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n2 = 0, F = function F() {}; return { s: F, n: function n() { return _n2 >= r.length ? { done: !0 } : { done: !1, value: r[_n2++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
3
- function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
4
- function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
5
3
  function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
6
- function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
7
- function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
8
4
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
5
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
6
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
9
7
  function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
10
8
  function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
11
9
  function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
@@ -53,7 +51,7 @@ var ThemeList = /*#__PURE__*/function (_React$Component) {
53
51
  }
54
52
  _this = _callSuper(this, ThemeList, [].concat(args));
55
53
  _defineProperty(_this, "state", {
56
- expandedGroups: [],
54
+ expandedGroups: {},
57
55
  visibleThemeInfoMenu: null
58
56
  });
59
57
  _defineProperty(_this, "groupMatchesFilter", function (group, filter) {
@@ -74,6 +72,7 @@ var ThemeList = /*#__PURE__*/function (_React$Component) {
74
72
  return false;
75
73
  });
76
74
  _defineProperty(_this, "renderThemeGroup", function (group, filter) {
75
+ var defaultExpanded = _this.props.expandGroups;
77
76
  var assetsPath = ConfigUtils.getAssetsPath();
78
77
  var subdirs = group && group.subdirs ? group.subdirs : [];
79
78
  if (filter) {
@@ -82,7 +81,8 @@ var ThemeList = /*#__PURE__*/function (_React$Component) {
82
81
  });
83
82
  }
84
83
  var subtree = subdirs.map(function (subdir) {
85
- var expanded = !_this.props.collapsibleGroups || filter || _this.state.expandedGroups.includes(subdir.id) || _this.props.activeTheme && _this.groupContainsActiveTheme(subdir);
84
+ var _this$state$expandedG;
85
+ var expanded = !_this.props.collapsibleGroups || filter || ((_this$state$expandedG = _this.state.expandedGroups[subdir.id]) !== null && _this$state$expandedG !== void 0 ? _this$state$expandedG : defaultExpanded) || _this.props.activeTheme && _this.groupContainsActiveTheme(subdir);
86
86
  if (isEmpty(subdir.items) && isEmpty(subdir.subdirs)) {
87
87
  return null;
88
88
  }
@@ -93,15 +93,13 @@ var ThemeList = /*#__PURE__*/function (_React$Component) {
93
93
  onClick: function onClick() {
94
94
  return _this.setState(function (state) {
95
95
  return {
96
- expandedGroups: expanded ? state.expandedGroups.filter(function (id) {
97
- return id !== subdir.id;
98
- }) : [].concat(_toConsumableArray(state.expandedGroups), [subdir.id])
96
+ expandedGroups: _objectSpread(_objectSpread({}, state.expandedGroups), {}, _defineProperty({}, subdir.id, !expanded))
99
97
  };
100
98
  });
101
99
  }
102
100
  }, _this.props.collapsibleGroups ? /*#__PURE__*/React.createElement(Icon, {
103
101
  icon: expanded ? "collapse" : "expand"
104
- }) : null, " ", subdir.title), expanded ? _this.renderThemeGroup(subdir, filter) : null);
102
+ }) : null, " ", subdir.titleMsgId ? LocaleUtils.tr(subdir.titleMsgId) : subdir.title), expanded ? _this.renderThemeGroup(subdir, filter) : null);
105
103
  });
106
104
  var activeThemeId = _this.props.activeTheme ? _this.props.activeTheme.id : null;
107
105
  var addLayersTitle = LocaleUtils.tr("themeswitcher.addlayerstotheme");
@@ -358,6 +356,7 @@ _defineProperty(ThemeList, "propTypes", {
358
356
  collapsibleGroups: PropTypes.bool,
359
357
  defaultUrlParams: PropTypes.string,
360
358
  dontPreserveSettingsOnSwitch: PropTypes.bool,
359
+ expandGroups: PropTypes.bool,
361
360
  filter: PropTypes.string,
362
361
  layers: PropTypes.array,
363
362
  setActiveLayerInfo: PropTypes.func,
@@ -687,7 +687,7 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
687
687
  _this2.objectMap = {};
688
688
  // Add 3d tiles
689
689
  (((_this2$props$theme$ma9 = _this2.props.theme.map3d) === null || _this2$props$theme$ma9 === void 0 ? void 0 : _this2$props$theme$ma9.tiles3d) || []).forEach(function (entry) {
690
- var _entry$title;
690
+ var _entry$visibility, _entry$title;
691
691
  var tiles = new Tiles3D({
692
692
  url: MiscUtils.resolveAssetsPath(entry.url),
693
693
  errorTarget: 32
@@ -723,7 +723,7 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
723
723
  _this2.instance.add(tiles);
724
724
  _this2.objectMap[entry.name] = tiles;
725
725
  sceneObjects[entry.name] = {
726
- visibility: true,
726
+ visibility: (_entry$visibility = entry.visibility) !== null && _entry$visibility !== void 0 ? _entry$visibility : true,
727
727
  opacity: 255,
728
728
  layertree: true,
729
729
  title: (_entry$title = entry.title) !== null && _entry$title !== void 0 ? _entry$title : entry.name,
@@ -740,7 +740,10 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
740
740
 
741
741
  // Add other objects
742
742
  (((_this2$props$theme$ma10 = _this2.props.theme.map3d) === null || _this2$props$theme$ma10 === void 0 ? void 0 : _this2$props$theme$ma10.objects3d) || []).forEach(function (entry) {
743
- importGltf(MiscUtils.resolveAssetsPath(entry.url), entry.name, _this2.state.sceneContext);
743
+ var _entry$visibility2;
744
+ importGltf(MiscUtils.resolveAssetsPath(entry.url), entry.name, _this2.state.sceneContext, {
745
+ visibility: (_entry$visibility2 = entry.visibility) !== null && _entry$visibility2 !== void 0 ? _entry$visibility2 : true
746
+ });
744
747
  });
745
748
  _this2.setState(function (state) {
746
749
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qwc2",
3
- "version": "2025.10.30",
3
+ "version": "2025.11.12",
4
4
  "description": "QGIS Web Client",
5
5
  "author": "Sourcepole AG",
6
6
  "license": "BSD-2-Clause",
@@ -23,6 +23,7 @@
23
23
  "@loaders.gl/shapefile": "^4.3.3",
24
24
  "@loaders.gl/zip": "^4.3.3",
25
25
  "@mapbox/shp-write": "^0.4.3",
26
+ "@norbulcz/num-parse": "^0.1.0",
26
27
  "@panoramax/web-viewer": "^4.0.1",
27
28
  "@reduxjs/toolkit": "^2.4.0",
28
29
  "@turf/buffer": "^6.5.0",
@@ -142,7 +142,8 @@ var Cyclomedia = /*#__PURE__*/function (_React$Component) {
142
142
  styleOptions: {
143
143
  img: "cyclomedia-cone",
144
144
  rotation: posData.yaw,
145
- size: dimensions
145
+ size: dimensions,
146
+ anchor: [0.5, 1]
146
147
  }
147
148
  };
148
149
  var layer = {
@@ -181,7 +182,7 @@ var Cyclomedia = /*#__PURE__*/function (_React$Component) {
181
182
  }
182
183
  }
183
184
  var loginOauth = !!_this.props.clientId && !_this.state.loginFailed;
184
- return "\n <!DOCTYPE html>\n <html>\n <head>\n <script type=\"text/javascript\" src=\"https://unpkg.com/react@16.12.0/umd/react.production.min.js\"></script>\n <script type=\"text/javascript\" src=\"https://unpkg.com/react-dom@16.12.0/umd/react-dom.production.min.js\"></script>\n <script type=\"text/javascript\" src=\"https://streetsmart.cyclomedia.com/api/v".concat(_this.props.cyclomediaVersion, "/StreetSmartApi.js\"></script>\n <script type=\"text/javascript\">\n let apiInitialized = false;\n let initCallback = null;\n let posCallback = null;\n let measureCallback = null;\n\n function initApi() {\n StreetSmartApi.init({\n targetElement: document.getElementById(\"streetsmartApi\"),\n username: \"").concat(_this.state.username || undefined, "\",\n password: \"").concat(_this.state.password || undefined, "\",\n apiKey: \"").concat(_this.props.apikey, "\",\n clientId: \"").concat(_this.props.clientId, "\",\n loginOauth: ").concat(loginOauth, ",\n loginRedirectUri: \"").concat(_this.props.loginRedirectUri, "\",\n logoutRedirectUri: \"").concat(_this.props.logoutRedirectUri, "\",\n srs: \"").concat(_this.props.projection, "\",\n locale: \"").concat(lang, "\",\n configurationUrl: 'https://atlas.cyclomedia.com/configuration',\n addressSettings: {\n locale: \"us\",\n database: \"Nokia\"\n }\n }).then(() => {\n apiInitialized = true;\n if (initCallback) {\n initCallback(true);\n }\n }, (e) => {\n apiInitialized = false;\n if (initCallback) {\n initCallback(false, e.message);\n }\n });\n }\n function openImage(posStr, crs) {\n if (!apiInitialized) {\n return;\n }\n StreetSmartApi.open(posStr, {\n viewerType: StreetSmartApi.ViewerType.PANORAMA,\n srs: crs,\n panoramaViewer: {\n closable: false,\n maximizable: true,\n replace: true,\n recordingsVisible: true,\n navbarVisible: true,\n timeTravelVisible: true,\n measureTypeButtonVisible: true,\n measureTypeButtonStart: true,\n measureTypeButtonToggle: true,\n },\n }).then((result) => {\n if (result && result[0]){\n window.panoramaViewer = result[0];\n window.panoramaViewer.on(StreetSmartApi.Events.panoramaViewer.IMAGE_CHANGE, changeView);\n window.panoramaViewer.on(StreetSmartApi.Events.panoramaViewer.VIEW_CHANGE, changeView);\n StreetSmartApi.on(StreetSmartApi.Events.measurement.MEASUREMENT_CHANGED, changeMeasurement);\n StreetSmartApi.on(StreetSmartApi.Events.measurement.MEASUREMENT_STOPPED, stopMeasurement);\n }\n }).catch((reason) => {\n console.log('Failed to create component(s) through API: ' + reason);\n });\n }\n function changeView() {\n if (posCallback) {\n const recording = window.panoramaViewer.getRecording();\n const orientation = window.panoramaViewer.getOrientation();\n const pos = recording.xyz;\n const posData = {\n pos: [pos[0], pos[1]],\n crs: recording.srs,\n yaw: orientation.yaw * Math.PI / 180,\n hFov: orientation.hFov * Math.PI / 180.0\n }\n posCallback(posData);\n }\n }\n function changeMeasurement(e) {\n measureCallback(e.detail.activeMeasurement);\n }\n function stopMeasurement() {\n measureCallback(null);\n }\n function registerCallbacks(_initCallback, _posCallback, _measureCallback) {\n initCallback = _initCallback;\n posCallback = _posCallback;\n measureCallback = _measureCallback;\n }\n </script>\n <style>\n html, body, #streetsmartApi {height: 100%;}\n </style>\n </head>\n <body style=\"margin: 0\">\n <div id=\"streetsmartApi\">\n </div>\n </body>\n </html>\n ");
185
+ return "\n <!DOCTYPE html>\n <html>\n <head>\n <script type=\"text/javascript\" src=\"https://unpkg.com/react@18.3.1/umd/react.production.min.js\"></script>\n <script type=\"text/javascript\" src=\"https://unpkg.com/react-dom@18.3.1/umd/react-dom.production.min.js\"></script>\n <script type=\"text/javascript\" src=\"https://streetsmart.cyclomedia.com/api/v".concat(_this.props.cyclomediaVersion, "/StreetSmartApi.js\"></script>\n <script type=\"text/javascript\">\n let apiInitialized = false;\n let initCallback = null;\n let posCallback = null;\n let measureCallback = null;\n\n function initApi() {\n StreetSmartApi.init({\n targetElement: document.getElementById(\"streetsmartApi\"),\n username: \"").concat(_this.state.username || undefined, "\",\n password: \"").concat(_this.state.password || undefined, "\",\n apiKey: \"").concat(_this.props.apikey, "\",\n clientId: \"").concat(_this.props.clientId, "\",\n loginOauth: ").concat(loginOauth, ",\n loginRedirectUri: \"").concat(_this.props.loginRedirectUri, "\",\n logoutRedirectUri: \"").concat(_this.props.logoutRedirectUri, "\",\n srs: \"").concat(_this.props.projection, "\",\n locale: \"").concat(lang, "\",\n configurationUrl: 'https://atlas.cyclomedia.com/configuration',\n addressSettings: {\n locale: \"us\",\n database: \"Nokia\"\n }\n }).then(() => {\n apiInitialized = true;\n if (initCallback) {\n initCallback(true);\n }\n }, (e) => {\n apiInitialized = false;\n if (initCallback) {\n initCallback(false, e.message);\n }\n });\n }\n function openImage(posStr, crs) {\n if (!apiInitialized) {\n return;\n }\n StreetSmartApi.open(posStr, {\n viewerType: StreetSmartApi.ViewerType.PANORAMA,\n srs: crs,\n panoramaViewer: {\n closable: false,\n maximizable: true,\n replace: true,\n recordingsVisible: true,\n navbarVisible: true,\n timeTravelVisible: true,\n measureTypeButtonVisible: true,\n measureTypeButtonStart: true,\n measureTypeButtonToggle: true,\n },\n }).then((result) => {\n if (result && result[0]){\n window.panoramaViewer = result[0];\n window.panoramaViewer.on(StreetSmartApi.Events.panoramaViewer.IMAGE_CHANGE, changeView);\n window.panoramaViewer.on(StreetSmartApi.Events.panoramaViewer.VIEW_CHANGE, changeView);\n StreetSmartApi.on(StreetSmartApi.Events.measurement.MEASUREMENT_CHANGED, changeMeasurement);\n StreetSmartApi.on(StreetSmartApi.Events.measurement.MEASUREMENT_STOPPED, stopMeasurement);\n }\n }).catch((reason) => {\n console.log('Failed to create component(s) through API: ' + reason);\n });\n }\n function changeView() {\n if (posCallback) {\n const recording = window.panoramaViewer.getRecording();\n const orientation = window.panoramaViewer.getOrientation();\n const pos = recording.xyz;\n const posData = {\n pos: [pos[0], pos[1]],\n crs: recording.srs,\n yaw: orientation.yaw * Math.PI / 180,\n hFov: orientation.hFov * Math.PI / 180.0\n }\n posCallback(posData);\n }\n }\n function changeMeasurement(e) {\n measureCallback(e.detail.activeMeasurement);\n }\n function stopMeasurement() {\n measureCallback(null);\n }\n function registerCallbacks(_initCallback, _posCallback, _measureCallback) {\n initCallback = _initCallback;\n posCallback = _posCallback;\n measureCallback = _measureCallback;\n }\n </script>\n <style>\n html, body, #streetsmartApi {height: 100%;}\n </style>\n </head>\n <body style=\"margin: 0\">\n <div id=\"streetsmartApi\">\n </div>\n </body>\n </html>\n ");
185
186
  });
186
187
  _defineProperty(_this, "addRecordingsWFS", function () {
187
188
  var layer = {
@@ -235,7 +236,7 @@ var Cyclomedia = /*#__PURE__*/function (_React$Component) {
235
236
  });
236
237
  _this.iframe = null;
237
238
  _this.iframePollIntervall = null;
238
- if (props.credentialUserInfoFields) {
239
+ if (props.credentialUserInfoFields && props.userInfos) {
239
240
  _this.state.username = props.userInfos[props.credentialUserInfoFields.username];
240
241
  _this.state.password = props.userInfos[props.credentialUserInfoFields.password];
241
242
  }
@@ -417,7 +418,7 @@ _defineProperty(Cyclomedia, "propTypes", {
417
418
  userInfos: PropTypes.object
418
419
  });
419
420
  _defineProperty(Cyclomedia, "defaultProps", {
420
- cyclomediaVersion: '24.1',
421
+ cyclomediaVersion: '25.7',
421
422
  displayMeasurements: true,
422
423
  geometry: {
423
424
  initialWidth: 480,