qwc2 2026.8.7 → 2026.8.9

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.
@@ -363,11 +363,33 @@ var IdentifyViewer = /*#__PURE__*/function (_React$Component) {
363
363
  _defineProperty(_this, "storeIdentifyResults", function () {
364
364
  return new Promise(function (resolve) {
365
365
  return resolve({
366
- identifyResults: _this.state.resultTree,
366
+ identifyResults: _this.serializeResults(),
367
367
  currentResultDisplayMode: _this.props.resultDisplayMode
368
368
  });
369
369
  });
370
370
  });
371
+ _defineProperty(_this, "serializeResults", function () {
372
+ return Object.fromEntries(Object.entries(_this.state.resultTree).map(function (_ref10) {
373
+ var _ref11 = _slicedToArray(_ref10, 2),
374
+ layerid = _ref11[0],
375
+ features = _ref11[1];
376
+ var _layerid$split = layerid.split("#", 2),
377
+ _layerid$split2 = _slicedToArray(_layerid$split, 2),
378
+ layerUrl = _layerid$split2[0],
379
+ layerName = _layerid$split2[1];
380
+ var match = LayerUtils.searchLayer(_this.props.layers, 'url', layerUrl, 'name', layerName);
381
+ if (match && match.sublayer.primary_key) {
382
+ return [layerid, {
383
+ key: match.sublayer.primary_key,
384
+ values: features.map(function (feature) {
385
+ return MiscUtils.isNumeric(feature.id) ? Number(feature.id) : feature.id;
386
+ })
387
+ }];
388
+ } else {
389
+ return [layerid, features];
390
+ }
391
+ }));
392
+ });
371
393
  _defineProperty(_this, "getCurrentResultFeature", function () {
372
394
  var _this$state$resultTre, _this$state$resultTre2, _this$state$resultTre3, _this$state$currentRe;
373
395
  return (_this$state$resultTre = (_this$state$resultTre2 = _this.state.resultTree[(_this$state$currentRe = _this.state.currentResult) === null || _this$state$currentRe === void 0 ? void 0 : _this$state$currentRe.layerid]) === null || _this$state$resultTre2 === void 0 || (_this$state$resultTre3 = _this$state$resultTre2.find) === null || _this$state$resultTre3 === void 0 ? void 0 : _this$state$resultTre3.call(_this$state$resultTre2, function (feature) {
@@ -490,10 +512,10 @@ var IdentifyViewer = /*#__PURE__*/function (_React$Component) {
490
512
  });
491
513
  if (exporter) {
492
514
  if (!_this.props.exportGeometry) {
493
- json = Object.entries(json).reduce(function (res, _ref12) {
494
- var _ref13 = _slicedToArray(_ref12, 2),
495
- layerId = _ref13[0],
496
- features = _ref13[1];
515
+ json = Object.entries(json).reduce(function (res, _ref14) {
516
+ var _ref15 = _slicedToArray(_ref14, 2),
517
+ layerId = _ref15[0],
518
+ features = _ref15[1];
497
519
  return _objectSpread(_objectSpread({}, res), {}, _defineProperty({}, layerId, features.map(function (feature) {
498
520
  return MiscUtils.objectOmit(feature, ['geometry']);
499
521
  })));
@@ -521,10 +543,10 @@ var IdentifyViewer = /*#__PURE__*/function (_React$Component) {
521
543
  style: {
522
544
  maxHeight: _this.state.currentResult ? '10em' : 'initial'
523
545
  }
524
- }, Object.entries(_this.state.resultTree).map(function (_ref14) {
525
- var _ref15 = _slicedToArray(_ref14, 2),
526
- layerid = _ref15[0],
527
- features = _ref15[1];
546
+ }, Object.entries(_this.state.resultTree).map(function (_ref16) {
547
+ var _ref17 = _slicedToArray(_ref16, 2),
548
+ layerid = _ref17[0],
549
+ features = _ref17[1];
528
550
  if (features.length === 0) {
529
551
  return null;
530
552
  }
@@ -805,20 +827,20 @@ var IdentifyViewer = /*#__PURE__*/function (_React$Component) {
805
827
  _defineProperty(_this, "renderResultsTable", function () {
806
828
  return /*#__PURE__*/React.createElement("div", {
807
829
  className: "identify-results-tables"
808
- }, Object.entries(_this.state.resultTree).map(function (_ref16) {
809
- var _ref17 = _slicedToArray(_ref16, 2),
810
- layerid = _ref17[0],
811
- features = _ref17[1];
830
+ }, Object.entries(_this.state.resultTree).map(function (_ref18) {
831
+ var _ref19 = _slicedToArray(_ref18, 2),
832
+ layerid = _ref19[0],
833
+ features = _ref19[1];
812
834
  if (features.length === 0 || _this.state.selectedLayer && layerid !== _this.state.selectedLayer) {
813
835
  return null;
814
836
  }
815
837
  var fields = {};
816
838
  features.map(function (feature) {
817
- Object.entries(feature.properties).map(function (_ref18) {
818
- var _ref19 = _slicedToArray(_ref18, 2),
819
- attr = _ref19[0],
820
- value = _ref19[1];
821
- if (!(attr in fields)) {
839
+ Object.entries(feature.properties).map(function (_ref20) {
840
+ var _ref21 = _slicedToArray(_ref20, 2),
841
+ attr = _ref21[0],
842
+ value = _ref21[1];
843
+ if (!(attr in fields) && !['htmlContent', 'htmlContentInline'].includes(attr)) {
822
844
  fields[attr] = {
823
845
  id: attr,
824
846
  name: attr
@@ -1061,10 +1083,10 @@ var IdentifyViewer = /*#__PURE__*/function (_React$Component) {
1061
1083
  }, /*#__PURE__*/React.createElement("option", {
1062
1084
  disabled: true,
1063
1085
  value: ""
1064
- }, LocaleUtils.tr("identify.selectreport")), Object.entries(_this.state.reports).map(function (_ref21) {
1065
- var _ref22 = _slicedToArray(_ref21, 2),
1066
- layername = _ref22[0],
1067
- reports = _ref22[1];
1086
+ }, LocaleUtils.tr("identify.selectreport")), Object.entries(_this.state.reports).map(function (_ref23) {
1087
+ var _ref24 = _slicedToArray(_ref23, 2),
1088
+ layername = _ref24[0],
1089
+ reports = _ref24[1];
1068
1090
  return reports.map(function (report, idx) {
1069
1091
  return /*#__PURE__*/React.createElement("option", {
1070
1092
  key: layername + "::" + idx,
@@ -1328,6 +1350,7 @@ var IdentifyViewer = /*#__PURE__*/function (_React$Component) {
1328
1350
  key: "componentDidMount",
1329
1351
  value: function componentDidMount() {
1330
1352
  this.updateResultTree();
1353
+ this.props.innerRef(this);
1331
1354
  }
1332
1355
  }, {
1333
1356
  key: "componentDidUpdate",
@@ -1360,6 +1383,7 @@ var IdentifyViewer = /*#__PURE__*/function (_React$Component) {
1360
1383
  }, {
1361
1384
  key: "componentWillUnmount",
1362
1385
  value: function componentWillUnmount() {
1386
+ this.props.innerRef(null);
1363
1387
  this.props.removeLayer("__identifyviewerhighlight");
1364
1388
  unregisterPermalinkDataStoreHook("identifyresultstate");
1365
1389
  }
@@ -1369,10 +1393,10 @@ var IdentifyViewer = /*#__PURE__*/function (_React$Component) {
1369
1393
  var _this2 = this;
1370
1394
  var body = null;
1371
1395
  var resultTree = this.state.selectedLayer !== '' ? _defineProperty({}, this.state.selectedLayer, this.state.resultTree[this.state.selectedLayer]) : this.state.resultTree;
1372
- var flatResults = Object.entries(resultTree).map(function (_ref25) {
1373
- var _ref26 = _slicedToArray(_ref25, 2),
1374
- layerid = _ref26[0],
1375
- features = _ref26[1];
1396
+ var flatResults = Object.entries(resultTree).map(function (_ref27) {
1397
+ var _ref28 = _slicedToArray(_ref27, 2),
1398
+ layerid = _ref28[0],
1399
+ features = _ref28[1];
1376
1400
  return features.map(function (feature) {
1377
1401
  return [layerid, feature];
1378
1402
  });
@@ -1400,10 +1424,10 @@ var IdentifyViewer = /*#__PURE__*/function (_React$Component) {
1400
1424
  } else if (this.props.resultDisplayMode === 'flat') {
1401
1425
  body = /*#__PURE__*/React.createElement("div", {
1402
1426
  className: "identify-flat-results-list"
1403
- }, Object.entries(resultTree).map(function (_ref27) {
1404
- var _ref28 = _slicedToArray(_ref27, 2),
1405
- layerid = _ref28[0],
1406
- features = _ref28[1];
1427
+ }, Object.entries(resultTree).map(function (_ref29) {
1428
+ var _ref30 = _slicedToArray(_ref29, 2),
1429
+ layerid = _ref30[0],
1430
+ features = _ref30[1];
1407
1431
  return features.map(function (feature) {
1408
1432
  return _this2.renderResultAttributes(layerid, feature, 'identify-result-frame');
1409
1433
  });
@@ -1417,10 +1441,10 @@ var IdentifyViewer = /*#__PURE__*/function (_React$Component) {
1417
1441
  body = /*#__PURE__*/React.createElement("div", {
1418
1442
  className: "identify-compare-results",
1419
1443
  style: _style
1420
- }, results.map(function (_ref29) {
1421
- var _ref30 = _slicedToArray(_ref29, 2),
1422
- layerid = _ref30[0],
1423
- feature = _ref30[1];
1444
+ }, results.map(function (_ref31) {
1445
+ var _ref32 = _slicedToArray(_ref31, 2),
1446
+ layerid = _ref32[0],
1447
+ feature = _ref32[1];
1424
1448
  return _this2.renderResultAttributes(layerid, feature, 'identify-result-frame');
1425
1449
  }));
1426
1450
  } else if (this.state.currentPage < flatResults.length) {
@@ -1455,6 +1479,7 @@ _defineProperty(IdentifyViewer, "propTypes", {
1455
1479
  highlightAllResults: PropTypes.bool,
1456
1480
  identifyResults: PropTypes.object,
1457
1481
  iframeDialogsInitiallyDocked: PropTypes.bool,
1482
+ innerRef: PropTypes.func,
1458
1483
  layers: PropTypes.array,
1459
1484
  longAttributesDisplay: PropTypes.oneOf(['ellipsis', 'wrap']),
1460
1485
  map: PropTypes.object,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qwc2",
3
- "version": "2026.08.07",
3
+ "version": "2026.08.09",
4
4
  "description": "QGIS Web Client",
5
5
  "author": "Sourcepole AG",
6
6
  "license": "BSD-2-Clause",
@@ -47,6 +47,7 @@ import NumberInput from '../components/widgets/NumberInput';
47
47
  import ConfigUtils from '../utils/ConfigUtils';
48
48
  import CoordinatesUtils from '../utils/CoordinatesUtils';
49
49
  import IdentifyUtils from '../utils/IdentifyUtils';
50
+ import LayerUtils from '../utils/LayerUtils';
50
51
  import LocaleUtils from '../utils/LocaleUtils';
51
52
  import MeasureUtils from '../utils/MeasureUtils';
52
53
  import VectorLayerUtils from '../utils/VectorLayerUtils';
@@ -76,7 +77,8 @@ var Identify = /*#__PURE__*/function (_React$Component) {
76
77
  radiusUnits: _this.props.initialRadiusUnits,
77
78
  exitTaskOnResultsClose: null,
78
79
  filterGeom: null,
79
- filterGeomModifiers: {}
80
+ filterGeomModifiers: {},
81
+ importErrors: null
80
82
  });
81
83
  _defineProperty(_this, "queryPoint", function (prevProps) {
82
84
  if (_this.props.click.button !== 0 || _this.props.click === prevProps.click || (_this.props.click.features || []).find(function (feature) {
@@ -103,10 +105,6 @@ var Identify = /*#__PURE__*/function (_React$Component) {
103
105
  var identifyResults = _this.props.click.modifiers.ctrl !== true && !appendResultsByDefault ? {} : (_state$identifyResult = state.identifyResults) !== null && _state$identifyResult !== void 0 ? _state$identifyResult : {};
104
106
  var params = _objectSpread({}, _this.props.params);
105
107
  var resultDisplayMode = _this.props.taskEnabled ? (_this$props$taskResul = _this.props.taskResultDisplayMode) !== null && _this$props$taskResul !== void 0 ? _this$props$taskResul : _this.props.resultDisplayMode : _this.props.resultDisplayMode;
106
- if (resultDisplayMode === "table") {
107
- params.with_htmlcontent = false;
108
- params.with_maptip = false;
109
- }
110
108
  var queryableLayers = [];
111
109
  queryableLayers = IdentifyUtils.getQueryLayers(_this.props.layers, _this.props.map);
112
110
  queryableLayers.forEach(function (l) {
@@ -171,10 +169,6 @@ var Identify = /*#__PURE__*/function (_React$Component) {
171
169
  var pendingRequests = 0;
172
170
  var params = _objectSpread({}, _this.props.params);
173
171
  var resultDisplayMode = _this.props.taskEnabled ? (_this$props$taskResul2 = _this.props.taskResultDisplayMode) !== null && _this$props$taskResul2 !== void 0 ? _this$props$taskResul2 : _this.props.resultDisplayMode : _this.props.resultDisplayMode;
174
- if (resultDisplayMode === "table") {
175
- params.with_htmlcontent = false;
176
- params.with_maptip = false;
177
- }
178
172
  if (_this.props.params.region_feature_count) {
179
173
  params.feature_count = _this.props.params.region_feature_count;
180
174
  delete params.region_feature_count;
@@ -254,6 +248,7 @@ var Identify = /*#__PURE__*/function (_React$Component) {
254
248
  identifyResults: identifyResults
255
249
  };
256
250
  });
251
+ return newResults;
257
252
  });
258
253
  _defineProperty(_this, "onShow", function (mode, data) {
259
254
  _this.setState({
@@ -384,10 +379,13 @@ var Identify = /*#__PURE__*/function (_React$Component) {
384
379
  }
385
380
  });
386
381
  _defineProperty(_this, "export", function () {
387
- var data = JSON.stringify(_this.state.identifyResults, null, ' ');
388
- FileSaver.saveAs(new Blob([data], {
389
- type: 'application/json'
390
- }), 'results.json');
382
+ if (_this.viewerRef) {
383
+ var results = _this.viewerRef.serializeResults();
384
+ var data = JSON.stringify(results, null, ' ');
385
+ FileSaver.saveAs(new Blob([data], {
386
+ type: 'application/json'
387
+ }), 'results.json');
388
+ }
391
389
  });
392
390
  _defineProperty(_this, "import", function () {
393
391
  _this.fileinput.click();
@@ -397,27 +395,91 @@ var Identify = /*#__PURE__*/function (_React$Component) {
397
395
  reader.readAsText(ev.target.files[0]);
398
396
  reader.onload = function () {
399
397
  try {
400
- var identifyResults = JSON.parse(reader.result);
401
- _this.setState({
402
- identifyResults: identifyResults,
403
- pendingRequests: 0
404
- });
398
+ var _this$props$taskResul3;
399
+ var resultDisplayMode = _this.props.taskEnabled ? (_this$props$taskResul3 = _this.props.taskResultDisplayMode) !== null && _this$props$taskResul3 !== void 0 ? _this$props$taskResul3 : _this.props.resultDisplayMode : _this.props.resultDisplayMode;
400
+ _this.deserializeResults(JSON.parse(reader.result), resultDisplayMode);
405
401
  } catch (_unused2) {
406
402
  /* eslint-disable-next-line no-alert */
407
403
  alert(LocaleUtils.tr("common.dataloadfailed"));
408
404
  }
409
405
  };
410
406
  });
407
+ _defineProperty(_this, "deserializeResults", function (identifyResults, resultDisplayMode) {
408
+ var pendingRequests = 0;
409
+ Object.entries(identifyResults).forEach(function (_ref5) {
410
+ var _ref6 = _slicedToArray(_ref5, 2),
411
+ layerid = _ref6[0],
412
+ layerresults = _ref6[1];
413
+ if (layerresults.key && layerresults.values) {
414
+ delete identifyResults[layerid]; // Features will be re-queried
415
+ var _layerid$split = layerid.split("#", 2),
416
+ _layerid$split2 = _slicedToArray(_layerid$split, 2),
417
+ layerUrl = _layerid$split2[0],
418
+ layerName = _layerid$split2[1];
419
+ var match = LayerUtils.searchLayer(_this.props.layers, 'url', layerUrl, 'name', layerName);
420
+ if (match) {
421
+ var values = layerresults.values.map(function (x) {
422
+ return typeof x === "string" ? "\"".concat(x, "\"") : x;
423
+ }).join(" , ");
424
+ var filter = {
425
+ filter: "".concat(layerName, ":\"").concat(layerresults.key, "\" IN ( ").concat(values, " )")
426
+ };
427
+ var request = IdentifyUtils.buildFilterRequest(match.layer, layerName, undefined, _this.props.map, filter);
428
+ ++pendingRequests;
429
+ IdentifyUtils.sendRequest(request, function (response) {
430
+ _this.setState(function (state2) {
431
+ return {
432
+ pendingRequests: state2.pendingRequests - 1
433
+ };
434
+ });
435
+ if (response) {
436
+ var results = _this.parseResult(response, match.layer, request.params.info_format, [0, 0], false);
437
+ var restoredkeys = new Set(results[layerName].map(function (f) {
438
+ return String(f.id);
439
+ }));
440
+ var missing = layerresults.values.filter(function (x) {
441
+ return !restoredkeys.has(String(x));
442
+ });
443
+ if (missing.length > 0) {
444
+ _this.setState(function (state) {
445
+ return {
446
+ importErrors: _objectSpread(_objectSpread({}, state.importErrors), {}, _defineProperty({}, layerid, {
447
+ key: layerresults.key,
448
+ missing: missing
449
+ }))
450
+ };
451
+ });
452
+ }
453
+ } else {
454
+ _this.setState(function (state) {
455
+ return {
456
+ importErrors: _objectSpread(_objectSpread({}, state.importErrors), {}, _defineProperty({}, layerid, true))
457
+ };
458
+ });
459
+ }
460
+ });
461
+ }
462
+ }
463
+ });
464
+ _this.setState({
465
+ identifyResults: identifyResults,
466
+ pendingRequests: pendingRequests,
467
+ importErrors: {},
468
+ currentResultDisplayMode: resultDisplayMode
469
+ });
470
+ });
411
471
  _this.fileinput = document.createElement("input");
412
472
  _this.fileinput.type = "file";
413
473
  _this.fileinput.accept = "application/json";
414
474
  _this.fileinput.addEventListener("change", _this.fileSelected);
475
+ _this.viewerRef = null;
415
476
  return _this;
416
477
  }
417
478
  _inherits(Identify, _React$Component);
418
479
  return _createClass(Identify, [{
419
480
  key: "componentDidUpdate",
420
481
  value: function componentDidUpdate(prevProps, prevState) {
482
+ var _this2 = this;
421
483
  if (this.props.enabled && this.props.theme && !prevProps.theme) {
422
484
  var startupParams = this.props.startupParams;
423
485
  var haveIc = ["1", "true"].includes((startupParams.ic || "").toLowerCase());
@@ -428,7 +490,7 @@ var Identify = /*#__PURE__*/function (_React$Component) {
428
490
  var mapCrs = this.props.theme.mapCrs;
429
491
  this.identifyPoint(CoordinatesUtils.reproject(c, startupParams.crs || mapCrs, mapCrs));
430
492
  } else if (this.props.startupState.identifyresultstate) {
431
- this.setState(_objectSpread({}, this.props.startupState.identifyresultstate));
493
+ this.deserializeResults(_objectSpread({}, this.props.startupState.identifyresultstate.identifyResults), this.props.startupState.identifyresultstate.currentResultDisplayMode);
432
494
  }
433
495
  } else if (this.props.theme !== prevProps.theme) {
434
496
  this.clearResults();
@@ -482,16 +544,38 @@ var Identify = /*#__PURE__*/function (_React$Component) {
482
544
  if (isEmpty(this.state.identifyResults) && this.props.onlyShowDialogWithResults) {
483
545
  this.clearResults();
484
546
  }
547
+ if (!isEmpty(this.state.importErrors)) {
548
+ var errMsg = Object.entries(this.state.importErrors).map(function (_ref7) {
549
+ var _match$sublayer$title, _match$sublayer;
550
+ var _ref8 = _slicedToArray(_ref7, 2),
551
+ layerid = _ref8[0],
552
+ errors = _ref8[1];
553
+ var _layerid$split3 = layerid.split("#", 2),
554
+ _layerid$split4 = _slicedToArray(_layerid$split3, 2),
555
+ layerUrl = _layerid$split4[0],
556
+ layerName = _layerid$split4[1];
557
+ var match = LayerUtils.searchLayer(_this2.props.layers, 'url', layerUrl, 'name', layerName);
558
+ var layertitle = (_match$sublayer$title = match === null || match === void 0 || (_match$sublayer = match.sublayer) === null || _match$sublayer === void 0 ? void 0 : _match$sublayer.title) !== null && _match$sublayer$title !== void 0 ? _match$sublayer$title : layerName;
559
+ if (errors === true) {
560
+ return "- ".concat(layertitle, ": ").concat(LocaleUtils.tr("identify.missinglayer"));
561
+ } else {
562
+ return "- ".concat(layertitle, ": ").concat(LocaleUtils.tr("identify.featuresmissing", errors.missing.length, "".concat(errors.key, " = {").concat(errors.missing.join(","), "}")));
563
+ }
564
+ }).join("\n");
565
+ // eslint-disable-next-line no-alert
566
+ alert(LocaleUtils.tr("identify.importerrors", errMsg));
567
+ }
485
568
  this.setState({
486
569
  filterGeom: null,
487
- filterGeomModifiers: {}
570
+ filterGeomModifiers: {},
571
+ importErrors: null
488
572
  });
489
573
  }
490
574
  }
491
575
  }, {
492
576
  key: "render",
493
577
  value: function render() {
494
- var _this2 = this;
578
+ var _this3 = this;
495
579
  var resultWindow = null;
496
580
  if (this.props.onlyShowDialogWithResults && isEmpty(this.state.identifyResults)) {
497
581
  // pass
@@ -523,6 +607,9 @@ var Identify = /*#__PURE__*/function (_React$Component) {
523
607
  highlightAllResults: this.props.highlightAllResults,
524
608
  identifyResults: this.state.identifyResults,
525
609
  iframeDialogsInitiallyDocked: this.props.iframeDialogsInitiallyDocked,
610
+ innerRef: function innerRef(el) {
611
+ _this3.viewerRef = el;
612
+ },
526
613
  longAttributesDisplay: this.props.longAttributesDisplay,
527
614
  replaceImageUrls: this.props.replaceImageUrls,
528
615
  resultDisplayMode: this.state.currentResultDisplayMode,
@@ -561,14 +648,14 @@ var Identify = /*#__PURE__*/function (_React$Component) {
561
648
  task: "Identify"
562
649
  }, function () {
563
650
  return {
564
- body: _this2.renderBody()
651
+ body: _this3.renderBody()
565
652
  };
566
653
  }), ["Region", "Rectangle", "Radius", "Circle"].includes(this.state.mode) ? /*#__PURE__*/React.createElement(MapSelection, {
567
654
  active: this.state.mode !== "Radius",
568
655
  geomType: geomTypeMap[this.state.mode],
569
656
  geometry: this.state.filterGeom,
570
657
  geometryChanged: function geometryChanged(geom, mod) {
571
- return _this2.setState({
658
+ return _this3.setState({
572
659
  filterGeom: geom,
573
660
  filterGeomModifiers: mod
574
661
  });
@@ -170,6 +170,7 @@ function getLayerTree(layer, resultLayers, visibleLayers, printLayers, level, co
170
170
  title: layer.Title
171
171
  };
172
172
  if (layer.Layer === undefined) {
173
+ var _layer$PrimaryKey;
173
174
  if (layer.$_geometryType === "WKBNoGeometry" || layer.$_geometryType === "NoGeometry") {
174
175
  // skip layers without geometry
175
176
  return;
@@ -186,6 +187,9 @@ function getLayerTree(layer, resultLayers, visibleLayers, printLayers, level, co
186
187
  // collect visible layers
187
188
  visibleLayers.push(layer.Name);
188
189
  }
190
+ if ((_layer$PrimaryKey = layer.PrimaryKey) !== null && _layer$PrimaryKey !== void 0 && _layer$PrimaryKey.PrimaryKeyAttribute) {
191
+ layerEntry.primary_key = layer.PrimaryKey.PrimaryKeyAttribute;
192
+ }
189
193
  layerEntry.queryable = layer.$_queryable === '1';
190
194
  if (layerEntry.queryable) {
191
195
  layerEntry.displayField = layer.$_displayField;
@@ -187,6 +187,8 @@ def getLayerTree(layer, resultLayers, visibleLayers, printLayers, level, collaps
187
187
  # collect visible layers
188
188
  visibleLayers.append(name)
189
189
 
190
+ layerEntry['primary_key'] = getChildElementValue(layer, 'PrimaryKey/PrimaryKeyAttribute')
191
+
190
192
  layerEntry["queryable"] = layer.getAttribute("queryable") == "1"
191
193
  if layerEntry["queryable"] and layer.getAttribute("displayField"):
192
194
  layerEntry["displayField"] = layer.getAttribute("displayField")
@@ -303,8 +303,11 @@
303
303
  "comparing": "",
304
304
  "featureReport": "Отчет за функциите",
305
305
  "featurecount": "",
306
+ "featuresmissing": "",
307
+ "importerrors": "",
306
308
  "layerall": "Всички слоеве",
307
309
  "link": "Връзка към",
310
+ "missinglayer": "",
308
311
  "multiview": "",
309
312
  "noattributes": "Без атрибути",
310
313
  "noresults": "Няма налична информация за избраната точка",
@@ -303,8 +303,11 @@
303
303
  "comparing": "Comparant {0} elements",
304
304
  "featureReport": "Informe d'element",
305
305
  "featurecount": "{0} element(s)",
306
+ "featuresmissing": "",
307
+ "importerrors": "",
306
308
  "layerall": "Totes les capes",
307
309
  "link": "Link",
310
+ "missinglayer": "",
308
311
  "multiview": "Multivista",
309
312
  "noattributes": "Sense atributs",
310
313
  "noresults": "Sense informació disponible sobre el punt seleccionat",
@@ -303,8 +303,11 @@
303
303
  "comparing": "",
304
304
  "featureReport": "Report prvku",
305
305
  "featurecount": "",
306
+ "featuresmissing": "",
307
+ "importerrors": "",
306
308
  "layerall": "",
307
309
  "link": "Odkaz",
310
+ "missinglayer": "",
308
311
  "multiview": "",
309
312
  "noattributes": "Bez atributů",
310
313
  "noresults": "V tomto bodu nejsou k dispozici informace o žádném prvku",
@@ -303,8 +303,11 @@
303
303
  "comparing": "Vergleich von {0} Objekte",
304
304
  "featureReport": "Objektblatt",
305
305
  "featurecount": "{0} Objekt(e)",
306
+ "featuresmissing": "{0} Objekte konnten nicht abgefragt werden: {1}",
307
+ "importerrors": "Beim Import sind Fehler aufgetreten:\n{0}",
306
308
  "layerall": "Alle Ebenen",
307
309
  "link": "Link",
310
+ "missinglayer": "Ebene konnte nicht abgefragt werden",
308
311
  "multiview": "Mehrfachansicht",
309
312
  "noattributes": "Keine Attribute",
310
313
  "noresults": "Keine Treffer an der ausgewählten Position",
@@ -303,8 +303,11 @@
303
303
  "comparing": "Vergleich von {0} Objekte",
304
304
  "featureReport": "Objektblatt",
305
305
  "featurecount": "{0} Objekt(e)",
306
+ "featuresmissing": "{0} Objekte konnten nicht abgefragt werden: {1}",
307
+ "importerrors": "Beim Import sind Fehler aufgetreten:\n{0}",
306
308
  "layerall": "Alle Ebenen",
307
309
  "link": "Link",
310
+ "missinglayer": "Ebene konnte nicht abgefragt werden",
308
311
  "multiview": "Mehrfachansicht",
309
312
  "noattributes": "Keine Attribute",
310
313
  "noresults": "Keine Treffer an der ausgewählten Position",
@@ -303,8 +303,11 @@
303
303
  "comparing": "Comparing {0} features",
304
304
  "featureReport": "Feature report",
305
305
  "featurecount": "{0} feature(s)",
306
+ "featuresmissing": "{0} features could not be queried: {1}",
307
+ "importerrors": "Errors occurred during import:\n{0}",
306
308
  "layerall": "All layers",
307
309
  "link": "Link",
310
+ "missinglayer": "Layer could not be queried",
308
311
  "multiview": "Multi-view",
309
312
  "noattributes": "No attributes",
310
313
  "noresults": "No information available for the selected point",
@@ -303,8 +303,11 @@
303
303
  "comparing": "Comparando {0} elementos",
304
304
  "featureReport": "Informe del elemento",
305
305
  "featurecount": "{0} elemento(s)",
306
+ "featuresmissing": "",
307
+ "importerrors": "",
306
308
  "layerall": "Todas las capas",
307
309
  "link": "Link",
310
+ "missinglayer": "",
308
311
  "multiview": "Vista múltiple",
309
312
  "noattributes": "Sin atributos",
310
313
  "noresults": "Sin información disponible sobre el punto seleccionado",
@@ -303,8 +303,11 @@
303
303
  "comparing": "",
304
304
  "featureReport": "Ominaisuustietoraportti",
305
305
  "featurecount": "",
306
+ "featuresmissing": "",
307
+ "importerrors": "",
306
308
  "layerall": "",
307
309
  "link": "Linkki",
310
+ "missinglayer": "",
308
311
  "multiview": "",
309
312
  "noattributes": "Attribuutteja ei löytynyt",
310
313
  "noresults": "Valitulla pisteellä ei ole informaatiota",
@@ -303,8 +303,11 @@
303
303
  "comparing": "Comparison de {0} objets",
304
304
  "featureReport": "Données de l'objet",
305
305
  "featurecount": "{0} élément(s)",
306
+ "featuresmissing": "{0} objects pas identifiables: {1}",
307
+ "importerrors": "Erreurs de importation:\n{0}",
306
308
  "layerall": "Toutes les couches",
307
309
  "link": "Lien",
310
+ "missinglayer": "Couche pas identifiable",
308
311
  "multiview": "Vue multiple",
309
312
  "noattributes": "Pas d'attribut",
310
313
  "noresults": "Pas de résultats pour la position sélectionnée",
@@ -303,8 +303,11 @@
303
303
  "comparing": "",
304
304
  "featureReport": "Lekérdezés eredménye",
305
305
  "featurecount": "",
306
+ "featuresmissing": "",
307
+ "importerrors": "",
306
308
  "layerall": "",
307
309
  "link": "Link",
310
+ "missinglayer": "",
308
311
  "multiview": "",
309
312
  "noattributes": "",
310
313
  "noresults": "Nincs információ a kiválasztott pontról",
@@ -303,8 +303,11 @@
303
303
  "comparing": "Confronto di {0} oggetti",
304
304
  "featureReport": "Oggetto formulario",
305
305
  "featurecount": "{0} oggetti",
306
+ "featuresmissing": "{0} oggetti non identificabili: {1}",
307
+ "importerrors": "Errori di importazione:\n{0}",
306
308
  "layerall": "Tutti i livelli",
307
309
  "link": "Link",
310
+ "missinglayer": "Livello non identificabile",
308
311
  "multiview": "Vista multipla",
309
312
  "noattributes": "Nessun attributo",
310
313
  "noresults": "Nessun risultato",
@@ -303,8 +303,11 @@
303
303
  "comparing": "",
304
304
  "featureReport": "地物レポート",
305
305
  "featurecount": "",
306
+ "featuresmissing": "",
307
+ "importerrors": "",
306
308
  "layerall": "全てのレイヤ",
307
309
  "link": "リンク",
310
+ "missinglayer": "",
308
311
  "multiview": "",
309
312
  "noattributes": "属性無し",
310
313
  "noresults": "選択された点には情報がありません",
@@ -303,8 +303,11 @@
303
303
  "comparing": "",
304
304
  "featureReport": "Rapport",
305
305
  "featurecount": "",
306
+ "featuresmissing": "",
307
+ "importerrors": "",
306
308
  "layerall": "",
307
309
  "link": "Link",
310
+ "missinglayer": "",
308
311
  "multiview": "",
309
312
  "noattributes": "Geen attributen",
310
313
  "noresults": "Geen informatie beschikbaar voor het aangewezen punt",
@@ -303,8 +303,11 @@
303
303
  "comparing": "",
304
304
  "featureReport": "Objektrapport",
305
305
  "featurecount": "",
306
+ "featuresmissing": "",
307
+ "importerrors": "",
306
308
  "layerall": "",
307
309
  "link": "Lenke",
310
+ "missinglayer": "",
308
311
  "multiview": "",
309
312
  "noattributes": "Ingen attributt",
310
313
  "noresults": "Ingen informasjon for valgt punkt",
@@ -303,8 +303,11 @@
303
303
  "comparing": "",
304
304
  "featureReport": "Feature report",
305
305
  "featurecount": "",
306
+ "featuresmissing": "",
307
+ "importerrors": "",
306
308
  "layerall": "",
307
309
  "link": "Link",
310
+ "missinglayer": "",
308
311
  "multiview": "",
309
312
  "noattributes": "Brak atrybutów",
310
313
  "noresults": "Brak dostępnych danych dla wybranego punktu",
@@ -303,8 +303,11 @@
303
303
  "comparing": "",
304
304
  "featureReport": "Relatório de recurso",
305
305
  "featurecount": "",
306
+ "featuresmissing": "",
307
+ "importerrors": "",
306
308
  "layerall": "",
307
309
  "link": "Link",
310
+ "missinglayer": "",
308
311
  "multiview": "",
309
312
  "noattributes": "Sem atributos",
310
313
  "noresults": "Nenhuma informação disponível para o ponto selecionado",
@@ -303,8 +303,11 @@
303
303
  "comparing": "",
304
304
  "featureReport": "Relatório de Recurso",
305
305
  "featurecount": "",
306
+ "featuresmissing": "",
307
+ "importerrors": "",
306
308
  "layerall": "",
307
309
  "link": "Link",
310
+ "missinglayer": "",
308
311
  "multiview": "",
309
312
  "noattributes": "Sem Atributos",
310
313
  "noresults": "Nenhuma informação disponível para o ponto selecionado",
@@ -303,8 +303,11 @@
303
303
  "comparing": "Se compară {0} entități",
304
304
  "featureReport": "Raport obiect spațial",
305
305
  "featurecount": "{0} entități",
306
+ "featuresmissing": "",
307
+ "importerrors": "",
306
308
  "layerall": "Toate straturile",
307
309
  "link": "Link",
310
+ "missinglayer": "",
308
311
  "multiview": "Vizualizare multiplă",
309
312
  "noattributes": "Fără atribute",
310
313
  "noresults": "Nu există informații în punctul selectat",
@@ -303,8 +303,11 @@
303
303
  "comparing": "",
304
304
  "featureReport": "Отчёт об объекте",
305
305
  "featurecount": "",
306
+ "featuresmissing": "",
307
+ "importerrors": "",
306
308
  "layerall": "",
307
309
  "link": "гиперссылка",
310
+ "missinglayer": "",
308
311
  "multiview": "",
309
312
  "noattributes": "Аттрибуты отсутствуют",
310
313
  "noresults": "Для выбранной точки нет доступной информации",
@@ -303,8 +303,11 @@
303
303
  "comparing": "",
304
304
  "featureReport": "Objektrapport",
305
305
  "featurecount": "",
306
+ "featuresmissing": "",
307
+ "importerrors": "",
306
308
  "layerall": "",
307
309
  "link": "Länk",
310
+ "missinglayer": "",
308
311
  "multiview": "",
309
312
  "noattributes": "Inga attribut",
310
313
  "noresults": "Ingen information för vald punkt",
@@ -303,8 +303,11 @@
303
303
  "comparing": "",
304
304
  "featureReport": "Obje raporu",
305
305
  "featurecount": "Obje sayısı",
306
+ "featuresmissing": "",
307
+ "importerrors": "",
306
308
  "layerall": "Tüm katmanlar",
307
309
  "link": "Bağlantı",
310
+ "missinglayer": "",
308
311
  "multiview": "",
309
312
  "noattributes": "Öznitelik yok",
310
313
  "noresults": "Seçilen nokta için geçerli bilgi yok",
@@ -300,8 +300,11 @@
300
300
  "identify.comparing",
301
301
  "identify.featureReport",
302
302
  "identify.featurecount",
303
+ "identify.featuresmissing",
304
+ "identify.importerrors",
303
305
  "identify.layerall",
304
306
  "identify.link",
307
+ "identify.missinglayer",
305
308
  "identify.multiview",
306
309
  "identify.noattributes",
307
310
  "identify.noresults",
@@ -303,8 +303,11 @@
303
303
  "comparing": "",
304
304
  "featureReport": "Звіт по об’єкту",
305
305
  "featurecount": "",
306
+ "featuresmissing": "",
307
+ "importerrors": "",
306
308
  "layerall": "",
307
309
  "link": "Посилання",
310
+ "missinglayer": "",
308
311
  "multiview": "",
309
312
  "noattributes": "Атрибути відсутні",
310
313
  "noresults": "Для обраної точки інформація відсутня",
@@ -250,6 +250,7 @@ var ServiceLayerUtils = {
250
250
  _Object$keys$,
251
251
  _layer$Attribution,
252
252
  _layer$Attribution2,
253
+ _layer$PrimaryKey,
253
254
  _layer$opacity;
254
255
  var groupbbox = arguments.length > 10 && arguments[10] !== undefined ? arguments[10] : null;
255
256
  var supportedCrs = MiscUtils.ensureArray(layer.CRS);
@@ -344,6 +345,7 @@ var ServiceLayerUtils = {
344
345
  editConfigUrl: editConfigUrl,
345
346
  translationsUrl: translationsUrl,
346
347
  wms_name: wmsName,
348
+ primary_key: (_layer$PrimaryKey = layer.PrimaryKey) === null || _layer$PrimaryKey === void 0 ? void 0 : _layer$PrimaryKey.PrimaryKeyAttribute,
347
349
  version: version,
348
350
  infoFormats: infoFormats,
349
351
  mapFormats: mapFormats,