qwc2 2026.7.9 → 2026.7.18

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 (39) hide show
  1. package/components/ExportSelection.js +21 -9
  2. package/components/MapSelection.js +2 -11
  3. package/components/SearchBox.js +10 -10
  4. package/components/share/ShareSocials.js +6 -14
  5. package/components/widgets/LayerCatalogWidget.js +7 -2
  6. package/components/widgets/MenuButton.js +8 -5
  7. package/extra/plugins/PlotInfoTool.js +1 -1
  8. package/package.json +4 -3
  9. package/plugins/BackgroundSwitcher.js +7 -3
  10. package/plugins/Identify.js +200 -135
  11. package/plugins/LayerCatalog.js +7 -3
  12. package/plugins/ThemeBrowser.js +2 -2
  13. package/plugins/ZoomButtons.js +3 -3
  14. package/plugins/map3d/MapExport3D.js +23 -10
  15. package/plugins/style/Identify.css +13 -0
  16. package/static/translations/bg-BG.json +3 -2
  17. package/static/translations/ca-ES.json +4 -3
  18. package/static/translations/cs-CZ.json +3 -2
  19. package/static/translations/de-CH.json +3 -2
  20. package/static/translations/de-DE.json +3 -2
  21. package/static/translations/en-US.json +4 -3
  22. package/static/translations/es-ES.json +4 -3
  23. package/static/translations/fi-FI.json +3 -2
  24. package/static/translations/fr-FR.json +4 -3
  25. package/static/translations/hu-HU.json +3 -2
  26. package/static/translations/it-IT.json +3 -2
  27. package/static/translations/ja-JP.json +3 -2
  28. package/static/translations/nl-NL.json +3 -2
  29. package/static/translations/no-NO.json +3 -2
  30. package/static/translations/pl-PL.json +3 -2
  31. package/static/translations/pt-BR.json +3 -2
  32. package/static/translations/pt-PT.json +3 -2
  33. package/static/translations/ro-RO.json +3 -2
  34. package/static/translations/ru-RU.json +3 -2
  35. package/static/translations/sv-SE.json +3 -2
  36. package/static/translations/tr-TR.json +3 -2
  37. package/static/translations/tsconfig.json +3 -2
  38. package/static/translations/uk-UA.json +3 -2
  39. package/utils/MiscUtils.js +15 -11
@@ -128,24 +128,36 @@ var ExportSelection = /*#__PURE__*/function (_React$Component) {
128
128
  }
129
129
  if (this.props.frameRatio !== prevProps.frameRatio) {
130
130
  this.setState(function (state) {
131
- var maxWidth = _this2.exportContainer.offsetWidth;
132
- var maxHeight = _this2.exportContainer.offsetHeight;
133
- var newheight = _this2.props.frameRatio ? Math.round(state.width * _this2.props.frameRatio) : state.height;
134
- var newwidth = state.width;
131
+ var containerWidth = _this2.exportContainer.offsetWidth;
132
+ var containerHeight = _this2.exportContainer.offsetHeight;
133
+ var maxWidth = 0.75 * containerWidth;
134
+ var maxHeight = 0.75 * containerHeight;
135
+ var newwidth;
136
+ var newheight;
135
137
  if (_this2.props.frameRatio) {
136
- if (newwidth > maxWidth) {
138
+ if (_this2.props.frameRatio >= 1) {
137
139
  newwidth = maxWidth;
138
140
  newheight = Math.round(newwidth * _this2.props.frameRatio);
139
- }
140
- if (newheight > maxHeight) {
141
+ if (newheight > maxHeight) {
142
+ newheight = maxHeight;
143
+ newwidth = Math.round(newheight / _this2.props.frameRatio);
144
+ }
145
+ } else {
141
146
  newheight = maxHeight;
142
147
  newwidth = Math.round(newheight / _this2.props.frameRatio);
148
+ if (newwidth > maxWidth) {
149
+ newwidth = maxWidth;
150
+ newheight = Math.round(newwidth * _this2.props.frameRatio);
151
+ }
143
152
  }
153
+ } else {
154
+ newwidth = state.width;
155
+ newheight = state.height;
144
156
  }
145
157
  return {
146
158
  frameRatio: _this2.props.frameRatio,
147
- x: 0.5 * (maxWidth - newwidth),
148
- y: 0.5 * (maxHeight - newheight),
159
+ x: 0.5 * (containerWidth - newwidth),
160
+ y: 0.5 * (containerHeight - newheight),
149
161
  width: newwidth,
150
162
  height: newheight
151
163
  };
@@ -124,7 +124,6 @@ var MapSelection = /*#__PURE__*/function (_React$Component) {
124
124
  if (!geometry) {
125
125
  return;
126
126
  }
127
- var coords = _this.props.geomType === 'Circle' ? null : geometry.getCoordinates();
128
127
  if (_this.props.geomType === "Circle") {
129
128
  // Also store poligonized circle
130
129
  var center = geometry.getCenter();
@@ -141,19 +140,11 @@ var MapSelection = /*#__PURE__*/function (_React$Component) {
141
140
  radius: radius
142
141
  }
143
142
  });
144
- } else if (_this.props.geomType === "DragBox" || _this.props.geomType === "Box") {
145
- var boxcoords = [[Math.min(coords[0][0][0], coords[0][2][0]), Math.min(coords[0][0][1], coords[0][2][1]), Math.max(coords[0][0][0], coords[0][2][0]), Math.max(coords[0][0][1], coords[0][2][1])]];
146
- _this.setState({
147
- geometry: {
148
- type: "Polygon",
149
- coordinates: boxcoords
150
- }
151
- });
152
143
  } else {
153
144
  _this.setState({
154
145
  geometry: {
155
- type: _this.props.geomType,
156
- coordinates: coords
146
+ type: geometry.getType(),
147
+ coordinates: geometry.getCoordinates()
157
148
  }
158
149
  });
159
150
  }
@@ -422,21 +422,21 @@ var SearchBox = /*#__PURE__*/function (_React$Component) {
422
422
  }) : null);
423
423
  });
424
424
  _defineProperty(_this, "renderLayerResult", function (provider, group, result) {
425
- var _result$label3, _result$layer;
425
+ var _ConfigUtils$getPlugi, _result$label3, _result$layer;
426
426
  var parent = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;
427
427
  var level = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 0;
428
428
  var key = provider + ":" + group.id + ":" + result.id;
429
429
  var addThemes = ConfigUtils.getConfigProp("allowAddingOtherThemes", _this.props.theme);
430
430
  var icon = null;
431
+ var toggleLayerGroup = function toggleLayerGroup(ev) {
432
+ MiscUtils.killEvent(ev);
433
+ _this.setState(function (state) {
434
+ return {
435
+ expandedLayerGroup: state.expandedLayerGroup === key ? null : key
436
+ };
437
+ });
438
+ };
431
439
  if (result.sublayers) {
432
- var toggleLayerGroup = function toggleLayerGroup(ev) {
433
- MiscUtils.killEvent(ev);
434
- _this.setState(function (state) {
435
- return {
436
- expandedLayerGroup: state.expandedLayerGroup === key ? null : key
437
- };
438
- });
439
- };
440
440
  icon = /*#__PURE__*/React.createElement(Icon, {
441
441
  icon: _this.state.expandedLayerGroup === key ? "minus" : "plus",
442
442
  onClick: function onClick(ev) {
@@ -456,7 +456,7 @@ var SearchBox = /*#__PURE__*/function (_React$Component) {
456
456
  return [/*#__PURE__*/React.createElement("div", {
457
457
  className: "searchbox-result",
458
458
  key: key,
459
- onClick: function onClick() {
459
+ onClick: (_ConfigUtils$getPlugi = ConfigUtils.getPluginConfig("LayerCatalog")) !== null && _ConfigUtils$getPlugi !== void 0 && (_ConfigUtils$getPlugi = _ConfigUtils$getPlugi.cfg) !== null && _ConfigUtils$getPlugi !== void 0 && _ConfigUtils$getPlugi.toggleGroupOnClick && result.sublayers ? toggleLayerGroup : function () {
460
460
  return selectResult(provider, group, result);
461
461
  },
462
462
  style: {
@@ -1,5 +1,4 @@
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
- function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
3
2
  function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
4
3
  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); } }
5
4
  function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
@@ -23,7 +22,7 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
23
22
  */
24
23
 
25
24
  import React from 'react';
26
- import { FacebookShareButton, LinkedinShareButton, TwitterShareButton, WhatsappShareButton, EmailShareButton, FacebookShareCount, FacebookIcon, TwitterIcon, LinkedinIcon, WhatsappIcon, EmailIcon } from 'react-share';
25
+ import { FacebookShareButton, LinkedinShareButton, TwitterShareButton, WhatsappShareButton, EmailShareButton, FacebookIcon, TwitterIcon, LinkedinIcon, WhatsappIcon, EmailIcon } from 'react-share';
27
26
  import PropTypes from 'prop-types';
28
27
  import LocaleUtils from '../../utils/LocaleUtils';
29
28
  import './style/ShareSocials.css';
@@ -52,7 +51,7 @@ var ShareSocials = /*#__PURE__*/function (_React$Component) {
52
51
  }, /*#__PURE__*/React.createElement(EmailIcon, {
53
52
  round: true,
54
53
  size: 32
55
- })), /*#__PURE__*/React.createElement("div", null, "\xA0")),
54
+ }))),
56
55
  facebook: /*#__PURE__*/React.createElement("div", {
57
56
  className: "social-box",
58
57
  key: "facebook"
@@ -62,11 +61,7 @@ var ShareSocials = /*#__PURE__*/function (_React$Component) {
62
61
  }, /*#__PURE__*/React.createElement(FacebookIcon, {
63
62
  round: true,
64
63
  size: 32
65
- })), /*#__PURE__*/React.createElement(FacebookShareCount, _extends({
66
- url: url
67
- }, countProps), function (count) {
68
- return count;
69
- })),
64
+ }))),
70
65
  twitter: /*#__PURE__*/React.createElement("div", {
71
66
  className: "social-box",
72
67
  key: "twitter"
@@ -76,7 +71,7 @@ var ShareSocials = /*#__PURE__*/function (_React$Component) {
76
71
  }, /*#__PURE__*/React.createElement(TwitterIcon, {
77
72
  round: true,
78
73
  size: 32
79
- })), /*#__PURE__*/React.createElement("div", null, "\xA0")),
74
+ }))),
80
75
  linkedin: /*#__PURE__*/React.createElement("div", {
81
76
  className: "social-box",
82
77
  key: "linkedin"
@@ -86,7 +81,7 @@ var ShareSocials = /*#__PURE__*/function (_React$Component) {
86
81
  }, /*#__PURE__*/React.createElement(LinkedinIcon, {
87
82
  round: true,
88
83
  size: 32
89
- })), /*#__PURE__*/React.createElement("div", null, "\xA0")),
84
+ }))),
90
85
  whatsapp: /*#__PURE__*/React.createElement("div", {
91
86
  className: "social-box",
92
87
  key: "whatsapp"
@@ -96,7 +91,7 @@ var ShareSocials = /*#__PURE__*/function (_React$Component) {
96
91
  }, /*#__PURE__*/React.createElement(WhatsappIcon, {
97
92
  round: true,
98
93
  size: 32
99
- })), /*#__PURE__*/React.createElement("div", null, "\xA0"))
94
+ })))
100
95
  };
101
96
  var socialBoxes = [];
102
97
  if (this.props.showSocials === true) {
@@ -125,7 +120,4 @@ _defineProperty(ShareSocials, "propTypes", {
125
120
  shareUrl: PropTypes.string,
126
121
  showSocials: PropTypes.oneOfType([PropTypes.bool, PropTypes.array])
127
122
  });
128
- _defineProperty(ShareSocials, "defaultProps", {
129
- shareTitle: 'GeoSolutions'
130
- });
131
123
  export { ShareSocials as default };
@@ -55,7 +55,11 @@ var LayerCatalogWidget = /*#__PURE__*/function (_React$PureComponent) {
55
55
  _this.checkAddServiceLayer(entry, true);
56
56
  }
57
57
  } else {
58
- _this.checkAddServiceLayer(entry, false);
58
+ if (_this.props.toggleGroupOnClick && !isEmpty(entry.sublayers)) {
59
+ _this.toggleLayerListEntry(path);
60
+ } else {
61
+ _this.checkAddServiceLayer(entry, false);
62
+ }
59
63
  }
60
64
  } else {
61
65
  _this.toggleLayerListEntry(path);
@@ -382,7 +386,8 @@ _defineProperty(LayerCatalogWidget, "propTypes", {
382
386
  pendingRequests: PropTypes.number,
383
387
  removeLayer: PropTypes.func,
384
388
  replacePlaceholderLayer: PropTypes.func,
385
- showNotification: PropTypes.func
389
+ showNotification: PropTypes.func,
390
+ toggleGroupOnClick: PropTypes.bool
386
391
  });
387
392
  export default connect(function (state) {
388
393
  return {
@@ -40,7 +40,8 @@ var MenuButton = /*#__PURE__*/function (_React$Component) {
40
40
  _defineProperty(_this, "onButtonClicked", function (ev) {
41
41
  ev.stopPropagation();
42
42
  if (_this.state.selected) {
43
- _this.props.onActivate(_this.state.selected);
43
+ var _this$props$onActivat, _this$props;
44
+ (_this$props$onActivat = (_this$props = _this.props).onActivate) === null || _this$props$onActivat === void 0 || _this$props$onActivat.call(_this$props, _this.state.selected);
44
45
  _this.setState({
45
46
  popup: false
46
47
  });
@@ -48,14 +49,16 @@ var MenuButton = /*#__PURE__*/function (_React$Component) {
48
49
  _this.onMenuClicked();
49
50
  }
50
51
  });
51
- _defineProperty(_this, "onChildClicked", function (child) {
52
+ _defineProperty(_this, "onChildClicked", function (ev, child) {
52
53
  if (!child.props.disabled) {
54
+ var _this$props$onActivat2, _this$props2, _child$props$onClick, _child$props;
53
55
  if (_this.state.selected) {
54
56
  _this.setState({
55
57
  selected: child.props.value
56
58
  });
57
59
  }
58
- _this.props.onActivate(child.props.value);
60
+ (_this$props$onActivat2 = (_this$props2 = _this.props).onActivate) === null || _this$props$onActivat2 === void 0 || _this$props$onActivat2.call(_this$props2, child.props.value);
61
+ (_child$props$onClick = (_child$props = child.props).onClick) === null || _child$props$onClick === void 0 || _child$props$onClick.call(_child$props, ev);
59
62
  }
60
63
  });
61
64
  _this.el = null;
@@ -140,8 +143,8 @@ var MenuButton = /*#__PURE__*/function (_React$Component) {
140
143
  return /*#__PURE__*/React.cloneElement(child, {
141
144
  className: classNames,
142
145
  disabled: child.props.disabled,
143
- onClick: function onClick() {
144
- return _this2.onChildClicked(child);
146
+ onClick: function onClick(ev) {
147
+ return _this2.onChildClicked(ev, child);
145
148
  }
146
149
  });
147
150
  })) : null);
@@ -225,7 +225,7 @@ var PlotInfoTool = /*#__PURE__*/function (_React$Component) {
225
225
  _defineProperty(_this, "renderError", function () {
226
226
  return /*#__PURE__*/React.createElement("div", {
227
227
  className: "plot-info-dialog-query-failed"
228
- }, _this.state.expandedInfoData.failed === true ? LocaleUtils.tr("plotinfotool.failed") : LocaleUtils.tr(_this.state.expandedInfoData.failed));
228
+ }, _this.state.expandedInfoData.failed === true ? LocaleUtils.tr("common.dataloadfailed") : LocaleUtils.tr(_this.state.expandedInfoData.failed));
229
229
  });
230
230
  _defineProperty(_this, "renderInfoData", function () {
231
231
  if (_this.props.customInfoComponents[_this.state.expandedInfo]) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qwc2",
3
- "version": "2026.07.09",
3
+ "version": "2026.07.18",
4
4
  "description": "QGIS Web Client",
5
5
  "author": "Sourcepole AG",
6
6
  "license": "BSD-2-Clause",
@@ -117,7 +117,7 @@
117
117
  "@types/three": "^0.180.0",
118
118
  "babel-loader": "^10.0.0",
119
119
  "babel-plugin-transform-react-remove-prop-types": "^0.4.24",
120
- "copy-webpack-plugin": "^13.0.1",
120
+ "copy-webpack-plugin": "^14.0.0",
121
121
  "css-loader": "^7.1.3",
122
122
  "eslint": "^9.39.2",
123
123
  "eslint-plugin-perfectionist": "^5.5.0",
@@ -130,7 +130,7 @@
130
130
  "webpack": "^5.105.0",
131
131
  "webpack-bundle-analyzer": "^5.2.0",
132
132
  "webpack-cli": "^6.0.1",
133
- "webpack-dev-server": "^5.2.3"
133
+ "webpack-dev-server": "^6.0.0"
134
134
  },
135
135
  "bin": {
136
136
  "qwc_build_iconfont": "./scripts/makeIconkit.js",
@@ -138,6 +138,7 @@
138
138
  "qwc_update_translations": "./scripts/updateTranslations.js"
139
139
  },
140
140
  "scripts": {
141
+ "preinstall": "node -e \"const ua=process.env.npm_config_user_agent||''; if(ua.startsWith('yarn/')){console.error('This project uses npm. Run npm install instead.'); process.exit(1)}\"",
141
142
  "prod": "npm run tsupdate && npm run themesconfig && npm run iconfont && webpack --mode production --progress",
142
143
  "start": "npm run tsupdate && npm run themesconfig && npm run iconfont && webpack serve --mode development --progress --host 0.0.0.0 --port 8081",
143
144
  "iconfont": "node scripts/makeIconkit.js",
@@ -63,7 +63,11 @@ export var BackgroundSwitcher = /*#__PURE__*/function (_React$Component) {
63
63
  }, backgroundLayers.filter(function (entry) {
64
64
  return !(entry !== null && entry !== void 0 && entry.omitFromSelect);
65
65
  }).map(function (entry) {
66
- return Array.isArray(entry) ? _this.renderGroupItem(entry, visibleBgLayer) : _this.renderLayerItem(entry, visibleBgLayer);
66
+ if (Array.isArray(entry)) {
67
+ return entry.length > 1 ? _this.renderGroupItem(entry, visibleBgLayer) : _this.renderLayerItem(entry[0], visibleBgLayer);
68
+ } else {
69
+ return _this.renderLayerItem(entry, visibleBgLayer);
70
+ }
67
71
  }));
68
72
  });
69
73
  _defineProperty(_this, "itemTitle", function (item) {
@@ -401,8 +405,8 @@ var selector = function selector(state) {
401
405
  var backgroundLayers = Object.values(state.layers.flat.filter(function (layer) {
402
406
  return layer.role === LayerRole.BACKGROUND;
403
407
  }).reduce(function (res, l) {
404
- return _objectSpread(_objectSpread({}, res), {}, _defineProperty({}, "_" + (l.group || l.name), l.group ? [].concat(_toConsumableArray(res["_" + l.group] || []), [l]) : l));
405
- }, {}));
408
+ return _objectSpread(_objectSpread({}, res), {}, _defineProperty({}, "_" + (l.group || l.name), l.group ? [l].concat(_toConsumableArray(res["_" + l.group] || [])) : l));
409
+ }, {})).reverse();
406
410
  return {
407
411
  backgroundLayers: backgroundLayers
408
412
  };