qwc2 2025.10.30 → 2025.11.12

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 (55) hide show
  1. package/actions/layers.js +6 -29
  2. package/components/AttributeForm.js +106 -77
  3. package/components/AttributeTableWidget.js +89 -88
  4. package/components/IdentifyViewer.js +4 -2
  5. package/components/LinkFeatureForm.js +17 -9
  6. package/components/LocationRecorder.js +1 -1
  7. package/components/PickFeature.js +45 -33
  8. package/components/QtDesignerForm.js +20 -18
  9. package/components/StandardApp.js +4 -0
  10. package/components/ThemeList.js +9 -10
  11. package/components/map3d/Map3D.js +6 -3
  12. package/package.json +2 -1
  13. package/plugins/Cyclomedia.js +5 -4
  14. package/plugins/Editing.js +307 -72
  15. package/plugins/FeatureForm.js +103 -111
  16. package/plugins/LayerTree.js +4 -1
  17. package/plugins/NewsPopup.js +2 -2
  18. package/plugins/Portal.js +3 -1
  19. package/plugins/Print.js +4 -4
  20. package/plugins/Redlining.js +9 -0
  21. package/plugins/ThemeSwitcher.js +3 -0
  22. package/plugins/map/EditingSupport.js +2 -2
  23. package/plugins/map/RedliningSupport.js +63 -13
  24. package/plugins/style/Editing.css +34 -0
  25. package/reducers/editing.js +12 -7
  26. package/reducers/layers.js +27 -5
  27. package/static/translations/bg-BG.json +10 -0
  28. package/static/translations/ca-ES.json +10 -0
  29. package/static/translations/cs-CZ.json +10 -0
  30. package/static/translations/de-CH.json +10 -0
  31. package/static/translations/de-DE.json +10 -0
  32. package/static/translations/en-US.json +11 -1
  33. package/static/translations/es-ES.json +10 -0
  34. package/static/translations/fi-FI.json +10 -0
  35. package/static/translations/fr-FR.json +10 -0
  36. package/static/translations/hu-HU.json +10 -0
  37. package/static/translations/it-IT.json +10 -0
  38. package/static/translations/ja-JP.json +10 -0
  39. package/static/translations/nl-NL.json +10 -0
  40. package/static/translations/no-NO.json +10 -0
  41. package/static/translations/pl-PL.json +10 -0
  42. package/static/translations/pt-BR.json +10 -0
  43. package/static/translations/pt-PT.json +10 -0
  44. package/static/translations/ro-RO.json +10 -0
  45. package/static/translations/ru-RU.json +10 -0
  46. package/static/translations/sv-SE.json +10 -0
  47. package/static/translations/tr-TR.json +10 -0
  48. package/static/translations/tsconfig.json +10 -0
  49. package/static/translations/uk-UA.json +10 -0
  50. package/utils/EditingUtils.js +15 -13
  51. package/utils/ElevationInterface.js +1 -2
  52. package/utils/LayerUtils.js +5 -3
  53. package/utils/MapUtils.js +2 -11
  54. package/utils/ServiceLayerUtils.js +53 -2
  55. package/utils/ThemeUtils.js +3 -1
@@ -1,17 +1,17 @@
1
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 _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
3
- function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
4
- function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
5
- function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
6
2
  function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
7
3
  function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
8
- function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
9
4
  function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
10
5
  function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
11
- function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
12
6
  function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
13
7
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
14
8
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
9
+ function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
10
+ function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
11
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
12
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
13
+ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
14
+ function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
15
15
  function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
16
16
  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); } }
17
17
  function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
@@ -93,37 +93,43 @@ var AttributeTableWidget = /*#__PURE__*/function (_React$Component) {
93
93
  });
94
94
  });
95
95
  _defineProperty(_this, "reload", function () {
96
- var layerName = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
96
+ var selectedLayer = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
97
97
  _this.setState(function (state) {
98
98
  var _this$props$filter$fi;
99
- var selectedLayer = layerName || state.selectedLayer;
100
- var editConfig = _this.props.theme.editConfig || {};
101
- var currentEditConfig = editConfig[selectedLayer];
99
+ selectedLayer = selectedLayer || state.selectedLayer;
100
+ var _selectedLayer$split = selectedLayer.split("#"),
101
+ _selectedLayer$split2 = _slicedToArray(_selectedLayer$split, 2),
102
+ wmsName = _selectedLayer$split2[0],
103
+ layerName = _selectedLayer$split2[1];
104
+ var editConfig = _this.props.editConfigs[wmsName][layerName];
102
105
  KeyValCache.clear();
103
106
  FeatureCache.clear();
104
107
  var bbox = _this.state.limitToExtent ? _this.props.mapBbox.bounds : null;
105
- _this.props.iface.getFeatures(currentEditConfig, _this.props.mapCrs, function (result) {
108
+ _this.props.iface.getFeatures(editConfig, _this.props.mapCrs, function (result) {
106
109
  if (result) {
110
+ var _this$props$layers$fi, _this$props$layers$fi2;
107
111
  var features = result.features || [];
112
+ var fieldTranslations = (_this$props$layers$fi = (_this$props$layers$fi2 = _this.props.layers.find(function (layer) {
113
+ return layer.wms_name === wmsName;
114
+ })) === null || _this$props$layers$fi2 === void 0 || (_this$props$layers$fi2 = _this$props$layers$fi2.translations) === null || _this$props$layers$fi2 === void 0 || (_this$props$layers$fi2 = _this$props$layers$fi2.layers) === null || _this$props$layers$fi2 === void 0 || (_this$props$layers$fi2 = _this$props$layers$fi2[layerName]) === null || _this$props$layers$fi2 === void 0 ? void 0 : _this$props$layers$fi2.fields) !== null && _this$props$layers$fi !== void 0 ? _this$props$layers$fi : {};
108
115
  _this.setState(function (state2) {
109
116
  return {
110
117
  loading: false,
111
118
  features: features,
112
119
  filteredSortedFeatures: _this.filteredSortedFeatures(features, state2),
113
- loadedLayer: selectedLayer
120
+ loadedLayer: selectedLayer,
121
+ curEditConfig: editConfig,
122
+ curFieldTranslations: fieldTranslations
114
123
  };
115
124
  });
116
125
  } else {
117
126
  // eslint-disable-next-line
118
127
  alert(LocaleUtils.tr("attribtable.loadfailed"));
119
128
  _this.setState({
120
- loading: false,
121
- features: [],
122
- filteredSortedFeatures: [],
123
- loadedLayer: ""
129
+ loading: false
124
130
  });
125
131
  }
126
- }, bbox, (_this$props$filter$fi = _this.props.filter.filterParams) === null || _this$props$filter$fi === void 0 ? void 0 : _this$props$filter$fi[selectedLayer], _this.props.filter.filterGeom, _this.props.showDisplayFieldOnly ? [currentEditConfig.displayField, "geometry"] : null);
132
+ }, bbox, (_this$props$filter$fi = _this.props.filter.filterParams) === null || _this$props$filter$fi === void 0 ? void 0 : _this$props$filter$fi[selectedLayer], _this.props.filter.filterGeom, _this.props.showDisplayFieldOnly ? [editConfig.displayField, "geometry"] : null);
127
133
  return _objectSpread(_objectSpread({}, AttributeTableWidget.defaultState), {}, {
128
134
  loading: true,
129
135
  selectedLayer: selectedLayer,
@@ -151,13 +157,12 @@ var AttributeTableWidget = /*#__PURE__*/function (_React$Component) {
151
157
  newState.filteredSortedFeatures = _this.filteredSortedFeatures(_this.state.features, _objectSpread(_objectSpread({}, _this.state), newState));
152
158
  _this.setState(newState);
153
159
  });
154
- _defineProperty(_this, "renderField", function (currentEditConfig, field, featureidx, filteredIndex, fielddisabled) {
160
+ _defineProperty(_this, "renderField", function (editConfig, mapPrefix, field, featureidx, filteredIndex, fielddisabled) {
155
161
  var feature = _this.state.features[featureidx];
156
162
  var value = feature.properties[field.id];
157
163
  if (value === undefined || value === null) {
158
164
  value = "";
159
165
  }
160
- var mapPrefix = (currentEditConfig.editDataset.match(/^[^.]+\./) || [""])[0];
161
166
  var updateField = function updateField(fieldid, val) {
162
167
  var emptynull = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
163
168
  return _this.updateField(featureidx, filteredIndex, fieldid, val, emptynull);
@@ -179,7 +184,7 @@ var AttributeTableWidget = /*#__PURE__*/function (_React$Component) {
179
184
  } else if (constraints.values || constraints.keyvalrel) {
180
185
  var filterExpr = null;
181
186
  if (field.filterExpression) {
182
- filterExpr = parseExpression(field.filterExpression, feature, currentEditConfig, _this.props.iface, mapPrefix, _this.props.mapCrs, function () {
187
+ filterExpr = parseExpression(field.filterExpression, feature, editConfig, _this.props.iface, mapPrefix, _this.props.mapCrs, function () {
183
188
  return _this.setState({
184
189
  reevaluate: +new Date()
185
190
  });
@@ -233,7 +238,7 @@ var AttributeTableWidget = /*#__PURE__*/function (_React$Component) {
233
238
  } else if (field.type === "file") {
234
239
  return /*#__PURE__*/React.createElement(EditUploadField, {
235
240
  constraints: constraints,
236
- dataset: currentEditConfig.editDataset,
241
+ dataset: editConfig.editDataset,
237
242
  disabled: disabled,
238
243
  fieldId: field.id,
239
244
  iface: _this.props.iface,
@@ -284,12 +289,7 @@ var AttributeTableWidget = /*#__PURE__*/function (_React$Component) {
284
289
  return input;
285
290
  });
286
291
  _defineProperty(_this, "addFeature", function () {
287
- var editConfig = _this.props.theme.editConfig || {};
288
- var currentEditConfig = editConfig[_this.state.loadedLayer];
289
- if (!currentEditConfig) {
290
- return;
291
- }
292
- var hasGeometry = (currentEditConfig || {}).geomType !== null;
292
+ var hasGeometry = _this.state.curEditConfig.geomType !== null;
293
293
  if (!_this.props.allowAddForGeometryLayers && hasGeometry) {
294
294
  // eslint-disable-next-line
295
295
  alert(LocaleUtils.tr("attribtable.geomnoadd"));
@@ -298,15 +298,15 @@ var AttributeTableWidget = /*#__PURE__*/function (_React$Component) {
298
298
  var featureSkel = {
299
299
  type: "Feature",
300
300
  geometry: null,
301
- properties: currentEditConfig.fields.reduce(function (res, field) {
301
+ properties: _this.state.curEditConfig.fields.reduce(function (res, field) {
302
302
  if (field.id !== "id") {
303
303
  res[field.id] = field.type === "text" ? "" : null;
304
304
  }
305
305
  return res;
306
306
  }, {})
307
307
  };
308
- var mapPrefix = (currentEditConfig.editDataset.match(/^[^.]+\./) || [""])[0];
309
- getFeatureTemplate(currentEditConfig, featureSkel, _this.props.iface, mapPrefix, _this.props.mapCrs, function (feature) {
308
+ var mapPrefix = _this.state.curEditConfig.editDataset.split(".")[0];
309
+ getFeatureTemplate(_this.state.curEditConfig, featureSkel, _this.props.iface, mapPrefix, _this.props.mapCrs, function (feature) {
310
310
  _this.setState(function (state) {
311
311
  return {
312
312
  features: [].concat(_toConsumableArray(state.features), [feature]),
@@ -327,11 +327,8 @@ var AttributeTableWidget = /*#__PURE__*/function (_React$Component) {
327
327
  var features = state.filteredSortedFeatures.filter(function (feature) {
328
328
  return state.selectedFeatures[feature.id] === true;
329
329
  });
330
- var selectedLayer = state.selectedLayer;
331
- var editConfig = _this.props.theme.editConfig || {};
332
- var currentEditConfig = editConfig[selectedLayer];
333
330
  features.forEach(function (feature) {
334
- _this.props.iface.deleteFeature(currentEditConfig, feature.id, function (success) {
331
+ _this.props.iface.deleteFeature(state.curEditConfig, feature.id, function (success) {
335
332
  _this.setState(function (state2) {
336
333
  var newState = {
337
334
  deleteTask: _objectSpread(_objectSpread({}, state2.deleteTask), {}, {
@@ -399,20 +396,18 @@ var AttributeTableWidget = /*#__PURE__*/function (_React$Component) {
399
396
  }
400
397
  }
401
398
  });
402
- var editConfig = _this.props.theme.editConfig || {};
403
- var currentEditConfig = editConfig[_this.state.loadedLayer];
404
399
  Object.keys(feature.properties || {}).forEach(function (name) {
405
- var _currentEditConfig$fi, _currentEditConfig$fi2, _currentEditConfig$fi3;
406
- var fieldConfig = (_currentEditConfig$fi = (_currentEditConfig$fi2 = currentEditConfig.fields) === null || _currentEditConfig$fi2 === void 0 || (_currentEditConfig$fi3 = _currentEditConfig$fi2.find) === null || _currentEditConfig$fi3 === void 0 ? void 0 : _currentEditConfig$fi3.call(_currentEditConfig$fi2, function (f) {
400
+ var _this$state$curEditCo, _this$state$curEditCo2, _this$state$curEditCo3;
401
+ var fieldConfig = (_this$state$curEditCo = (_this$state$curEditCo2 = _this.state.curEditConfig.fields) === null || _this$state$curEditCo2 === void 0 || (_this$state$curEditCo3 = _this$state$curEditCo2.find) === null || _this$state$curEditCo3 === void 0 ? void 0 : _this$state$curEditCo3.call(_this$state$curEditCo2, function (f) {
407
402
  return f.id === name;
408
- })) !== null && _currentEditConfig$fi !== void 0 ? _currentEditConfig$fi : {};
403
+ })) !== null && _this$state$curEditCo !== void 0 ? _this$state$curEditCo : {};
409
404
  if (fieldConfig.expression) {
410
405
  // Skip virtual fields
411
406
  delete feature.properties[name];
412
407
  }
413
408
  });
414
409
  // Omit geometry if it is read-only
415
- var canEditGeometry = ['Point', 'LineString', 'Polygon'].includes((currentEditConfig.geomType || "").replace(/^Multi/, '').replace(/Z$/, ''));
410
+ var canEditGeometry = ['Point', 'LineString', 'Polygon'].includes((_this.state.curEditConfig.geomType || "").replace(/^Multi/, '').replace(/Z$/, ''));
416
411
  if (!canEditGeometry) {
417
412
  delete feature.geometry;
418
413
  }
@@ -428,11 +423,11 @@ var AttributeTableWidget = /*#__PURE__*/function (_React$Component) {
428
423
  featureData.set('g-recaptcha-response', _this.state.captchaResponse);
429
424
  }
430
425
  if (_this.state.newFeature) {
431
- _this.props.iface.addFeatureMultipart(currentEditConfig, _this.props.mapCrs, featureData, function (success, result) {
426
+ _this.props.iface.addFeatureMultipart(_this.state.curEditConfig, _this.props.mapCrs, featureData, function (success, result) {
432
427
  return _this.featureCommited(success, result);
433
428
  });
434
429
  } else {
435
- _this.props.iface.editFeatureMultipart(currentEditConfig, _this.props.mapCrs, feature.id, featureData, function (success, result) {
430
+ _this.props.iface.editFeatureMultipart(_this.state.curEditConfig, _this.props.mapCrs, feature.id, featureData, function (success, result) {
436
431
  return _this.featureCommited(success, result);
437
432
  });
438
433
  }
@@ -513,9 +508,7 @@ var AttributeTableWidget = /*#__PURE__*/function (_React$Component) {
513
508
  }
514
509
  });
515
510
  _defineProperty(_this, "switchToFormEditMode", function () {
516
- var editConfig = _this.props.theme.editConfig || {};
517
- var currentEditConfig = editConfig[_this.state.loadedLayer];
518
- var hasGeometry = (currentEditConfig || {}).geomType !== null;
511
+ var hasGeometry = _this.state.curEditConfig.geomType !== null;
519
512
  if (!hasGeometry) {
520
513
  // eslint-disable-next-line
521
514
  alert(LocaleUtils.tr("attribtable.nogeomnoform"));
@@ -572,9 +565,7 @@ var AttributeTableWidget = /*#__PURE__*/function (_React$Component) {
572
565
  };
573
566
  }
574
567
  // Build value relation lookup
575
- var editConfig = _this.props.theme.editConfig || {};
576
- var currentEditConfig = editConfig[_this.state.loadedLayer];
577
- var valueLookup = currentEditConfig.fields.reduce(function (res, field) {
568
+ var valueLookup = _this.state.curEditConfig.fields.reduce(function (res, field) {
578
569
  if (field.constraints && field.constraints.values) {
579
570
  res[field.id] = field.constraints.values.reduce(function (res2, constraint) {
580
571
  res2[constraint.value] = constraint.label;
@@ -658,14 +649,9 @@ var AttributeTableWidget = /*#__PURE__*/function (_React$Component) {
658
649
  }
659
650
  });
660
651
  _defineProperty(_this, "csvExport", function () {
661
- var editConfig = _this.props.theme.editConfig || {};
662
- var currentEditConfig = editConfig[_this.state.loadedLayer];
663
- if (!currentEditConfig) {
664
- return;
665
- }
666
- var fields = _this.props.showDisplayFieldOnly ? currentEditConfig.fields.filter(function (field) {
667
- return field.name === currentEditConfig.displayField;
668
- }) : currentEditConfig.fields.filter(function (field) {
652
+ var fields = _this.props.showDisplayFieldOnly ? _this.state.curEditConfig.fields.filter(function (field) {
653
+ return field.name === _this.state.curEditConfig.displayField;
654
+ }) : _this.state.curEditConfig.fields.filter(function (field) {
669
655
  return field.id !== 'id';
670
656
  });
671
657
  var data = "";
@@ -686,9 +672,9 @@ var AttributeTableWidget = /*#__PURE__*/function (_React$Component) {
686
672
  type: "text/plain;charset=utf-8"
687
673
  }), _this.state.loadedLayer + ".csv");
688
674
  });
689
- _defineProperty(_this, "translateFieldName", function (fieldName, layerName) {
690
- var _this$props$theme$tra, _this$props$theme$tra2;
691
- return (_this$props$theme$tra = (_this$props$theme$tra2 = _this.props.theme.translations) === null || _this$props$theme$tra2 === void 0 || (_this$props$theme$tra2 = _this$props$theme$tra2.layers) === null || _this$props$theme$tra2 === void 0 || (_this$props$theme$tra2 = _this$props$theme$tra2[layerName]) === null || _this$props$theme$tra2 === void 0 || (_this$props$theme$tra2 = _this$props$theme$tra2.fields) === null || _this$props$theme$tra2 === void 0 ? void 0 : _this$props$theme$tra2[fieldName]) !== null && _this$props$theme$tra !== void 0 ? _this$props$theme$tra : fieldName;
675
+ _defineProperty(_this, "translateFieldName", function (fieldName) {
676
+ var _this$state$fieldTran, _this$state$fieldTran2;
677
+ return (_this$state$fieldTran = (_this$state$fieldTran2 = _this.state.fieldTranslations) === null || _this$state$fieldTran2 === void 0 ? void 0 : _this$state$fieldTran2[fieldName]) !== null && _this$state$fieldTran !== void 0 ? _this$state$fieldTran : fieldName;
692
678
  });
693
679
  _this.changedFiles = {};
694
680
  _this.state = AttributeTableWidget.defaultState;
@@ -735,9 +721,8 @@ var AttributeTableWidget = /*#__PURE__*/function (_React$Component) {
735
721
  var _this2 = this;
736
722
  var captchaRequired = ConfigUtils.getConfigProp("editServiceCaptchaSiteKey") && !ConfigUtils.getConfigProp("username");
737
723
  var captchaPending = captchaRequired && !this.state.captchaResponse;
738
- var editConfig = this.props.theme.editConfig || {};
739
- var currentEditConfig = editConfig[this.state.loadedLayer];
740
- var editPermissions = (editConfig[this.state.loadedLayer] || {}).permissions || {};
724
+ var curEditConfig = this.state.curEditConfig;
725
+ var editPermissions = (curEditConfig === null || curEditConfig === void 0 ? void 0 : curEditConfig.permissions) || {};
741
726
  var readOnly = this.props.readOnly || editPermissions.updatable === false;
742
727
  var loadOverlay = null;
743
728
  if (this.state.selectedLayer && this.state.selectedLayer !== this.state.loadedLayer) {
@@ -750,17 +735,18 @@ var AttributeTableWidget = /*#__PURE__*/function (_React$Component) {
750
735
  className: "attribtable-overlay"
751
736
  }, /*#__PURE__*/React.createElement("span", null, LocaleUtils.tr("attribtable.pleasereload")));
752
737
  }
753
- } else if (this.state.selectedLayer && this.state.deleteTask) {
738
+ } else if (this.state.deleteTask) {
754
739
  loadOverlay = /*#__PURE__*/React.createElement("div", {
755
740
  className: "attribtable-overlay"
756
741
  }, /*#__PURE__*/React.createElement(Spinner, null), /*#__PURE__*/React.createElement("span", null, LocaleUtils.tr("attribtable.deleting")));
757
742
  }
758
743
  var table = null;
759
744
  var footbar = null;
760
- if (currentEditConfig && this.state.features) {
761
- var fields = this.props.showDisplayFieldOnly ? currentEditConfig.fields.filter(function (field) {
762
- return field.name === currentEditConfig.displayField;
763
- }) : currentEditConfig.fields.filter(function (field) {
745
+ if (curEditConfig && this.state.features) {
746
+ var mapPrefix = this.state.curEditConfig.editDataset.split(".")[0];
747
+ var fields = this.props.showDisplayFieldOnly ? curEditConfig.fields.filter(function (field) {
748
+ return field.name === curEditConfig.displayField;
749
+ }) : curEditConfig.fields.filter(function (field) {
764
750
  var _field$constraints;
765
751
  return field.id !== "id" && (_this2.props.showHiddenFields || ((_field$constraints = field.constraints) === null || _field$constraints === void 0 ? void 0 : _field$constraints.hidden) !== true);
766
752
  });
@@ -775,19 +761,19 @@ var AttributeTableWidget = /*#__PURE__*/function (_React$Component) {
775
761
  onClick: function onClick() {
776
762
  return _this2.sortBy("id");
777
763
  },
778
- title: this.translateFieldName("id", this.state.loadedLayer)
764
+ title: this.translateFieldName("id")
779
765
  }, /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement("span", {
780
766
  className: "attribtable-table-headername"
781
- }, this.translateFieldName("id", this.state.loadedLayer)), this.renderSortIndicator("id"), this.renderColumnResizeHandle(1, 'r'))) : null, fields.map(function (field, idx) {
767
+ }, this.translateFieldName("id")), this.renderSortIndicator("id"), this.renderColumnResizeHandle(1, 'r'))) : null, fields.map(function (field, idx) {
782
768
  return /*#__PURE__*/React.createElement("th", {
783
769
  key: field.id,
784
770
  onClick: function onClick() {
785
771
  return _this2.sortBy(field.id);
786
772
  },
787
- title: _this2.translateFieldName(field.name, _this2.state.loadedLayer)
773
+ title: _this2.translateFieldName(field.name)
788
774
  }, /*#__PURE__*/React.createElement("span", null, _this2.renderColumnResizeHandle(idx + 1, 'l'), /*#__PURE__*/React.createElement("span", {
789
775
  className: "attribtable-table-headername"
790
- }, _this2.translateFieldName(field.name, _this2.state.loadedLayer)), _this2.renderSortIndicator(field.id), idx < fields.length - 1 ? _this2.renderColumnResizeHandle(idx + 2, 'r') : null));
776
+ }, _this2.translateFieldName(field.name)), _this2.renderSortIndicator(field.id), idx < fields.length - 1 ? _this2.renderColumnResizeHandle(idx + 2, 'r') : null));
791
777
  }))), /*#__PURE__*/React.createElement("tbody", null, features.map(function (feature, filteredIndex) {
792
778
  var featureidx = feature.originalIndex;
793
779
  var disabled = readOnly || _this2.state.changedFeatureIdx !== null && _this2.state.changedFeatureIdx !== featureidx;
@@ -820,7 +806,7 @@ var AttributeTableWidget = /*#__PURE__*/function (_React$Component) {
820
806
  }), _this2.renderRowResizeHandle(filteredIndex + 1, 'b'))), !_this2.props.showDisplayFieldOnly ? /*#__PURE__*/React.createElement("td", null, feature.id) : null, fields.map(function (field) {
821
807
  return /*#__PURE__*/React.createElement("td", {
822
808
  key: field.id
823
- }, _this2.renderField(currentEditConfig, field, featureidx, indexOffset + filteredIndex, disabled || !!_this2.state.filterVal && field.id === _this2.state.filterField));
809
+ }, _this2.renderField(curEditConfig, mapPrefix, field, featureidx, indexOffset + filteredIndex, disabled || !!_this2.state.filterVal && field.id === _this2.state.filterField));
824
810
  }));
825
811
  })));
826
812
  var npages = Math.ceil(this.state.filteredSortedFeatures.length / this.state.pageSize);
@@ -866,11 +852,11 @@ var AttributeTableWidget = /*#__PURE__*/function (_React$Component) {
866
852
  value: this.state.filterField
867
853
  }, /*#__PURE__*/React.createElement("option", {
868
854
  value: "id"
869
- }, this.translateFieldName("id", this.state.loadedLayer)), fields.map(function (field) {
855
+ }, this.translateFieldName("id")), fields.map(function (field) {
870
856
  return /*#__PURE__*/React.createElement("option", {
871
857
  key: field.id,
872
858
  value: field.id
873
- }, _this2.translateFieldName(field.name, _this2.state.loadedLayer));
859
+ }, _this2.translateFieldName(field.name));
874
860
  })), /*#__PURE__*/React.createElement("select", {
875
861
  disabled: this.state.changedFeatureIdx !== null,
876
862
  onChange: function onChange(ev) {
@@ -905,11 +891,11 @@ var AttributeTableWidget = /*#__PURE__*/function (_React$Component) {
905
891
  type: "checkbox"
906
892
  }), " ", LocaleUtils.tr("attribtable.limittoextent"))) : null);
907
893
  }
908
- var nolayer = !this.state.selectedLayer;
894
+ var nolayer = curEditConfig === null;
909
895
  var loading = this.state.loading;
910
896
  var editing = this.state.changedFeatureIdx !== null;
911
897
  var layerChanged = this.state.selectedLayer !== this.state.loadedLayer;
912
- var hasGeometry = (currentEditConfig || {}).geomType !== null;
898
+ var hasGeometry = (curEditConfig || {}).geomType !== null;
913
899
  var showAddButton = !this.props.readOnly && editPermissions.creatable !== false && (this.props.allowAddForGeometryLayers || !hasGeometry);
914
900
  var showDelButton = !this.props.readOnly && editPermissions.deletable !== false;
915
901
  var showEditButton = !this.props.readOnly && ConfigUtils.havePlugin("Editing") && this.props.showEditFormButton;
@@ -951,17 +937,29 @@ var AttributeTableWidget = /*#__PURE__*/function (_React$Component) {
951
937
  }, /*#__PURE__*/React.createElement("option", {
952
938
  disabled: true,
953
939
  value: ""
954
- }, LocaleUtils.tr("attribtable.selectlayer")), Object.keys(editConfig).map(function (layerId) {
955
- var _this2$props$theme$tr, _this2$props$theme$tr2, _LayerUtils$searchLay, _LayerUtils$searchLay2;
956
- var layerName = editConfig[layerId].layerName;
957
- var layerTitle = editConfig[layerId].layerTitle ? (_this2$props$theme$tr = (_this2$props$theme$tr2 = _this2.props.theme.translations) === null || _this2$props$theme$tr2 === void 0 || (_this2$props$theme$tr2 = _this2$props$theme$tr2.layertree) === null || _this2$props$theme$tr2 === void 0 ? void 0 : _this2$props$theme$tr2[layerName]) !== null && _this2$props$theme$tr !== void 0 ? _this2$props$theme$tr : editConfig[layerId].layerTitle : (_LayerUtils$searchLay = (_LayerUtils$searchLay2 = LayerUtils.searchLayer(_this2.props.layers, _this2.props.theme.url, layerName)) === null || _LayerUtils$searchLay2 === void 0 || (_LayerUtils$searchLay2 = _LayerUtils$searchLay2.sublayer) === null || _LayerUtils$searchLay2 === void 0 ? void 0 : _LayerUtils$searchLay2.title) !== null && _LayerUtils$searchLay !== void 0 ? _LayerUtils$searchLay : layerName;
958
- return /*#__PURE__*/React.createElement("option", {
959
- key: layerId,
960
- value: layerId
961
- }, layerTitle);
940
+ }, LocaleUtils.tr("attribtable.selectlayer")), Object.entries(this.props.editConfigs).map(function (_ref4) {
941
+ var _ref5 = _slicedToArray(_ref4, 2),
942
+ wmsName = _ref5[0],
943
+ serviceConfigs = _ref5[1];
944
+ return Object.entries(serviceConfigs).map(function (_ref6) {
945
+ var _ref8, _ref9, _match$layer$translat, _match$layer$translat2, _match$sublayer;
946
+ var _ref7 = _slicedToArray(_ref6, 2),
947
+ layerName = _ref7[0],
948
+ editConfig = _ref7[1];
949
+ var match = LayerUtils.searchLayer(_this2.props.layers, 'wms_name', wmsName, 'name', layerName);
950
+ if (!match) {
951
+ return null;
952
+ }
953
+ var layerTitle = (_ref8 = (_ref9 = (_match$layer$translat = (_match$layer$translat2 = match.layer.translations) === null || _match$layer$translat2 === void 0 || (_match$layer$translat2 = _match$layer$translat2.layertree) === null || _match$layer$translat2 === void 0 ? void 0 : _match$layer$translat2[layerName]) !== null && _match$layer$translat !== void 0 ? _match$layer$translat : editConfig.layerTitle) !== null && _ref9 !== void 0 ? _ref9 : match === null || match === void 0 || (_match$sublayer = match.sublayer) === null || _match$sublayer === void 0 ? void 0 : _match$sublayer.title) !== null && _ref8 !== void 0 ? _ref8 : layerName;
954
+ var value = wmsName + "#" + layerName;
955
+ return /*#__PURE__*/React.createElement("option", {
956
+ key: value,
957
+ value: value
958
+ }, layerTitle);
959
+ });
962
960
  })) : null, /*#__PURE__*/React.createElement("button", {
963
961
  className: "button",
964
- disabled: editing || nolayer || this.state.loading,
962
+ disabled: !this.state.selectedLayer || editing || this.state.loading,
965
963
  onClick: function onClick() {
966
964
  return _this2.reload();
967
965
  },
@@ -1042,6 +1040,7 @@ _defineProperty(AttributeTableWidget, "propTypes", {
1042
1040
  addLayerFeatures: PropTypes.func,
1043
1041
  /** Whether to allow adding records for datasets which have a geometry column. */
1044
1042
  allowAddForGeometryLayers: PropTypes.bool,
1043
+ editConfigs: PropTypes.object,
1045
1044
  filter: PropTypes.object,
1046
1045
  iface: PropTypes.object,
1047
1046
  initialLayer: PropTypes.string,
@@ -1065,7 +1064,6 @@ _defineProperty(AttributeTableWidget, "propTypes", {
1065
1064
  showLayerSelection: PropTypes.bool,
1066
1065
  /** Whether to show the "Limit to extent" checkbox */
1067
1066
  showLimitToExtent: PropTypes.bool,
1068
- theme: PropTypes.object,
1069
1067
  /** The zoom level for zooming to point features. */
1070
1068
  zoomLevel: PropTypes.number,
1071
1069
  zoomToExtent: PropTypes.func,
@@ -1082,6 +1080,9 @@ _defineProperty(AttributeTableWidget, "defaultState", {
1082
1080
  loading: false,
1083
1081
  selectedLayer: "",
1084
1082
  loadedLayer: "",
1083
+ curEditConfig: null,
1084
+ curTranslations: null,
1085
+ fieldTranslations: null,
1085
1086
  features: [],
1086
1087
  filteredSortedFeatures: [],
1087
1088
  selectedFeatures: {},
@@ -1102,12 +1103,12 @@ _defineProperty(AttributeTableWidget, "defaultState", {
1102
1103
  });
1103
1104
  export default connect(function (state) {
1104
1105
  return {
1106
+ editConfigs: state.layers.editConfigs,
1105
1107
  layers: state.layers.flat,
1106
1108
  filter: state.layers.filter,
1107
1109
  mapBbox: state.map.bbox,
1108
1110
  mapCrs: state.map.projection,
1109
- mapScales: state.map.scales,
1110
- theme: state.theme.current
1111
+ mapScales: state.map.scales
1111
1112
  };
1112
1113
  }, {
1113
1114
  addLayerFeatures: addLayerFeatures,
@@ -671,7 +671,9 @@ var IdentifyViewer = /*#__PURE__*/function (_React$Component) {
671
671
  }, /*#__PURE__*/React.createElement("i", null, LocaleUtils.tr("identify.featureReport") + ": " + report.title)), /*#__PURE__*/React.createElement("td", {
672
672
  className: "identify-attr-value " + _this.props.longAttributesDisplay
673
673
  }, /*#__PURE__*/React.createElement("a", {
674
- href: _this.getFeatureReportUrl(report, feature)
674
+ href: _this.getFeatureReportUrl(report, feature),
675
+ rel: "noreferrer",
676
+ target: "_blank"
675
677
  }, LocaleUtils.tr("identify.link")))));
676
678
  });
677
679
  if (isEmpty(rows)) {
@@ -1056,7 +1058,7 @@ var IdentifyViewer = /*#__PURE__*/function (_React$Component) {
1056
1058
  _layer$split2 = _slicedToArray(_layer$split, 2),
1057
1059
  layerUrl = _layer$split2[0],
1058
1060
  layerName = _layer$split2[1];
1059
- var match = LayerUtils.searchLayer(_this.props.layers, layerUrl, layerName);
1061
+ var match = LayerUtils.searchLayer(_this.props.layers, 'url', layerUrl, 'name', layerName);
1060
1062
  if (match) {
1061
1063
  _this.props.setActiveLayerInfo(match.layer, match.sublayer);
1062
1064
  }
@@ -117,7 +117,9 @@ var LinkFeatureForm = /*#__PURE__*/function (_React$Component) {
117
117
  this.props.setEditContext(this.props.editContextId, {
118
118
  action: 'Pick',
119
119
  feature: this.props.feature,
120
- geomType: this.props.editConfig.geomType
120
+ geomType: this.props.editConfig.geomType,
121
+ editConfig: this.props.editConfig,
122
+ mapPrefix: this.props.mapPrefix
121
123
  });
122
124
  } else {
123
125
  this.props.iface.getFeatureById(this.props.editConfig, this.props.featureId, this.props.map.projection, function (result) {
@@ -125,7 +127,9 @@ var LinkFeatureForm = /*#__PURE__*/function (_React$Component) {
125
127
  _this2.props.setEditContext(_this2.props.editContextId, {
126
128
  action: 'Pick',
127
129
  feature: result,
128
- geomType: _this2.props.editConfig.geomType
130
+ geomType: _this2.props.editConfig.geomType,
131
+ editConfig: _this2.props.editConfig,
132
+ mapPrefix: _this2.props.mapPrefix
129
133
  });
130
134
  }
131
135
  });
@@ -135,17 +139,19 @@ var LinkFeatureForm = /*#__PURE__*/function (_React$Component) {
135
139
  type: "Feature",
136
140
  properties: {}
137
141
  }, this.props.feature);
138
- var mapPrefix = (this.props.editConfig.editDataset.match(/^[^.]+\./) || [""])[0];
139
- getFeatureTemplate(this.props.editConfig, featureSkel, this.props.iface, mapPrefix, this.props.map.projection, function (feature) {
142
+ getFeatureTemplate(this.props.editConfig, featureSkel, this.props.iface, this.props.mapPrefix, this.props.map.projection, function (feature) {
140
143
  _this2.props.setEditContext(_this2.props.editContextId, {
141
144
  action: 'Draw',
142
145
  geomType: _this2.props.editConfig.geomType,
143
- feature: feature
146
+ feature: feature,
147
+ editConfig: _this2.props.editConfig,
148
+ mapPrefix: _this2.props.mapPrefix
144
149
  });
145
150
  });
146
151
  } else if (this.props.action === 'Pick') {
147
152
  this.props.setEditContext(this.props.editContextId, {
148
- action: null
153
+ editConfig: this.props.editConfig,
154
+ mapPrefix: this.props.mapPrefix
149
155
  });
150
156
  }
151
157
  }
@@ -202,12 +208,12 @@ var LinkFeatureForm = /*#__PURE__*/function (_React$Component) {
202
208
  }, drawing ? /*#__PURE__*/React.createElement("div", {
203
209
  className: "link-feature-form-hint"
204
210
  }, /*#__PURE__*/React.createElement("span", null, LocaleUtils.tr("linkfeatureform.drawhint"))) : /*#__PURE__*/React.createElement(AttributeForm, {
205
- editConfig: this.props.editConfig,
206
211
  editContext: editContext,
207
212
  hideDelete: this.props.hideDelete,
208
213
  iface: this.props.iface,
209
214
  onDiscard: this.onDiscard,
210
- readOnly: this.props.readOnly
215
+ readOnly: this.props.readOnly,
216
+ translations: this.props.translations
211
217
  }), /*#__PURE__*/React.createElement("div", {
212
218
  className: "link-feature-form-close"
213
219
  }, /*#__PURE__*/React.createElement("button", {
@@ -234,10 +240,12 @@ _defineProperty(LinkFeatureForm, "propTypes", {
234
240
  hideDelete: PropTypes.bool,
235
241
  iface: PropTypes.object,
236
242
  map: PropTypes.object,
243
+ mapPrefix: PropTypes.string,
237
244
  pickFilter: PropTypes.func,
238
245
  readOnly: PropTypes.bool,
239
246
  removeLayer: PropTypes.func,
240
- setEditContext: PropTypes.func
247
+ setEditContext: PropTypes.func,
248
+ translations: PropTypes.object
241
249
  });
242
250
  export default connect(function (state) {
243
251
  return {
@@ -56,7 +56,7 @@ var LocationRecorder = /*#__PURE__*/function (_React$Component) {
56
56
  console.error("Geolocation not supported");
57
57
  } else {
58
58
  _this.props.drawInteraction.appendCoordinates([_this.props.locatePosition]);
59
- if (_this.props.geomType === "Point") {
59
+ if (_this.props.geomType.replace(/^Multi/, '') === "Point") {
60
60
  _this.stopRecording();
61
61
  } else {
62
62
  _this.pollInterval = setInterval(function () {