qwc2 2026.2.25 → 2026.2.27

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.
@@ -170,7 +170,7 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
170
170
  var _this2$state$sceneCon;
171
171
  var currentBaseLayer = ((_this2$state$sceneCon = _this2.state.sceneContext.baseLayers.find(function (l) {
172
172
  return l.visibility === true;
173
- })) === null || _this2$state$sceneCon === void 0 ? void 0 : _this2$state$sceneCon.name) || "";
173
+ })) === null || _this2$state$sceneCon === void 0 ? void 0 : _this2$state$sceneCon.name) || null;
174
174
  if (visibility && layer.name === currentBaseLayer) {
175
175
  // Nothing changed
176
176
  return;
@@ -594,7 +594,7 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
594
594
  }
595
595
  // Ensure labels are removed
596
596
  object.traverse(function (c) {
597
- if (c.isCSS2DObject) {
597
+ if (c.isCSS2DObject && c.element.parentNode) {
598
598
  c.element.parentNode.removeChild(c.element);
599
599
  }
600
600
  });
@@ -645,6 +645,9 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
645
645
  });
646
646
  _defineProperty(_this2, "applySceneObjectState", function (objectId, options, prevOptions, objectTree) {
647
647
  var object = _this2.objectMap[objectId];
648
+ if (!object) {
649
+ return;
650
+ }
648
651
  var changed = false;
649
652
  if (options.visibility !== prevOptions.visibility || options.opacity !== (prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.opacity)) {
650
653
  var _objectTree$options$p;
@@ -935,7 +938,7 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
935
938
  visibility: (_entry$visibility3 = entry.visibility) !== null && _entry$visibility3 !== void 0 ? _entry$visibility3 : true,
936
939
  opacity: 255
937
940
  };
938
- _this2.importObject3D(entry, entry.name, false, {}, false, function () {
941
+ _this2.importObject3D(MiscUtils.resolveAssetsPath(entry.url), entry.name, false, {}, false, function () {
939
942
  _this2.applySceneObjectState(entry.name, objectTree[entry.name], {}, objectTree);
940
943
  });
941
944
  nodeIds.push(entry.name);
@@ -1300,10 +1303,13 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
1300
1303
  }
1301
1304
  });
1302
1305
  _this2.state.sceneContext.restoreView(data);
1303
- var bl3d = (_data$baseLayer = data.baseLayer) !== null && _data$baseLayer !== void 0 ? _data$baseLayer : "";
1304
- _this2.setBaseLayer({
1305
- name: bl3d
1306
- }, bl3d !== "null");
1306
+ if (((_data$baseLayer = data.baseLayer) !== null && _data$baseLayer !== void 0 ? _data$baseLayer : null) !== null) {
1307
+ var _data$baseLayer2;
1308
+ var bl3d = (_data$baseLayer2 = data.baseLayer) !== null && _data$baseLayer2 !== void 0 ? _data$baseLayer2 : "";
1309
+ _this2.setBaseLayer({
1310
+ name: bl3d
1311
+ }, bl3d !== "null");
1312
+ }
1307
1313
  _this2.state.sceneContext.scene.notifyChange();
1308
1314
  });
1309
1315
  _this2.container = null;
@@ -1383,11 +1389,16 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
1383
1389
  this.setState(function (state) {
1384
1390
  return {
1385
1391
  sceneContext: _objectSpread(_objectSpread({}, state.sceneContext), {}, {
1386
- collisionObjects: Object.entries(state.sceneContext.objectTree).reduce(function (res, entry) {
1392
+ collisionObjects: Object.entries(state.sceneContext.objectTree).reduce(function (res, _ref12) {
1393
+ var _ref13 = _slicedToArray(_ref12, 2),
1394
+ objectid = _ref13[0],
1395
+ entry = _ref13[1];
1387
1396
  if (entry.visibility && entry.opacity > 0) {
1388
- var _obj$tiles$group, _obj$tiles;
1389
1397
  var obj = _this3.objectMap[entry.objectId];
1390
- 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);
1398
+ if (obj) {
1399
+ var _obj$tiles$group, _obj$tiles;
1400
+ 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);
1401
+ }
1391
1402
  }
1392
1403
  return res;
1393
1404
  }, [])
@@ -1428,10 +1439,10 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
1428
1439
  sceneContext: this.state.sceneContext
1429
1440
  }), /*#__PURE__*/React.createElement(ViewSwitcher, {
1430
1441
  position: 1
1431
- }), Object.entries(this.props.plugins3d).map(function (_ref12) {
1432
- var _ref13 = _slicedToArray(_ref12, 2),
1433
- name = _ref13[0],
1434
- Component = _ref13[1];
1442
+ }), Object.entries(this.props.plugins3d).map(function (_ref14) {
1443
+ var _ref15 = _slicedToArray(_ref14, 2),
1444
+ name = _ref15[0],
1445
+ Component = _ref15[1];
1435
1446
  return /*#__PURE__*/React.createElement(Suspense, {
1436
1447
  key: name
1437
1448
  }, /*#__PURE__*/React.createElement(Component, _extends({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qwc2",
3
- "version": "2026.02.25",
3
+ "version": "2026.02.27",
4
4
  "description": "QGIS Web Client",
5
5
  "author": "Sourcepole AG",
6
6
  "license": "BSD-2-Clause",
package/plugins/API.js CHANGED
@@ -156,7 +156,7 @@ var actionFunctions = _objectSpread(_objectSpread(_objectSpread(_objectSpread(_o
156
156
  * ```
157
157
  * You can also post multiple calls at once as follows:
158
158
  * ```
159
- * * qwcframe.contentWindow.postMessage([{
159
+ * qwcframe.contentWindow.postMessage([{
160
160
  * "method": "zoomToPoint",
161
161
  * "params": [[2684764, 1247841], 18, "EPSG:2056"]
162
162
  * }, {
@@ -269,20 +269,17 @@ var actionFunctions = _objectSpread(_objectSpread(_objectSpread(_objectSpread(_o
269
269
  * In addition, the following methods are available on `window.qwc2`:
270
270
  */
271
271
  var API = /*#__PURE__*/function (_React$Component) {
272
- function API() {
272
+ function API(props) {
273
273
  var _this;
274
274
  _classCallCheck(this, API);
275
- for (var _len = arguments.length, _args = new Array(_len), _key = 0; _key < _len; _key++) {
276
- _args[_key] = arguments[_key];
277
- }
278
- _this = _callSuper(this, API, [].concat(_args));
275
+ _this = _callSuper(this, API, [props]);
279
276
  _defineProperty(_this, "handleMessage", function (ev) {
280
277
  if (!_this.props.allowedMessageOrigins.includes(ev.origin)) {
281
278
  /* eslint-disable-next-line */
282
279
  console.warn("Discarding message from not-allowed origin " + ev.origin);
283
280
  return;
284
281
  }
285
- var allowedMemberFunctions = ["addExternalLayer", "getState"];
282
+ var allowedMemberFunctions = ["addExternalLayer", "getState", "drawGeometry", "onMapClick"];
286
283
  if (ev.data === "help") {
287
284
  var signatures = Object.fromEntries(Object.entries(actionFunctions).map(function (_ref3) {
288
285
  var _val$toString$match$, _val$toString$match;
@@ -305,19 +302,45 @@ var API = /*#__PURE__*/function (_React$Component) {
305
302
  var func = message.method;
306
303
  var args = (_message$params = message.params) !== null && _message$params !== void 0 ? _message$params : [];
307
304
  var result = null;
305
+ var postResult = true;
308
306
  if (func in actionFunctions) {
309
307
  var _this$props;
310
308
  result = (_this$props = _this.props)[func].apply(_this$props, _toConsumableArray(args));
311
309
  } else if (allowedMemberFunctions.includes(func)) {
312
310
  var _this2;
311
+ // Inject proper callback function
312
+ if (func === "drawGeometry") {
313
+ args.splice(2, 0, function (features, crs) {
314
+ if (message.requestId) {
315
+ ev.source.postMessage({
316
+ requestId: message.requestId,
317
+ result: {
318
+ features: features,
319
+ crs: crs
320
+ }
321
+ }, ev.origin);
322
+ }
323
+ });
324
+ postResult = false;
325
+ } else if (func === "onMapClick") {
326
+ args = [function (click) {
327
+ if (message.requestId) {
328
+ ev.source.postMessage({
329
+ requestId: message.requestId,
330
+ result: click
331
+ }, ev.origin);
332
+ }
333
+ }];
334
+ postResult = false;
335
+ }
313
336
  result = (_this2 = _this)[func].apply(_this2, _toConsumableArray(args));
314
337
  } else {
315
338
  /* eslint-disable-next-line */
316
339
  console.warn("Unhandeled message: " + JSON.stringify(message));
317
340
  }
318
- if (message.requestId) {
341
+ if (postResult && message.requestId) {
319
342
  ev.source.postMessage({
320
- requestId: ev.data.requestId,
343
+ requestId: message.requestId,
321
344
  result: result
322
345
  }, ev.origin);
323
346
  }
@@ -446,7 +469,9 @@ var API = /*#__PURE__*/function (_React$Component) {
446
469
  });
447
470
  });
448
471
  /**
449
- * Draw geometries, and return these as GeoJSON to the calling application.
472
+ * Draw geometries, and return these as GeoJSON to the calling application.
473
+ *
474
+ * *NOTE*: when calling `drawGeometry` through the `postMessage` interface, omit the `callback` parameter. The response will be sent via the response message.
450
475
  *
451
476
  * * `geomType`: `Point`, `LineString`, `Polygon`, `Circle` or `Box`.
452
477
  * * `message`: A descriptive string to display in the tool taskbar.
@@ -477,6 +502,11 @@ var API = /*#__PURE__*/function (_React$Component) {
477
502
  _defineProperty(_this, "getState", function () {
478
503
  return _this.props.state;
479
504
  });
505
+ /** Fires the callback on the next click on the map. */
506
+ _defineProperty(_this, "onMapClick", function (callback) {
507
+ _this.onclickCallbacks.push(callback);
508
+ });
509
+ _this.onclickCallbacks = [];
480
510
  return _this;
481
511
  }
482
512
  _inherits(API, _React$Component);
@@ -589,6 +619,17 @@ var API = /*#__PURE__*/function (_React$Component) {
589
619
  window.addEventListener("message", this.handleMessage);
590
620
  window.dispatchEvent(new Event("QWC2ApiReady"));
591
621
  }
622
+ }, {
623
+ key: "componentDidUpdate",
624
+ value: function componentDidUpdate(prevProps) {
625
+ var _this3 = this;
626
+ if (this.props.click !== prevProps.click && this.onclickCallbacks.length > 0) {
627
+ this.onclickCallbacks.forEach(function (cb) {
628
+ return cb(_objectSpread({}, _this3.props.click));
629
+ });
630
+ this.onclickCallbacks = [];
631
+ }
632
+ }
592
633
  }, {
593
634
  key: "render",
594
635
  value: function render() {
@@ -600,6 +641,7 @@ _defineProperty(API, "propTypes", {
600
641
  addLayer: PropTypes.func,
601
642
  /* List of origins which are allowed to post messages via `qwcIframe.postMessage`. */
602
643
  allowedMessageOrigins: PropTypes.arrayOf(PropTypes.string),
644
+ click: PropTypes.object,
603
645
  mapCrs: PropTypes.string,
604
646
  registerCustomPlugin: PropTypes.func,
605
647
  setCurrentTask: PropTypes.func,
@@ -611,6 +653,9 @@ _defineProperty(API, "defaultProps", {
611
653
  });
612
654
  export default connect(function (state) {
613
655
  return {
656
+ click: state.map.click || {
657
+ modifiers: {}
658
+ },
614
659
  mapCrs: state.map.projection,
615
660
  state: state
616
661
  };
@@ -55,6 +55,7 @@ var TaskButton = /*#__PURE__*/function (_React$Component) {
55
55
  }
56
56
  var title = LocaleUtils.tr("appmenu.items." + this.props.task + (this.props.mode || ""));
57
57
  return /*#__PURE__*/React.createElement(MapButton, {
58
+ active: this.props.currentTask === this.props.task,
58
59
  icon: this.props.icon,
59
60
  onClick: this.buttonClicked,
60
61
  position: this.props.position,
@@ -87,7 +87,7 @@ function parsePropDesc(prop) {
87
87
  var _ref4 = _slicedToArray(_ref3, 2),
88
88
  name = _ref4[0],
89
89
  subprop = _ref4[1];
90
- return "- " + name + ": " + subprop.description;
90
+ return "- `" + name + "`: " + subprop.description;
91
91
  }).join("<br />");
92
92
  } else {
93
93
  return prop.description.replaceAll("\n", "<br />");