qwc2 2025.12.17 → 2025.12.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 (70) hide show
  1. package/components/AttributeForm.js +8 -8
  2. package/components/AttributeTableWidget.js +3 -3
  3. package/components/EditComboField.js +1 -1
  4. package/components/EditUploadField.js +1 -1
  5. package/components/IdentifyViewer.js +3 -4
  6. package/components/LinkFeatureForm.js +21 -4
  7. package/components/MeasureSwitcher.js +115 -0
  8. package/components/PluginsContainer.js +3 -2
  9. package/components/QtDesignerForm.js +2 -2
  10. package/components/ResizeableWindow.js +1 -1
  11. package/components/SearchBox.js +7 -7
  12. package/components/map3d/drawtool/EditTool3D.js +1 -1
  13. package/components/style/IdentifyViewer.css +1 -1
  14. package/components/style/LocationRecorder.css +1 -6
  15. package/components/style/PluginsContainer.css +11 -6
  16. package/components/timeline/FixedTimeline.js +2 -2
  17. package/components/timeline/InfiniteTimeline.js +2 -2
  18. package/components/timeline/TimelineFeaturesSlider.js +1 -1
  19. package/components/widgets/LayerCatalogWidget.js +1 -1
  20. package/package.json +1 -1
  21. package/plugins/Editing.js +20 -5
  22. package/plugins/FeatureForm.js +1 -1
  23. package/plugins/FeatureSearch.js +3 -3
  24. package/plugins/GeometryDigitizer.js +32 -18
  25. package/plugins/Identify.js +1 -4
  26. package/plugins/MapExport.js +4 -4
  27. package/plugins/MapFilter.js +10 -10
  28. package/plugins/NewsPopup.js +1 -1
  29. package/plugins/ObliqueView.js +88 -17
  30. package/plugins/Print.js +7 -7
  31. package/plugins/Redlining.js +25 -73
  32. package/plugins/Reports.js +3 -3
  33. package/plugins/Routing.js +4 -4
  34. package/plugins/ValueTool.js +1 -1
  35. package/plugins/View3D.js +2 -2
  36. package/plugins/ZoomButtons.js +1 -1
  37. package/plugins/map/EditingSupport.js +50 -20
  38. package/plugins/map/RedliningSupport.js +2 -2
  39. package/plugins/map/SnapSupport.js +12 -10
  40. package/plugins/map/style/SnappingSupport.css +1 -8
  41. package/plugins/map3d/Draw3D.js +2 -2
  42. package/plugins/map3d/ExportObjects3D.js +2 -2
  43. package/plugins/map3d/MapExport3D.js +4 -4
  44. package/reducers/editing.js +6 -1
  45. package/static/translations/bg-BG.json +39 -74
  46. package/static/translations/ca-ES.json +39 -74
  47. package/static/translations/cs-CZ.json +39 -74
  48. package/static/translations/de-CH.json +39 -74
  49. package/static/translations/de-DE.json +39 -74
  50. package/static/translations/en-US.json +39 -74
  51. package/static/translations/es-ES.json +39 -74
  52. package/static/translations/fi-FI.json +39 -74
  53. package/static/translations/fr-FR.json +39 -74
  54. package/static/translations/hu-HU.json +39 -74
  55. package/static/translations/it-IT.json +39 -74
  56. package/static/translations/ja-JP.json +39 -74
  57. package/static/translations/nl-NL.json +39 -74
  58. package/static/translations/no-NO.json +39 -74
  59. package/static/translations/pl-PL.json +39 -74
  60. package/static/translations/pt-BR.json +39 -74
  61. package/static/translations/pt-PT.json +39 -74
  62. package/static/translations/ro-RO.json +39 -74
  63. package/static/translations/ru-RU.json +39 -74
  64. package/static/translations/sv-SE.json +39 -74
  65. package/static/translations/tr-TR.json +39 -74
  66. package/static/translations/tsconfig.json +30 -67
  67. package/static/translations/uk-UA.json +39 -74
  68. package/utils/FeatureStyles.js +13 -18
  69. package/utils/IdentifyUtils.js +14 -11
  70. package/utils/SearchProviders.js +1 -1
@@ -99,7 +99,7 @@ var AttributeForm = /*#__PURE__*/function (_React$Component) {
99
99
  var deleteButtons = [{
100
100
  key: 'Delete',
101
101
  icon: 'trash',
102
- label: (_this$props$deleteLab = _this.props.deleteLabel) !== null && _this$props$deleteLab !== void 0 ? _this$props$deleteLab : LocaleUtils.tr("editing.delete")
102
+ label: (_this$props$deleteLab = _this.props.deleteLabel) !== null && _this$props$deleteLab !== void 0 ? _this$props$deleteLab : LocaleUtils.tr("common.delete")
103
103
  }];
104
104
  deleteBar = /*#__PURE__*/React.createElement(ButtonBar, {
105
105
  buttons: deleteButtons,
@@ -564,7 +564,7 @@ var AttributeForm = /*#__PURE__*/function (_React$Component) {
564
564
  var parts = name.split("__");
565
565
  var value = element.type === "radio" || element.type === "checkbox" ? element.checked : element.value;
566
566
  var nullElements = ["date", "number", "radio"];
567
- var nullFieldTypes = ["date", "number"];
567
+ var textDataTypes = ["character varying", "text"];
568
568
  if (parts.length >= 3) {
569
569
  var _relEditConfig$fields, _relEditConfig$fields2, _relEditConfig$fields3;
570
570
  // Relation value
@@ -577,17 +577,17 @@ var AttributeForm = /*#__PURE__*/function (_React$Component) {
577
577
  var nrelFieldConfig = (_relEditConfig$fields = (_relEditConfig$fields2 = relEditConfig.fields) === null || _relEditConfig$fields2 === void 0 || (_relEditConfig$fields3 = _relEditConfig$fields2.find) === null || _relEditConfig$fields3 === void 0 ? void 0 : _relEditConfig$fields3.call(_relEditConfig$fields2, function (f) {
578
578
  return f.id === field;
579
579
  })) !== null && _relEditConfig$fields !== void 0 ? _relEditConfig$fields : {};
580
- var nrelFieldDataType = nrelFieldConfig.type;
580
+ var nrelFieldDataType = nrelFieldConfig.data_type;
581
581
  if (nrelFieldConfig.expression) {
582
582
  // Skip virtual fields
583
583
  delete relationValues[datasetname].features[index][field];
584
584
  return;
585
585
  }
586
- if ((element instanceof RadioNodeList || nullElements.includes(element.type) || nullFieldTypes.includes(nrelFieldDataType)) && element.value === "") {
586
+ if ((element instanceof RadioNodeList || nullElements.includes(element.type) || !textDataTypes.includes(nrelFieldDataType)) && element.value === "") {
587
587
  // Set empty value to null instead of empty string
588
588
  value = null;
589
589
  }
590
- if (nrelFieldDataType === "text" && textNullValue !== undefined && element.value === textNullValue) {
590
+ if (textDataTypes.includes(nrelFieldDataType) && textNullValue !== undefined && element.value === textNullValue) {
591
591
  // Convert text NULL to null
592
592
  value = null;
593
593
  }
@@ -624,12 +624,12 @@ var AttributeForm = /*#__PURE__*/function (_React$Component) {
624
624
  delete feature.properties[name];
625
625
  return;
626
626
  }
627
- var dataType = fieldConfig.type;
628
- if ((element instanceof RadioNodeList || nullElements.includes(element.type) || nullFieldTypes.includes(dataType)) && element.value === "") {
627
+ var dataType = fieldConfig.data_type;
628
+ if ((element instanceof RadioNodeList || nullElements.includes(element.type) || !textDataTypes.includes(dataType)) && element.value === "") {
629
629
  // Set empty value to null instead of empty string
630
630
  value = null;
631
631
  }
632
- if (dataType === "text" && textNullValue !== undefined && element.value === textNullValue) {
632
+ if (textDataTypes.includes(dataType) && textNullValue !== undefined && element.value === textNullValue) {
633
633
  // Convert text NULL to null
634
634
  value = null;
635
635
  }
@@ -730,7 +730,7 @@ var AttributeTableWidget = /*#__PURE__*/function (_React$Component) {
730
730
  if (this.state.loading) {
731
731
  loadOverlay = /*#__PURE__*/React.createElement("div", {
732
732
  className: "attribtable-overlay"
733
- }, /*#__PURE__*/React.createElement(Spinner, null), /*#__PURE__*/React.createElement("span", null, LocaleUtils.tr("attribtable.loading")));
733
+ }, /*#__PURE__*/React.createElement(Spinner, null), /*#__PURE__*/React.createElement("span", null, LocaleUtils.tr("common.loading")));
734
734
  } else {
735
735
  loadOverlay = /*#__PURE__*/React.createElement("div", {
736
736
  className: "attribtable-overlay"
@@ -942,7 +942,7 @@ var AttributeTableWidget = /*#__PURE__*/function (_React$Component) {
942
942
  }, /*#__PURE__*/React.createElement("option", {
943
943
  disabled: true,
944
944
  value: ""
945
- }, LocaleUtils.tr("attribtable.selectlayer")), Object.entries(this.props.editConfigs).map(function (_ref4) {
945
+ }, LocaleUtils.tr("common.selectlayer")), Object.entries(this.props.editConfigs).map(function (_ref4) {
946
946
  var _ref5 = _slicedToArray(_ref4, 2),
947
947
  wmsName = _ref5[0],
948
948
  serviceConfigs = _ref5[1];
@@ -1009,7 +1009,7 @@ var AttributeTableWidget = /*#__PURE__*/function (_React$Component) {
1009
1009
  onClick: this.deleteSelectedFeatured
1010
1010
  }, /*#__PURE__*/React.createElement(Icon, {
1011
1011
  icon: "ok"
1012
- }), /*#__PURE__*/React.createElement("span", null, LocaleUtils.tr("attribtable.delete"))) : deleteButton, this.state.confirmDelete ? /*#__PURE__*/React.createElement("button", {
1012
+ }), /*#__PURE__*/React.createElement("span", null, LocaleUtils.tr("common.delete"))) : deleteButton, this.state.confirmDelete ? /*#__PURE__*/React.createElement("button", {
1013
1013
  className: "button button-reject",
1014
1014
  onClick: function onClick() {
1015
1015
  return _this2.setState({
@@ -103,7 +103,7 @@ var EditComboField = /*#__PURE__*/function (_React$Component) {
103
103
  }, _this.state.showPlaceholder ? /*#__PURE__*/React.createElement("option", {
104
104
  disabled: _this.props.required,
105
105
  value: ""
106
- }, (_this$props$placehold = _this.props.placeholder) !== null && _this$props$placehold !== void 0 ? _this$props$placehold : LocaleUtils.tr("editing.select")) : null, _this.state.values.map(function (item, index) {
106
+ }, (_this$props$placehold = _this.props.placeholder) !== null && _this$props$placehold !== void 0 ? _this$props$placehold : LocaleUtils.tr("common.select")) : null, _this.state.values.map(function (item, index) {
107
107
  var _this$itemValueLabel2 = _this.itemValueLabel(item),
108
108
  value = _this$itemValueLabel2.value,
109
109
  label = _this$itemValueLabel2.label;
@@ -224,7 +224,7 @@ var EditUploadField = /*#__PURE__*/function (_React$Component) {
224
224
  }, {
225
225
  key: 'Clear',
226
226
  icon: 'clear',
227
- tooltip: LocaleUtils.tr("editing.clearpicture"),
227
+ tooltip: LocaleUtils.tr("common.clear"),
228
228
  disabled: this.props.disabled
229
229
  }];
230
230
  return /*#__PURE__*/React.createElement("span", {
@@ -49,6 +49,7 @@ import { zoomToPoint } from '../actions/map';
49
49
  import { openExternalUrl } from '../actions/windows';
50
50
  import ConfigUtils from '../utils/ConfigUtils';
51
51
  import CoordinatesUtils from '../utils/CoordinatesUtils';
52
+ import { EXCLUDE_ATTRS, EXCLUDE_PROPS } from '../utils/IdentifyUtils';
52
53
  import LayerUtils from '../utils/LayerUtils';
53
54
  import LocaleUtils from '../utils/LocaleUtils';
54
55
  import MapUtils from '../utils/MapUtils';
@@ -59,8 +60,6 @@ import NavBar from './widgets/NavBar';
59
60
  import Spinner from './widgets/Spinner';
60
61
  import ToggleSwitch from './widgets/ToggleSwitch';
61
62
  import './style/IdentifyViewer.css';
62
- var EXCLUDE_PROPS = ['featurereport', 'displayfield', 'layername', 'layertitle', 'layerinfo', 'attribnames', 'clickPos', 'displayname', 'bbox'];
63
- var EXCLUDE_ATTRS = ['htmlContent', 'htmlContentInline'];
64
63
  var BuiltinExporters = [{
65
64
  id: 'json',
66
65
  title: 'json',
@@ -880,7 +879,7 @@ var IdentifyViewer = /*#__PURE__*/function (_React$Component) {
880
879
  multiViewEnabled: active
881
880
  });
882
881
  }
883
- }))) : null, exportEnabled ? /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, LocaleUtils.tr("identify.export"), ":"), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement("div", {
882
+ }))) : null, exportEnabled ? /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, LocaleUtils.tr("common.export"), ":"), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement("div", {
884
883
  className: "controlgroup"
885
884
  }, /*#__PURE__*/React.createElement("select", {
886
885
  className: "controlgroup-expanditem",
@@ -901,7 +900,7 @@ var IdentifyViewer = /*#__PURE__*/function (_React$Component) {
901
900
  onClick: function onClick() {
902
901
  return _this.exportResults();
903
902
  },
904
- title: LocaleUtils.tr("identify.download")
903
+ title: LocaleUtils.tr("common.download")
905
904
  }, /*#__PURE__*/React.createElement(Icon, {
906
905
  icon: "export"
907
906
  })), /*#__PURE__*/React.createElement("button", {
@@ -23,6 +23,7 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
23
23
  */
24
24
 
25
25
  import React from 'react';
26
+ import ReactDOM from 'react-dom';
26
27
  import { connect } from 'react-redux';
27
28
  import PropTypes from 'prop-types';
28
29
  import { setEditContext } from '../actions/editing';
@@ -31,6 +32,8 @@ import { getFeatureTemplate } from '../utils/EditingUtils';
31
32
  import LocaleUtils from '../utils/LocaleUtils';
32
33
  import MapUtils from '../utils/MapUtils';
33
34
  import AttributeForm from './AttributeForm';
35
+ import MeasureSwitcher from './MeasureSwitcher';
36
+ import { BottomToolPortalContext } from './PluginsContainer';
34
37
  import './style/LinkFeatureForm.css';
35
38
  var LinkFeatureForm = /*#__PURE__*/function (_React$Component) {
36
39
  function LinkFeatureForm() {
@@ -45,6 +48,12 @@ var LinkFeatureForm = /*#__PURE__*/function (_React$Component) {
45
48
  pickedFeatures: null,
46
49
  highlightedFeature: null
47
50
  });
51
+ _defineProperty(_this, "changeMeasurementState", function (diff) {
52
+ var editContext = _this.props.editing.contexts[_this.props.editContextId];
53
+ _this.props.setEditContext(_this.props.editContextId, {
54
+ measurements: _objectSpread(_objectSpread({}, editContext.measurements), diff)
55
+ });
56
+ });
48
57
  _defineProperty(_this, "childPickQuery", function (coordinate) {
49
58
  var scale = Math.round(MapUtils.computeForZoom(_this.props.map.scales, _this.props.map.zoom));
50
59
  _this.props.iface.getFeature(_this.props.editConfig, coordinate, _this.props.map.projection, scale, 96, function (featureCollection) {
@@ -200,11 +209,13 @@ var LinkFeatureForm = /*#__PURE__*/function (_React$Component) {
200
209
  className: "button",
201
210
  disabled: editContext.changed,
202
211
  onClick: this.finish
203
- }, LocaleUtils.tr("linkfeatureform.cancel"))));
212
+ }, LocaleUtils.tr("common.cancel"))));
204
213
  } else if (editContext.feature) {
214
+ var _editContext$feature;
205
215
  var drawing = editContext.action === 'Draw' && !editContext.feature.geometry && this.props.editConfig.geomType;
206
- return /*#__PURE__*/React.createElement("div", {
207
- className: "link-feature-form"
216
+ return [/*#__PURE__*/React.createElement("div", {
217
+ className: "link-feature-form",
218
+ key: "LinkFeatureForm"
208
219
  }, drawing ? /*#__PURE__*/React.createElement("div", {
209
220
  className: "link-feature-form-hint"
210
221
  }, /*#__PURE__*/React.createElement("span", null, LocaleUtils.tr("linkfeatureform.drawhint"))) : /*#__PURE__*/React.createElement(AttributeForm, {
@@ -220,13 +231,19 @@ var LinkFeatureForm = /*#__PURE__*/function (_React$Component) {
220
231
  className: "button",
221
232
  disabled: editContext.changed,
222
233
  onClick: this.finish
223
- }, drawing ? LocaleUtils.tr("linkfeatureform.cancel") : LocaleUtils.tr("linkfeatureform.close"))));
234
+ }, drawing ? LocaleUtils.tr("common.cancel") : LocaleUtils.tr("common.close")))), drawing || (_editContext$feature = editContext.feature) !== null && _editContext$feature !== void 0 && _editContext$feature.geometry ? /*#__PURE__*/ReactDOM.createPortal(/*#__PURE__*/React.createElement(MeasureSwitcher, {
235
+ changeMeasureState: this.changeMeasurementState,
236
+ geomType: editContext.geomType,
237
+ iconSize: "large",
238
+ measureState: editContext.measurements
239
+ }), this.context) : null];
224
240
  } else {
225
241
  return null;
226
242
  }
227
243
  }
228
244
  }]);
229
245
  }(React.Component);
246
+ _defineProperty(LinkFeatureForm, "contextType", BottomToolPortalContext);
230
247
  _defineProperty(LinkFeatureForm, "propTypes", {
231
248
  action: PropTypes.string,
232
249
  addLayerFeatures: PropTypes.func,
@@ -0,0 +1,115 @@
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 _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
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); } }
4
+ function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
5
+ function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
6
+ function _possibleConstructorReturn(t, e) { if (e && ("object" == _typeof(e) || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); }
7
+ function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; }
8
+ function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
9
+ function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }
10
+ function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); }
11
+ function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }
12
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
13
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
14
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
15
+ /**
16
+ * Copyright 2025 Sourcepole AG
17
+ * All rights reserved.
18
+ *
19
+ * This source code is licensed under the BSD-style license found in the
20
+ * LICENSE file in the root directory of this source tree.
21
+ */
22
+
23
+ import React from "react";
24
+ import PropTypes from "prop-types";
25
+ import LocaleUtils from "../utils/LocaleUtils";
26
+ import Icon from "./Icon";
27
+ var MeasureSwitcher = /*#__PURE__*/function (_React$PureComponent) {
28
+ function MeasureSwitcher() {
29
+ _classCallCheck(this, MeasureSwitcher);
30
+ return _callSuper(this, MeasureSwitcher, arguments);
31
+ }
32
+ _inherits(MeasureSwitcher, _React$PureComponent);
33
+ return _createClass(MeasureSwitcher, [{
34
+ key: "render",
35
+ value: function render() {
36
+ var _this$props$className,
37
+ _this = this;
38
+ var style = {
39
+ width: 'fit-content'
40
+ };
41
+ return /*#__PURE__*/React.createElement("div", {
42
+ className: "controlgroup " + ((_this$props$className = this.props.className) !== null && _this$props$className !== void 0 ? _this$props$className : "")
43
+ }, /*#__PURE__*/React.createElement("button", {
44
+ className: "button" + (this.props.measureState.showmeasurements ? " pressed" : ""),
45
+ onClick: function onClick() {
46
+ return _this.props.changeMeasureState({
47
+ showmeasurements: !_this.props.measureState.showmeasurements
48
+ });
49
+ },
50
+ title: LocaleUtils.tr("measureComponent.showmeasurements")
51
+ }, /*#__PURE__*/React.createElement(Icon, {
52
+ icon: "measure",
53
+ size: this.props.iconSize
54
+ })), this.props.measureState.showmeasurements && ['LineString', 'Circle'].includes(this.props.geomType) ? /*#__PURE__*/React.createElement("select", {
55
+ className: "controlgroup-fillitem",
56
+ onChange: function onChange(ev) {
57
+ return _this.props.changeMeasureState({
58
+ lenUnit: ev.target.value
59
+ });
60
+ },
61
+ style: style,
62
+ value: this.props.measureState.lenUnit
63
+ }, /*#__PURE__*/React.createElement("option", {
64
+ value: "metric"
65
+ }, LocaleUtils.tr("measureComponent.metric")), /*#__PURE__*/React.createElement("option", {
66
+ value: "imperial"
67
+ }, LocaleUtils.tr("measureComponent.imperial")), /*#__PURE__*/React.createElement("option", {
68
+ value: "m"
69
+ }, "m"), /*#__PURE__*/React.createElement("option", {
70
+ value: "km"
71
+ }, "km"), /*#__PURE__*/React.createElement("option", {
72
+ value: "ft"
73
+ }, "ft"), /*#__PURE__*/React.createElement("option", {
74
+ value: "mi"
75
+ }, "mi")) : null, this.props.measureState.showmeasurements && ['Polygon', 'Ellipse', 'Square', 'Box'].includes(this.props.geomType) ? /*#__PURE__*/React.createElement("select", {
76
+ className: "controlgroup-fillitem",
77
+ onChange: function onChange(ev) {
78
+ return _this.props.changeMeasureState({
79
+ areaUnit: ev.target.value
80
+ });
81
+ },
82
+ style: style,
83
+ value: this.props.measureState.areaUnit
84
+ }, /*#__PURE__*/React.createElement("option", {
85
+ value: "metric"
86
+ }, LocaleUtils.tr("measureComponent.metric")), /*#__PURE__*/React.createElement("option", {
87
+ value: "imperial"
88
+ }, LocaleUtils.tr("measureComponent.imperial")), /*#__PURE__*/React.createElement("option", {
89
+ value: "sqm"
90
+ }, "m\xB2"), /*#__PURE__*/React.createElement("option", {
91
+ value: "ha"
92
+ }, "ha"), /*#__PURE__*/React.createElement("option", {
93
+ value: "sqkm"
94
+ }, "km\xB2"), /*#__PURE__*/React.createElement("option", {
95
+ value: "sqft"
96
+ }, "ft\xB2"), /*#__PURE__*/React.createElement("option", {
97
+ value: "acre"
98
+ }, "acre"), /*#__PURE__*/React.createElement("option", {
99
+ value: "sqmi"
100
+ }, "mi\xB2")) : null);
101
+ }
102
+ }]);
103
+ }(React.PureComponent);
104
+ _defineProperty(MeasureSwitcher, "propTypes", {
105
+ changeMeasureState: PropTypes.func,
106
+ className: PropTypes.string,
107
+ geomType: PropTypes.string,
108
+ iconSize: PropTypes.string,
109
+ measureState: PropTypes.shape({
110
+ showmeasurements: PropTypes.bool,
111
+ lenUnit: PropTypes.string,
112
+ areaUnit: PropTypes.string
113
+ })
114
+ });
115
+ export { MeasureSwitcher as default };
@@ -268,9 +268,10 @@ var PluginsContainer = /*#__PURE__*/function (_React$Component) {
268
268
  style: mapContainerStyle
269
269
  }), /*#__PURE__*/React.createElement("div", {
270
270
  className: "map-bottom-tool-container",
271
- ref: this.setBottomToolContanerRef,
272
271
  style: mapContainerStyle
273
- }));
272
+ }, /*#__PURE__*/React.createElement("div", {
273
+ ref: this.setBottomToolContanerRef
274
+ })));
274
275
  }
275
276
  }]);
276
277
  }(React.Component);
@@ -652,7 +652,7 @@ var QtDesignerForm = /*#__PURE__*/function (_React$Component) {
652
652
  _featurebuttons.push({
653
653
  key: 'Pick',
654
654
  icon: 'pick',
655
- label: LocaleUtils.tr("editing.pick")
655
+ label: LocaleUtils.tr("common.pick")
656
656
  });
657
657
  }
658
658
  _featurebuttons.push({
@@ -697,7 +697,7 @@ var QtDesignerForm = /*#__PURE__*/function (_React$Component) {
697
697
  var _featurebuttons3 = [{
698
698
  key: 'Pick',
699
699
  icon: 'pick',
700
- label: LocaleUtils.tr("editing.pick")
700
+ label: LocaleUtils.tr("common.pick")
701
701
  }, {
702
702
  key: 'Create',
703
703
  icon: 'editdraw',
@@ -137,7 +137,7 @@ var ResizeableWindow = /*#__PURE__*/function (_React$Component) {
137
137
  className: iconClasses,
138
138
  icon: "remove",
139
139
  onClick: _this.onClose,
140
- title: LocaleUtils.tr("window.close")
140
+ title: LocaleUtils.tr("common.close")
141
141
  }) : null);
142
142
  });
143
143
  _defineProperty(_this, "renderInternalWindowContainer", function () {
@@ -128,7 +128,7 @@ var SearchBox = /*#__PURE__*/function (_React$Component) {
128
128
  value: _this.state.selectedProvider
129
129
  }, /*#__PURE__*/React.createElement("div", {
130
130
  value: ""
131
- }, LocaleUtils.tr("search.all")), Object.entries(_this.props.searchProviders).map(function (_ref) {
131
+ }, LocaleUtils.tr("common.all")), Object.entries(_this.props.searchProviders).map(function (_ref) {
132
132
  var _prov$params, _prov$label;
133
133
  var _ref2 = _slicedToArray(_ref, 2),
134
134
  key = _ref2[0],
@@ -162,14 +162,14 @@ var SearchBox = /*#__PURE__*/function (_React$Component) {
162
162
  }
163
163
  var filterButtons = [{
164
164
  key: "Polygon",
165
- tooltip: LocaleUtils.tr("redlining.polygon"),
165
+ tooltip: LocaleUtils.tr("common.polygon"),
166
166
  icon: "polygon",
167
- label: LocaleUtils.tr("redlining.polygon")
167
+ label: LocaleUtils.tr("common.polygon")
168
168
  }, {
169
169
  key: "Circle",
170
- tooltip: LocaleUtils.tr("redlining.circle"),
170
+ tooltip: LocaleUtils.tr("common.circle"),
171
171
  icon: "circle",
172
- label: LocaleUtils.tr("redlining.circle")
172
+ label: LocaleUtils.tr("common.circle")
173
173
  }];
174
174
  return /*#__PURE__*/React.createElement("div", {
175
175
  className: "searchbox-filter-options"
@@ -182,7 +182,7 @@ var SearchBox = /*#__PURE__*/function (_React$Component) {
182
182
  }), searchRegionSelection, /*#__PURE__*/React.createElement("button", {
183
183
  className: "button",
184
184
  onClick: _this.clearFilter,
185
- title: LocaleUtils.tr("search.clearfilter")
185
+ title: LocaleUtils.tr("common.clear")
186
186
  }, /*#__PURE__*/React.createElement(Icon, {
187
187
  icon: "clear"
188
188
  }))))), _this.state.filterGeomType === 'Circle' ? /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, LocaleUtils.tr("search.circleradius"), ":"), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(NumberInput, {
@@ -253,7 +253,7 @@ var SearchBox = /*#__PURE__*/function (_React$Component) {
253
253
  className: "searchbox-noresults",
254
254
  disabled: true,
255
255
  key: "noresults"
256
- }, LocaleUtils.tr("search.noresults"));
256
+ }, LocaleUtils.tr("common.noresults"));
257
257
  } else {
258
258
  return null;
259
259
  }
@@ -498,7 +498,7 @@ var EditTool3D = /*#__PURE__*/function (_React$Component) {
498
498
  }];
499
499
  var extraButtons = [{
500
500
  key: "clone",
501
- tooltip: LocaleUtils.tr("draw3d.clone"),
501
+ tooltip: LocaleUtils.tr("common.clone"),
502
502
  icon: "clone"
503
503
  }, {
504
504
  key: "NumericInput",
@@ -194,7 +194,7 @@ span.identify-toolbar-spacer {
194
194
 
195
195
  div.identify-settings-menu {
196
196
  position: absolute;
197
- bottom: 100%;
197
+ bottom: calc(100% - 0.25em);
198
198
  left: 0;
199
199
  border: 1px solid var(--border-color);
200
200
  background-color: var(--container-bg-color);
@@ -1,10 +1,5 @@
1
1
  div.LocationRecorder {
2
- display: inline-flex;
2
+ display: flex;
3
3
  align-items: center;
4
- padding: 0.25em 0.5em;
5
- background-color: var(--container-bg-color);
6
- box-shadow: 0px -2px 4px rgba(136, 136, 136, 0.5);
7
- border-bottom: 1px solid rgba(136, 136, 136, 0.5);
8
4
  column-gap: 0.25em;
9
- order: 1;
10
5
  }
@@ -30,15 +30,20 @@ div.map-bottom-tool-container {
30
30
  position: absolute;
31
31
  pointer-events: none;
32
32
  display: flex;
33
- flex-direction: column-reverse;
34
- align-items: center;
35
- align-content: flex-start;
36
- justify-content: flex-start;
37
- margin-bottom: -1px;
33
+ justify-content: center;
34
+ align-items: flex-end;
38
35
  }
39
36
 
40
- div.map-bottom-tool-container > * {
37
+ div.map-bottom-tool-container > div {
38
+ display: flex;
39
+ flex-wrap: wrap;
40
+ justify-content: center;
41
+ margin-bottom: -1px;
41
42
  pointer-events: initial;
43
+ padding: 0.25em 0.5em;
44
+ gap: 1em;
45
+ background-color: var(--container-bg-color);
46
+ box-shadow: 0px -2px 4px rgba(136, 136, 136, 0.5);
42
47
  }
43
48
 
44
49
  div.app-info {
@@ -158,11 +158,11 @@ var FixedTimeline = /*#__PURE__*/function (_React$Component) {
158
158
  icon: "home"
159
159
  }, {
160
160
  key: "zoomout",
161
- tooltip: LocaleUtils.tr("timemanager.zoomout"),
161
+ tooltip: LocaleUtils.tr("common.zoomout"),
162
162
  icon: "zoomout"
163
163
  }, {
164
164
  key: "zoomin",
165
- tooltip: LocaleUtils.tr("timemanager.zoomin"),
165
+ tooltip: LocaleUtils.tr("common.zoomin"),
166
166
  icon: "zoomin"
167
167
  }];
168
168
  return /*#__PURE__*/React.createElement("div", {
@@ -257,11 +257,11 @@ var InfiniteTimeline = /*#__PURE__*/function (_React$Component) {
257
257
  icon: "home"
258
258
  }, {
259
259
  key: "zoomout",
260
- tooltip: LocaleUtils.tr("timemanager.zoomout"),
260
+ tooltip: LocaleUtils.tr("common.zoomout"),
261
261
  icon: "zoomout"
262
262
  }, {
263
263
  key: "zoomin",
264
- tooltip: LocaleUtils.tr("timemanager.zoomin"),
264
+ tooltip: LocaleUtils.tr("common.zoomin"),
265
265
  icon: "zoomin"
266
266
  }];
267
267
  return /*#__PURE__*/React.createElement("div", {
@@ -414,7 +414,7 @@ var TimelineFeaturesSlider = /*#__PURE__*/function (_React$Component) {
414
414
  onPointerDown: this.pickCurrentTimestamp
415
415
  }, this.props.displayMode === "features" ? this.renderTimeFeatures(sliderGeom) : null, this.props.displayMode === "layers" ? this.renderTimeLayers(sliderGeom) : null, this.renderGradient(sliderGeom)), this.renderCursor(timestamp), this.props.timeFeatures.pendingRequests > 0 ? /*#__PURE__*/React.createElement("div", {
416
416
  className: "timeline-slider-loading"
417
- }, /*#__PURE__*/React.createElement(Spinner, null), /*#__PURE__*/React.createElement("span", null, LocaleUtils.tr("timemanager.loading"))) : null);
417
+ }, /*#__PURE__*/React.createElement(Spinner, null), /*#__PURE__*/React.createElement("span", null, LocaleUtils.tr("common.loading"))) : null);
418
418
  }
419
419
  }]);
420
420
  }(React.Component);
@@ -247,7 +247,7 @@ var LayerCatalogWidget = /*#__PURE__*/function (_React$PureComponent) {
247
247
  } else if (isEmpty(this.state.catalog)) {
248
248
  emptyEntry = /*#__PURE__*/React.createElement("div", {
249
249
  className: "layer-catalog-placeholder"
250
- }, LocaleUtils.tr("importlayer.loading"));
250
+ }, LocaleUtils.tr("common.loading"));
251
251
  }
252
252
  var filterplaceholder = LocaleUtils.tr("importlayer.filter");
253
253
  var catalog = (_this$state$filteredC = this.state.filteredCatalog) !== null && _this$state$filteredC !== void 0 ? _this$state$filteredC : this.state.catalog;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qwc2",
3
- "version": "2025.12.17",
3
+ "version": "2025.12.18",
4
4
  "description": "QGIS Web Client",
5
5
  "author": "Sourcepole AG",
6
6
  "license": "BSD-2-Clause",
@@ -33,6 +33,7 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
33
33
  */
34
34
 
35
35
  import React from 'react';
36
+ import ReactDOM from 'react-dom';
36
37
  import { connect } from 'react-redux';
37
38
  import { parseNumber } from '@norbulcz/num-parse';
38
39
  import dateParser from 'any-date-parser';
@@ -46,7 +47,9 @@ import { setSnappingConfig } from '../actions/map';
46
47
  import { setCurrentTask, setCurrentTaskBlocked } from '../actions/task';
47
48
  import AttributeForm from '../components/AttributeForm';
48
49
  import Icon from '../components/Icon';
50
+ import MeasureSwitcher from '../components/MeasureSwitcher';
49
51
  import PickFeature from '../components/PickFeature';
52
+ import { BottomToolPortalContext } from '../components/PluginsContainer';
50
53
  import SideBar from '../components/SideBar';
51
54
  import ButtonBar from '../components/widgets/ButtonBar';
52
55
  import ConfigUtils from '../utils/ConfigUtils';
@@ -173,7 +176,7 @@ var Editing = /*#__PURE__*/function (_React$Component) {
173
176
  actionButtons.push({
174
177
  key: 'Pick',
175
178
  icon: 'pick',
176
- label: LocaleUtils.tr("editing.pick"),
179
+ label: LocaleUtils.tr("common.pick"),
177
180
  data: {
178
181
  action: 'Pick',
179
182
  feature: null
@@ -258,7 +261,7 @@ var Editing = /*#__PURE__*/function (_React$Component) {
258
261
  }, /*#__PURE__*/React.createElement("option", {
259
262
  disabled: true,
260
263
  value: ""
261
- }, LocaleUtils.tr("editing.selectlayer")), Object.entries(_this.props.editConfigs).map(function (_ref) {
264
+ }, LocaleUtils.tr("common.selectlayer")), Object.entries(_this.props.editConfigs).map(function (_ref) {
262
265
  var _ref2 = _slicedToArray(_ref, 2),
263
266
  mapName = _ref2[0],
264
267
  serviceConfigs = _ref2[1];
@@ -285,6 +288,11 @@ var Editing = /*#__PURE__*/function (_React$Component) {
285
288
  onClick: _this.actionClicked
286
289
  }), featureSelection, pickBar, attributeForm);
287
290
  });
291
+ _defineProperty(_this, "changeMeasurementState", function (diff) {
292
+ _this.props.setEditContext('Editing', {
293
+ measurements: _objectSpread(_objectSpread({}, _this.props.editContext.measurements), diff)
294
+ });
295
+ });
288
296
  _defineProperty(_this, "actionClicked", function (action, data) {
289
297
  _this.setState({
290
298
  drawPick: false,
@@ -635,8 +643,9 @@ var Editing = /*#__PURE__*/function (_React$Component) {
635
643
  }, {
636
644
  key: "render",
637
645
  value: function render() {
638
- var _this3 = this;
639
- var minMaxTooltip = this.state.minimized ? LocaleUtils.tr("editing.maximize") : LocaleUtils.tr("editing.minimize");
646
+ var _this3 = this,
647
+ _this$props$editConte3;
648
+ var minMaxTooltip = this.state.minimized ? LocaleUtils.tr("window.maximize") : LocaleUtils.tr("window.minimize");
640
649
  var extraTitlebarContent = /*#__PURE__*/React.createElement(Icon, {
641
650
  className: "editing-minimize-maximize",
642
651
  icon: this.state.minimized ? 'chevron-down' : 'chevron-up',
@@ -669,10 +678,16 @@ var Editing = /*#__PURE__*/function (_React$Component) {
669
678
  featureFilter: this.pickFilter,
670
679
  featurePicked: this.geomPicked,
671
680
  key: "FeaturePicker"
672
- }) : null];
681
+ }) : null, this.props.editContext.action === "Draw" || (_this$props$editConte3 = this.props.editContext.feature) !== null && _this$props$editConte3 !== void 0 && _this$props$editConte3.geometry ? /*#__PURE__*/ReactDOM.createPortal(/*#__PURE__*/React.createElement(MeasureSwitcher, {
682
+ changeMeasureState: this.changeMeasurementState,
683
+ geomType: this.props.editContext.geomType,
684
+ iconSize: "large",
685
+ measureState: this.props.editContext.measurements
686
+ }), this.context) : null];
673
687
  }
674
688
  }]);
675
689
  }(React.Component);
690
+ _defineProperty(Editing, "contextType", BottomToolPortalContext);
676
691
  _defineProperty(Editing, "propTypes", {
677
692
  addLayerFeatures: PropTypes.func,
678
693
  /** Whether to enable the "Clone existing geometry" functionality. */
@@ -233,7 +233,7 @@ var FeatureForm = /*#__PURE__*/function (_React$Component) {
233
233
  className: "feature-query-body"
234
234
  }, /*#__PURE__*/React.createElement("span", {
235
235
  className: "identify-body-message"
236
- }, LocaleUtils.tr("featureform.noresults")));
236
+ }, LocaleUtils.tr("common.noresults")));
237
237
  } else {
238
238
  var featureText = LocaleUtils.tr("featureform.feature");
239
239
  var attributeForm = null;