qwc2 2026.6.26 → 2026.7.1

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.
@@ -192,9 +192,11 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
192
192
  });
193
193
  });
194
194
  _defineProperty(_this2, "collectColorLayers", function (prevColorLayers, prevLayers) {
195
+ var _ConfigUtils$getPlugi;
195
196
  var prevLayerMap = prevLayers.reduce(function (res, layer) {
196
197
  return _objectSpread(_objectSpread({}, res), {}, _defineProperty({}, layer.id, layer));
197
198
  }, {});
199
+ var showRootEntry = ((_ConfigUtils$getPlugi = ConfigUtils.getPluginConfig("LayerTree")) === null || _ConfigUtils$getPlugi === void 0 || (_ConfigUtils$getPlugi = _ConfigUtils$getPlugi.cfg) === null || _ConfigUtils$getPlugi === void 0 ? void 0 : _ConfigUtils$getPlugi.showRootEntry) !== false;
198
200
  return _this2.props.layers.reduce(function (colorLayers, layer) {
199
201
  var _prevOptions$projecti, _prevOptions$visibili, _prevOptions$opacity, _prevOptions$extrusio, _prevOptions$fields;
200
202
  if (layer.role !== LayerRole.THEME && layer.role !== LayerRole.USERLAYER) {
@@ -220,16 +222,18 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
220
222
  return _objectSpread(_objectSpread({}, child), {}, {
221
223
  visibility: prevChild.visibility,
222
224
  opacity: prevChild.opacity,
223
- sublayers: _preserveSublayerOptions(child, prevChild)
225
+ sublayers: _preserveSublayerOptions(child, prevChild, false)
224
226
  });
225
227
  } else {
226
- return child;
228
+ return _objectSpread(_objectSpread({}, child), {}, {
229
+ visibility: (entry === null || entry === void 0 ? void 0 : entry.role) === LayerRole.THEME && !showRootEntry ? _this2.props.defaultColorLayerVisibility : child.visibility
230
+ });
227
231
  }
228
232
  });
229
233
  };
230
234
  colorLayers[layer.id] = _objectSpread(_objectSpread({}, layer), {}, {
231
235
  projection: (_prevOptions$projecti = prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.projection) !== null && _prevOptions$projecti !== void 0 ? _prevOptions$projecti : _this2.props.theme.mapCrs,
232
- visibility: (_prevOptions$visibili = prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.visibility) !== null && _prevOptions$visibili !== void 0 ? _prevOptions$visibili : false,
236
+ visibility: (_prevOptions$visibili = prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.visibility) !== null && _prevOptions$visibili !== void 0 ? _prevOptions$visibili : layer.role === LayerRole.THEME && !showRootEntry ? true : _this2.props.defaultColorLayerVisibility,
233
237
  opacity: (_prevOptions$opacity = prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.opacity) !== null && _prevOptions$opacity !== void 0 ? _prevOptions$opacity : 255,
234
238
  extrusionHeight: (_prevOptions$extrusio = prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.extrusionHeight) !== null && _prevOptions$extrusio !== void 0 ? _prevOptions$extrusio : layerCreator.createFeatureSource ? 0 : undefined,
235
239
  fields: (_prevOptions$fields = prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.fields) !== null && _prevOptions$fields !== void 0 ? _prevOptions$fields : undefined,
@@ -1463,6 +1467,7 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
1463
1467
  _defineProperty(Map3D, "contextType", MapContainerPortalContext);
1464
1468
  _defineProperty(Map3D, "propTypes", {
1465
1469
  controlsPosition: PropTypes.string,
1470
+ defaultColorLayerVisibility: PropTypes.bool,
1466
1471
  defaultFov: PropTypes.number,
1467
1472
  defaultPointSize: PropTypes.number,
1468
1473
  defaultSceneQuality: PropTypes.number,
@@ -31,10 +31,10 @@ styleExpressionParser.functions.color = function (name) {
31
31
  })), [alpha]);
32
32
  };
33
33
  styleExpressionParser.functions.rgb = function (r, g, b) {
34
- return [r / 255, g / 255, g / 255, 1];
34
+ return [r / 255, g / 255, b / 255, 1];
35
35
  };
36
36
  styleExpressionParser.functions.rgba = function (r, g, b, a) {
37
- return [r / 255, g / 255, g / 255, a];
37
+ return [r / 255, g / 255, b / 255, a];
38
38
  };
39
39
  styleExpressionParser.functions.hsl = function (h, s, l) {
40
40
  return [].concat(_toConsumableArray(MiscUtils.hslToRgb(h, s, l)), [1]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qwc2",
3
- "version": "2026.06.26",
3
+ "version": "2026.07.01",
4
4
  "description": "QGIS Web Client",
5
5
  "author": "Sourcepole AG",
6
6
  "license": "BSD-2-Clause",
@@ -380,7 +380,10 @@ var Identify = /*#__PURE__*/function (_React$Component) {
380
380
  }
381
381
  }
382
382
  if (this.props.enabled) {
383
- if (this.state.mode === "Point") {
383
+ if (this.props.identifySearchResults && this.props.currentSearchResult && this.props.currentSearchResult !== prevProps.currentSearchResult) {
384
+ var res = this.props.currentSearchResult;
385
+ this.identifyPoint(CoordinatesUtils.reproject([res.x, res.y], res.crs, this.props.map.projection));
386
+ } else if (this.state.mode === "Point") {
384
387
  var clickPoint = this.queryPoint(prevProps);
385
388
  this.identifyPoint(clickPoint);
386
389
  } else if (this.state.mode === "Region") {
@@ -496,6 +499,7 @@ _defineProperty(Identify, "propTypes", {
496
499
  clearResultsOnClose: PropTypes.bool,
497
500
  click: PropTypes.object,
498
501
  currentIdentifyTool: PropTypes.string,
502
+ currentSearchResult: PropTypes.object,
499
503
  currentTask: PropTypes.string,
500
504
  /** Optional list of custom exporters to offer along with the built-in exporters. See js/IdentifyExtensions.js for details. This prop can be specified in the appConfig.js cfg section. */
501
505
  customExporters: PropTypes.array,
@@ -519,8 +523,10 @@ _defineProperty(Identify, "propTypes", {
519
523
  initiallyDocked: PropTypes.bool,
520
524
  side: PropTypes.string
521
525
  }),
522
- /** Whether to highlight all results if no result is hovered */
526
+ /** Whether to highlight all results if no result is hovered. */
523
527
  highlightAllResults: PropTypes.bool,
528
+ /** Whether to trigger an identify when selecting a search result. */
529
+ identifySearchResults: PropTypes.bool,
524
530
  iframeDialogsInitiallyDocked: PropTypes.bool,
525
531
  /** The initial radius units of the identify dialog in radius mode. One of 'm', 'ft', 'km', 'mi'. */
526
532
  initialRadiusUnits: PropTypes.string,
@@ -584,6 +590,7 @@ export default connect(function (state) {
584
590
  click: state.map.click || {
585
591
  modifiers: {}
586
592
  },
593
+ currentSearchResult: state.search.currentResult,
587
594
  enabled: enabled,
588
595
  layerFilterGeom: (_state$layers$filter = state.layers.filter) === null || _state$layers$filter === void 0 ? void 0 : _state$layers$filter.filterGeom,
589
596
  layers: state.layers.flat,
@@ -22,6 +22,7 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
22
22
 
23
23
  import React from 'react';
24
24
  import { connect } from 'react-redux';
25
+ import axios from 'axios';
25
26
  import PropTypes from 'prop-types';
26
27
  import { setCurrentTask } from '../actions/task';
27
28
  import Icon from '../components/Icon';
@@ -42,6 +43,7 @@ var NewsPopup = /*#__PURE__*/function (_React$Component) {
42
43
  _classCallCheck(this, NewsPopup);
43
44
  _this = _callSuper(this, NewsPopup, [props]);
44
45
  _defineProperty(_this, "state", {
46
+ body: '',
45
47
  dontShowAgain: false,
46
48
  showPopup: false,
47
49
  side: 'right',
@@ -51,8 +53,13 @@ var NewsPopup = /*#__PURE__*/function (_React$Component) {
51
53
  return /*#__PURE__*/React.createElement("div", {
52
54
  className: "newspopup-dialog-popup-body",
53
55
  role: "body"
54
- }, /*#__PURE__*/React.createElement("iframe", {
56
+ }, _this.props.embedIframe ? /*#__PURE__*/React.createElement("iframe", {
55
57
  src: _this.props.newsDocument.replace('{lang}', LocaleUtils.lang())
58
+ }) : /*#__PURE__*/React.createElement("div", {
59
+ className: "newspopup-dialog-popup-content",
60
+ dangerouslySetInnerHTML: {
61
+ __html: _this.state.body
62
+ }
56
63
  }), /*#__PURE__*/React.createElement("div", {
57
64
  className: "newspopup-dialog-popup-buttonbar"
58
65
  }, /*#__PURE__*/React.createElement("button", {
@@ -97,6 +104,23 @@ var NewsPopup = /*#__PURE__*/function (_React$Component) {
97
104
  }
98
105
  _inherits(NewsPopup, _React$Component);
99
106
  return _createClass(NewsPopup, [{
107
+ key: "componentDidMount",
108
+ value: function componentDidMount() {
109
+ this.componentDidUpdate({});
110
+ }
111
+ }, {
112
+ key: "componentDidUpdate",
113
+ value: function componentDidUpdate(prevProps) {
114
+ var _this2 = this;
115
+ if (this.props.newsDocument && this.props.newsDocument !== prevProps.newsDocument) {
116
+ axios.get(this.props.newsDocument.replace('{lang}', LocaleUtils.lang())).then(function (response) {
117
+ _this2.setState({
118
+ body: response.data
119
+ });
120
+ })["catch"](function () {});
121
+ }
122
+ }
123
+ }, {
100
124
  key: "render",
101
125
  value: function render() {
102
126
  if (this.props.showInSidebar) {
@@ -126,6 +150,8 @@ var NewsPopup = /*#__PURE__*/function (_React$Component) {
126
150
  }]);
127
151
  }(React.Component);
128
152
  _defineProperty(NewsPopup, "propTypes", {
153
+ /** Whether to embed the news document in an iframe instead of a div. */
154
+ embedIframe: PropTypes.bool,
129
155
  /** URL to the news HTML document to display in the popup. Can contain `{lang}` as a placeholder which will be replaced with the current viewer language.*/
130
156
  newsDocument: PropTypes.string,
131
157
  /** Revision of the document. */
@@ -138,6 +164,9 @@ _defineProperty(NewsPopup, "propTypes", {
138
164
  /** The default width of the sidebar, as a CSS width string. */
139
165
  sidebarWidth: PropTypes.string
140
166
  });
167
+ _defineProperty(NewsPopup, "defaultProps", {
168
+ embedIframe: true
169
+ });
141
170
  export default connect(function () {
142
171
  return {};
143
172
  }, {
package/plugins/View3D.js CHANGED
@@ -455,6 +455,7 @@ var View3D = /*#__PURE__*/function (_React$Component) {
455
455
  pluginsConfig: pluginsConfig
456
456
  }, /*#__PURE__*/React.createElement(Map3D, {
457
457
  controlsPosition: this.props.controlsPosition,
458
+ defaultColorLayerVisibility: this.props.defaultColorLayerVisibility,
458
459
  defaultFov: this.props.defaultFov,
459
460
  defaultPointSize: this.props.defaultPointSize,
460
461
  defaultSceneQuality: this.props.defaultSceneQuality,
@@ -480,6 +481,8 @@ _defineProperty(View3D, "propTypes", {
480
481
  bookmark: PropTypes.object,
481
482
  /** The position of the navigation controls. Either `top` or `bottom`. */
482
483
  controlsPosition: PropTypes.string,
484
+ /** Whether 2D layers should be visible by default when opening the 3D view. */
485
+ defaultColorLayerVisibility: PropTypes.bool,
483
486
  /** The default field of view (`20`: min, `100`: max). */
484
487
  defaultFov: PropTypes.number,
485
488
  /** The default point size for point cloud tiles (`0`: min, `20`: max). Automatic size computation when the value is `0`. */
@@ -522,6 +525,7 @@ _defineProperty(View3D, "propTypes", {
522
525
  });
523
526
  _defineProperty(View3D, "defaultProps", {
524
527
  controlsPosition: 'top',
528
+ defaultColorLayerVisibility: false,
525
529
  defaultFov: 30,
526
530
  defaultPointSize: 0,
527
531
  defaultSceneQuality: 100,
@@ -37,11 +37,13 @@ import { connect } from 'react-redux';
37
37
  import classNames from 'classnames';
38
38
  import isEmpty from 'lodash.isempty';
39
39
  import PropTypes from 'prop-types';
40
+ import { LayerRole } from '../../actions/layers';
40
41
  import { setCurrentTask } from '../../actions/task';
41
42
  import Icon from '../../components/Icon';
42
43
  import ImportObjects3D from '../../components/map3d/ImportObjects3D';
43
44
  import SideBar from '../../components/SideBar';
44
45
  import NumberInput from '../../components/widgets/NumberInput';
46
+ import ConfigUtils from '../../utils/ConfigUtils';
45
47
  import LayerUtils from '../../utils/LayerUtils';
46
48
  import LocaleUtils from '../../utils/LocaleUtils';
47
49
  import './style/LayerTree3D.css';
@@ -63,12 +65,20 @@ var LayerTree3D = /*#__PURE__*/function (_React$Component) {
63
65
  importvisible: false
64
66
  });
65
67
  _defineProperty(_this, "renderBody", function () {
68
+ var _ConfigUtils$getPlugi;
69
+ var showRootEntry = ((_ConfigUtils$getPlugi = ConfigUtils.getPluginConfig("LayerTree")) === null || _ConfigUtils$getPlugi === void 0 || (_ConfigUtils$getPlugi = _ConfigUtils$getPlugi.cfg) === null || _ConfigUtils$getPlugi === void 0 ? void 0 : _ConfigUtils$getPlugi.showRootEntry) !== false;
66
70
  var sceneContext = _this.props.sceneContext;
67
71
  var objectsHaveGroups = sceneContext.objectTree["null"].children.some(function (child) {
68
72
  return !isEmpty(sceneContext.objectTree[child].children);
69
73
  });
70
74
  var layersHaveSublayers = Object.values(sceneContext.colorLayers).some(function (layer) {
71
- return !isEmpty(layer.sublayers);
75
+ if (layer.role === LayerRole.THEME && !showRootEntry) {
76
+ return layer.sublayers.some(function (sublayer) {
77
+ return !isEmpty(sublayer.sublayers);
78
+ });
79
+ } else {
80
+ return !isEmpty(layer.sublayers);
81
+ }
72
82
  });
73
83
  return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", {
74
84
  className: "layertree3d-layers"
@@ -82,7 +92,13 @@ var LayerTree3D = /*#__PURE__*/function (_React$Component) {
82
92
  var _ref2 = _slicedToArray(_ref, 2),
83
93
  layerId = _ref2[0],
84
94
  entry = _ref2[1];
85
- return _this.renderLayerEntry(layerId, entry, null, _this.updateColorLayer, false, true, [], layersHaveSublayers);
95
+ if (entry.role === LayerRole.THEME && !showRootEntry) {
96
+ return entry.sublayers.map(function (sublayer, idx) {
97
+ return _this.renderLayerEntry(layerId, sublayer, entry, _this.updateColorLayer, false, true, [idx]);
98
+ });
99
+ } else {
100
+ return _this.renderLayerEntry(layerId, entry, null, _this.updateColorLayer, false, true, [], layersHaveSublayers);
101
+ }
86
102
  }), /*#__PURE__*/React.createElement("div", {
87
103
  className: "layertree3d-option",
88
104
  onClick: function onClick() {
@@ -47,6 +47,7 @@ div.newspopup-dialog-popup-body {
47
47
  flex: 1 1 auto;
48
48
  display: flex;
49
49
  flex-direction: column;
50
+ overflow: hidden;
50
51
  }
51
52
 
52
53
  div.newspopup-dialog-popup-body > iframe {
@@ -57,6 +58,12 @@ div.newspopup-dialog-popup-body > iframe {
57
58
  height: 0;
58
59
  }
59
60
 
61
+ div.newspopup-dialog-popup-body > div.newspopup-dialog-popup-content {
62
+ flex: 1 1 auto;
63
+ overflow: auto;
64
+ padding: 0.5em;
65
+ }
66
+
60
67
  div.newspopup-dialog-popup-body > div.newspopup-dialog-popup-buttonbar {
61
68
  border-top: 1px solid var(--border-color);
62
69
  flex: 0 0 auto;