qwc2 2026.4.3 → 2026.4.13

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 (37) hide show
  1. package/components/AppMenu.js +2 -1
  2. package/components/SearchBox.js +10 -2
  3. package/components/map3d/layers/MVTLayer3D.js +1 -2
  4. package/components/style/SearchBox.css +11 -0
  5. package/components/widgets/LayerCatalogWidget.js +19 -1
  6. package/components/widgets/style/LayerCatalogWidget.css +11 -0
  7. package/package.json +3 -3
  8. package/plugins/MapExport.js +59 -36
  9. package/plugins/MapInfoTooltip.js +3 -2
  10. package/plugins/NewsPopup.js +0 -1
  11. package/plugins/map/MeasurementSupport.js +19 -7
  12. package/plugins/style/LayerTree.css +5 -0
  13. package/scripts/gen-plugin-docs.js +2 -0
  14. package/static/translations/bg-BG.json +1 -0
  15. package/static/translations/ca-ES.json +1 -0
  16. package/static/translations/cs-CZ.json +1 -0
  17. package/static/translations/de-CH.json +1 -0
  18. package/static/translations/de-DE.json +1 -0
  19. package/static/translations/en-US.json +1 -0
  20. package/static/translations/es-ES.json +1 -0
  21. package/static/translations/fi-FI.json +1 -0
  22. package/static/translations/fr-FR.json +1 -0
  23. package/static/translations/hu-HU.json +1 -0
  24. package/static/translations/it-IT.json +1 -0
  25. package/static/translations/ja-JP.json +1 -0
  26. package/static/translations/nl-NL.json +1 -0
  27. package/static/translations/no-NO.json +1 -0
  28. package/static/translations/pl-PL.json +1 -0
  29. package/static/translations/pt-BR.json +1 -0
  30. package/static/translations/pt-PT.json +1 -0
  31. package/static/translations/ro-RO.json +1 -0
  32. package/static/translations/ru-RU.json +1 -0
  33. package/static/translations/sv-SE.json +1 -0
  34. package/static/translations/tr-TR.json +1 -0
  35. package/static/translations/tsconfig.json +1 -0
  36. package/static/translations/uk-UA.json +1 -0
  37. package/utils/ThemeUtils.js +2 -1
@@ -373,7 +373,8 @@ _defineProperty(AppMenu, "propTypes", {
373
373
  showOnStartup: PropTypes.bool
374
374
  });
375
375
  _defineProperty(AppMenu, "defaultProps", {
376
- onMenuToggled: function onMenuToggled() {}
376
+ onMenuToggled: function onMenuToggled() {},
377
+ menuDisplayMode: "normal"
377
378
  });
378
379
  export default connect(function (state) {
379
380
  return {
@@ -490,6 +490,14 @@ var SearchBox = /*#__PURE__*/function (_React$Component) {
490
490
  onClick: function onClick(ev) {
491
491
  return _this.toggleLayerInfo(ev, provider, group, result, key, parent);
492
492
  }
493
+ }) : null, result.layer.link ? /*#__PURE__*/React.createElement(Icon, {
494
+ className: "searchbox-entry-link",
495
+ icon: "info-sign",
496
+ onClick: function onClick(ev) {
497
+ var _result$label4;
498
+ return _this.openUrl(ev, result.layer.link, result.target, (_result$label4 = result.label) !== null && _result$label4 !== void 0 ? _result$label4 : result.text);
499
+ },
500
+ title: LocaleUtils.tr("layercatalog.openlink")
493
501
  }) : null), _this.state.activeLayerInfo === key ? /*#__PURE__*/React.createElement("div", {
494
502
  className: "searchbox-result-abstract",
495
503
  dangerouslySetInnerHTML: {
@@ -505,7 +513,7 @@ var SearchBox = /*#__PURE__*/function (_React$Component) {
505
513
  }) : null].flat();
506
514
  });
507
515
  _defineProperty(_this, "renderThemeResult", function (provider, group, result) {
508
- var _result$label4;
516
+ var _result$label5;
509
517
  var addThemes = ConfigUtils.getConfigProp("allowAddingOtherThemes", _this.props.theme);
510
518
  return /*#__PURE__*/React.createElement("div", {
511
519
  className: "searchbox-result",
@@ -527,7 +535,7 @@ var SearchBox = /*#__PURE__*/function (_React$Component) {
527
535
  dangerouslySetInnerHTML: {
528
536
  __html: DOMPurify.sanitize(result.text).replace(/<br\s*\/>/ig, ' ')
529
537
  },
530
- title: (_result$label4 = result.label) !== null && _result$label4 !== void 0 ? _result$label4 : result.text
538
+ title: (_result$label5 = result.label) !== null && _result$label5 !== void 0 ? _result$label5 : result.text
531
539
  }), result.theme && addThemes ? /*#__PURE__*/React.createElement(Icon, {
532
540
  icon: "plus",
533
541
  onClick: function onClick(ev) {
@@ -16,8 +16,7 @@ export default {
16
16
  var style = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
17
17
  var source = new VectorTileSource({
18
18
  url: url,
19
- style: style,
20
- backgroundColor: "white"
19
+ style: style
21
20
  });
22
21
  return new ColorLayer({
23
22
  name: options.name,
@@ -136,3 +136,14 @@ div.searchbox-filter-options-geometry > div.combobox {
136
136
  flex: 1 1 auto;
137
137
  height: 2em;
138
138
  }
139
+
140
+ .searchbox-entry-link {
141
+ margin-right: 0.5em;
142
+ margin-left: 0.5em;
143
+ opacity: 0.6;
144
+ transition: opacity 0.2s;
145
+ }
146
+
147
+ .searchbox-entry-link:hover {
148
+ opacity: 1;
149
+ }
@@ -27,7 +27,7 @@ import { remove as removeDiacritics } from 'diacritics';
27
27
  import isEmpty from 'lodash.isempty';
28
28
  import PropTypes from 'prop-types';
29
29
  import { addLayer, removeLayer, replacePlaceholderLayer, LayerRole } from '../../actions/layers';
30
- import { NotificationType, showNotification, closeWindow } from '../../actions/windows';
30
+ import { openExternalUrl, NotificationType, showNotification, closeWindow } from '../../actions/windows';
31
31
  import LayerUtils from '../../utils/LayerUtils';
32
32
  import LocaleUtils from '../../utils/LocaleUtils';
33
33
  import MiscUtils from '../../utils/MiscUtils';
@@ -172,6 +172,15 @@ var LayerCatalogWidget = /*#__PURE__*/function (_React$PureComponent) {
172
172
  }
173
173
  }
174
174
  });
175
+ _defineProperty(_this, "openUrl", function (ev, url, target, title) {
176
+ MiscUtils.killEvent(ev);
177
+ if (target === "iframe") {
178
+ target = ":iframedialog:externallinkiframe";
179
+ }
180
+ _this.props.openExternalUrl(url, target, {
181
+ title: title
182
+ });
183
+ });
175
184
  _this.state.catalog = props.catalog || [];
176
185
  return _this;
177
186
  }
@@ -232,6 +241,13 @@ var LayerCatalogWidget = /*#__PURE__*/function (_React$PureComponent) {
232
241
  return _this2.checkAddServiceLayer(entry, true);
233
242
  },
234
243
  title: LocaleUtils.tr("importlayer.asgroup")
244
+ }) : null, entry.link ? /*#__PURE__*/React.createElement(Icon, {
245
+ className: "layer-catalog-widget-entry-link",
246
+ icon: "info-sign",
247
+ onClick: function onClick(ev) {
248
+ return _this2.openUrl(ev, entry.link, entry.target);
249
+ },
250
+ title: LocaleUtils.tr("layercatalog.openlink")
235
251
  }) : null), entry.expanded ? sublayers : null);
236
252
  }
237
253
  }, {
@@ -287,6 +303,7 @@ _defineProperty(LayerCatalogWidget, "propTypes", {
287
303
  layers: PropTypes.array,
288
304
  levelBasedIndentSize: PropTypes.bool,
289
305
  mapCrs: PropTypes.string,
306
+ openExternalUrl: PropTypes.func,
290
307
  pendingRequests: PropTypes.number,
291
308
  removeLayer: PropTypes.func,
292
309
  replacePlaceholderLayer: PropTypes.func,
@@ -299,6 +316,7 @@ export default connect(function (state) {
299
316
  }, {
300
317
  addLayer: addLayer,
301
318
  closeWindow: closeWindow,
319
+ openExternalUrl: openExternalUrl,
302
320
  removeLayer: removeLayer,
303
321
  replacePlaceholderLayer: replacePlaceholderLayer,
304
322
  showNotification: showNotification
@@ -57,3 +57,14 @@ span.layer-catalog-widget-entry-service {
57
57
  border-radius: 0.25em;
58
58
  width: 6ch;
59
59
  }
60
+
61
+ .layer-catalog-widget-entry-link {
62
+ margin-right: 0.5em;
63
+ margin-left: 0.5em;
64
+ opacity: 0.6;
65
+ transition: opacity 0.2s;
66
+ }
67
+
68
+ .layer-catalog-widget-entry-link:hover {
69
+ opacity: 1;
70
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qwc2",
3
- "version": "2026.04.03",
3
+ "version": "2026.04.13",
4
4
  "description": "QGIS Web Client",
5
5
  "author": "Sourcepole AG",
6
6
  "license": "BSD-2-Clause",
@@ -17,7 +17,7 @@
17
17
  ],
18
18
  "dependencies": {
19
19
  "@furkot/webfonts-generator": "^2.0.3",
20
- "@giro3d/giro3d": "2.0.0-beta.1",
20
+ "@giro3d/giro3d": "^2.0.0",
21
21
  "@kayahr/text-encoding": "^2.1.0",
22
22
  "@loaders.gl/core": "^4.3.4",
23
23
  "@loaders.gl/shapefile": "^4.3.4",
@@ -32,7 +32,7 @@
32
32
  "@turf/intersect": "^7.3.3",
33
33
  "@vtaits/react-color-picker": "^2.0.0",
34
34
  "any-date-parser": "^1.5.4",
35
- "axios": "^1.13.4",
35
+ "axios": "^1.15.0",
36
36
  "buffer": "^6.0.3",
37
37
  "chart.js": "^4.5.1",
38
38
  "chartjs-adapter-dayjs-4": "^1.0.4",
@@ -294,7 +294,8 @@ var MapExport = /*#__PURE__*/function (_React$Component) {
294
294
  width: 0,
295
295
  height: 0,
296
296
  scale: null,
297
- pageSize: null
297
+ pageSize: null,
298
+ exporting: false
298
299
  });
299
300
  });
300
301
  _defineProperty(_this, "geometryChanged", function (center, extents, rotation, scale) {
@@ -448,18 +449,37 @@ var MapExport = /*#__PURE__*/function (_React$Component) {
448
449
  });
449
450
  });
450
451
  _defineProperty(_this, "dxfExport", function (baseParams, fileName, formatConfiguration) {
451
- var promises = _this.props.layers.filter(function (layer) {
452
- var _layer$mapFormats;
453
- return layer.type === 'wms' && layer.role > LayerRole.BACKGROUND && ((_layer$mapFormats = layer.mapFormats) === null || _layer$mapFormats === void 0 ? void 0 : _layer$mapFormats.includes("application/dxf"));
454
- }).reverse().map(function (layer) {
455
- var _layer$params$FILTER, _layer$params$FILTER_;
456
- var params = _objectSpread(_objectSpread({}, baseParams), {}, {
457
- LAYERS: layer.params.LAYERS,
458
- OPACITIES: layer.params.OPACITIES,
459
- STYLES: layer.params.STYLES,
460
- FILTER: (_layer$params$FILTER = layer.params.FILTER) !== null && _layer$params$FILTER !== void 0 ? _layer$params$FILTER : '',
461
- FILTER_GEOM: (_layer$params$FILTER_ = layer.params.FILTER_GEOM) !== null && _layer$params$FILTER_ !== void 0 ? _layer$params$FILTER_ : ''
452
+ // If formatConfiguration overrides LAYERS, only export theme layer with those layers
453
+ var layersOverridden = (formatConfiguration.extraQuery || "").split(/[?&]/).find(function (entry) {
454
+ return entry.split("=")[0].toLowerCase() === "layers";
455
+ }) !== undefined;
456
+ var jobs = [];
457
+ if (layersOverridden) {
458
+ jobs.push({
459
+ layer: _this.props.theme,
460
+ params: baseParams
462
461
  });
462
+ } else {
463
+ jobs = _this.props.layers.filter(function (layer) {
464
+ var _layer$mapFormats;
465
+ return layer.type === 'wms' && layer.role > LayerRole.BACKGROUND && ((_layer$mapFormats = layer.mapFormats) === null || _layer$mapFormats === void 0 ? void 0 : _layer$mapFormats.includes("application/dxf"));
466
+ }).reverse().map(function (layer) {
467
+ var _layer$params$FILTER, _layer$params$FILTER_;
468
+ return {
469
+ layer: layer,
470
+ params: _objectSpread(_objectSpread({}, baseParams), {}, {
471
+ LAYERS: layer.params.LAYERS,
472
+ OPACITIES: layer.params.OPACITIES,
473
+ STYLES: layer.params.STYLES,
474
+ FILTER: (_layer$params$FILTER = layer.params.FILTER) !== null && _layer$params$FILTER !== void 0 ? _layer$params$FILTER : '',
475
+ FILTER_GEOM: (_layer$params$FILTER_ = layer.params.FILTER_GEOM) !== null && _layer$params$FILTER_ !== void 0 ? _layer$params$FILTER_ : ''
476
+ })
477
+ };
478
+ });
479
+ }
480
+ var promises = jobs.map(function (_ref3) {
481
+ var layer = _ref3.layer,
482
+ params = _ref3.params;
463
483
  var data = Object.entries(params).map(function (pair) {
464
484
  return pair.map(function (entry) {
465
485
  return encodeURIComponent(entry).replace(/%20/g, '+');
@@ -485,21 +505,26 @@ var MapExport = /*#__PURE__*/function (_React$Component) {
485
505
  Promise.all(promises).then(function (responses) {
486
506
  var decoder = new TextDecoder("iso-8859-1");
487
507
  var dxfDocuments = responses.filter(function (response) {
488
- return response.headers['content-type'] === "application/dxf";
508
+ return response && response.headers['content-type'] === "application/dxf";
489
509
  }).map(function (response) {
490
510
  return explodeDxf(decoder.decode(response.data));
491
511
  });
492
- var dxfDocument = mergeDxf(dxfDocuments);
493
- var result = implodeDxf(dxfDocument);
494
- var encoder = new TextEncoder("iso-8859-1");
495
- FileSaver.saveAs(new Blob([encoder.encode(result)], {
496
- type: "application/dxf"
497
- }), fileName);
498
- /*
499
- responses.forEach((response, idx) => {
500
- FileSaver.saveAs(new Blob([response.data], {type: "application/dxf"}), "orig_" + idx + "_" + fileName);
501
- });
502
- */
512
+ if (dxfDocuments.length !== 0) {
513
+ var dxfDocument = mergeDxf(dxfDocuments);
514
+ var result = implodeDxf(dxfDocument);
515
+ var encoder = new TextEncoder("iso-8859-1");
516
+ FileSaver.saveAs(new Blob([encoder.encode(result)], {
517
+ type: "application/dxf"
518
+ }), fileName);
519
+ /*
520
+ responses.forEach((response, idx) => {
521
+ FileSaver.saveAs(new Blob([response.data], {type: "application/dxf"}), "orig_" + idx + "_" + fileName);
522
+ });
523
+ */
524
+ } else {
525
+ /* eslint-disable-next-line */
526
+ alert('Export failed');
527
+ }
503
528
  _this.setState({
504
529
  exporting: false
505
530
  });
@@ -573,7 +598,7 @@ _defineProperty(MapExport, "propTypes", {
573
598
  fileNameTemplate: PropTypes.string,
574
599
  /** Formats to force as available even if the map capabilities report otherwise. Useful if a serviceUrl is defined in a format configuration. */
575
600
  forceAvailableFormats: PropTypes.array,
576
- /** Custom export configuration per format.
601
+ /** Custom format export configuration. Specify a format mime-type (i.e. `application/dxf`) as key, and an array of one or more configurations as value.
577
602
  * If more than one configuration per format is provided, a selection combo will be displayed.
578
603
  * `labelMsgId` is a translation string message id for the combo label. If not defined, `name` will be displayed.
579
604
  * `extraQuery` will be appended to the query string (replacing any existing parameters).
@@ -581,17 +606,15 @@ _defineProperty(MapExport, "propTypes", {
581
606
  * `baseLayer` will be appended to the LAYERS instead of the background layer.
582
607
  * `projections` is a list of export projections. If empty, the map projection is automatically used.
583
608
  * `serviceUrl` is the address of a custom service to use instead of the layer OWS service url. */
584
- formatConfiguration: PropTypes.shape({
585
- format: PropTypes.arrayOf(PropTypes.shape({
586
- name: PropTypes.string,
587
- labelMsgId: PropTypes.string,
588
- extraQuery: PropTypes.string,
589
- formatOptions: PropTypes.string,
590
- baseLayer: PropTypes.string,
591
- projections: PropTypes.array,
592
- serviceUrl: PropTypes.string
593
- }))
594
- }),
609
+ formatConfiguration: PropTypes.objectOf(PropTypes.arrayOf(PropTypes.shape({
610
+ name: PropTypes.string,
611
+ labelMsgId: PropTypes.string,
612
+ extraQuery: PropTypes.string,
613
+ formatOptions: PropTypes.string,
614
+ baseLayer: PropTypes.string,
615
+ projections: PropTypes.array,
616
+ serviceUrl: PropTypes.string
617
+ }))),
595
618
  layers: PropTypes.array,
596
619
  map: PropTypes.object,
597
620
  /** List of image sizes to offer, in addition to the free-hand selection. The width and height are in millimeters. */
@@ -53,7 +53,7 @@ import './style/MapInfoTooltip.css';
53
53
  * [ElevationInterface.js](https://github.com/qgis/qwc2/blob/master/utils/ElevationInterface.js)), the
54
54
  * height at the picked position is also displayed.
55
55
  *
56
- * If `mapInfoService` in `config.json` points to a `qwc-mapinfo-service`, additional
56
+ * If `mapInfoServiceUrl` in `config.json` points to a `qwc-mapinfo-service`, additional
57
57
  * custom information according to the `qwc-mapinfo-service` configuration is returned.
58
58
  *
59
59
  * You can pass additional plugin components to the `MapInfoTooltip` in `appConfig.js`:
@@ -122,7 +122,7 @@ var MapInfoTooltip = /*#__PURE__*/function (_React$Component) {
122
122
  elevation: elevation
123
123
  });
124
124
  })["catch"](function () {});
125
- var mapInfoService = ConfigUtils.getConfigProp("mapInfoService");
125
+ var mapInfoService = ConfigUtils.getConfigProp("mapInfoServiceUrl") || ConfigUtils.getConfigProp("mapInfoService");
126
126
  if (mapInfoService) {
127
127
  axios.get(mapInfoService, {
128
128
  params: {
@@ -284,6 +284,7 @@ _defineProperty(MapInfoTooltip, "propTypes", {
284
284
  /** The number of decimal places to display for elevation values. */
285
285
  elevationPrecision: PropTypes.number,
286
286
  enabled: PropTypes.bool,
287
+ /** Whether to display WGS84 coordinates in addition to map CRS coordinates. */
287
288
  includeWGS84: PropTypes.bool,
288
289
  map: PropTypes.object,
289
290
  /** Additional plugin components for the map info tooltip. */
@@ -125,7 +125,6 @@ var NewsPopup = /*#__PURE__*/function (_React$Component) {
125
125
  }
126
126
  }]);
127
127
  }(React.Component);
128
- _defineProperty(NewsPopup, "availableIn3D", true);
129
128
  _defineProperty(NewsPopup, "propTypes", {
130
129
  /** URL to the news HTML document to display in the popup. Can contain `{lang}` as a placeholder which will be replaced with the current viewer language.*/
131
130
  newsDocument: PropTypes.string,
@@ -170,6 +170,19 @@ var MeasurementSupport = /*#__PURE__*/function (_React$Component) {
170
170
  }
171
171
  }
172
172
  });
173
+ _defineProperty(_this, "createPoint", function (coord) {
174
+ _this.currentFeature = new ol.Feature({
175
+ geometry: new ol.geom.Point(coord)
176
+ });
177
+ _this.currentFeature.setId(uuidv4());
178
+ _this.currentFeature.set('measureMode', _this.props.measurement.mode);
179
+ _this.currentFeature.setStyle(_this.featureStyleFunction);
180
+ _this.currentFeature.on('change', function (evt) {
181
+ return _this.updateMeasurementResults(evt.target);
182
+ });
183
+ _this.measureLayer.getSource().addFeature(_this.currentFeature);
184
+ _this.enterEditMode(_this.currentFeature);
185
+ });
173
186
  _defineProperty(_this, "enterEditMode", function (feature) {
174
187
  _this.currentFeature = feature;
175
188
  _this.updateMeasurementResults(_this.currentFeature, false);
@@ -209,15 +222,14 @@ var MeasurementSupport = /*#__PURE__*/function (_React$Component) {
209
222
  }
210
223
  });
211
224
  if (features.length === 0) {
212
- _this.leaveEditMode();
213
- // Immediately start new drawing
214
225
  var clickCoord = MapUtils.getHook(MapUtils.GET_SNAPPED_COORDINATES_FROM_PIXEL_HOOK)(evt.pixel);
215
- _this.drawInteraction.appendCoordinates([clickCoord]);
216
226
  if (_this.props.measurement.mode === 'Point') {
217
- // Ughh... Apparently we need to wait 250ms for the 'singleclick' event processing to finish to avoid pick interactions picking up the current event
218
- setTimeout(function () {
219
- return _this.drawInteraction.finishDrawing();
220
- }, 300);
227
+ // Special handling for Point: create point feature directly instead of starting a draw interaction
228
+ _this.createPoint(clickCoord);
229
+ } else {
230
+ _this.leaveEditMode();
231
+ // Immediately start new drawing
232
+ _this.drawInteraction.appendCoordinates([clickCoord]);
221
233
  }
222
234
  } else {
223
235
  _this.enterEditMode(features[0]);
@@ -234,6 +234,11 @@ img.layertree-item-legend-tooltip {
234
234
  color: red;
235
235
  }
236
236
 
237
+
238
+ #LayerTree span.layertree-item-metadata {
239
+ width: 1.75em;
240
+ }
241
+
237
242
  #LayerTree span.layertree-item-menubutton {
238
243
  text-align: center;
239
244
  width: 1.75em;
@@ -81,6 +81,8 @@ function parsePropType(type) {
81
81
  return "{".concat(type.value.map(function (x) {
82
82
  return x.value;
83
83
  }).join(", "), "}");
84
+ } else if (type.name === 'objectOf') {
85
+ return '<key>: ' + parsePropType(type.value);
84
86
  } else {
85
87
  return type.name;
86
88
  }
@@ -336,6 +336,7 @@
336
336
  "radius": "Радиус"
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": "Каталог на слоевете"
340
341
  },
341
342
  "layerinfo": {
@@ -336,6 +336,7 @@
336
336
  "radius": "Radi"
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": "Titol"
340
341
  },
341
342
  "layerinfo": {
@@ -336,6 +336,7 @@
336
336
  "radius": "Velikost okruhu"
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": "Katalog vrstev"
340
341
  },
341
342
  "layerinfo": {
@@ -336,6 +336,7 @@
336
336
  "radius": "Radius"
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": "Ebenenkatalog"
340
341
  },
341
342
  "layerinfo": {
@@ -336,6 +336,7 @@
336
336
  "radius": "Radius"
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": "Ebenenkatalog"
340
341
  },
341
342
  "layerinfo": {
@@ -336,6 +336,7 @@
336
336
  "radius": "Radius"
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "Info link",
339
340
  "windowtitle": "Layer catalog"
340
341
  },
341
342
  "layerinfo": {
@@ -336,6 +336,7 @@
336
336
  "radius": "Radio"
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": "Catálogo de capas"
340
341
  },
341
342
  "layerinfo": {
@@ -336,6 +336,7 @@
336
336
  "radius": ""
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": ""
340
341
  },
341
342
  "layerinfo": {
@@ -336,6 +336,7 @@
336
336
  "radius": "Rayon"
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "Lien d'information",
339
340
  "windowtitle": "Catalogue de couches"
340
341
  },
341
342
  "layerinfo": {
@@ -336,6 +336,7 @@
336
336
  "radius": ""
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": ""
340
341
  },
341
342
  "layerinfo": {
@@ -336,6 +336,7 @@
336
336
  "radius": "Raggio"
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": "Catalogo livelli"
340
341
  },
341
342
  "layerinfo": {
@@ -336,6 +336,7 @@
336
336
  "radius": "半径"
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": "レイヤ・カタログ"
340
341
  },
341
342
  "layerinfo": {
@@ -336,6 +336,7 @@
336
336
  "radius": "Straal"
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": "Lagencatalogus"
340
341
  },
341
342
  "layerinfo": {
@@ -336,6 +336,7 @@
336
336
  "radius": ""
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": ""
340
341
  },
341
342
  "layerinfo": {
@@ -336,6 +336,7 @@
336
336
  "radius": ""
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": ""
340
341
  },
341
342
  "layerinfo": {
@@ -336,6 +336,7 @@
336
336
  "radius": "Raio"
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": "Titulo da janela"
340
341
  },
341
342
  "layerinfo": {
@@ -336,6 +336,7 @@
336
336
  "radius": ""
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": "Catálogo de Camadas"
340
341
  },
341
342
  "layerinfo": {
@@ -336,6 +336,7 @@
336
336
  "radius": "Raza"
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": "Catalog straturi"
340
341
  },
341
342
  "layerinfo": {
@@ -336,6 +336,7 @@
336
336
  "radius": ""
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": ""
340
341
  },
341
342
  "layerinfo": {
@@ -336,6 +336,7 @@
336
336
  "radius": ""
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": ""
340
341
  },
341
342
  "layerinfo": {
@@ -336,6 +336,7 @@
336
336
  "radius": "Yarıçap"
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": "Katman kataloğu"
340
341
  },
341
342
  "layerinfo": {
@@ -321,6 +321,7 @@
321
321
  "infotool.clickhelpPolygon",
322
322
  "infotool.clickhelpRadius",
323
323
  "infotool.radius",
324
+ "layercatalog.openlink",
324
325
  "layercatalog.windowtitle",
325
326
  "layerinfo.abstract",
326
327
  "layerinfo.attribution",
@@ -336,6 +336,7 @@
336
336
  "radius": ""
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": ""
340
341
  },
341
342
  "layerinfo": {
@@ -80,7 +80,8 @@ var ThemeUtils = {
80
80
  (externalLayers[key] = externalLayers[key] || []).push(params);
81
81
  delete bgLayer.resource;
82
82
  } else if (bgLayer.type === "wms") {
83
- bgLayer.version = bgLayer.params.VERSION || bgLayer.version || themes.defaultWMSVersion || "1.3.0";
83
+ var _bgLayer$params;
84
+ bgLayer.version = ((_bgLayer$params = bgLayer.params) === null || _bgLayer$params === void 0 ? void 0 : _bgLayer$params.VERSION) || bgLayer.version || themes.defaultWMSVersion || "1.3.0";
84
85
  } else if (bgLayer.type === "group") {
85
86
  bgLayer.items = bgLayer.items.map(function (item) {
86
87
  if (item.ref) {