qwc2 2025.12.15 → 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 (87) 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 +91 -38
  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 +9 -1
  11. package/components/SearchBox.js +19 -12
  12. package/components/SideBar.js +4 -0
  13. package/components/map3d/drawtool/EditTool3D.js +1 -1
  14. package/components/style/IdentifyViewer.css +8 -6
  15. package/components/style/LocationRecorder.css +1 -6
  16. package/components/style/PluginsContainer.css +11 -6
  17. package/components/timeline/FixedTimeline.js +2 -2
  18. package/components/timeline/InfiniteTimeline.js +2 -2
  19. package/components/timeline/TimelineFeaturesSlider.js +1 -1
  20. package/components/widgets/EditableSelect.js +2 -1
  21. package/components/widgets/LayerCatalogWidget.js +26 -15
  22. package/components/widgets/MenuButton.js +7 -2
  23. package/components/widgets/NavBar.js +4 -2
  24. package/components/widgets/PopupMenu.js +44 -13
  25. package/components/widgets/SearchWidget.js +39 -50
  26. package/components/widgets/style/SearchWidget.css +3 -19
  27. package/package.json +1 -1
  28. package/plugins/Editing.js +20 -5
  29. package/plugins/FeatureForm.js +1 -1
  30. package/plugins/FeatureSearch.js +3 -3
  31. package/plugins/GeometryDigitizer.js +32 -18
  32. package/plugins/HeightProfile.js +4 -1
  33. package/plugins/Identify.js +5 -4
  34. package/plugins/LayerTree.js +5 -1
  35. package/plugins/MapExport.js +4 -4
  36. package/plugins/MapFilter.js +10 -10
  37. package/plugins/Measure.js +5 -1
  38. package/plugins/NewsPopup.js +1 -1
  39. package/plugins/ObliqueView.js +88 -17
  40. package/plugins/Print.js +8 -8
  41. package/plugins/Redlining.js +25 -73
  42. package/plugins/Reports.js +3 -3
  43. package/plugins/Routing.js +4 -4
  44. package/plugins/TopBar.js +2 -0
  45. package/plugins/ValueTool.js +1 -1
  46. package/plugins/View3D.js +2 -2
  47. package/plugins/ZoomButtons.js +1 -1
  48. package/plugins/map/EditingSupport.js +50 -20
  49. package/plugins/map/MeasurementSupport.js +1 -0
  50. package/plugins/map/RedliningSupport.js +9 -7
  51. package/plugins/map/SnapSupport.js +12 -10
  52. package/plugins/map/style/SnappingSupport.css +1 -8
  53. package/plugins/map3d/Draw3D.js +2 -2
  54. package/plugins/map3d/ExportObjects3D.js +2 -2
  55. package/plugins/map3d/MapExport3D.js +4 -4
  56. package/reducers/editing.js +6 -1
  57. package/reducers/layers.js +18 -36
  58. package/reducers/measurement.js +2 -1
  59. package/scripts/wmts_config_generator.py +1 -1
  60. package/static/translations/bg-BG.json +45 -75
  61. package/static/translations/ca-ES.json +45 -75
  62. package/static/translations/cs-CZ.json +45 -75
  63. package/static/translations/de-CH.json +45 -75
  64. package/static/translations/de-DE.json +45 -75
  65. package/static/translations/en-US.json +45 -75
  66. package/static/translations/es-ES.json +45 -75
  67. package/static/translations/fi-FI.json +45 -75
  68. package/static/translations/fr-FR.json +46 -76
  69. package/static/translations/hu-HU.json +45 -75
  70. package/static/translations/it-IT.json +45 -75
  71. package/static/translations/ja-JP.json +45 -75
  72. package/static/translations/nl-NL.json +45 -75
  73. package/static/translations/no-NO.json +45 -75
  74. package/static/translations/pl-PL.json +45 -75
  75. package/static/translations/pt-BR.json +45 -75
  76. package/static/translations/pt-PT.json +45 -75
  77. package/static/translations/ro-RO.json +45 -75
  78. package/static/translations/ru-RU.json +45 -75
  79. package/static/translations/sv-SE.json +45 -75
  80. package/static/translations/tr-TR.json +45 -75
  81. package/static/translations/tsconfig.json +35 -67
  82. package/static/translations/uk-UA.json +45 -75
  83. package/utils/FeatureStyles.js +18 -20
  84. package/utils/IdentifyUtils.js +14 -11
  85. package/utils/MiscUtils.js +2 -1
  86. package/utils/SearchProviders.js +1 -1
  87. package/utils/VectorLayerUtils.js +4 -2
@@ -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';
@@ -57,9 +58,8 @@ import VectorLayerUtils from '../utils/VectorLayerUtils';
57
58
  import Icon from './Icon';
58
59
  import NavBar from './widgets/NavBar';
59
60
  import Spinner from './widgets/Spinner';
61
+ import ToggleSwitch from './widgets/ToggleSwitch';
60
62
  import './style/IdentifyViewer.css';
61
- var EXCLUDE_PROPS = ['featurereport', 'displayfield', 'layername', 'layertitle', 'layerinfo', 'attribnames', 'clickPos', 'displayname', 'bbox'];
62
- var EXCLUDE_ATTRS = ['htmlContent', 'htmlContentInline'];
63
63
  var BuiltinExporters = [{
64
64
  id: 'json',
65
65
  title: 'json',
@@ -334,7 +334,9 @@ var IdentifyViewer = /*#__PURE__*/function (_React$Component) {
334
334
  generatingReport: false,
335
335
  selectedLayer: '',
336
336
  compareEnabled: false,
337
- currentPage: 0
337
+ multiViewEnabled: false,
338
+ currentPage: 0,
339
+ pageSize: 1
338
340
  });
339
341
  _defineProperty(_this, "getCurrentResultFeature", function () {
340
342
  var _this$state$resultTre, _this$state$resultTre2, _this$state$resultTre3, _this$state$currentRe;
@@ -720,7 +722,13 @@ var IdentifyViewer = /*#__PURE__*/function (_React$Component) {
720
722
  var selected = _this.state.selectedResults.has(key);
721
723
  return /*#__PURE__*/React.createElement("div", {
722
724
  className: resultClass,
723
- key: key
725
+ key: key,
726
+ onMouseEnter: function onMouseEnter() {
727
+ return _this.setHighlightedFeatures([feature]);
728
+ },
729
+ onMouseLeave: function onMouseLeave() {
730
+ return _this.setHighlightedFeatures(null);
731
+ }
724
732
  }, /*#__PURE__*/React.createElement("div", {
725
733
  className: "identify-result-title"
726
734
  }, _this.props.collapsible ? /*#__PURE__*/React.createElement(Icon, {
@@ -737,7 +745,8 @@ var IdentifyViewer = /*#__PURE__*/function (_React$Component) {
737
745
  icon: selected ? "checked" : "unchecked",
738
746
  onClick: function onClick() {
739
747
  return _this.toggleSelectedResult(key);
740
- }
748
+ },
749
+ title: LocaleUtils.tr("identify.selectforcompare")
741
750
  }) : null, /*#__PURE__*/React.createElement("span", null, (_this.props.showLayerTitles ? feature.layertitle + ": " : "") + feature.displayname), zoomToFeatureButton, /*#__PURE__*/React.createElement(Icon, {
742
751
  icon: "info-sign",
743
752
  onClick: function onClick() {
@@ -761,6 +770,34 @@ var IdentifyViewer = /*#__PURE__*/function (_React$Component) {
761
770
  };
762
771
  });
763
772
  });
773
+ _defineProperty(_this, "initBody", function (el) {
774
+ if (el) {
775
+ // HACK to trigger an additional repaint, since Safari/Chrome on iOS render the element cut off the first time
776
+ el.style.background = 'inherit';
777
+ var resizeObserver = new ResizeObserver(function (entries) {
778
+ var contentRectEntry = entries.find(function (entry) {
779
+ return entry.contentRect;
780
+ });
781
+ if (contentRectEntry) {
782
+ _this.computePageSize(contentRectEntry.contentRect);
783
+ }
784
+ });
785
+ resizeObserver.observe(el);
786
+ _this.bodyEl = el;
787
+ }
788
+ });
789
+ _defineProperty(_this, "computePageSize", function (rect) {
790
+ var s = 2 * _this.props.resultGridSize;
791
+ if (_this.state.multiViewEnabled && (rect.height >= s || rect.width >= s)) {
792
+ _this.setState({
793
+ pageSize: rect.height >= s && rect.width >= s ? 4 : 2
794
+ });
795
+ } else {
796
+ _this.setState({
797
+ pageSize: 1
798
+ });
799
+ }
800
+ });
764
801
  _defineProperty(_this, "renderToolbar", function (results) {
765
802
  var resultCount = results.length;
766
803
  var toggleButton = function toggleButton(key, icon, disabled) {
@@ -781,12 +818,12 @@ var IdentifyViewer = /*#__PURE__*/function (_React$Component) {
781
818
  var infoLabel = null;
782
819
  if (_this.state.compareEnabled) {
783
820
  infoLabel = /*#__PURE__*/React.createElement("span", null, LocaleUtils.tr("identify.comparing", _this.state.selectedResults.size()));
784
- } else if (_this.props.resultDisplayMode !== 'paginated') {
821
+ } else {
785
822
  infoLabel = /*#__PURE__*/React.createElement("span", null, LocaleUtils.tr("identify.featurecount", resultCount));
786
823
  }
787
824
  var checkedPages = results.reduce(function (res, entry, idx) {
788
825
  if (_this.state.selectedResults.has(entry[0] + "$" + entry[1].id)) {
789
- return [].concat(_toConsumableArray(res), [idx]);
826
+ return [].concat(_toConsumableArray(res), [Math.floor(idx / _this.state.pageSize)]);
790
827
  }
791
828
  return res;
792
829
  }, []);
@@ -796,9 +833,9 @@ var IdentifyViewer = /*#__PURE__*/function (_React$Component) {
796
833
  className: "identify-toolbar-spacer"
797
834
  }), infoLabel, /*#__PURE__*/React.createElement("span", {
798
835
  className: "identify-toolbar-spacer"
799
- }), _this.props.resultDisplayMode === 'paginated' ? /*#__PURE__*/React.createElement(NavBar, {
836
+ }), _this.props.resultDisplayMode === 'paginated' && !_this.state.compareEnabled ? /*#__PURE__*/React.createElement(NavBar, {
800
837
  currentPage: _this.state.currentPage,
801
- nPages: resultCount,
838
+ nPages: Math.ceil(resultCount / _this.state.pageSize),
802
839
  pageChanged: function pageChanged(page) {
803
840
  return _this.setState({
804
841
  currentPage: page
@@ -835,7 +872,14 @@ var IdentifyViewer = /*#__PURE__*/function (_React$Component) {
835
872
  key: layer,
836
873
  value: layer
837
874
  }, _this.state.resultTree[layer][0].layertitle);
838
- }))))), exportEnabled ? /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, LocaleUtils.tr("identify.export"), ":"), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement("div", {
875
+ }))))), _this.props.resultDisplayMode === 'paginated' ? /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, LocaleUtils.tr("identify.multiview")), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(ToggleSwitch, {
876
+ active: _this.state.multiViewEnabled,
877
+ onChange: function onChange(active) {
878
+ return _this.setState({
879
+ multiViewEnabled: active
880
+ });
881
+ }
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", {
839
883
  className: "controlgroup"
840
884
  }, /*#__PURE__*/React.createElement("select", {
841
885
  className: "controlgroup-expanditem",
@@ -856,7 +900,7 @@ var IdentifyViewer = /*#__PURE__*/function (_React$Component) {
856
900
  onClick: function onClick() {
857
901
  return _this.exportResults();
858
902
  },
859
- title: LocaleUtils.tr("identify.download")
903
+ title: LocaleUtils.tr("common.download")
860
904
  }, /*#__PURE__*/React.createElement(Icon, {
861
905
  icon: "export"
862
906
  })), /*#__PURE__*/React.createElement("button", {
@@ -1128,6 +1172,7 @@ var IdentifyViewer = /*#__PURE__*/function (_React$Component) {
1128
1172
  _this.resultsTreeRef = null;
1129
1173
  _this.currentResultElRef = null;
1130
1174
  _this.scrollIntoView = false;
1175
+ _this.bodyEl = null;
1131
1176
  _this.state.exportFormat = !Array.isArray(props.enableExport) ? 'geojson' : props.enableExport[0];
1132
1177
  return _this;
1133
1178
  }
@@ -1161,6 +1206,9 @@ var IdentifyViewer = /*#__PURE__*/function (_React$Component) {
1161
1206
  };
1162
1207
  });
1163
1208
  }
1209
+ if (this.state.multiViewEnabled !== prevState.multiViewEnabled) {
1210
+ this.computePageSize(this.bodyEl.getBoundingClientRect());
1211
+ }
1164
1212
  }
1165
1213
  }, {
1166
1214
  key: "componentWillUnmount",
@@ -1182,8 +1230,12 @@ var IdentifyViewer = /*#__PURE__*/function (_React$Component) {
1182
1230
  });
1183
1231
  }).flat();
1184
1232
  if (this.state.compareEnabled) {
1233
+ var style = {
1234
+ gridTemplateColumns: "repeat(auto-fit, minmax(".concat(this.resultGridSize / 2 - 2, "px, 1fr))")
1235
+ };
1185
1236
  body = /*#__PURE__*/React.createElement("div", {
1186
- className: "identify-compare-results"
1237
+ className: "identify-compare-results",
1238
+ style: style
1187
1239
  }, this.state.selectedResults.entries().map(function (key) {
1188
1240
  var _key$split3 = key.split("$"),
1189
1241
  _key$split4 = _slicedToArray(_key$split3, 2),
@@ -1205,37 +1257,36 @@ var IdentifyViewer = /*#__PURE__*/function (_React$Component) {
1205
1257
  layerid = _ref26[0],
1206
1258
  features = _ref26[1];
1207
1259
  return features.map(function (feature) {
1208
- return /*#__PURE__*/React.createElement("div", {
1209
- key: layerid + "$" + feature.id,
1210
- onMouseEnter: function onMouseEnter() {
1211
- return _this2.setHighlightedFeatures([feature]);
1212
- },
1213
- onMouseLeave: function onMouseLeave() {
1214
- return _this2.setHighlightedFeatures(null);
1215
- }
1216
- }, _this2.renderResultAttributes(layerid, feature, 'identify-result-frame'));
1260
+ return _this2.renderResultAttributes(layerid, feature, 'identify-result-frame');
1217
1261
  });
1218
1262
  }));
1219
- } else if (this.props.resultDisplayMode === 'paginated' && this.state.currentPage < flatResults.length) {
1220
- var _flatResults$this$sta = _slicedToArray(flatResults[this.state.currentPage], 2),
1221
- layerid = _flatResults$this$sta[0],
1222
- feature = _flatResults$this$sta[1];
1223
- body = /*#__PURE__*/React.createElement("div", {
1224
- className: "identify-flat-results-list",
1225
- onMouseEnter: function onMouseEnter() {
1226
- return _this2.setHighlightedFeatures([feature]);
1227
- },
1228
- onMouseLeave: function onMouseLeave() {
1229
- return _this2.setHighlightedFeatures(null);
1230
- }
1231
- }, this.renderResultAttributes(layerid, feature, 'identify-result-frame'));
1263
+ } else if (this.props.resultDisplayMode === 'paginated') {
1264
+ if (this.state.multiViewEnabled) {
1265
+ var results = flatResults.slice(this.state.currentPage * this.state.pageSize, (this.state.currentPage + 1) * this.state.pageSize);
1266
+ var _style = {
1267
+ gridTemplateColumns: "repeat(auto-fit, minmax(".concat(this.resultGridSize - 2, "px, 1fr))")
1268
+ };
1269
+ body = /*#__PURE__*/React.createElement("div", {
1270
+ className: "identify-compare-results",
1271
+ style: _style
1272
+ }, results.map(function (_ref27) {
1273
+ var _ref28 = _slicedToArray(_ref27, 2),
1274
+ layerid = _ref28[0],
1275
+ feature = _ref28[1];
1276
+ return _this2.renderResultAttributes(layerid, feature, 'identify-result-frame');
1277
+ }));
1278
+ } else if (this.state.currentPage < flatResults.length) {
1279
+ var _flatResults$this$sta = _slicedToArray(flatResults[this.state.currentPage], 2),
1280
+ layerid = _flatResults$this$sta[0],
1281
+ feature = _flatResults$this$sta[1];
1282
+ body = /*#__PURE__*/React.createElement("div", {
1283
+ className: "identify-flat-results-list"
1284
+ }, this.renderResultAttributes(layerid, feature, 'identify-result-frame'));
1285
+ }
1232
1286
  }
1233
- // "el.style.background='inherit'": HACK to trigger an additional repaint, since Safari/Chrome on iOS render the element cut off the first time
1234
1287
  return /*#__PURE__*/React.createElement("div", {
1235
1288
  className: "identify-body",
1236
- ref: function ref(el) {
1237
- if (el) el.style.background = 'inherit';
1238
- }
1289
+ ref: this.initBody
1239
1290
  }, body, flatResults.length > 0 ? this.renderToolbar(flatResults) : null);
1240
1291
  }
1241
1292
  }]);
@@ -1261,6 +1312,7 @@ _defineProperty(IdentifyViewer, "propTypes", {
1261
1312
  removeLayer: PropTypes.func,
1262
1313
  replaceImageUrls: PropTypes.bool,
1263
1314
  resultDisplayMode: PropTypes.string,
1315
+ resultGridSize: PropTypes.number,
1264
1316
  setActiveLayerInfo: PropTypes.func,
1265
1317
  showLayerSelector: PropTypes.bool,
1266
1318
  showLayerTitles: PropTypes.bool,
@@ -1278,6 +1330,7 @@ _defineProperty(IdentifyViewer, "defaultProps", {
1278
1330
  },
1279
1331
  enableAggregatedReports: true,
1280
1332
  resultDisplayMode: 'flat',
1333
+ resultGridSize: 200,
1281
1334
  showLayerTitles: true,
1282
1335
  showLayerSelector: true,
1283
1336
  highlightAllResults: true
@@ -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 () {
@@ -306,6 +306,11 @@ var ResizeableWindow = /*#__PURE__*/function (_React$Component) {
306
306
  if (el) {
307
307
  _this.rnd = el;
308
308
  _this.rnd.updatePosition(_this.state.geometry);
309
+ // Set focus to first focusable element
310
+ if (_this.props.visible) {
311
+ var _this$rnd$resizableEl, _this$rnd$resizableEl2, _this$rnd$resizableEl3;
312
+ (_this$rnd$resizableEl = _this.rnd.resizableElement) === null || _this$rnd$resizableEl === void 0 || (_this$rnd$resizableEl = _this$rnd$resizableEl.current) === null || _this$rnd$resizableEl === void 0 || (_this$rnd$resizableEl2 = _this$rnd$resizableEl.querySelector) === null || _this$rnd$resizableEl2 === void 0 || (_this$rnd$resizableEl2 = _this$rnd$resizableEl2.call(_this$rnd$resizableEl, '[tabindex="0"]')) === null || _this$rnd$resizableEl2 === void 0 || (_this$rnd$resizableEl3 = _this$rnd$resizableEl2.focus) === null || _this$rnd$resizableEl3 === void 0 || _this$rnd$resizableEl3.call(_this$rnd$resizableEl2);
313
+ }
309
314
  }
310
315
  });
311
316
  _defineProperty(_this, "onDragStart", function () {
@@ -495,8 +500,11 @@ var ResizeableWindow = /*#__PURE__*/function (_React$Component) {
495
500
  return;
496
501
  }
497
502
  if (this.rnd && this.props.visible && this.props.visible !== prevProps.visible) {
503
+ var _this$rnd$resizableEl4, _this$rnd$resizableEl5, _this$rnd$resizableEl6;
498
504
  this.props.onGeometryChanged(this.state.geometry);
499
505
  this.rnd.updatePosition(this.state.geometry);
506
+ // Set focus to first focusable element
507
+ (_this$rnd$resizableEl4 = this.rnd.resizableElement) === null || _this$rnd$resizableEl4 === void 0 || (_this$rnd$resizableEl4 = _this$rnd$resizableEl4.current) === null || _this$rnd$resizableEl4 === void 0 || (_this$rnd$resizableEl5 = _this$rnd$resizableEl4.querySelector) === null || _this$rnd$resizableEl5 === void 0 || (_this$rnd$resizableEl5 = _this$rnd$resizableEl5.call(_this$rnd$resizableEl4, '[tabindex="0"]')) === null || _this$rnd$resizableEl5 === void 0 || (_this$rnd$resizableEl6 = _this$rnd$resizableEl5.focus) === null || _this$rnd$resizableEl6 === void 0 || _this$rnd$resizableEl6.call(_this$rnd$resizableEl5);
500
508
  }
501
509
  if (this.state.geometry !== prevState.geometry) {
502
510
  this.props.onGeometryChanged(this.state.geometry);