qwc2 2026.2.17 → 2026.2.24

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 (58) hide show
  1. package/actions/layers.js +31 -11
  2. package/actions/theme.js +2 -1
  3. package/components/AttributeForm.js +2 -1
  4. package/components/SearchBox.js +11 -5
  5. package/components/map/layers/WMSLayer.js +7 -7
  6. package/components/map3d/ImportObjects3D.js +5 -4
  7. package/components/map3d/Map3D.js +420 -275
  8. package/components/map3d/layers/VectorLayer3D.js +5 -4
  9. package/components/map3d/layers/WMSLayer3D.js +17 -8
  10. package/components/map3d/utils/MiscUtils3D.js +1 -57
  11. package/components/style/AttributeForm.css +7 -8
  12. package/components/style/LinkFeatureForm.css +3 -1
  13. package/components/widgets/LayerCatalogWidget.js +2 -2
  14. package/components/widgets/NumberInput.js +7 -0
  15. package/package.json +1 -1
  16. package/plugins/BackgroundSwitcher.js +5 -3
  17. package/plugins/LayerTree.js +3 -8
  18. package/plugins/ObliqueView.js +9 -2
  19. package/plugins/Settings.js +20 -10
  20. package/plugins/map/SnappingSupport.js +14 -0
  21. package/plugins/map3d/BackgroundSwitcher3D.js +3 -1
  22. package/plugins/map3d/Compare3D.js +29 -27
  23. package/plugins/map3d/Draw3D.js +16 -38
  24. package/plugins/map3d/ExportObjects3D.js +8 -11
  25. package/plugins/map3d/HideObjects3D.js +6 -13
  26. package/plugins/map3d/Identify3D.js +14 -17
  27. package/plugins/map3d/LayerTree3D.js +119 -79
  28. package/plugins/map3d/MapLight3D.js +28 -5
  29. package/plugins/map3d/style/LayerTree3D.css +6 -0
  30. package/plugins/map3d/style/MapLight3D.css +6 -1
  31. package/reducers/layers.js +88 -61
  32. package/scripts/themesConfig.js +1 -0
  33. package/scripts/themesConfig.py +1 -0
  34. package/static/translations/bg-BG.json +2 -0
  35. package/static/translations/ca-ES.json +2 -0
  36. package/static/translations/cs-CZ.json +2 -0
  37. package/static/translations/de-CH.json +2 -0
  38. package/static/translations/de-DE.json +2 -0
  39. package/static/translations/en-US.json +2 -0
  40. package/static/translations/es-ES.json +2 -0
  41. package/static/translations/fi-FI.json +2 -0
  42. package/static/translations/fr-FR.json +3 -1
  43. package/static/translations/hu-HU.json +2 -0
  44. package/static/translations/it-IT.json +3 -1
  45. package/static/translations/ja-JP.json +2 -0
  46. package/static/translations/nl-NL.json +2 -0
  47. package/static/translations/no-NO.json +2 -0
  48. package/static/translations/pl-PL.json +2 -0
  49. package/static/translations/pt-BR.json +2 -0
  50. package/static/translations/pt-PT.json +2 -0
  51. package/static/translations/ro-RO.json +2 -0
  52. package/static/translations/ru-RU.json +2 -0
  53. package/static/translations/sv-SE.json +2 -0
  54. package/static/translations/tr-TR.json +2 -0
  55. package/static/translations/tsconfig.json +2 -0
  56. package/static/translations/uk-UA.json +2 -0
  57. package/utils/EditingUtils.js +4 -4
  58. package/utils/LayerUtils.js +57 -44
package/actions/layers.js CHANGED
@@ -22,6 +22,7 @@ export var REMOVE_LAYER_FEATURES = 'REMOVE_LAYER_FEATURES';
22
22
  export var CLEAR_LAYER = 'CLEAR_LAYER';
23
23
  export var CHANGE_LAYER_PROPERTY = 'CHANGE_LAYER_PROPERTY';
24
24
  export var SET_LAYER_DIMENSIONS = 'SET_LAYER_DIMENSIONS';
25
+ export var SET_LAYER_METADATA = 'SET_LAYER_METADATA';
25
26
  export var REFRESH_LAYER = 'REFRESH_LAYER';
26
27
  export var REMOVE_ALL_LAYERS = 'REMOVE_ALL_LAYERS';
27
28
  export var REPLACE_PLACEHOLDER_LAYER = 'REPLACE_PLACEHOLDER_LAYER';
@@ -39,12 +40,17 @@ export function addLayer(layer) {
39
40
  var pos = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
40
41
  var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
41
42
  return function (dispatch) {
43
+ dispatch({
44
+ type: ADD_LAYER,
45
+ layer: layer,
46
+ pos: pos,
47
+ options: options
48
+ });
42
49
  LayerUtils.queryLayerMetadata(layer, function (result) {
43
50
  return dispatch({
44
- type: ADD_LAYER,
45
- layer: result,
46
- pos: pos,
47
- options: options
51
+ type: SET_LAYER_METADATA,
52
+ id: layer.id,
53
+ metadata: result
48
54
  });
49
55
  });
50
56
  };
@@ -65,11 +71,11 @@ export function removeLayer(layerId) {
65
71
  sublayerpath: sublayerpath
66
72
  };
67
73
  }
68
- export function reorderLayer(layer, sublayerpath, direction) {
74
+ export function reorderLayer(layerId, sublayerpath, direction) {
69
75
  return function (dispatch, getState) {
70
76
  dispatch({
71
77
  type: REORDER_LAYER,
72
- layer: layer,
78
+ layerId: layerId,
73
79
  sublayerpath: sublayerpath,
74
80
  direction: direction,
75
81
  preventSplittingGroups: ConfigUtils.getConfigProp("preventSplittingGroupsWhenReordering", getState().theme.current)
@@ -101,11 +107,20 @@ export function clearLayer(layerId) {
101
107
  };
102
108
  }
103
109
  export function addThemeSublayer(layer) {
104
- return function (dispatch) {
110
+ return function (dispatch, getState) {
111
+ var _getState$layers$flat;
112
+ dispatch({
113
+ type: ADD_THEME_SUBLAYER,
114
+ layer: layer
115
+ });
116
+ var layerId = (_getState$layers$flat = getState().layers.flat.find(function (l) {
117
+ return l.role === LayerRole.THEME;
118
+ })) === null || _getState$layers$flat === void 0 ? void 0 : _getState$layers$flat.id;
105
119
  LayerUtils.queryLayerMetadata(layer, function (result) {
106
120
  return dispatch({
107
- type: ADD_THEME_SUBLAYER,
108
- layer: result
121
+ type: SET_LAYER_METADATA,
122
+ id: layerId,
123
+ metadata: result
109
124
  });
110
125
  });
111
126
  };
@@ -177,11 +192,16 @@ export function removeAllLayers() {
177
192
  }
178
193
  export function replacePlaceholderLayer(id, layer) {
179
194
  return function (dispatch) {
195
+ dispatch({
196
+ type: REPLACE_PLACEHOLDER_LAYER,
197
+ id: id,
198
+ layer: layer
199
+ });
180
200
  LayerUtils.queryLayerMetadata(layer, function (result) {
181
201
  return dispatch({
182
- type: REPLACE_PLACEHOLDER_LAYER,
202
+ type: SET_LAYER_METADATA,
183
203
  id: id,
184
- layer: result
204
+ metadata: result
185
205
  });
186
206
  });
187
207
  };
package/actions/theme.js CHANGED
@@ -163,7 +163,7 @@ export function setCurrentTheme(theme, themes) {
163
163
  var themeLayerRestorer = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : null;
164
164
  var externalLayerRestorer = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : null;
165
165
  return function (dispatch, getState) {
166
- var _getState$layers;
166
+ var _getState$layers, _ref, _theme$mapTips;
167
167
  var curLayers = ((_getState$layers = getState().layers) === null || _getState$layers === void 0 ? void 0 : _getState$layers.flat) || [];
168
168
  var mapCrs = theme.mapCrs || themes.defaultMapCrs || "EPSG:3857";
169
169
  if (!(mapCrs in CoordinatesUtils.getAvailableCRS())) {
@@ -230,6 +230,7 @@ export function setCurrentTheme(theme, themes) {
230
230
  printGrid: theme.printGrid || themes.defaultPrintGrid || undefined,
231
231
  searchProviders: theme.searchProviders || themes.defaultSearchProviders || undefined,
232
232
  backgroundLayers: theme.backgroundLayers || themes.defaultBackgroundLayers || [],
233
+ mapTips: (_ref = (_theme$mapTips = theme.mapTips) !== null && _theme$mapTips !== void 0 ? _theme$mapTips : themes.defaultMapTips) !== null && _ref !== void 0 ? _ref : undefined,
233
234
  defaultDisplayCrs: theme.defaultDisplayCrs || themes.defaultDisplayCrs || undefined
234
235
  });
235
236
 
@@ -161,11 +161,12 @@ var AttributeForm = /*#__PURE__*/function (_React$Component) {
161
161
  readOnlyMsg = LocaleUtils.tr("editing.geomnonzeroz");
162
162
  }
163
163
  return /*#__PURE__*/React.createElement("div", {
164
- className: "AttributeForm"
164
+ className: "AttributeForm ".concat(_this.state.childEdit ? "attrib-form-has-child" : "")
165
165
  }, readOnlyMsg ? /*#__PURE__*/React.createElement("div", {
166
166
  className: "attrib-form-geom-readonly"
167
167
  }, readOnlyMsg) : null, /*#__PURE__*/React.createElement("form", {
168
168
  action: "",
169
+ className: "attrib-form-parent-form",
169
170
  onChange: function onChange(ev) {
170
171
  return _this.formChanged(ev);
171
172
  },
@@ -473,14 +473,16 @@ var SearchBox = /*#__PURE__*/function (_React$Component) {
473
473
  title: (_result$label3 = result.label) !== null && _result$label3 !== void 0 ? _result$label3 : result.text
474
474
  }), result.theme && addThemes ? /*#__PURE__*/React.createElement(Icon, {
475
475
  icon: "plus",
476
- onClick: function onClick() {
477
- return _this.selectLayerResult(provider, group, result);
476
+ onClick: function onClick(ev) {
477
+ MiscUtils.killEvent(ev);
478
+ _this.selectLayerResult(provider, group, result);
478
479
  },
479
480
  title: LocaleUtils.tr("themeswitcher.addtotheme")
480
481
  }) : null, _this.props.searchOptions.allowAddLayerAsGroup && result.sublayers ? /*#__PURE__*/React.createElement(Icon, {
481
482
  icon: "group",
482
- onClick: function onClick() {
483
- return _this.selectLayerResult(provider, group, result, true);
483
+ onClick: function onClick(ev) {
484
+ MiscUtils.killEvent(ev);
485
+ _this.selectLayerResult(provider, group, result, true);
484
486
  },
485
487
  title: LocaleUtils.tr("importlayer.asgroup")
486
488
  }) : null, result.info ? /*#__PURE__*/React.createElement(Icon, {
@@ -666,7 +668,7 @@ var SearchBox = /*#__PURE__*/function (_React$Component) {
666
668
  type: "placeholder",
667
669
  name: params.name,
668
670
  title: (_entry$title = entry.title) !== null && _entry$title !== void 0 ? _entry$title : params.name,
669
- role: params.USERLAYER,
671
+ role: LayerRole.USERLAYER,
670
672
  loading: true
671
673
  });
672
674
  ServiceLayerUtils.findLayers(params.type, params.url, [params], _this.props.map.projection, function (id, layer) {
@@ -1022,7 +1024,11 @@ var SearchBox = /*#__PURE__*/function (_React$Component) {
1022
1024
  var text = LocaleUtils.tr("search.existinglayer") + ": " + existingLayerName;
1023
1025
  _this.props.showNotification("existinglayer", text);
1024
1026
  } else {
1027
+ var existingLayer = _this.props.layers.find(function (l) {
1028
+ return l.type === layer.type && l.url === layer.url;
1029
+ });
1025
1030
  _this.props.addLayer(_objectSpread(_objectSpread({}, layer), {}, {
1031
+ srcid: existingLayer === null || existingLayer === void 0 ? void 0 : existingLayer.srcid,
1026
1032
  role: LayerRole.USERLAYER
1027
1033
  }));
1028
1034
  }
@@ -138,8 +138,8 @@ export default {
138
138
  }, options.sourceConfig || {}))
139
139
  }, options.layerConfig || {}));
140
140
  }
141
- layer.setVisible(queryParameters.LAYERS && options.visibility);
142
- layer.setOpacity(clientSideOpacity !== null && clientSideOpacity !== void 0 ? clientSideOpacity : 100);
141
+ layer.setVisible(queryParameters.LAYERS !== "" && options.visibility);
142
+ layer.setOpacity(clientSideOpacity !== null && clientSideOpacity !== void 0 ? clientSideOpacity : 1);
143
143
  return layer;
144
144
  },
145
145
  update: function update(layer, newOptions, oldOptions) {
@@ -147,7 +147,7 @@ export default {
147
147
  if (oldOptions && layer !== null && layer !== void 0 && (_layer$getSource = layer.getSource()) !== null && _layer$getSource !== void 0 && _layer$getSource.updateParams) {
148
148
  var changed = (oldOptions.rev || 0) !== (newOptions.rev || 0);
149
149
  var oldParams = wmsToOpenlayersOptions(oldOptions);
150
- getClientSideOpacity(oldOptions, oldParams);
150
+ getClientSideOpacity(oldOptions, oldParams); // Make getClientSideOpacity transform oldParams if necessary
151
151
  var newParams = wmsToOpenlayersOptions(newOptions);
152
152
  var clientSideOpacity = getClientSideOpacity(newOptions, newParams);
153
153
  Object.keys(oldParams).forEach(function (key) {
@@ -168,18 +168,18 @@ export default {
168
168
  if (layer.get("updateTimeout")) {
169
169
  clearTimeout(layer.get("updateTimeout"));
170
170
  }
171
- if (!newOptions.visibility || !queryParameters.LAYERS) {
171
+ if (!newOptions.visibility || queryParameters.LAYERS === "") {
172
172
  layer.setVisible(false);
173
173
  }
174
- layer.setOpacity(clientSideOpacity !== null && clientSideOpacity !== void 0 ? clientSideOpacity : 100);
174
+ layer.setOpacity(clientSideOpacity !== null && clientSideOpacity !== void 0 ? clientSideOpacity : 1);
175
175
  layer.set("updateTimeout", setTimeout(function () {
176
- layer.setVisible(queryParameters.LAYERS && newOptions.visibility);
176
+ layer.setVisible(queryParameters.LAYERS !== "" && newOptions.visibility);
177
177
  layer.getSource().updateParams(queryParameters);
178
178
  layer.getSource().changed();
179
179
  layer.set("updateTimeout", null);
180
180
  }, 500));
181
181
  } else {
182
- layer.setOpacity(clientSideOpacity !== null && clientSideOpacity !== void 0 ? clientSideOpacity : 100);
182
+ layer.setOpacity(clientSideOpacity !== null && clientSideOpacity !== void 0 ? clientSideOpacity : 1);
183
183
  }
184
184
  }
185
185
  }
@@ -30,7 +30,6 @@ import ConfigUtils from '../../utils/ConfigUtils';
30
30
  import LocaleUtils from '../../utils/LocaleUtils';
31
31
  import FileSelector from '../widgets/FileSelector';
32
32
  import Spinner from '../widgets/Spinner';
33
- import { importGltf } from './utils/MiscUtils3D';
34
33
  import './style/ImportObjects3D.css';
35
34
  var ImportObjects3D = /*#__PURE__*/function (_React$Component) {
36
35
  function ImportObjects3D() {
@@ -63,7 +62,8 @@ var ImportObjects3D = /*#__PURE__*/function (_React$Component) {
63
62
  _defineProperty(_this, "importGltfFile", function (file, taskid) {
64
63
  var reader = new FileReader();
65
64
  reader.onload = function (ev) {
66
- importGltf(ev.target.result, file.name, _this.props.sceneContext, {
65
+ _this.props.sceneContext.importObject3D(ev.target.result, uuidv4(), true, {
66
+ title: file.name,
67
67
  drawGroup: true,
68
68
  imported: true
69
69
  }, true);
@@ -110,8 +110,9 @@ var ImportObjects3D = /*#__PURE__*/function (_React$Component) {
110
110
  headers: headers
111
111
  }).then(function (response) {
112
112
  var tilesetUrl = _this.props.importedTilesBaseUrl + response.data.result.value;
113
- _this.props.sceneContext.add3dTiles(tilesetUrl, taskid, {
114
- title: file.name
113
+ _this.props.sceneContext.importTiles3D(tilesetUrl, taskid, true, {
114
+ title: file.name,
115
+ imported: true
115
116
  }, true);
116
117
  _this.setState({
117
118
  selectedfile: null,