qwc2 2026.4.21 → 2026.4.23

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.
@@ -44,7 +44,7 @@ import { refreshLayer } from '../actions/layers';
44
44
  import { setCurrentTaskBlocked } from '../actions/task';
45
45
  import ConfigUtils from '../utils/ConfigUtils';
46
46
  import CoordinatesUtils from '../utils/CoordinatesUtils';
47
- import { getFeatureTemplate, parseExpressionsAsync } from '../utils/EditingUtils';
47
+ import { FeatureCache, getFeatureTemplate, KeyValCache, parseExpressionsAsync } from '../utils/EditingUtils';
48
48
  import LocaleUtils from '../utils/LocaleUtils';
49
49
  import AutoEditForm from './AutoEditForm';
50
50
  import LinkFeatureForm from './LinkFeatureForm';
@@ -206,6 +206,10 @@ var AttributeForm = /*#__PURE__*/function (_React$Component) {
206
206
  });
207
207
  });
208
208
  _defineProperty(_this, "updateField", function (key, value) {
209
+ var _this$props$editConte;
210
+ if (value === ((_this$props$editConte = _this.props.editContext.feature) === null || _this$props$editConte === void 0 || (_this$props$editConte = _this$props$editConte.properties) === null || _this$props$editConte === void 0 ? void 0 : _this$props$editConte[key])) {
211
+ return;
212
+ }
209
213
  var newProperties = _objectSpread(_objectSpread({}, _this.props.editContext.feature.properties), {}, _defineProperty({}, key, value));
210
214
  var newFeature = _objectSpread(_objectSpread({}, _this.props.editContext.feature), {}, {
211
215
  properties: newProperties
@@ -344,14 +348,15 @@ var AttributeForm = /*#__PURE__*/function (_React$Component) {
344
348
  changed: true
345
349
  });
346
350
  });
347
- _defineProperty(_this, "editRelationRecord", function (action, layer, table, idx, displayField) {
348
- var editConfig = _this.props.editConfigs[_this.props.editContext.mapPrefix][table.split('.').slice(-1)];
349
- var feature = _this.props.editContext.feature.relationValues[table].features[idx];
351
+ _defineProperty(_this, "editRelationRecord", function (action, layer, idx, displayField) {
352
+ var dataset = _this.props.editContext.mapPrefix + "." + layer;
353
+ var editConfig = _this.props.editConfigs[_this.props.editContext.mapPrefix][layer];
354
+ var feature = _this.props.editContext.feature.relationValues[dataset].features[idx];
350
355
  var childEdit = {
351
356
  action: action,
352
357
  editConfig: editConfig,
353
358
  editContextId: ':' + layer,
354
- dataset: table,
359
+ dataset: dataset,
355
360
  idx: idx,
356
361
  feature: feature,
357
362
  finishCallback: _this.finishEditRelationRecord,
@@ -491,11 +496,11 @@ var AttributeForm = /*#__PURE__*/function (_React$Component) {
491
496
  var element = _this.form.elements.namedItem(key);
492
497
  if (element) {
493
498
  if (value === false) {
494
- var _this$props$editConte, _this$props$editConte2;
499
+ var _this$props$editConte2, _this$props$editConte3;
495
500
  valid = false;
496
- var reason = (_this$props$editConte = (_this$props$editConte2 = _this.props.editContext.editConfig.fields.find(function (field) {
501
+ var reason = (_this$props$editConte2 = (_this$props$editConte3 = _this.props.editContext.editConfig.fields.find(function (field) {
497
502
  return field.id === key;
498
- })) === null || _this$props$editConte2 === void 0 || (_this$props$editConte2 = _this$props$editConte2.constraints) === null || _this$props$editConte2 === void 0 ? void 0 : _this$props$editConte2.placeholder) !== null && _this$props$editConte !== void 0 ? _this$props$editConte : LocaleUtils.tr("editing.contraintviolation");
503
+ })) === null || _this$props$editConte3 === void 0 || (_this$props$editConte3 = _this$props$editConte3.constraints) === null || _this$props$editConte3 === void 0 ? void 0 : _this$props$editConte3.placeholder) !== null && _this$props$editConte2 !== void 0 ? _this$props$editConte2 : LocaleUtils.tr("editing.contraintviolation");
499
504
  reasons.push(reason);
500
505
  element.setCustomValidity(reason);
501
506
  } else {
@@ -876,7 +881,8 @@ var AttributeForm = /*#__PURE__*/function (_React$Component) {
876
881
  displayField: displayField,
877
882
  featureId: featureId,
878
883
  updateField: updateField,
879
- finishCallback: _this.finishChildEdit
884
+ finishCallback: _this.finishChildEdit,
885
+ hideDelete: true
880
886
  };
881
887
  _this.setState({
882
888
  childEdit: childEdit
@@ -885,8 +891,8 @@ var AttributeForm = /*#__PURE__*/function (_React$Component) {
885
891
  });
886
892
  _defineProperty(_this, "finishChildEdit", function (feature) {
887
893
  _this.props.clearEditContext(_this.state.childEdit.editContextId, _this.props.editContext.id);
888
- if (feature && feature.id !== _this.state.childEdit.featureId) {
889
- _this.state.childEdit.updateField(feature.id);
894
+ if (feature) {
895
+ _this.state.childEdit.updateField(feature);
890
896
  }
891
897
  _this.setState({
892
898
  childEdit: null
@@ -921,6 +927,14 @@ var AttributeForm = /*#__PURE__*/function (_React$Component) {
921
927
  this.validateFieldConstraints(this.props.editContext.feature);
922
928
  }
923
929
  }
930
+ }, {
931
+ key: "componentWillUnmount",
932
+ value: function componentWillUnmount() {
933
+ if (!this.props.nested) {
934
+ KeyValCache.clear();
935
+ FeatureCache.clear();
936
+ }
937
+ }
924
938
  }]);
925
939
  }(React.Component);
926
940
  _defineProperty(AttributeForm, "propTypes", {
@@ -932,6 +946,7 @@ _defineProperty(AttributeForm, "propTypes", {
932
946
  hideDelete: PropTypes.bool,
933
947
  iface: PropTypes.object,
934
948
  map: PropTypes.object,
949
+ nested: PropTypes.bool,
935
950
  onCommit: PropTypes.func,
936
951
  onDelete: PropTypes.func,
937
952
  onDiscard: PropTypes.func,
@@ -30,6 +30,8 @@ import React from 'react';
30
30
  import PropTypes from 'prop-types';
31
31
  import { KeyValCache } from '../utils/EditingUtils';
32
32
  import LocaleUtils from '../utils/LocaleUtils';
33
+ import Icon from './Icon';
34
+ import ComboBox from './widgets/ComboBox';
33
35
  import './style/EditComboField.css';
34
36
  var EditComboField = /*#__PURE__*/function (_React$Component) {
35
37
  function EditComboField() {
@@ -91,27 +93,39 @@ var EditComboField = /*#__PURE__*/function (_React$Component) {
91
93
  });
92
94
  _defineProperty(_this, "renderComboSelect", function () {
93
95
  var _this$props$placehold;
94
- return /*#__PURE__*/React.createElement("select", {
95
- disabled: _this.props.readOnly,
96
+ return /*#__PURE__*/React.createElement("div", {
97
+ className: "edit-single-select controlgroup"
98
+ }, /*#__PURE__*/React.createElement(ComboBox, {
99
+ className: "controlgroup-expanditem",
96
100
  name: _this.props.name,
97
- onChange: function onChange(ev) {
98
- return _this.props.updateField(_this.props.fieldId, ev.target.selectedIndex === 0 && _this.state.showPlaceholder ? null : ev.target.value);
101
+ onChange: function onChange(value) {
102
+ return _this.props.updateField(_this.props.fieldId, value);
99
103
  },
104
+ placeholder: _this.state.showPlaceholder ? (_this$props$placehold = _this.props.placeholder) !== null && _this$props$placehold !== void 0 ? _this$props$placehold : LocaleUtils.tr("common.select") : undefined,
100
105
  required: _this.props.required,
101
106
  style: _this.props.style,
102
107
  value: String(_this.props.value)
103
- }, _this.state.showPlaceholder ? /*#__PURE__*/React.createElement("option", {
104
- disabled: _this.props.required,
105
- value: ""
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) {
108
+ }, _this.state.values.map(function (item, index) {
107
109
  var _this$itemValueLabel2 = _this.itemValueLabel(item),
108
110
  value = _this$itemValueLabel2.value,
109
111
  label = _this$itemValueLabel2.label;
110
- return /*#__PURE__*/React.createElement("option", {
112
+ return /*#__PURE__*/React.createElement("div", {
111
113
  key: _this.props.fieldId + index,
112
114
  value: String(value)
113
115
  }, label);
114
- }));
116
+ })), _this.props.showEdit ? /*#__PURE__*/React.createElement("button", {
117
+ className: "button",
118
+ onClick: _this.onEdit,
119
+ type: "button"
120
+ }, /*#__PURE__*/React.createElement(Icon, {
121
+ icon: "draw"
122
+ })) : null, _this.props.showAdd ? /*#__PURE__*/React.createElement("button", {
123
+ className: "button",
124
+ onClick: _this.onAdd,
125
+ type: "button"
126
+ }, /*#__PURE__*/React.createElement(Icon, {
127
+ icon: "plus"
128
+ })) : null);
115
129
  });
116
130
  _defineProperty(_this, "itemValueLabel", function (item) {
117
131
  var value = "";
@@ -127,6 +141,25 @@ var EditComboField = /*#__PURE__*/function (_React$Component) {
127
141
  label: label
128
142
  };
129
143
  });
144
+ _defineProperty(_this, "onAdd", function () {
145
+ var parts = _this.props.keyvalrel.split(":");
146
+ _this.props.switchEditContext("Create", parts[0], null, _this.childContextDone, parts[2]);
147
+ });
148
+ _defineProperty(_this, "onEdit", function () {
149
+ var parts = _this.props.keyvalrel.split(":");
150
+ _this.props.switchEditContext("Edit", parts[0], _this.props.value, _this.childContextDone, parts[2]);
151
+ });
152
+ _defineProperty(_this, "childContextDone", function (feature) {
153
+ var _this$props$filterExp;
154
+ var parts = _this.props.keyvalrel.split(":");
155
+ KeyValCache.get(_this.props.editIface, _this.props.mapPrefix + "." + _this.props.keyvalrel, (_this$props$filterExp = _this.props.filterExpr) !== null && _this$props$filterExp !== void 0 ? _this$props$filterExp : null, true).then(function (values) {
156
+ _this.setState({
157
+ values: values,
158
+ showPlaceholder: !_this.hasEmptyValue(values)
159
+ });
160
+ _this.props.updateField(_this.props.fieldId, feature.properties[parts[1]]);
161
+ });
162
+ });
130
163
  return _this;
131
164
  }
132
165
  _inherits(EditComboField, _React$Component);
@@ -140,8 +173,8 @@ var EditComboField = /*#__PURE__*/function (_React$Component) {
140
173
  showPlaceholder: !this.hasEmptyValue(this.props.values)
141
174
  });
142
175
  } else if (this.props.keyvalrel) {
143
- var _this$props$filterExp;
144
- KeyValCache.get(this.props.editIface, this.props.keyvalrel, (_this$props$filterExp = this.props.filterExpr) !== null && _this$props$filterExp !== void 0 ? _this$props$filterExp : null).then(function (values) {
176
+ var _this$props$filterExp2;
177
+ KeyValCache.get(this.props.editIface, this.props.mapPrefix + "." + this.props.keyvalrel, (_this$props$filterExp2 = this.props.filterExpr) !== null && _this$props$filterExp2 !== void 0 ? _this$props$filterExp2 : null).then(function (values) {
145
178
  _this2.setState({
146
179
  values: values,
147
180
  showPlaceholder: !_this2.hasEmptyValue(values)
@@ -154,8 +187,8 @@ var EditComboField = /*#__PURE__*/function (_React$Component) {
154
187
  value: function componentDidUpdate(prevProps) {
155
188
  var _this3 = this;
156
189
  if (this.props.keyvalrel && this.props.filterExpr !== prevProps.filterExpr) {
157
- var _this$props$filterExp2;
158
- KeyValCache.get(this.props.editIface, this.props.keyvalrel, (_this$props$filterExp2 = this.props.filterExpr) !== null && _this$props$filterExp2 !== void 0 ? _this$props$filterExp2 : null).then(function (values) {
190
+ var _this$props$filterExp3;
191
+ KeyValCache.get(this.props.editIface, this.props.mapPrefix + "." + this.props.keyvalrel, (_this$props$filterExp3 = this.props.filterExpr) !== null && _this$props$filterExp3 !== void 0 ? _this$props$filterExp3 : null).then(function (values) {
159
192
  _this3.setState({
160
193
  values: values,
161
194
  showPlaceholder: !_this3.hasEmptyValue(values)
@@ -179,12 +212,16 @@ _defineProperty(EditComboField, "propTypes", {
179
212
  fieldId: PropTypes.string,
180
213
  filterExpr: PropTypes.array,
181
214
  keyvalrel: PropTypes.string,
215
+ mapPrefix: PropTypes.string,
182
216
  multiSelect: PropTypes.bool,
183
217
  name: PropTypes.string,
184
218
  placeholder: PropTypes.string,
185
219
  readOnly: PropTypes.bool,
186
220
  required: PropTypes.bool,
221
+ showAdd: PropTypes.bool,
222
+ showEdit: PropTypes.bool,
187
223
  style: PropTypes.object,
224
+ switchEditContext: PropTypes.func,
188
225
  updateField: PropTypes.func,
189
226
  value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
190
227
  values: PropTypes.array
@@ -65,9 +65,9 @@ var LinkFeatureForm = /*#__PURE__*/function (_React$Component) {
65
65
  }
66
66
  });
67
67
  });
68
- _defineProperty(_this, "finish", function () {
68
+ _defineProperty(_this, "close", function () {
69
69
  var editContext = _this.props.editing.contexts[_this.props.editContextId];
70
- _this.props.finished(editContext.feature);
70
+ _this.props.finished(editContext.action === 'Draw' ? null : editContext.feature);
71
71
  });
72
72
  _defineProperty(_this, "hoverFeature", function (feature) {
73
73
  var layer = {
@@ -194,13 +194,12 @@ var LinkFeatureForm = /*#__PURE__*/function (_React$Component) {
194
194
  return _this3.hoverFeature(feature);
195
195
  }
196
196
  }, (_feature$properties$_ = feature.properties[_this3.props.displayField]) !== null && _feature$properties$_ !== void 0 ? _feature$properties$_ : feature.id);
197
- })), /*#__PURE__*/React.createElement("div", {
197
+ })), !editContext.changed && /*#__PURE__*/React.createElement("div", {
198
198
  className: "link-feature-form-close"
199
199
  }, /*#__PURE__*/React.createElement("button", {
200
200
  className: "button",
201
- disabled: editContext.changed,
202
- onClick: this.finish
203
- }, LocaleUtils.tr("common.cancel"))));
201
+ onClick: this.close
202
+ }, LocaleUtils.tr("common.close"))));
204
203
  } else if (editContext.feature) {
205
204
  var drawing = editContext.action === 'Draw' && !editContext.feature.geometry && this.props.editConfig.geomType;
206
205
  return /*#__PURE__*/React.createElement("div", {
@@ -211,16 +210,16 @@ var LinkFeatureForm = /*#__PURE__*/function (_React$Component) {
211
210
  editContext: editContext,
212
211
  hideDelete: this.props.hideDelete,
213
212
  iface: this.props.iface,
213
+ nested: true,
214
214
  onDiscard: this.onDiscard,
215
215
  readOnly: this.props.readOnly,
216
216
  translations: this.props.translations
217
- }), /*#__PURE__*/React.createElement("div", {
217
+ }), !editContext.changed && /*#__PURE__*/React.createElement("div", {
218
218
  className: "link-feature-form-close"
219
219
  }, /*#__PURE__*/React.createElement("button", {
220
220
  className: "button",
221
- disabled: editContext.changed,
222
- onClick: this.finish
223
- }, drawing ? LocaleUtils.tr("common.cancel") : LocaleUtils.tr("common.close"))));
221
+ onClick: this.close
222
+ }, editContext.action === 'Draw' ? LocaleUtils.tr("common.cancel") : LocaleUtils.tr("common.close"))));
224
223
  } else {
225
224
  return null;
226
225
  }
@@ -37,7 +37,7 @@ import isEmpty from 'lodash.isempty';
37
37
  import PropTypes from 'prop-types';
38
38
  import { v4 as uuidv4 } from 'uuid';
39
39
  import ConfigUtils from '../utils/ConfigUtils';
40
- import { parseExpression, FeatureCache, KeyValCache } from '../utils/EditingUtils';
40
+ import { parseExpression } from '../utils/EditingUtils';
41
41
  import LocaleUtils from '../utils/LocaleUtils';
42
42
  import MiscUtils from '../utils/MiscUtils';
43
43
  import EditComboField from './EditComboField';
@@ -482,7 +482,7 @@ var QtDesignerForm = /*#__PURE__*/function (_React$Component) {
482
482
  var count = parts.length;
483
483
  var _fieldId = parts.slice(1, count - 3).join("__");
484
484
  value = (_fieldId2 = (feature.properties || [])[_fieldId]) !== null && _fieldId2 !== void 0 ? _fieldId2 : "";
485
- var keyvalrel = _this.props.mapPrefix + "." + parts[count - 3] + ":" + parts[count - 2] + ":" + parts[count - 1];
485
+ var keyvalrel = parts[count - 3] + ":" + parts[count - 2] + ":" + parts[count - 1];
486
486
  var filterExpr = null;
487
487
  if (field !== null && field !== void 0 && field.filterExpression) {
488
488
  filterExpr = parseExpression(field.filterExpression, feature, editConfig, _this.props.iface, _this.props.mapPrefix, _this.props.mapCrs, function () {
@@ -497,12 +497,16 @@ var QtDesignerForm = /*#__PURE__*/function (_React$Component) {
497
497
  filterExpr: filterExpr,
498
498
  key: _fieldId,
499
499
  keyvalrel: keyvalrel,
500
+ mapPrefix: _this.props.mapPrefix,
500
501
  multiSelect: widget.property.allowMulti === true || widget.allowMulti === "true",
501
502
  name: nametransform(_fieldId),
502
503
  placeholder: inputConstraints.placeholder,
503
504
  readOnly: inputConstraints.readOnly || fieldConstraints.readOnly,
504
505
  required: inputConstraints.required || fieldConstraints.required,
506
+ showAdd: fieldConstraints.showAdd,
507
+ showEdit: fieldConstraints.showEdit,
505
508
  style: fontStyle,
509
+ switchEditContext: _this.props.switchEditContext,
506
510
  updateField: updateField,
507
511
  value: value
508
512
  });
@@ -650,7 +654,6 @@ var QtDesignerForm = /*#__PURE__*/function (_React$Component) {
650
654
  value = (_feature$properties7 = feature.properties) === null || _feature$properties7 === void 0 ? void 0 : _feature$properties7[attrname];
651
655
  if (layer === reltable) {
652
656
  var index = parseInt(nametransform("").split("__")[1], 10); // Ugh..
653
- var reldataset = _this.props.mapPrefix + "." + reltable;
654
657
  var displayField = attrname.split("__")[1];
655
658
  if (feature.__status__ !== "empty") {
656
659
  var featurebuttons = [{
@@ -664,7 +667,7 @@ var QtDesignerForm = /*#__PURE__*/function (_React$Component) {
664
667
  buttons: featurebuttons,
665
668
  forceLabel: true,
666
669
  onClick: function onClick() {
667
- return _this.props.editRelationRecord('Edit', reltable, reldataset, index, displayField);
670
+ return _this.props.editRelationRecord('Edit', reltable, index, displayField);
668
671
  }
669
672
  }));
670
673
  } else {
@@ -685,7 +688,7 @@ var QtDesignerForm = /*#__PURE__*/function (_React$Component) {
685
688
  buttons: _featurebuttons,
686
689
  forceLabel: true,
687
690
  onClick: function onClick(action) {
688
- return _this.props.editRelationRecord(action, reltable, reldataset, index, displayField);
691
+ return _this.props.editRelationRecord(action, reltable, index, displayField);
689
692
  }
690
693
  });
691
694
  }
@@ -701,8 +704,8 @@ var QtDesignerForm = /*#__PURE__*/function (_React$Component) {
701
704
  }, /*#__PURE__*/React.createElement(ButtonBar, {
702
705
  buttons: _featurebuttons2,
703
706
  onClick: function onClick() {
704
- return _this.props.switchEditContext('Edit', layer, value, function (v) {
705
- return updateField(attrname, v);
707
+ return _this.props.switchEditContext('Edit', layer, value, function (f) {
708
+ return updateField(attrname, f.id);
706
709
  }, attrname);
707
710
  }
708
711
  }), /*#__PURE__*/React.createElement("button", {
@@ -727,8 +730,8 @@ var QtDesignerForm = /*#__PURE__*/function (_React$Component) {
727
730
  return /*#__PURE__*/React.createElement(ButtonBar, {
728
731
  buttons: _featurebuttons3,
729
732
  onClick: function onClick(action) {
730
- return _this.props.switchEditContext(action, layer, null, function (v) {
731
- return updateField(attrname, v);
733
+ return _this.props.switchEditContext(action, layer, null, function (f) {
734
+ return updateField(attrname, f.id);
732
735
  }, attrname);
733
736
  }
734
737
  });
@@ -1112,12 +1115,6 @@ var QtDesignerForm = /*#__PURE__*/function (_React$Component) {
1112
1115
  });
1113
1116
  }
1114
1117
  }
1115
- }, {
1116
- key: "componentWillUnmount",
1117
- value: function componentWillUnmount() {
1118
- KeyValCache.clear();
1119
- FeatureCache.clear();
1120
- }
1121
1118
  }, {
1122
1119
  key: "render",
1123
1120
  value: function render() {
@@ -585,7 +585,7 @@ var SearchBox = /*#__PURE__*/function (_React$Component) {
585
585
  });
586
586
  } else if (_this.props.searchProviders[provider].getResultGeometry) {
587
587
  _this.props.searchProviders[provider].getResultGeometry(result, function (response) {
588
- _this.showResultGeometry(result, response);
588
+ return _this.showResultGeometry(result, response);
589
589
  }, axios);
590
590
  } else {
591
591
  // Display marker
@@ -1049,73 +1049,98 @@ var SearchBox = /*#__PURE__*/function (_React$Component) {
1049
1049
  _this.props.setCurrentTask('LayerTree');
1050
1050
  });
1051
1051
  _defineProperty(_this, "showResultGeometry", function (item, response) {
1052
- var _response$crs3, _item$bbox, _item$crs4;
1052
+ var _ref0, _item$label, _response$crs3, _item$bbox, _item$crs3;
1053
1053
  var scale = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined;
1054
+ // Collect highlight features
1055
+ var features = [];
1056
+ if (response !== null && response !== void 0 && response.geometry) {
1057
+ var feature = response.geometry.coordinates ? {
1058
+ type: "Feature",
1059
+ geometry: response.geometry
1060
+ } : VectorLayerUtils.wktToGeoJSON(response.geometry, response.crs, response.crs);
1061
+ if (feature) {
1062
+ features.push(feature);
1063
+ }
1064
+ } else if (response !== null && response !== void 0 && response.feature) {
1065
+ var _response$feature$fea;
1066
+ features = (_response$feature$fea = response.feature.features) !== null && _response$feature$fea !== void 0 ? _response$feature$fea : [response.feature];
1067
+ }
1068
+ // Add highlight features and markers
1054
1069
  var mapCrs = _this.props.map.projection;
1055
- var feature = response !== null && response !== void 0 && response.geometry ? {
1056
- type: "Feature",
1057
- geometry: response.geometry
1058
- } : response === null || response === void 0 ? void 0 : response.feature;
1070
+ var showMarkers = !response.hidemarker && _this.props.searchOptions.showHighlightMarker;
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, '');
1059
1072
  var layer = {
1060
1073
  id: "searchselection",
1061
1074
  role: LayerRole.SELECTION
1062
1075
  };
1063
- if (feature) {
1064
- var _feature$features;
1065
- var features = (_feature$features = feature.features) !== null && _feature$features !== void 0 ? _feature$features : [feature];
1066
- features.forEach(function (feat) {
1067
- var _response$crs, _feat$geometry, _feat$crs;
1068
- feat.geometry = VectorLayerUtils.reprojectGeometry(feat.geometry, (_response$crs = response.crs) !== null && _response$crs !== void 0 ? _response$crs : mapCrs, mapCrs);
1069
- feat.styleName = ((_feat$geometry = feat.geometry) === null || _feat$geometry === void 0 ? void 0 : _feat$geometry.type) === 'Point' && _this.props.searchOptions.showHighlightMarker ? 'marker' : 'default';
1070
- feat.styleOptions = _this.props.searchOptions.highlightStyle || {};
1071
- if ((_feat$crs = feat.crs) !== null && _feat$crs !== void 0 && (_feat$crs = _feat$crs.properties) !== null && _feat$crs !== void 0 && _feat$crs.name) {
1072
- feat.crs = CoordinatesUtils.fromOgcUrnCrs(feat.crs.properties.name);
1073
- }
1074
- });
1075
- // If first feature is not a point(=marker), add a marker
1076
- if (features[0].styleName !== "marker" && !response.hidemarker && _this.props.searchOptions.showHighlightMarker) {
1077
- var _response$crs2, _item$crs2;
1078
- var center = response.center ? CoordinatesUtils.reproject(response.center, (_response$crs2 = response.crs) !== null && _response$crs2 !== void 0 ? _response$crs2 : mapCrs, mapCrs) : CoordinatesUtils.reproject([item.x, item.y], (_item$crs2 = item.crs) !== null && _item$crs2 !== void 0 ? _item$crs2 : mapCrs, mapCrs);
1079
- features.unshift({
1080
- geometry: {
1081
- type: 'Point',
1082
- coordinates: center
1083
- },
1084
- styleName: 'marker'
1085
- });
1076
+ var highlightFeatures = [];
1077
+ features.forEach(function (feature) {
1078
+ var _response$crs;
1079
+ feature.geometry = VectorLayerUtils.reprojectGeometry(feature.geometry, (_response$crs = response.crs) !== null && _response$crs !== void 0 ? _response$crs : mapCrs, mapCrs);
1080
+ if (!showMarkers || !feature.geometry.type.endsWith("Point")) {
1081
+ highlightFeatures.push(_objectSpread(_objectSpread({}, feature), {}, {
1082
+ properties: _objectSpread({}, !showMarkers && !_this.props.searchOptions.hideResultLabels && {
1083
+ label: label
1084
+ }),
1085
+ styleName: 'default',
1086
+ styleOptions: _this.props.searchOptions.highlightStyle || {}
1087
+ }));
1086
1088
  }
1087
- // Label first feature
1088
- if (!_this.props.searchOptions.hideResultLabels) {
1089
- var _ref0, _item$label;
1090
- 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, '');
1091
- features[0].properties = _objectSpread(_objectSpread({}, features[0].properties), {}, {
1092
- label: label
1093
- });
1089
+ if (showMarkers) {
1090
+ if (feature.geometry.type.endsWith("Point")) {
1091
+ var parts = feature.geometry.type.startsWith("Multi") ? feature.geometry.coordinates : [feature.geometry.coordinates];
1092
+ parts.forEach(function (part) {
1093
+ highlightFeatures.push({
1094
+ type: "Feature",
1095
+ geometry: {
1096
+ type: 'Point',
1097
+ coordinates: part
1098
+ },
1099
+ properties: _objectSpread({}, !_this.props.searchOptions.hideResultLabels && {
1100
+ label: label
1101
+ }),
1102
+ styleName: 'marker'
1103
+ });
1104
+ });
1105
+ } else {
1106
+ var _response$crs2;
1107
+ var center = response.center ? CoordinatesUtils.reproject(response.center, (_response$crs2 = response.crs) !== null && _response$crs2 !== void 0 ? _response$crs2 : mapCrs, mapCrs) : VectorLayerUtils.getFeatureCenter(feature);
1108
+ highlightFeatures.push({
1109
+ type: "Feature",
1110
+ geometry: {
1111
+ type: 'Point',
1112
+ coordinates: center
1113
+ },
1114
+ properties: _objectSpread({}, !_this.props.searchOptions.hideResultLabels && {
1115
+ label: label
1116
+ }),
1117
+ styleName: 'marker'
1118
+ });
1119
+ }
1094
1120
  }
1095
- // Mark first feature as searchmarker
1096
- features[0].id = 'searchmarker';
1097
- _this.props.addLayerFeatures(layer, features, true);
1098
- } else {
1099
- var _item$crs3;
1100
- var _center = CoordinatesUtils.reproject([item.x, item.y], (_item$crs3 = item.crs) !== null && _item$crs3 !== void 0 ? _item$crs3 : mapCrs, mapCrs);
1121
+ });
1122
+ if (isEmpty(highlightFeatures)) {
1123
+ var _item$crs2;
1124
+ var center = CoordinatesUtils.reproject([item.x, item.y], (_item$crs2 = item.crs) !== null && _item$crs2 !== void 0 ? _item$crs2 : mapCrs, mapCrs);
1101
1125
  var marker = {
1102
1126
  type: "Feature",
1103
1127
  geometry: {
1104
1128
  type: "Point",
1105
- coordinates: _center
1129
+ coordinates: center
1106
1130
  },
1131
+ properties: _objectSpread({}, !_this.props.searchOptions.hideResultLabels && {
1132
+ label: label
1133
+ }),
1107
1134
  styleName: 'marker'
1108
1135
  };
1109
- if (!_this.props.searchOptions.hideResultLabels) {
1110
- var _ref1, _item$label2;
1111
- var _label = ((_ref1 = (_item$label2 = item.label) !== null && _item$label2 !== void 0 ? _item$label2 : item.text) !== null && _ref1 !== void 0 ? _ref1 : '').replace(/<\/?\w+\s*\/?>/g, '');
1112
- marker.properties = {
1113
- label: _label
1114
- };
1115
- }
1116
- _this.props.addLayerFeatures(layer, [marker], true);
1136
+ highlightFeatures.push(marker);
1117
1137
  }
1118
- var bbox = response !== null && response !== void 0 && response.bbox ? CoordinatesUtils.reprojectBbox(response.bbox, (_response$crs3 = response.crs) !== null && _response$crs3 !== void 0 ? _response$crs3 : mapCrs, mapCrs) : CoordinatesUtils.reprojectBbox((_item$bbox = item.bbox) !== null && _item$bbox !== void 0 ? _item$bbox : [item.x, item.y, item.x, item.y], (_item$crs4 = item.crs) !== null && _item$crs4 !== void 0 ? _item$crs4 : mapCrs, mapCrs);
1138
+ // Mark first feature as searchmarker
1139
+ highlightFeatures[0].id = 'searchmarker';
1140
+ _this.props.addLayerFeatures(layer, highlightFeatures, true);
1141
+
1142
+ // Zoom to result bbox
1143
+ var bbox = response !== null && response !== void 0 && response.bbox ? CoordinatesUtils.reprojectBbox(response.bbox, (_response$crs3 = response.crs) !== null && _response$crs3 !== void 0 ? _response$crs3 : mapCrs, mapCrs) : CoordinatesUtils.reprojectBbox((_item$bbox = item.bbox) !== null && _item$bbox !== void 0 ? _item$bbox : [item.x, item.y, item.x, item.y], (_item$crs3 = item.crs) !== null && _item$crs3 !== void 0 ? _item$crs3 : mapCrs, mapCrs);
1119
1144
  _this.zoomToResultBBox(bbox, scale);
1120
1145
  _this.props.setCurrentSearchResult(item);
1121
1146
  });
@@ -236,7 +236,7 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
236
236
  sublayers: _preserveSublayerOptions(layer, prevOptions)
237
237
  });
238
238
  Object.assign(colorLayers[layer.id], LayerUtils.buildWMSLayerParams(colorLayers[layer.id]));
239
- if (colorLayers[layer.id].fields === undefined && layerCreator.getFields) {
239
+ if (layerCreator.getFields) {
240
240
  layerCreator.getFields(layer).then(function (fields) {
241
241
  _this2.updateColorLayer(layer.id, {
242
242
  fields: fields
@@ -545,9 +545,14 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
545
545
  _defineProperty(_this2, "updateSceneObject", function (objectId, options) {
546
546
  var flags = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
547
547
  _this2.setState(function (state) {
548
+ var _objectTree$options$p;
548
549
  var objectTree = _objectSpread({}, state.sceneContext.objectTree);
549
550
  var prevOptions = objectTree[objectId] || {};
550
551
  options = _objectSpread(_objectSpread({}, prevOptions), options);
552
+ // Don't allow hiding the visible child of a mutex group
553
+ if ((_objectTree$options$p = objectTree[options.parent]) !== null && _objectTree$options$p !== void 0 && _objectTree$options$p.mutuallyExclusive && !options.visibility && prevOptions.visibility) {
554
+ options.visibility = true;
555
+ }
551
556
  if (options.objectId) {
552
557
  _this2.applySceneObjectState(objectId, options, prevOptions, objectTree);
553
558
  } else if (options.children && options.visibility !== prevOptions.visibility) {
@@ -567,7 +572,7 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
567
572
  }
568
573
  var changed = false;
569
574
  if (options.visibility !== prevOptions.visibility || options.opacity !== (prevOptions === null || prevOptions === void 0 ? void 0 : prevOptions.opacity)) {
570
- var _objectTree$options$p;
575
+ var _objectTree$options$p2;
571
576
  // Visibile if object is visibile and parents also
572
577
  var isVisible = options.opacity > 0 && options.visibility;
573
578
  for (var curId = options.parent; isVisible && curId !== undefined; curId = objectTree[curId].parent) {
@@ -575,12 +580,13 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
575
580
  }
576
581
  changed |= object.visible !== isVisible;
577
582
  object.visible = isVisible;
578
- if ((_objectTree$options$p = objectTree[options.parent]) !== null && _objectTree$options$p !== void 0 && _objectTree$options$p.mutuallyExclusive && objectTree[options.parent].children) {
583
+ if ((_objectTree$options$p2 = objectTree[options.parent]) !== null && _objectTree$options$p2 !== void 0 && _objectTree$options$p2.mutuallyExclusive && objectTree[options.parent].children) {
579
584
  objectTree[options.parent].children.forEach(function (child) {
580
585
  if (child !== objectId) {
581
586
  objectTree[child] = _objectSpread(_objectSpread({}, objectTree[child]), {}, {
582
587
  visibility: false
583
588
  });
589
+ _this2.objectMap[child].visible = false;
584
590
  }
585
591
  });
586
592
  }
@@ -859,6 +865,14 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
859
865
  };
860
866
  // Need this separately to ensure object[groupId] is already assigned
861
867
  objectTree[groupId].children = _buildObjectTree(entry.items, groupId);
868
+ if (entry.mutuallyExclusive) {
869
+ // Ensure only one child is visible
870
+ var haveVisibleChild = false;
871
+ objectTree[groupId].children.forEach(function (childId) {
872
+ objectTree[childId].visibility = objectTree[childId].visibility && !haveVisibleChild;
873
+ haveVisibleChild |= objectTree[childId].visibility;
874
+ });
875
+ }
862
876
  nodeIds.push(groupId);
863
877
  } else if (entry.type === "tiles3d") {
864
878
  var _entry$title, _entry$visibility2, _entry$snap;
@@ -879,7 +893,8 @@ var Map3D = /*#__PURE__*/function (_React$Component2) {
879
893
  idAttr: entry.idAttr,
880
894
  colorAttr: entry.colorAttr,
881
895
  alphaAttr: entry.alphaAttr,
882
- labelAttr: entry.labelAttr
896
+ labelAttr: entry.labelAttr,
897
+ infoAttrBlacklist: entry.infoAttrBlacklist
883
898
  });
884
899
  _this2.applySceneObjectState(entry.name, objectTree[entry.name], {}, objectTree);
885
900
  nodeIds.push(entry.name);
@@ -84,6 +84,10 @@ export default {
84
84
  },
85
85
  getFields: function getFields(options) {
86
86
  return new Promise(function (resolve, reject) {
87
+ if (options.fields !== undefined) {
88
+ // Don't requery fields
89
+ resolve(options.fields);
90
+ }
87
91
  var typeName = options.version < "2.0.0" ? "typeName" : "typeNames";
88
92
  var urlParts = url.parse(options.url, true);
89
93
  var urlParams = Object.entries(urlParts.query).reduce(function (res, _ref3) {
@@ -247,7 +247,9 @@ export var TileMeshHelper = /*#__PURE__*/function () {
247
247
  }, {
248
248
  key: "getFeatureProperties",
249
249
  value: function getFeatureProperties(featureId) {
250
- if (featureId in this.propertiesCache) {
250
+ if (featureId === null) {
251
+ return {};
252
+ } else if (featureId in this.propertiesCache) {
251
253
  return this.propertiesCache[featureId];
252
254
  } else if (this.object.userData.structuralMetadata) {
253
255
  this.propertiesCache[featureId] = this.object.userData.structuralMetadata.getPropertyTableData([this.propertyTable], [featureId])[0];
@@ -1,3 +1,8 @@
1
+ div.edit-single-select {
2
+ display: flex;
3
+ align-items: center;
4
+ }
5
+
1
6
  div.edit-multi-select {
2
7
  border: 1px solid var(--border-color);
3
8
  padding: 0.25em;
@@ -103,8 +103,14 @@ var ComboBox = /*#__PURE__*/function (_React$Component) {
103
103
  });
104
104
  };
105
105
  return /*#__PURE__*/React.createElement("div", {
106
- className: "combobox " + (this.props.className || "")
107
- }, /*#__PURE__*/React.createElement("div", {
106
+ className: "combobox " + (this.props.className || ""),
107
+ style: this.props.style
108
+ }, this.props.name && /*#__PURE__*/React.createElement("input", {
109
+ name: this.props.name,
110
+ required: this.props.required,
111
+ type: "hidden",
112
+ value: this.props.value
113
+ }), /*#__PURE__*/React.createElement("div", {
108
114
  className: "combobox-button",
109
115
  onClick: onClick,
110
116
  onKeyDown: MiscUtils.checkKeyActivate,
@@ -161,9 +167,12 @@ _defineProperty(ComboBox, "propTypes", {
161
167
  className: PropTypes.string,
162
168
  filterable: PropTypes.bool,
163
169
  menuClassName: PropTypes.string,
170
+ name: PropTypes.string,
164
171
  onChange: PropTypes.func,
165
172
  placeholder: PropTypes.string,
166
173
  readOnly: PropTypes.bool,
174
+ required: PropTypes.bool,
175
+ style: PropTypes.object,
167
176
  value: PropTypes.string
168
177
  });
169
178
  _defineProperty(ComboBox, "defaultProps", {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qwc2",
3
- "version": "2026.04.21",
3
+ "version": "2026.04.23",
4
4
  "description": "QGIS Web Client",
5
5
  "author": "Sourcepole AG",
6
6
  "license": "BSD-2-Clause",
@@ -101,7 +101,7 @@
101
101
  "toposort": "^2.0.2",
102
102
  "url": "^0.11.4",
103
103
  "utif": "^3.1.0",
104
- "uuid": "^13.0.0",
104
+ "uuid": "^14.0.0",
105
105
  "xlsx": "^0.18.5"
106
106
  },
107
107
  "devDependencies": {
@@ -23,6 +23,7 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
23
23
  import React from 'react';
24
24
  import { connect } from 'react-redux';
25
25
  import PropTypes from 'prop-types';
26
+ import { setActiveServiceInfo } from '../actions/serviceinfo';
26
27
  import { setCurrentTask } from '../actions/task';
27
28
  import MapButton from '../components/MapButton';
28
29
  import ConfigUtils from '../utils/ConfigUtils';
@@ -31,6 +32,12 @@ import ThemeUtils from '../utils/ThemeUtils';
31
32
 
32
33
  /**
33
34
  * Generic map button to launch a task.
35
+ *
36
+ * The `task` generally corresponds to the `key` of a menuItem or toolbaritem.
37
+ *
38
+ * The following special values for `task` are suppported:
39
+ *
40
+ * * `ServiceInfo`: Open the service info of the current theme.
34
41
  */
35
42
  var TaskButton = /*#__PURE__*/function (_React$Component) {
36
43
  function TaskButton() {
@@ -41,8 +48,13 @@ var TaskButton = /*#__PURE__*/function (_React$Component) {
41
48
  }
42
49
  _this = _callSuper(this, TaskButton, [].concat(args));
43
50
  _defineProperty(_this, "buttonClicked", function () {
44
- var mapClickAction = ConfigUtils.getPluginConfig(_this.props.task).mapClickAction;
45
- _this.props.setCurrentTask(_this.props.currentTask === _this.props.task ? null : _this.props.task, _this.props.mode, mapClickAction);
51
+ // Special cases
52
+ if (_this.props.task === "ServiceInfo") {
53
+ _this.props.setActiveServiceInfo(_this.props.theme);
54
+ } else {
55
+ var mapClickAction = ConfigUtils.getPluginConfig(_this.props.task).mapClickAction;
56
+ _this.props.setCurrentTask(_this.props.currentTask === _this.props.task ? null : _this.props.task, _this.props.mode, mapClickAction);
57
+ }
46
58
  });
47
59
  return _this;
48
60
  }
@@ -72,6 +84,7 @@ _defineProperty(TaskButton, "propTypes", {
72
84
  mode: PropTypes.string,
73
85
  /** The position slot index of the map button, from the bottom (0: bottom slot). */
74
86
  position: PropTypes.number,
87
+ setActiveServiceInfo: PropTypes.func,
75
88
  setCurrentTask: PropTypes.func,
76
89
  /** The task name. */
77
90
  task: PropTypes.string,
@@ -91,5 +104,6 @@ var selector = function selector(state) {
91
104
  };
92
105
  };
93
106
  export default connect(selector, {
107
+ setActiveServiceInfo: setActiveServiceInfo,
94
108
  setCurrentTask: setCurrentTask
95
109
  })(TaskButton);
@@ -120,9 +120,17 @@ var Identify3D = /*#__PURE__*/function (_React$Component) {
120
120
  }
121
121
  });
122
122
  _defineProperty(_this, "identifyTilePick", function (pick) {
123
+ var _pick$object$userData, _pick$object$userData2;
123
124
  var helper = new TileMeshHelper(pick.object);
124
125
  var pickFeatureId = helper.getPickFeatureId(pick);
125
126
  var featureAttrs = helper.getFeatureProperties(pickFeatureId);
127
+ var infoAttrBlacklist = (_pick$object$userData = (_pick$object$userData2 = pick.object.userData) === null || _pick$object$userData2 === void 0 || (_pick$object$userData2 = _pick$object$userData2.parentEntity) === null || _pick$object$userData2 === void 0 || (_pick$object$userData2 = _pick$object$userData2.userData) === null || _pick$object$userData2 === void 0 ? void 0 : _pick$object$userData2.infoAttrBlacklist) !== null && _pick$object$userData !== void 0 ? _pick$object$userData : [];
128
+ var infoAttrs = Object.fromEntries(Object.entries(featureAttrs).filter(function (_ref) {
129
+ var _ref2 = _slicedToArray(_ref, 2),
130
+ key = _ref2[0],
131
+ value = _ref2[1];
132
+ return !infoAttrBlacklist.includes(key);
133
+ }));
126
134
 
127
135
  // Extract feature geometry
128
136
  var pickPosition = [];
@@ -147,23 +155,23 @@ var Identify3D = /*#__PURE__*/function (_React$Component) {
147
155
  var url = _this.props.tileInfoServiceUrl.replace('{tileset}', tilesetName).replace('{objectid}', featureAttrs[featureIdAttr]);
148
156
  axios.get(url).then(function (response) {
149
157
  response.data.forEach(function (attr) {
150
- if (attr.name in featureAttrs && featureAttrs[attr.name] === attr.value) {
158
+ if (attr.name in infoAttrs && infoAttrs[attr.name] === attr.value) {
151
159
  // Use attribute alias
152
- delete featureAttrs[attr.name];
160
+ delete infoAttrs[attr.name];
153
161
  }
154
- featureAttrs[attr.alias] = attr.value;
162
+ infoAttrs[attr.alias] = attr.value;
155
163
  });
156
164
  _this.setState({
157
- pickAttrs: featureAttrs
165
+ pickAttrs: infoAttrs
158
166
  });
159
167
  })["catch"](function () {
160
168
  _this.setState({
161
- pickAttrs: featureAttrs
169
+ pickAttrs: infoAttrs
162
170
  });
163
171
  });
164
172
  } else {
165
173
  _this.setState({
166
- pickAttrs: featureAttrs
174
+ pickAttrs: infoAttrs
167
175
  });
168
176
  }
169
177
  });
@@ -233,10 +241,10 @@ var Identify3D = /*#__PURE__*/function (_React$Component) {
233
241
  className: "identify-result-box"
234
242
  }, /*#__PURE__*/React.createElement("table", {
235
243
  className: "attribute-list"
236
- }, /*#__PURE__*/React.createElement("tbody", null, Object.entries(this.state.pickAttrs).map(function (_ref) {
237
- var _ref2 = _slicedToArray(_ref, 2),
238
- key = _ref2[0],
239
- value = _ref2[1];
244
+ }, /*#__PURE__*/React.createElement("tbody", null, Object.entries(this.state.pickAttrs).map(function (_ref3) {
245
+ var _ref4 = _slicedToArray(_ref3, 2),
246
+ key = _ref4[0],
247
+ value = _ref4[1];
240
248
  return /*#__PURE__*/React.createElement("tr", {
241
249
  key: key
242
250
  }, /*#__PURE__*/React.createElement("td", {
@@ -32,6 +32,7 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
32
32
 
33
33
  import React from 'react';
34
34
  import ReactDOM from 'react-dom';
35
+ import { connect } from 'react-redux';
35
36
  import DOMPurify from 'dompurify';
36
37
  import isEmpty from 'lodash.isempty';
37
38
  import PropTypes from 'prop-types';
@@ -53,6 +54,28 @@ var MapCopyright3D = /*#__PURE__*/function (_React$Component) {
53
54
  _defineProperty(_this, "state", {
54
55
  currentCopyrights: {}
55
56
  });
57
+ _defineProperty(_this, "collectCopyrights", function () {
58
+ var layers = [_this.props.theme];
59
+ if (!_this.props.showThemeCopyrightOnly) {
60
+ layers.push.apply(layers, _toConsumableArray(_this.props.sceneContext.baseLayers));
61
+ layers.push.apply(layers, _toConsumableArray(Object.values(_this.props.sceneContext.colorLayers)));
62
+ }
63
+ var copyrights = layers.reduce(function (res, layer) {
64
+ var _layer$attribution;
65
+ if ((_layer$attribution = layer.attribution) !== null && _layer$attribution !== void 0 && _layer$attribution.Title) {
66
+ var _res$key;
67
+ var key = layer.attribution.OnlineResource || layer.attribution.Title;
68
+ res[key] = {
69
+ title: layer.attribution.OnlineResource ? layer.attribution.Title : null,
70
+ layers: [].concat(_toConsumableArray(((_res$key = res[key]) === null || _res$key === void 0 ? void 0 : _res$key.layers) || []), [layer])
71
+ };
72
+ }
73
+ return res;
74
+ }, {});
75
+ _this.setState({
76
+ currentCopyrights: copyrights
77
+ });
78
+ });
56
79
  _defineProperty(_this, "layerNames", function (layers) {
57
80
  if (!_this.props.prefixCopyrightsWithLayerNames) {
58
81
  return "";
@@ -66,24 +89,15 @@ var MapCopyright3D = /*#__PURE__*/function (_React$Component) {
66
89
  }
67
90
  _inherits(MapCopyright3D, _React$Component);
68
91
  return _createClass(MapCopyright3D, [{
92
+ key: "componentDidMount",
93
+ value: function componentDidMount() {
94
+ this.collectCopyrights();
95
+ }
96
+ }, {
69
97
  key: "componentDidUpdate",
70
98
  value: function componentDidUpdate(prevProps) {
71
99
  if (this.props.sceneContext.baseLayers !== prevProps.sceneContext.baseLayers || this.props.sceneContext.colorLayers !== prevProps.sceneContext.colorLayers) {
72
- var layers = this.props.sceneContext.baseLayers.concat(this.props.sceneContext.colorLayers);
73
- var copyrights = layers.reduce(function (res, layer) {
74
- if (layer.attribution && layer.attribution.Title) {
75
- var _res$key;
76
- var key = layer.attribution.OnlineResource || layer.attribution.Title;
77
- res[key] = {
78
- title: layer.attribution.OnlineResource ? layer.attribution.Title : null,
79
- layers: [].concat(_toConsumableArray(((_res$key = res[key]) === null || _res$key === void 0 ? void 0 : _res$key.layers) || []), [layer])
80
- };
81
- }
82
- return res;
83
- }, {});
84
- this.setState({
85
- currentCopyrights: copyrights
86
- });
100
+ this.collectCopyrights();
87
101
  }
88
102
  }
89
103
  }, {
@@ -129,6 +143,11 @@ _defineProperty(MapCopyright3D, "propTypes", {
129
143
  prefixCopyrightsWithLayerNames: PropTypes.bool,
130
144
  sceneContext: PropTypes.object,
131
145
  /** Whether to only display the attribution of the theme, omitting external layers. */
132
- showThemeCopyrightOnly: PropTypes.bool
146
+ showThemeCopyrightOnly: PropTypes.bool,
147
+ theme: PropTypes.object
133
148
  });
134
- export { MapCopyright3D as default };
149
+ export default connect(function (state) {
150
+ return {
151
+ theme: state.theme.current
152
+ };
153
+ }, {})(MapCopyright3D);
@@ -343,9 +343,9 @@ var Measure3D = /*#__PURE__*/function (_React$Component) {
343
343
  _this.setState({
344
344
  result: {
345
345
  pos: [pos.x, pos.y, pos.z],
346
- ground: ground,
347
- haveResult: true
348
- }
346
+ ground: ground
347
+ },
348
+ haveResult: true
349
349
  });
350
350
 
351
351
  // Setup for next measurement
@@ -93,8 +93,9 @@ _KeyValCache = KeyValCache;
93
93
  _defineProperty(KeyValCache, "store", {});
94
94
  _defineProperty(KeyValCache, "requestPromises", {});
95
95
  _defineProperty(KeyValCache, "get", function (editIface, keyvalrel, filterExpr) {
96
+ var forceReload = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
96
97
  var key = keyvalrel + uuidv5(JSON.stringify(filterExpr !== null && filterExpr !== void 0 ? filterExpr : null), UUID_NS);
97
- if (key in _KeyValCache.store) {
98
+ if (key in _KeyValCache.store && !forceReload) {
98
99
  return new Promise(function (resolve) {
99
100
  return resolve(_KeyValCache.store[key]);
100
101
  });
@@ -36,7 +36,6 @@ import DataServiceExprUtils from './DataServiceExprUtils';
36
36
  import IdentifyUtils from './IdentifyUtils';
37
37
  import LayerUtils from './LayerUtils';
38
38
  import LocaleUtils from './LocaleUtils';
39
- import VectorLayerUtils from './VectorLayerUtils';
40
39
  export var SearchResultType = {
41
40
  PLACE: 0,
42
41
  THEMELAYER: 1,
@@ -521,13 +520,13 @@ export var FulltextSearch = /*#__PURE__*/function () {
521
520
  var quot = typeof resultItem.id === 'string' ? '"' : '';
522
521
  var filter = "[[\"".concat(resultItem.id_field_name, "\",\"=\", ").concat(quot).concat(resultItem.id).concat(quot, "]]");
523
522
  axios.get(dataServiceUrl.replace(/\/?$/, "/") + resultItem.dataproduct_id + "/?filter=" + filter).then(function (response) {
523
+ var feature = response.data;
524
524
  var bbox = response.data.bbox;
525
- var center = bbox ? [0.5 * (bbox[0] + bbox[2]), 0.5 * (bbox[1] + bbox[3])] : null;
526
525
  callback({
527
526
  bbox: bbox,
528
- center: center,
529
- feature: response.data,
530
- crs: response.data.crs.properties.name
527
+ center: null,
528
+ feature: feature,
529
+ crs: feature.crs.properties.name
531
530
  });
532
531
  })["catch"](function () {
533
532
  callback(null);
@@ -640,44 +639,6 @@ export function unregisterSearchProvider(key) {
640
639
  delete SearchProviders[key];
641
640
  addedSearchProviders["delete"](key);
642
641
  }
643
-
644
- // Uniformize the response of getResultGeometry
645
- function getResultGeometry(provider, item, callback) {
646
- provider.getResultGeometry(item, function (response) {
647
- var features = [];
648
- if (response !== null && response !== void 0 && response.geometry) {
649
- var highlightFeature = response.geometry.coordinates ? {
650
- type: "Feature",
651
- geometry: response.geometry
652
- } : VectorLayerUtils.wktToGeoJSON(response.geometry, response.crs, response.crs);
653
- if (highlightFeature) {
654
- features.push(highlightFeature);
655
- }
656
- } else if (response !== null && response !== void 0 && response.feature) {
657
- if (response.feature.features) {
658
- features.push.apply(features, _toConsumableArray(response.feature.features));
659
- } else {
660
- features.push(response.feature);
661
- }
662
- }
663
- if (features.length === 0) {
664
- callback(null);
665
- } else {
666
- callback(_objectSpread(_objectSpread({
667
- feature: {
668
- type: "FeatureCollection",
669
- features: features
670
- },
671
- crs: response.crs,
672
- hidemarker: response.hidemarker
673
- }, response.bbox && {
674
- bbox: response.bbox
675
- }), response.center && {
676
- center: response.center
677
- }));
678
- }
679
- });
680
- }
681
642
  export function collectSearchProviders(theme, layers) {
682
643
  var mapScale = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
683
644
  // Collect active layers/search terms
@@ -710,50 +671,43 @@ export function collectSearchProviders(theme, layers) {
710
671
  var _iterator2 = _createForOfIteratorHelper(enabledProviders),
711
672
  _step2;
712
673
  try {
713
- var _loop = function _loop() {
714
- var _entry;
715
- var entry = _step2.value;
716
- if (typeof entry === 'string') {
717
- entry = {
718
- provider: entry
719
- };
674
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
675
+ var _entry2;
676
+ var _entry = _step2.value;
677
+ if (typeof _entry === 'string') {
678
+ _entry = {
679
+ provider: _entry
680
+ };
681
+ }
682
+ // Omit qgis provider with field configuration, this is only supported through the FeatureSearch plugin
683
+ if (_entry.provider === 'qgis' && (_entry2 = _entry) !== null && _entry2 !== void 0 && (_entry2 = _entry2.params) !== null && _entry2 !== void 0 && _entry2.fields) {
684
+ continue;
685
+ }
686
+ var provider = searchProviders[_entry.provider];
687
+ if (provider) {
688
+ var _entry$key, _entry$label, _entry$labelmsgid;
689
+ if (provider.requiresLayer && !themeLayerNames.includes(provider.requiresLayer)) {
690
+ continue;
720
691
  }
721
- // Omit qgis provider with field configuration, this is only supported through the FeatureSearch plugin
722
- if (entry.provider === 'qgis' && (_entry = entry) !== null && _entry !== void 0 && (_entry = _entry.params) !== null && _entry !== void 0 && _entry.fields) {
723
- return 0; // continue
692
+ var key = (_entry$key = _entry.key) !== null && _entry$key !== void 0 ? _entry$key : _entry.provider;
693
+ if (providerKeys.has(key)) {
694
+ var i = 0;
695
+ for (i = 0; providerKeys.has(key + "_" + i); ++i);
696
+ key = key + "_" + i;
724
697
  }
725
- var provider = searchProviders[entry.provider];
726
- if (provider) {
727
- var _entry$key, _entry$label, _entry$labelmsgid;
728
- if (provider.requiresLayer && !themeLayerNames.includes(provider.requiresLayer)) {
729
- return 0; // continue
698
+ providerKeys.add(key);
699
+ availableProviders[key] = _objectSpread(_objectSpread({}, provider), {}, {
700
+ label: (_entry$label = _entry.label) !== null && _entry$label !== void 0 ? _entry$label : provider.label,
701
+ labelmsgid: (_entry$labelmsgid = _entry.labelmsgid) !== null && _entry$labelmsgid !== void 0 ? _entry$labelmsgid : provider.labelmsgid,
702
+ getResultGeometry: provider.getResultGeometry,
703
+ cfgParams: _entry.params || {},
704
+ params: {
705
+ searchTerms: searchTerms,
706
+ activeLayers: activeLayers,
707
+ theme: theme
730
708
  }
731
- var key = (_entry$key = entry.key) !== null && _entry$key !== void 0 ? _entry$key : entry.provider;
732
- if (providerKeys.has(key)) {
733
- var i = 0;
734
- for (i = 0; providerKeys.has(key + "_" + i); ++i);
735
- key = key + "_" + i;
736
- }
737
- providerKeys.add(key);
738
- availableProviders[key] = _objectSpread(_objectSpread({}, provider), {}, {
739
- label: (_entry$label = entry.label) !== null && _entry$label !== void 0 ? _entry$label : provider.label,
740
- labelmsgid: (_entry$labelmsgid = entry.labelmsgid) !== null && _entry$labelmsgid !== void 0 ? _entry$labelmsgid : provider.labelmsgid,
741
- getResultGeometry: provider.getResultGeometry ? function (item, callback) {
742
- return getResultGeometry(provider, item, callback);
743
- } : null,
744
- cfgParams: entry.params || {},
745
- params: {
746
- searchTerms: searchTerms,
747
- activeLayers: activeLayers,
748
- theme: theme
749
- }
750
- });
751
- }
752
- },
753
- _ret;
754
- for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
755
- _ret = _loop();
756
- if (_ret === 0) continue;
709
+ });
710
+ }
757
711
  }
758
712
  } catch (err) {
759
713
  _iterator2.e(err);