qwc2 2026.8.2 → 2026.8.6

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.
@@ -87,6 +87,13 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
87
87
  if (_this.menuEl && !_this.menuEl.contains(ev.target) && _this.props.menuDisplayMode === "normal") {
88
88
  _this.toggleMenu();
89
89
  MiscUtils.killEvent(ev);
90
+ _this.killClick = true;
91
+ }
92
+ });
93
+ _defineProperty(_this, "checkKillClick", function (ev) {
94
+ if (_this.killClick) {
95
+ MiscUtils.killEvent(ev);
96
+ _this.killClick = undefined;
90
97
  }
91
98
  });
92
99
  _defineProperty(_this, "onSubmenuClicked", function (key, level) {
@@ -242,6 +249,9 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
242
249
  if (this.props.appMenuShortcut) {
243
250
  mousetrap.bind(this.props.appMenuShortcut, this.toggleMenu);
244
251
  }
252
+ document.addEventListener('click', this.checkKillClick, {
253
+ capture: true
254
+ });
245
255
  }
246
256
  }, {
247
257
  key: "componentDidUpdate",
@@ -255,10 +265,14 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
255
265
  }, 400);
256
266
  // Delay one cycle
257
267
  setTimeout(function () {
258
- return document.addEventListener('click', _this2.checkCloseMenu);
268
+ return document.addEventListener('pointerdown', _this2.checkCloseMenu, {
269
+ capture: true
270
+ });
259
271
  }, 0);
260
272
  } else if (prevState.menuVisible && !this.state.menuVisible) {
261
- document.removeEventListener('click', this.checkCloseMenu);
273
+ document.removeEventListener('pointerdown', this.checkCloseMenu, {
274
+ capture: true
275
+ });
262
276
  }
263
277
  }
264
278
  }, {
@@ -270,7 +284,12 @@ var AppMenu = /*#__PURE__*/function (_React$Component) {
270
284
  if (this.props.appMenuShortcut) {
271
285
  mousetrap.unbind(this.props.appMenuShortcut, this.toggleMenu);
272
286
  }
273
- document.removeEventListener('click', this.checkCloseMenu);
287
+ document.removeEventListener('pointerdown', this.checkCloseMenu, {
288
+ capture: true
289
+ });
290
+ document.removeEventListener('click', this.checkKillClick, {
291
+ capture: true
292
+ });
274
293
  }
275
294
  }, {
276
295
  key: "render",
@@ -309,7 +309,8 @@ var BuiltinExporters = [{
309
309
  }
310
310
  features.forEach(function (feature) {
311
311
  var row = exportAttrs.map(function (attr) {
312
- return feature.properties[attr];
312
+ var value = feature.properties[attr];
313
+ return MiscUtils.isNumeric(value) ? Number(value) : value;
313
314
  });
314
315
  if (feature.geometry) {
315
316
  var geomWkt = VectorLayerUtils.geoJSONGeomToWkt(feature.geometry);
@@ -984,7 +985,9 @@ var IdentifyViewer = /*#__PURE__*/function (_React$Component) {
984
985
  var exporters = Object.fromEntries(_this.getExporters().map(function (exporter) {
985
986
  return [exporter.id, exporter];
986
987
  }));
987
- var enabledExporters = Array.isArray(_this.props.enableExport) ? _this.props.enableExport : Object.keys(exporters);
988
+ var enabledExporters = Array.isArray(_this.props.enableExport) ? _this.props.enableExport.filter(function (id) {
989
+ return id in exporters;
990
+ }) : Object.keys(exporters);
988
991
  var clipboardExportDisabled = ((_exporters$_this$stat = exporters[_this.state.exportFormat]) === null || _exporters$_this$stat === void 0 ? void 0 : _exporters$_this$stat.allowClipboard) !== true;
989
992
  return /*#__PURE__*/React.createElement("div", {
990
993
  className: "identify-settings-menu"
@@ -900,14 +900,17 @@ var QtDesignerForm = /*#__PURE__*/function (_React$Component) {
900
900
  _this.props.addRelationRecord(datasetname);
901
901
  });
902
902
  _defineProperty(_this, "startRelationTableResize", function (ev) {
903
- var container = ev.target.parentElement.parentElement;
903
+ var container = ev.target.parentElement;
904
904
  if (!container) {
905
905
  return;
906
906
  }
907
+ // Drop max-height as soon as a manual height is set
907
908
  var startHeight = container.offsetHeight;
909
+ container.style.height = container.offsetHeight + 'px';
910
+ container.style.maxHeight = 'initial';
908
911
  var startMouseY = ev.clientY;
909
912
  var resizeInput = function resizeInput(event) {
910
- container.style.height = Math.max(30, startHeight + (event.clientY - startMouseY)) + 'px';
913
+ container.style.height = Math.max(MiscUtils.convertEmToPx(4.5), startHeight + (event.clientY - startMouseY)) + 'px';
911
914
  };
912
915
  ev.view.document.body.style.userSelect = 'none';
913
916
  ev.view.addEventListener("pointermove", resizeInput);
@@ -1067,7 +1067,7 @@ var SearchBox = /*#__PURE__*/function (_React$Component) {
1067
1067
  }
1068
1068
  // Add highlight features and markers
1069
1069
  var mapCrs = _this.props.map.projection;
1070
- var showMarkers = !response.hidemarker && _this.props.searchOptions.showHighlightMarker;
1070
+ var showMarkers = !(response !== null && response !== void 0 && response.hidemarker) && _this.props.searchOptions.showHighlightMarker;
1071
1071
  var label = ((_ref0 = (_item$label = item.label) !== null && _item$label !== void 0 ? _item$label : item.text) !== null && _ref0 !== void 0 ? _ref0 : '').replace(/<\/?\w+\s*\/?>/g, '');
1072
1072
  var layer = {
1073
1073
  id: "searchselection",
@@ -1361,17 +1361,22 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
1361
1361
  return _createClass(Map3D, [{
1362
1362
  key: "componentDidMount",
1363
1363
  value: function componentDidMount() {
1364
+ var _this3 = this;
1364
1365
  this.props.innerRef(this);
1366
+ window.qwc2.__3dscenecontext = function () {
1367
+ return _this3.state.sceneContext;
1368
+ };
1365
1369
  }
1366
1370
  }, {
1367
1371
  key: "componentWillUnmount",
1368
1372
  value: function componentWillUnmount() {
1369
1373
  unregisterPermalinkDataStoreHook("map3d");
1374
+ window.qwc2.__3dscenecontext = undefined;
1370
1375
  }
1371
1376
  }, {
1372
1377
  key: "componentDidUpdate",
1373
1378
  value: function componentDidUpdate(prevProps, prevState) {
1374
- var _this3 = this;
1379
+ var _this4 = this;
1375
1380
  if (this.props.theme !== prevProps.theme) {
1376
1381
  if (this.props.theme.map3d) {
1377
1382
  this.setState(function (state) {
@@ -1386,7 +1391,7 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
1386
1391
  this.setState(function (state) {
1387
1392
  return {
1388
1393
  sceneContext: _objectSpread(_objectSpread({}, state.sceneContext), {}, {
1389
- colorLayers: _this3.collectColorLayers(state.sceneContext.colorLayers, prevProps.layers)
1394
+ colorLayers: _this4.collectColorLayers(state.sceneContext.colorLayers, prevProps.layers)
1390
1395
  })
1391
1396
  };
1392
1397
  });
@@ -1398,7 +1403,7 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
1398
1403
  return {
1399
1404
  sceneContext: _objectSpread(_objectSpread({}, state.sceneContext), {}, {
1400
1405
  collisionObjects: Object.keys(state.sceneContext.objectTree).reduce(function (res, objectId) {
1401
- var obj = _this3.objectMap[objectId];
1406
+ var obj = _this4.objectMap[objectId];
1402
1407
  if (obj !== null && obj !== void 0 && obj.visible) {
1403
1408
  var _obj$tiles$group, _obj$tiles;
1404
1409
  res.push((_obj$tiles$group = (_obj$tiles = obj.tiles) === null || _obj$tiles === void 0 ? void 0 : _obj$tiles.group) !== null && _obj$tiles$group !== void 0 ? _obj$tiles$group : obj);
@@ -1409,7 +1414,7 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
1409
1414
  var _ref1 = _slicedToArray(_ref0, 2),
1410
1415
  objectId = _ref1[0],
1411
1416
  entry = _ref1[1];
1412
- var obj = _this3.objectMap[objectId];
1417
+ var obj = _this4.objectMap[objectId];
1413
1418
  if (obj !== null && obj !== void 0 && obj.visible && entry.snap) {
1414
1419
  var _obj$tiles$group2, _obj$tiles2;
1415
1420
  res.push((_obj$tiles$group2 = (_obj$tiles2 = obj.tiles) === null || _obj$tiles2 === void 0 ? void 0 : _obj$tiles2.group) !== null && _obj$tiles$group2 !== void 0 ? _obj$tiles$group2 : obj);
@@ -1426,10 +1431,10 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
1426
1431
  }
1427
1432
  if (this.state.sceneContext.settings.pointSize !== prevState.sceneContext.settings.pointSize) {
1428
1433
  Object.values(this.state.sceneContext.objectTree).map(function (entry) {
1429
- var obj = _this3.state.sceneContext.getSceneObject(entry.objectId);
1430
- if (_this3.objectContainsPoints(obj)) {
1431
- obj.pointSize = _this3.state.sceneContext.settings.pointSize;
1432
- _this3.instance.notifyChange(obj);
1434
+ var obj = _this4.state.sceneContext.getSceneObject(entry.objectId);
1435
+ if (_this4.objectContainsPoints(obj)) {
1436
+ obj.pointSize = _this4.state.sceneContext.settings.pointSize;
1437
+ _this4.instance.notifyChange(obj);
1433
1438
  }
1434
1439
  });
1435
1440
  }
@@ -1442,14 +1447,14 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
1442
1447
  return (_entity$tiles2 = entity.tiles) === null || _entity$tiles2 === void 0 ? void 0 : _entity$tiles2.lruCache;
1443
1448
  }).forEach(function (entity) {
1444
1449
  var gigabyteBytes = Math.pow(2, 30);
1445
- entity.tiles.lruCache.maxBytesSize = 0.5 * gigabyteBytes * (1 + _this3.state.sceneContext.settings.sceneQuality / 100);
1450
+ entity.tiles.lruCache.maxBytesSize = 0.5 * gigabyteBytes * (1 + _this4.state.sceneContext.settings.sceneQuality / 100);
1446
1451
  });
1447
1452
  }
1448
1453
  }
1449
1454
  }, {
1450
1455
  key: "render",
1451
1456
  value: function render() {
1452
- var _this4 = this;
1457
+ var _this5 = this;
1453
1458
  return [/*#__PURE__*/ReactDOM.createPortal(/*#__PURE__*/React.createElement("div", {
1454
1459
  className: "map3d-map",
1455
1460
  id: "map3d",
@@ -1476,16 +1481,16 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
1476
1481
  return /*#__PURE__*/React.createElement(Suspense, {
1477
1482
  key: name
1478
1483
  }, /*#__PURE__*/React.createElement(Component, _extends({
1479
- sceneContext: _this4.state.sceneContext
1480
- }, _this4.props.pluginOptions[name])));
1484
+ sceneContext: _this5.state.sceneContext
1485
+ }, _this5.props.pluginOptions[name])));
1481
1486
  }), this.renderBaseLayer(), Object.values(this.state.sceneContext.colorLayers).map(function (options, idx) {
1482
- var _this4$state$sceneCon, _this4$state$sceneCon2;
1487
+ var _this5$state$sceneCon, _this5$state$sceneCon2;
1483
1488
  return /*#__PURE__*/React.createElement(ColorLayer3D, {
1484
1489
  key: options.id,
1485
- map: _this4.map,
1490
+ map: _this5.map,
1486
1491
  options: options,
1487
- prevLayerId: (_this4$state$sceneCon = (_this4$state$sceneCon2 = _this4.state.sceneContext.colorLayers[idx - 1]) === null || _this4$state$sceneCon2 === void 0 ? void 0 : _this4$state$sceneCon2.id) !== null && _this4$state$sceneCon !== void 0 ? _this4$state$sceneCon : "__baselayer",
1488
- sceneContext: _this4.state.sceneContext
1492
+ prevLayerId: (_this5$state$sceneCon = (_this5$state$sceneCon2 = _this5.state.sceneContext.colorLayers[idx - 1]) === null || _this5$state$sceneCon2 === void 0 ? void 0 : _this5$state$sceneCon2.id) !== null && _this5$state$sceneCon !== void 0 ? _this5$state$sceneCon : "__baselayer",
1493
+ sceneContext: _this5.state.sceneContext
1489
1494
  });
1490
1495
  }))) : null];
1491
1496
  }
@@ -86,6 +86,7 @@ div.qt-designer-widget-relation {
86
86
  display: flex;
87
87
  flex-direction: column;
88
88
  position: relative;
89
+ max-height: 6.5em;
89
90
  }
90
91
 
91
92
  div.qt-designer-widget-relation-resize-handle {
@@ -104,8 +105,10 @@ div.qt-designer-widget-relation-resize-handle {
104
105
  div.qt-designer-widget-relation-table-container {
105
106
  overflow-y: auto;
106
107
  flex: 1 1 auto;
107
- height: 4.5em;
108
108
  position: relative;
109
+ border-top: 1px solid var(--border-color);
110
+ border-left: 1px solid var(--border-color);
111
+ border-right: 1px solid var(--border-color);
109
112
  }
110
113
 
111
114
  div.qt-designer-widget-relation-table-loading {
@@ -128,7 +131,6 @@ div.qt-designer-widget-relation-table-loading > div.spinner {
128
131
 
129
132
  div.qt-designer-widget-relation-table-container > table {
130
133
  width: 100%;
131
- border: 1px solid var(--border-color);
132
134
  }
133
135
 
134
136
  div.qt-designer-widget-relation-table-container > table td {
@@ -137,7 +139,7 @@ div.qt-designer-widget-relation-table-container > table td {
137
139
  }
138
140
 
139
141
  div.qt-designer-widget-relation-table-container > table td.qt-designer-widget-relation-record-icon {
140
- width: 1px;
142
+ width: 1.5em;
141
143
  }
142
144
 
143
145
  td.qt-designer-widget-relation-record-icon > span.icon-trash:hover {
@@ -37,8 +37,7 @@ var MenuButton = /*#__PURE__*/function (_React$Component) {
37
37
  });
38
38
  }
39
39
  });
40
- _defineProperty(_this, "onButtonClicked", function (ev) {
41
- ev.stopPropagation();
40
+ _defineProperty(_this, "onButtonClicked", function () {
42
41
  if (_this.state.selected) {
43
42
  var _this$props$onActivat, _this$props;
44
43
  (_this$props$onActivat = (_this$props = _this.props).onActivate) === null || _this$props$onActivat === void 0 || _this$props$onActivat.call(_this$props, _this.state.selected);
@@ -112,7 +111,6 @@ var MenuButton = /*#__PURE__*/function (_React$Component) {
112
111
  className: classes
113
112
  }, /*#__PURE__*/React.createElement("div", {
114
113
  className: buttonClassnames,
115
- onClick: this.onMenuClicked,
116
114
  onKeyDown: MiscUtils.checkKeyActivate,
117
115
  ref: function ref(el) {
118
116
  _this2.el = el;
@@ -122,7 +120,8 @@ var MenuButton = /*#__PURE__*/function (_React$Component) {
122
120
  className: "menubutton-button-content",
123
121
  onClick: this.onButtonClicked
124
122
  }, buttonContents), /*#__PURE__*/React.createElement("span", {
125
- className: "menubotton-button-arrow"
123
+ className: "menubotton-button-arrow",
124
+ onClick: this.onMenuClicked
126
125
  }, /*#__PURE__*/React.createElement(Icon, {
127
126
  icon: "chevron-down"
128
127
  })), this.props.tooltip ? /*#__PURE__*/React.createElement("span", {
@@ -29,20 +29,37 @@ import MiscUtils from '../../utils/MiscUtils';
29
29
  import './style/PopupMenu.css';
30
30
  var PopupMenu = /*#__PURE__*/function (_React$PureComponent) {
31
31
  function PopupMenu(props) {
32
- var _this$props$anchor$ow, _this$props$anchor5, _this$props$anchor$ow3, _this$props$anchor7;
32
+ var _this$props$anchor$ow, _this$props$anchor6;
33
33
  var _this;
34
34
  _classCallCheck(this, PopupMenu);
35
35
  _this = _callSuper(this, PopupMenu, [props]);
36
+ _defineProperty(_this, "checkCloseMenu", function (ev) {
37
+ var _this$props$anchor, _this$props$anchor$co;
38
+ if (_this.menuEl && !_this.menuEl.contains(ev.target) && !((_this$props$anchor = _this.props.anchor) !== null && _this$props$anchor !== void 0 && (_this$props$anchor$co = _this$props$anchor.contains) !== null && _this$props$anchor$co !== void 0 && _this$props$anchor$co.call(_this$props$anchor, ev.target))) {
39
+ _this.props.onClose();
40
+ MiscUtils.killEvent(ev);
41
+ _this.killClick = true;
42
+ }
43
+ });
44
+ _defineProperty(_this, "checkKillClick", function (ev) {
45
+ if (_this.killClick) {
46
+ MiscUtils.killEvent(ev);
47
+ _this.killClick = undefined;
48
+ ev.currentTarget.removeEventListener('click', _this.checkKillClick, {
49
+ capture: true
50
+ });
51
+ }
52
+ });
36
53
  _defineProperty(_this, "setFocus", function (el) {
37
- var _this$props$anchor;
54
+ var _this$props$anchor2;
38
55
  _this.menuEl = el;
39
- if (el && ((_this$props$anchor = _this.props.anchor) === null || _this$props$anchor === void 0 ? void 0 : _this$props$anchor.nodeName) !== "INPUT") {
56
+ if (el && ((_this$props$anchor2 = _this.props.anchor) === null || _this$props$anchor2 === void 0 ? void 0 : _this$props$anchor2.nodeName) !== "INPUT") {
40
57
  _this.menuEl.focus();
41
58
  }
42
59
  });
43
60
  _defineProperty(_this, "clearFocus", function () {
44
- var _this$props$anchor2;
45
- if (((_this$props$anchor2 = _this.props.anchor) === null || _this$props$anchor2 === void 0 ? void 0 : _this$props$anchor2.nodeName) === "INPUT") {
61
+ var _this$props$anchor3;
62
+ if (((_this$props$anchor3 = _this.props.anchor) === null || _this$props$anchor3 === void 0 ? void 0 : _this$props$anchor3.nodeName) === "INPUT") {
46
63
  _this.props.anchor.focus();
47
64
  } else {
48
65
  _this.menuEl.focus();
@@ -81,18 +98,19 @@ var PopupMenu = /*#__PURE__*/function (_React$PureComponent) {
81
98
  }
82
99
  MiscUtils.killEvent(ev);
83
100
  } else if (ev.key === 'Escape') {
84
- var _this$props$onClose2, _this$props2, _this$props$anchor3, _this$props$anchor3$f;
101
+ var _this$props$onClose2, _this$props2, _this$props$anchor4, _this$props$anchor4$f;
85
102
  (_this$props$onClose2 = (_this$props2 = _this.props).onClose) === null || _this$props$onClose2 === void 0 || _this$props$onClose2.call(_this$props2);
86
- (_this$props$anchor3 = _this.props.anchor) === null || _this$props$anchor3 === void 0 || (_this$props$anchor3$f = _this$props$anchor3.focus) === null || _this$props$anchor3$f === void 0 || _this$props$anchor3$f.call(_this$props$anchor3);
103
+ (_this$props$anchor4 = _this.props.anchor) === null || _this$props$anchor4 === void 0 || (_this$props$anchor4$f = _this$props$anchor4.focus) === null || _this$props$anchor4$f === void 0 || _this$props$anchor4$f.call(_this$props$anchor4);
87
104
  MiscUtils.killEvent(ev);
88
105
  } else if (ev.key === 'Enter' || ev.key === ' ' && _this.props.spaceKeyActivation) {
89
106
  MiscUtils.killEvent(ev);
90
107
  } else if (ev.key !== 'Tab' && ev.key !== 'Shift') {
91
- var _this$props$anchor4, _this$props$anchor4$f;
92
- (_this$props$anchor4 = _this.props.anchor) === null || _this$props$anchor4 === void 0 || (_this$props$anchor4$f = _this$props$anchor4.focus) === null || _this$props$anchor4$f === void 0 || _this$props$anchor4$f.call(_this$props$anchor4);
108
+ var _this$props$anchor5, _this$props$anchor5$f;
109
+ (_this$props$anchor5 = _this.props.anchor) === null || _this$props$anchor5 === void 0 || (_this$props$anchor5$f = _this$props$anchor5.focus) === null || _this$props$anchor5$f === void 0 || _this$props$anchor5$f.call(_this$props$anchor5);
93
110
  }
94
111
  });
95
- _this.container = ((_this$props$anchor$ow = (_this$props$anchor5 = _this.props.anchor) === null || _this$props$anchor5 === void 0 ? void 0 : _this$props$anchor5.ownerDocument) !== null && _this$props$anchor$ow !== void 0 ? _this$props$anchor$ow : document).createElement("div");
112
+ var doc = (_this$props$anchor$ow = (_this$props$anchor6 = _this.props.anchor) === null || _this$props$anchor6 === void 0 ? void 0 : _this$props$anchor6.ownerDocument) !== null && _this$props$anchor$ow !== void 0 ? _this$props$anchor$ow : document;
113
+ _this.container = doc.createElement("div");
96
114
  _this.container.id = 'popup-container';
97
115
  _this.container.style.position = 'fixed';
98
116
  _this.container.style.left = 0;
@@ -100,60 +118,47 @@ var PopupMenu = /*#__PURE__*/function (_React$PureComponent) {
100
118
  _this.container.style.top = 0;
101
119
  _this.container.style.bottom = 0;
102
120
  _this.container.style.zIndex = 100000;
103
- if (_this.props.anchor) {
104
- _this.shields = [];
105
- var _loop = function _loop(i) {
106
- var _this$props$anchor$ow2, _this$props$anchor6;
107
- _this.shields[i] = ((_this$props$anchor$ow2 = (_this$props$anchor6 = _this.props.anchor) === null || _this$props$anchor6 === void 0 ? void 0 : _this$props$anchor6.ownerDocument) !== null && _this$props$anchor$ow2 !== void 0 ? _this$props$anchor$ow2 : document).createElement("div");
108
- _this.shields[i].style.position = 'absolute';
109
- _this.shields[i].style.left = "0px";
110
- _this.shields[i].style.right = "0px";
111
- _this.shields[i].style.top = "0px";
112
- _this.shields[i].style.bottom = "0px";
113
- _this.shields[i].style.pointerEvents = 'initial';
114
- _this.shields[i].style.zIndex = 0;
115
- setTimeout(function () {
116
- return _this.shields[i].addEventListener('click', function () {
117
- var _this$props$onClose3, _this$props3;
118
- (_this$props$onClose3 = (_this$props3 = _this.props).onClose) === null || _this$props$onClose3 === void 0 || _this$props$onClose3.call(_this$props3);
119
- });
120
- }, 0);
121
- _this.container.appendChild(_this.shields[i]);
122
- };
123
- for (var i = 0; i < 4; ++i) {
124
- _loop(i);
125
- }
126
- _this.container.style.pointerEvents = 'none';
127
- } else {
128
- setTimeout(function () {
129
- return _this.container.addEventListener('click', function () {
130
- var _this$props$onClose4, _this$props4;
131
- (_this$props$onClose4 = (_this$props4 = _this.props).onClose) === null || _this$props$onClose4 === void 0 || _this$props$onClose4.call(_this$props4);
132
- });
133
- }, 0);
134
- }
121
+ _this.container.style.pointerEvents = 'none';
135
122
  _this.menuEl = null;
136
- ((_this$props$anchor$ow3 = (_this$props$anchor7 = _this.props.anchor) === null || _this$props$anchor7 === void 0 ? void 0 : _this$props$anchor7.ownerDocument) !== null && _this$props$anchor$ow3 !== void 0 ? _this$props$anchor$ow3 : document).body.appendChild(_this.container);
123
+ doc.body.appendChild(_this.container);
124
+ // Delay one cycle
125
+ setTimeout(function () {
126
+ return doc.addEventListener('pointerdown', _this.checkCloseMenu, {
127
+ capture: true
128
+ });
129
+ }, 0);
130
+ doc.addEventListener('click', _this.checkKillClick, {
131
+ capture: true
132
+ });
137
133
  return _this;
138
134
  }
139
135
  _inherits(PopupMenu, _React$PureComponent);
140
136
  return _createClass(PopupMenu, [{
141
137
  key: "componentDidMount",
142
138
  value: function componentDidMount() {
143
- var _this$props$anchor8;
144
- if (((_this$props$anchor8 = this.props.anchor) === null || _this$props$anchor8 === void 0 ? void 0 : _this$props$anchor8.nodeName) === "INPUT") {
139
+ var _this$props$anchor7;
140
+ if (((_this$props$anchor7 = this.props.anchor) === null || _this$props$anchor7 === void 0 ? void 0 : _this$props$anchor7.nodeName) === "INPUT") {
145
141
  this.props.anchor.addEventListener('keydown', this.keyNav);
146
142
  }
147
143
  }
148
144
  }, {
149
145
  key: "componentWillUnmount",
150
146
  value: function componentWillUnmount() {
151
- var _this$props$anchor$ow4, _this$props$anchor9, _this$props$anchor0, _this$props$anchor1, _this$props$anchor1$f;
152
- ((_this$props$anchor$ow4 = (_this$props$anchor9 = this.props.anchor) === null || _this$props$anchor9 === void 0 ? void 0 : _this$props$anchor9.ownerDocument) !== null && _this$props$anchor$ow4 !== void 0 ? _this$props$anchor$ow4 : document).body.removeChild(this.container);
153
- if (((_this$props$anchor0 = this.props.anchor) === null || _this$props$anchor0 === void 0 ? void 0 : _this$props$anchor0.nodeName) === "INPUT") {
147
+ var _this$props$anchor$ow2, _this$props$anchor8, _this$props$anchor9, _this$props$anchor0, _this$props$anchor0$f;
148
+ var doc = (_this$props$anchor$ow2 = (_this$props$anchor8 = this.props.anchor) === null || _this$props$anchor8 === void 0 ? void 0 : _this$props$anchor8.ownerDocument) !== null && _this$props$anchor$ow2 !== void 0 ? _this$props$anchor$ow2 : document;
149
+ doc.body.removeChild(this.container);
150
+ if (((_this$props$anchor9 = this.props.anchor) === null || _this$props$anchor9 === void 0 ? void 0 : _this$props$anchor9.nodeName) === "INPUT") {
154
151
  this.props.anchor.removeEventListener('keydown', this.keyNav);
155
152
  }
156
- (_this$props$anchor1 = this.props.anchor) === null || _this$props$anchor1 === void 0 || (_this$props$anchor1$f = _this$props$anchor1.focus) === null || _this$props$anchor1$f === void 0 || _this$props$anchor1$f.call(_this$props$anchor1);
153
+ (_this$props$anchor0 = this.props.anchor) === null || _this$props$anchor0 === void 0 || (_this$props$anchor0$f = _this$props$anchor0.focus) === null || _this$props$anchor0$f === void 0 || _this$props$anchor0$f.call(_this$props$anchor0);
154
+ doc.removeEventListener('pointerdown', this.checkCloseMenu, {
155
+ capture: true
156
+ });
157
+ if (!this.killClick) {
158
+ doc.removeEventListener('click', this.checkKillClick, {
159
+ capture: true
160
+ });
161
+ }
157
162
  }
158
163
  }, {
159
164
  key: "render",
@@ -178,12 +183,6 @@ var PopupMenu = /*#__PURE__*/function (_React$PureComponent) {
178
183
  } else {
179
184
  rect = this.props.anchor.getBoundingClientRect();
180
185
  }
181
- this.shields[0].style.height = rect.top + "px";
182
- this.shields[0].style.bottom = 0;
183
- this.shields[1].style.width = rect.left + "px";
184
- this.shields[1].style.right = 0;
185
- this.shields[2].style.left = rect.right + "px";
186
- this.shields[3].style.top = rect.bottom + "px";
187
186
  }
188
187
  var x = (_ref = this.props.align === 'right' ? (_rect = rect) === null || _rect === void 0 ? void 0 : _rect.right : (_rect2 = rect) === null || _rect2 === void 0 ? void 0 : _rect2.left) !== null && _ref !== void 0 ? _ref : this.props.x;
189
188
  var y = ((_rect$bottom = (_rect3 = rect) === null || _rect3 === void 0 ? void 0 : _rect3.bottom) !== null && _rect$bottom !== void 0 ? _rect$bottom : this.props.y) - 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qwc2",
3
- "version": "2026.08.02",
3
+ "version": "2026.08.06",
4
4
  "description": "QGIS Web Client",
5
5
  "author": "Sourcepole AG",
6
6
  "license": "BSD-2-Clause",
package/plugins/API.js CHANGED
@@ -536,6 +536,13 @@ var API = /*#__PURE__*/function (_React$Component) {
536
536
  _defineProperty(_this, "getState", function () {
537
537
  return _this.props.state;
538
538
  });
539
+ /**
540
+ * Return the current 3d view scene context, if a 3D view is active.
541
+ */
542
+ _defineProperty(_this, "get3dSceneContext", function () {
543
+ var _window$qwc2$__3dscen, _window$qwc;
544
+ return (_window$qwc2$__3dscen = (_window$qwc = window.qwc2).__3dscenecontext) === null || _window$qwc2$__3dscen === void 0 ? void 0 : _window$qwc2$__3dscen.call(_window$qwc);
545
+ });
539
546
  /** Fires the callback on the next click on the map.
540
547
  *
541
548
  * *NOTE*: when calling `onMapClick` through the `postMessage` interface, omit the `callback` parameter. The response will be sent via the response message.
@@ -577,6 +584,7 @@ var API = /*#__PURE__*/function (_React$Component) {
577
584
  window.qwc2.drawScratch = this.drawScratch;
578
585
  window.qwc2.drawGeometry = this.drawGeometry;
579
586
  window.qwc2.getState = this.getState;
587
+ window.qwc2.get3dSceneContext = this.get3dSceneContext;
580
588
  window.qwc2.ConfigUtils = ConfigUtils;
581
589
  window.qwc2.CoordinatesUtils = CoordinatesUtils;
582
590
  window.qwc2.EditingInterface = EditingInterface;
@@ -56,9 +56,8 @@ var Panoramax = /*#__PURE__*/function (_React$Component) {
56
56
  currentTooltip: '',
57
57
  viewerInitialized: false
58
58
  });
59
- _defineProperty(_this, "onClose", function () {
59
+ _defineProperty(_this, "cleanUp", function () {
60
60
  var _this$viewer;
61
- _this.props.setCurrentTask(null);
62
61
  _this.props.removeLayer('panoramax-recordings');
63
62
  _this.props.removeLayer('panoramaxselection');
64
63
  _this.setState({
@@ -73,6 +72,9 @@ var Panoramax = /*#__PURE__*/function (_React$Component) {
73
72
  });
74
73
  (_this$viewer = _this.viewer) === null || _this$viewer === void 0 || _this$viewer.select(null, null, true);
75
74
  });
75
+ _defineProperty(_this, "onClose", function () {
76
+ _this.props.setCurrentTask(null);
77
+ });
76
78
  _defineProperty(_this, "initializeViewer", function () {
77
79
  var viewerElement = _this.viewerRef.current;
78
80
  if (viewerElement) {
@@ -199,6 +201,8 @@ var Panoramax = /*#__PURE__*/function (_React$Component) {
199
201
  this.addRecordingsMVT();
200
202
  }
201
203
  }
204
+ } else if (prevProps.active && !this.props.active) {
205
+ this.cleanUp();
202
206
  } else if (this.state.selectionGeom && this.state.selectionGeom !== prevState.selectionGeom) {
203
207
  this.queryPoint(this.state.selectionGeom);
204
208
  }
@@ -87,49 +87,59 @@ var ScratchDrawing = /*#__PURE__*/function (_React$Component) {
87
87
  _defineProperty(_this, "submitGeometry", function () {
88
88
  var _this$props$layers$fi;
89
89
  var features = ((_this$props$layers$fi = _this.props.layers.find(function (l) {
90
- return l.id === _this.props.redlining.layer;
90
+ return l.id === _this.layerId;
91
91
  })) === null || _this$props$layers$fi === void 0 ? void 0 : _this$props$layers$fi.features) || [];
92
- _this.submitted = true;
92
+ if (_this.props.redlining.selectedFeature) {
93
+ features = features.filter(function (f) {
94
+ return f.id !== _this.props.redlining.selectedFeature.id;
95
+ });
96
+ features.push(_this.props.redlining.selectedFeature);
97
+ }
93
98
  _this.props.task.data.callback(features, _this.props.projection);
99
+ _this.submitted = true;
94
100
  _this.props.setCurrentTask(null);
95
101
  });
96
102
  _this.submitted = false;
103
+ _this.layerId = null;
97
104
  return _this;
98
105
  }
99
106
  _inherits(ScratchDrawing, _React$Component);
100
107
  return _createClass(ScratchDrawing, [{
101
108
  key: "componentDidUpdate",
102
109
  value: function componentDidUpdate(prevProps) {
103
- // Clear when task changes
104
- if (this.props.task.id !== "ScratchDrawing" && prevProps.task.id === "ScratchDrawing") {
105
- if (!this.submitted) {
106
- prevProps.task.data.callback(null, null);
107
- this.submitted = true;
108
- }
109
- this.props.removeLayer(prevProps.redlining.layer);
110
- this.props.resetRedliningState();
111
- }
112
- // Setup redlining state
113
- if (this.props.task !== prevProps.task && this.props.task.id === "ScratchDrawing") {
114
- if (prevProps.task.id === "ScratchDrawing") {
115
- this.props.removeLayer(prevProps.redlining.layer);
116
- if (!this.submitted) {
117
- prevProps.task.data.callback(null, null);
118
- this.submitted = true;
119
- }
120
- }
121
- this.submitted = false;
110
+ if (this.props.task.id === "ScratchDrawing" && prevProps.task.id !== "ScratchDrawing") {
122
111
  var data = this.props.task.data;
123
- var layerId = this.createDrawLayer(data);
112
+ this.layerId = this.createDrawLayer(data);
124
113
  this.props.setSnappingConfig(data.snapping, data.snappingActive);
125
114
  this.props.changeRedliningState({
126
115
  action: 'PickDraw',
127
116
  geomType: data.geomType,
128
- layer: layerId,
117
+ layer: this.layerId,
129
118
  layerTitle: null,
130
119
  drawMultiple: data.drawMultiple,
131
120
  style: this.drawingStyle(data.style)
132
121
  });
122
+ } else if (prevProps.task.id === "ScratchDrawing" && this.props.task !== prevProps.task) {
123
+ this.props.resetRedliningState();
124
+ if (!this.submitted) {
125
+ prevProps.task.data.callback(null, null);
126
+ }
127
+ this.submitted = false;
128
+ } else if (this.props.redlining.layer === null && prevProps.redlining.layer === this.layerId) {
129
+ this.props.removeLayer(this.layerId);
130
+ if (this.props.task.id === "ScratchDrawing") {
131
+ var _data = this.props.task.data;
132
+ this.layerId = this.createDrawLayer(_data);
133
+ this.props.setSnappingConfig(_data.snapping, _data.snappingActive);
134
+ this.props.changeRedliningState({
135
+ action: 'PickDraw',
136
+ geomType: _data.geomType,
137
+ layer: this.layerId,
138
+ layerTitle: null,
139
+ drawMultiple: _data.drawMultiple,
140
+ style: this.drawingStyle(_data.style)
141
+ });
142
+ }
133
143
  }
134
144
  }
135
145
  }, {
@@ -78,13 +78,13 @@ var EditingSupport = /*#__PURE__*/function (_React$Component) {
78
78
  } else if (f.getGeometry().getType() === "LineString") {
79
79
  return new ol.geom.MultiPoint(f.getGeometry().getCoordinates());
80
80
  } else if (f.getGeometry().getType() === "Polygon") {
81
- return new ol.geom.MultiPoint(f.getGeometry().getCoordinates()[0]);
81
+ return new ol.geom.MultiPoint(f.getGeometry().getCoordinates().flat());
82
82
  } else if (f.getGeometry().getType() === "MultiPoint") {
83
83
  return f.getGeometry();
84
84
  } else if (f.getGeometry().getType() === "MultiLineString") {
85
- return new ol.geom.MultiPoint(f.getGeometry().getCoordinates()[0]);
85
+ return new ol.geom.MultiPoint(f.getGeometry().getCoordinates().flat());
86
86
  } else if (f.getGeometry().getType() === "MultiPolygon") {
87
- return new ol.geom.MultiPoint(f.getGeometry().getCoordinates()[0][0]);
87
+ return new ol.geom.MultiPoint(f.getGeometry().getCoordinates().flat(2));
88
88
  }
89
89
  return f.getGeometry();
90
90
  };
@@ -135,7 +135,6 @@ var EditingSupport = /*#__PURE__*/function (_React$Component) {
135
135
  });
136
136
  });
137
137
  _defineProperty(_this, "setEditInteraction", function () {
138
- var _this$props$editConte;
139
138
  _this.reset();
140
139
  _this.setCurrentLayer();
141
140
  var format = new ol.format.GeoJSON();
@@ -178,7 +177,7 @@ var EditingSupport = /*#__PURE__*/function (_React$Component) {
178
177
  _this.props.map.addInteraction(_this.interaction);
179
178
  _this.interaction.setSelection([_this.currentFeature]);
180
179
  }
181
- _this.interaction.setActive(_this.props.editContext.geomType && _this.props.editContext.permissions.updatable && ((_this$props$editConte = _this.props.editContext.editConfig) === null || _this$props$editConte === void 0 || (_this$props$editConte = _this$props$editConte.permissions) === null || _this$props$editConte === void 0 ? void 0 : _this$props$editConte.updatable) === true && !_this.props.editContext.geomReadOnly && !_this.props.editContext.geomNonZeroZ);
180
+ _this.interaction.setActive(_this.props.editContext.geomType && _this.props.editContext.permissions.updatable && !_this.props.editContext.geomReadOnly && !_this.props.editContext.geomNonZeroZ);
182
181
  });
183
182
  _defineProperty(_this, "updateMeasurements", function () {
184
183
  var _this$state$measureme;
@@ -285,11 +284,14 @@ var EditingSupport = /*#__PURE__*/function (_React$Component) {
285
284
  }, {
286
285
  key: "render",
287
286
  value: function render() {
288
- var _this$props$editConte2, _this$props$editConte3;
287
+ var _this$props$editConte, _this$props$editConte2;
288
+ if (!this.props.editContext.geomType || this.props.editContext.geomReadOnly || this.props.editContext.geomNonZeroZ) {
289
+ return null;
290
+ }
289
291
  var toolbar = null;
290
292
  var locationRecorder = null;
291
293
  var measureSwitcher = null;
292
- if ((_this$props$editConte2 = this.props.editContext.feature) !== null && _this$props$editConte2 !== void 0 && _this$props$editConte2.geometry) {
294
+ if ((_this$props$editConte = this.props.editContext.feature) !== null && _this$props$editConte !== void 0 && _this$props$editConte.geometry) {
293
295
  var editButtons = [{
294
296
  key: "Node",
295
297
  tooltip: LocaleUtils.tr("redlining.draw"),
@@ -307,7 +309,7 @@ var EditingSupport = /*#__PURE__*/function (_React$Component) {
307
309
  tooltipPos: "top"
308
310
  }), this.context);
309
311
  }
310
- if (this.state.showRecordLocation && this.props.editContext.geomType) {
312
+ if (this.state.showRecordLocation) {
311
313
  var geomType = this.props.editContext.geomType.replace(/Z$/, '');
312
314
  locationRecorder = /*#__PURE__*/React.createElement(LocationRecorder, {
313
315
  drawInteraction: this.interaction,
@@ -316,7 +318,7 @@ var EditingSupport = /*#__PURE__*/function (_React$Component) {
316
318
  map: this.props.map
317
319
  });
318
320
  }
319
- if (this.props.editContext.action === "Draw" || (_this$props$editConte3 = this.props.editContext.feature) !== null && _this$props$editConte3 !== void 0 && _this$props$editConte3.geometry) {
321
+ if (this.props.editContext.action === "Draw" || (_this$props$editConte2 = this.props.editContext.feature) !== null && _this$props$editConte2 !== void 0 && _this$props$editConte2.geometry) {
320
322
  measureSwitcher = /*#__PURE__*/ReactDOM.createPortal(/*#__PURE__*/React.createElement(MeasureSwitcher, {
321
323
  changeMeasureState: this.changeMeasurementState,
322
324
  geomType: this.props.editContext.geomType,
@@ -60,6 +60,7 @@ var OverviewMap3D = /*#__PURE__*/function (_React$Component) {
60
60
  return _createClass(OverviewMap3D, [{
61
61
  key: "componentDidMount",
62
62
  value: function componentDidMount() {
63
+ this.updateViewCone();
63
64
  this.props.sceneContext.eventDispatcher.addEventListener('cameraChanged', this.updateViewCone);
64
65
  }
65
66
  }, {
@@ -26,7 +26,7 @@ div.background-switcher {
26
26
  transform-origin: right;
27
27
  transition: transform 0.1s;
28
28
  width: calc(var(--buttons-container-width) - 7em);
29
- z-index: 1;
29
+ z-index: 3;
30
30
  display: flex;
31
31
  justify-content: flex-end;
32
32
  flex-wrap: wrap-reverse;
@@ -194,6 +194,9 @@ var MiscUtils = {
194
194
  capitalizeFirst: function capitalizeFirst(text) {
195
195
  return text.slice(0, 1).toUpperCase() + text.slice(1);
196
196
  },
197
+ isNumeric: function isNumeric(value) {
198
+ return typeof value === 'string' && value.trim() !== '' && String(Number(value)) === value.trim();
199
+ },
197
200
  isBrightColor: function isBrightColor(color) {
198
201
  var r;
199
202
  var g;
@@ -457,11 +457,15 @@ export var FulltextSearch = /*#__PURE__*/function () {
457
457
  items: data.results.filter(function (entry) {
458
458
  return entry.feature && entry.feature.bbox;
459
459
  }).map(function (entry) {
460
+ var center = entry.feature.center;
461
+ if (!center) {
462
+ center = [0.5 * (entry.feature.bbox[0] + entry.feature.bbox[2]), 0.5 * (entry.feature.bbox[1] + entry.feature.bbox[3])];
463
+ }
460
464
  return {
461
465
  id: entry.feature.feature_id,
462
466
  text: entry.feature.display,
463
- x: 0.5 * (entry.feature.bbox[0] + entry.feature.bbox[2]),
464
- y: 0.5 * (entry.feature.bbox[1] + entry.feature.bbox[3]),
467
+ x: center[0],
468
+ y: center[1],
465
469
  crs: entry.feature.srid ? "EPSG:" + String(entry.feature.srid).replace(/^EPSG:/, '') : null,
466
470
  bbox: entry.feature.bbox,
467
471
  thumbnail: iconPath + entry.feature.dataproduct_id + ".svg",