qwc2 2026.4.2 → 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 (43) hide show
  1. package/LICENSE +1 -6
  2. package/README.md +8 -4
  3. package/components/AppMenu.js +2 -1
  4. package/components/SearchBox.js +10 -2
  5. package/components/map/layers/MVTLayer.js +61 -23
  6. package/components/map3d/ColorLayer3D.js +2 -1
  7. package/components/map3d/layers/MVTLayer3D.js +8 -28
  8. package/components/style/SearchBox.css +11 -0
  9. package/components/widgets/LayerCatalogWidget.js +19 -1
  10. package/components/widgets/style/LayerCatalogWidget.css +11 -0
  11. package/package.json +3 -3
  12. package/plugins/MapExport.js +59 -36
  13. package/plugins/MapInfoTooltip.js +3 -2
  14. package/plugins/NewsPopup.js +0 -1
  15. package/plugins/SensorThingsTool.js +71 -8
  16. package/plugins/map/MeasurementSupport.js +19 -7
  17. package/plugins/style/LayerTree.css +5 -0
  18. package/plugins/style/SensorThingsTool.css +27 -1
  19. package/scripts/gen-plugin-docs.js +2 -0
  20. package/static/translations/bg-BG.json +3 -0
  21. package/static/translations/ca-ES.json +3 -0
  22. package/static/translations/cs-CZ.json +3 -0
  23. package/static/translations/de-CH.json +3 -0
  24. package/static/translations/de-DE.json +3 -0
  25. package/static/translations/en-US.json +3 -0
  26. package/static/translations/es-ES.json +3 -0
  27. package/static/translations/fi-FI.json +3 -0
  28. package/static/translations/fr-FR.json +3 -0
  29. package/static/translations/hu-HU.json +3 -0
  30. package/static/translations/it-IT.json +3 -0
  31. package/static/translations/ja-JP.json +3 -0
  32. package/static/translations/nl-NL.json +3 -0
  33. package/static/translations/no-NO.json +3 -0
  34. package/static/translations/pl-PL.json +3 -0
  35. package/static/translations/pt-BR.json +3 -0
  36. package/static/translations/pt-PT.json +3 -0
  37. package/static/translations/ro-RO.json +3 -0
  38. package/static/translations/ru-RU.json +3 -0
  39. package/static/translations/sv-SE.json +3 -0
  40. package/static/translations/tr-TR.json +3 -0
  41. package/static/translations/tsconfig.json +3 -0
  42. package/static/translations/uk-UA.json +3 -0
  43. package/utils/ThemeUtils.js +2 -1
package/LICENSE CHANGED
@@ -1,6 +1,5 @@
1
1
  Copyright (c) 2015-2016 GeoSolutions Sas
2
- Copyright (c) 2016-2024 Sourcepole AG
3
- Copyright (c) 2021 Oslandia SAS <infos+qwc2@oslandia.com>
2
+ Copyright (c) QWC Contributors <https://github.com/qgis/qwc2/graphs/contributors>
4
3
  All rights reserved.
5
4
 
6
5
  Redistribution and use in source and binary forms, with or without modification, are
@@ -22,7 +21,3 @@ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRU
22
21
  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
23
22
  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
23
  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
-
26
- The views and conclusions contained in the software and documentation are those
27
- of the authors and should not be interpreted as representing official policies,
28
- either expressed or implied, of the MapStore2 Project.
package/README.md CHANGED
@@ -8,18 +8,22 @@ The `qwc2` NPM package can be used as a dependency to build a custom QWC applica
8
8
 
9
9
  ![Screenshot](https://github.com/qgis/qwc2/blob/gh-pages/Screenshot.jpg?raw=true)
10
10
 
11
- ### Main Features
11
+ ## Homepage
12
+
13
+ See [qwc.app](https://qwc.app).
14
+
15
+ ## Main Features
12
16
 
13
17
  See [qwc.app/features](https://qwc.app/features).
14
18
 
15
19
  ## Quick start
16
20
 
17
- See [qwc-services.github.io/master/QuickStart/](https://qwc-services.github.io/master/QuickStart/)
21
+ See [docs.qwc.app/master/QuickStart/](https://docs.qwc.app/master/QuickStart/).
18
22
 
19
23
  ## Documentation
20
24
 
21
- * [qwc-services.github.io](https://qwc-services.github.io/)
22
- * [ChangeLog](https://qwc-services.github.io/master/release_notes/ChangeLog/)
25
+ * [docs.qwc.app](https://docs.qwc.app)
26
+ * [ChangeLog](https://docs.qwc.app/master/release_notes/ChangeLog/)
23
27
 
24
28
  ## Help
25
29
 
@@ -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) {
@@ -15,7 +15,7 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
15
15
  import axios from 'axios';
16
16
  import { applyStyle } from 'ol-mapbox-style';
17
17
  import ol from 'openlayers';
18
- export var createLayer = function createLayer(options) {
18
+ function createLayer(url, options) {
19
19
  return new ol.layer.VectorTile(_objectSpread({
20
20
  minResolution: options.minResolution,
21
21
  maxResolution: options.maxResolution,
@@ -23,37 +23,75 @@ export var createLayer = function createLayer(options) {
23
23
  source: new ol.source.VectorTile(_objectSpread({
24
24
  projection: options.projection,
25
25
  format: new ol.format.MVT({}),
26
- url: options.url,
26
+ url: url,
27
27
  tileGrid: options.tileGridConfig ? new ol.tilegrid.TileGrid(_objectSpread({}, options.tileGridConfig)) : undefined
28
28
  }, options.sourceConfig || {}))
29
29
  }, options.layerConfig || {}));
30
- };
30
+ }
31
+ export function createFromStyle(style, options, callback) {
32
+ axios.get(style).then(function (response) {
33
+ var _glStyle$sprite, _glStyle$glyphs;
34
+ var glStyle = response.data;
35
+ ((_glStyle$sprite = glStyle.sprite) === null || _glStyle$sprite === void 0 ? void 0 : _glStyle$sprite.startsWith(".")) && (glStyle.sprite = new URL(glStyle.sprite, options.style).href);
36
+ ((_glStyle$glyphs = glStyle.glyphs) === null || _glStyle$glyphs === void 0 ? void 0 : _glStyle$glyphs.startsWith(".")) && (glStyle.glyphs = new URL(glStyle.glyphs, options.style).href);
37
+ // Collect used sources
38
+ var usedSources = new Set(glStyle.layers.map(function (l) {
39
+ return l.source;
40
+ }).filter(Boolean));
41
+ // Create layer for each source
42
+ usedSources.forEach(function (sourceName) {
43
+ var _source$url, _source$tiles;
44
+ var source = glStyle.sources[sourceName];
45
+ if (source.type !== 'vector' && source.type !== 'geojson') {
46
+ return;
47
+ }
48
+ ((_source$url = source.url) === null || _source$url === void 0 ? void 0 : _source$url.startsWith(".")) && (source.url = new URL(source.url, options.style).href);
49
+ if ((_source$tiles = source.tiles) !== null && _source$tiles !== void 0 && _source$tiles.length) {
50
+ var layer = createLayer(source.tiles[0], options);
51
+ applyStyle(layer, style, sourceName, options.styleOptions).then(function () {
52
+ callback(layer);
53
+ })["catch"](function (e) {
54
+ /* eslint-disable-next-line */
55
+ console.warn("Unable to apply style " + sourceName + ": " + String(e));
56
+ });
57
+ } else if (source.url) {
58
+ axios.get(source.url).then(function (response2) {
59
+ var _response2$data;
60
+ if ((_response2$data = response2.data) !== null && _response2$data !== void 0 && (_response2$data = _response2$data.tiles) !== null && _response2$data !== void 0 && _response2$data.length) {
61
+ var _layer = createLayer(response2.data.tiles[0], options, callback);
62
+ applyStyle(_layer, style, sourceName, options.styleOptions).then(function () {
63
+ callback(_layer);
64
+ })["catch"](function (e) {
65
+ /* eslint-disable-next-line */
66
+ console.warn("Unable to apply style " + sourceName + ": " + String(e));
67
+ });
68
+ } else {
69
+ /* eslint-disable-next-line */
70
+ console.warn("Could not find source tile URL for style " + sourceName);
71
+ }
72
+ })["catch"](function () {
73
+ /* eslint-disable-next-line */
74
+ console.warn("Could not find source tile URL for style " + sourceName);
75
+ });
76
+ } else {
77
+ /* eslint-disable-next-line */
78
+ console.warn("Could not find source tile URL for style " + sourceName);
79
+ }
80
+ });
81
+ })["catch"](function (e) {
82
+ /* eslint-disable-next-line */
83
+ console.warn("Unable to load style " + options.style + ": " + String(e));
84
+ });
85
+ }
31
86
  export default {
32
87
  create: function create(options) {
33
88
  var group = new ol.layer.Group();
34
89
  if (options.style) {
35
- axios.get(options.style).then(function (response) {
36
- var _glStyle$sprite, _glStyle$glyphs;
37
- var glStyle = response.data;
38
- ((_glStyle$sprite = glStyle.sprite) === null || _glStyle$sprite === void 0 ? void 0 : _glStyle$sprite.startsWith(".")) && (glStyle.sprite = new URL(glStyle.sprite, options.style).href);
39
- ((_glStyle$glyphs = glStyle.glyphs) === null || _glStyle$glyphs === void 0 ? void 0 : _glStyle$glyphs.startsWith(".")) && (glStyle.glyphs = new URL(glStyle.glyphs, options.style).href);
40
- Object.keys(glStyle.sources).forEach(function (styleSource) {
41
- var _glStyle$sources$styl;
42
- ((_glStyle$sources$styl = glStyle.sources[styleSource].url) === null || _glStyle$sources$styl === void 0 ? void 0 : _glStyle$sources$styl.startsWith(".")) && (glStyle.sources[styleSource].url = new URL(glStyle.sources[styleSource].url, options.style).href);
43
- var layer = createLayer(options);
44
- applyStyle(layer, glStyle, styleSource, options.styleOptions).then(function () {
45
- group.getLayers().push(layer);
46
- })["catch"](function (e) {
47
- /* eslint-disable-next-line */
48
- console.warn("Unable to apply style " + options.style + ": " + String(e));
49
- });
50
- });
51
- })["catch"](function (e) {
52
- /* eslint-disable-next-line */
53
- console.warn("Unable to load style " + options.style + ": " + String(e));
90
+ createFromStyle(options.style, options, function (layer) {
91
+ group.getLayers().push(layer);
54
92
  });
55
93
  } else {
56
- group.getLayers().push(createLayer(options));
94
+ group.getLayers().push(createLayer(options.url, options));
57
95
  }
58
96
  return group;
59
97
  }
@@ -130,7 +130,8 @@ var ColorLayer3D = /*#__PURE__*/function (_React$Component) {
130
130
  value: function componentDidUpdate(prevProps) {
131
131
  var layerCreator = LayerRegistry3D[this.props.options.type];
132
132
  if (this.mapLayer && layerCreator) {
133
- layerCreator.update3d(this.mapLayer, this.props.options, prevProps.options, this.props.sceneContext.mapCrs);
133
+ var _layerCreator$update;
134
+ (_layerCreator$update = layerCreator.update3d) === null || _layerCreator$update === void 0 || _layerCreator$update.call(layerCreator, this.mapLayer, this.props.options, prevProps.options, this.props.sceneContext.mapCrs);
134
135
  this.applyLayerOptions(layerCreator, prevProps.options);
135
136
  }
136
137
  }
@@ -8,18 +8,15 @@
8
8
 
9
9
  import ColorLayer from '@giro3d/giro3d/core/layer/ColorLayer';
10
10
  import VectorTileSource from "@giro3d/giro3d/sources/VectorTileSource.js";
11
- import axios from 'axios';
12
- import { applyStyle } from 'ol-mapbox-style';
13
- import { createLayer } from '../../map/layers/MVTLayer';
11
+ import { createFromStyle } from '../../map/layers/MVTLayer';
14
12
  import { LayerGroup3D } from './Layer3D';
15
13
  export default {
16
14
  create3d: function create3d(options, projection) {
17
- var create3dLayer = function create3dLayer() {
18
- var style = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
15
+ var create3dLayer = function create3dLayer(url) {
16
+ var style = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
19
17
  var source = new VectorTileSource({
20
- url: options.url,
21
- style: style,
22
- backgroundColor: "white"
18
+ url: url,
19
+ style: style
23
20
  });
24
21
  return new ColorLayer({
25
22
  name: options.name,
@@ -28,28 +25,11 @@ export default {
28
25
  };
29
26
  var group = new LayerGroup3D(options.id);
30
27
  if (options.style) {
31
- axios.get(options.style).then(function (response) {
32
- var _glStyle$sprite, _glStyle$glyphs;
33
- var glStyle = response.data;
34
- ((_glStyle$sprite = glStyle.sprite) === null || _glStyle$sprite === void 0 ? void 0 : _glStyle$sprite.startsWith(".")) && (glStyle.sprite = new URL(glStyle.sprite, options.style).href);
35
- ((_glStyle$glyphs = glStyle.glyphs) === null || _glStyle$glyphs === void 0 ? void 0 : _glStyle$glyphs.startsWith(".")) && (glStyle.glyphs = new URL(glStyle.glyphs, options.style).href);
36
- Object.keys(glStyle.sources).forEach(function (styleSource) {
37
- var _glStyle$sources$styl;
38
- ((_glStyle$sources$styl = glStyle.sources[styleSource].url) === null || _glStyle$sources$styl === void 0 ? void 0 : _glStyle$sources$styl.startsWith(".")) && (glStyle.sources[styleSource].url = new URL(glStyle.sources[styleSource].url, options.style).href);
39
- var olLayer = createLayer(options);
40
- applyStyle(olLayer, glStyle, styleSource, options.styleOptions).then(function () {
41
- group.addLayer(create3dLayer(olLayer.getStyle()));
42
- })["catch"](function (e) {
43
- /* eslint-disable-next-line */
44
- console.warn("Unable to apply style " + options.style + ": " + String(e));
45
- });
46
- });
47
- })["catch"](function (e) {
48
- /* eslint-disable-next-line */
49
- console.warn("Unable to load style " + options.style + ": " + String(e));
28
+ createFromStyle(options.style, options, function (olLayer) {
29
+ group.addLayer(create3dLayer(olLayer.getSource().getUrls()[0], olLayer.getStyle()));
50
30
  });
51
31
  } else {
52
- group.addLayer(create3dLayer());
32
+ group.addLayer(create3dLayer(options.url));
53
33
  }
54
34
  return group;
55
35
  },
@@ -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.02",
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,
@@ -712,7 +712,7 @@ var SensorThingsTool = /*#__PURE__*/function (_React$Component) {
712
712
  }, datastream.description);
713
713
  })), /*#__PURE__*/React.createElement("button", {
714
714
  className: "button",
715
- onClick: _this.addDatastream,
715
+ onClick: _this.addSelectedDatastream,
716
716
  title: LocaleUtils.tr("sensorthingstool.addDatastream")
717
717
  }, /*#__PURE__*/React.createElement(Icon, {
718
718
  icon: "plus"
@@ -1079,8 +1079,13 @@ var SensorThingsTool = /*#__PURE__*/function (_React$Component) {
1079
1079
  };
1080
1080
  });
1081
1081
  });
1082
- _defineProperty(_this, "addDatastream", function () {
1082
+ _defineProperty(_this, "addSelectedDatastream", function () {
1083
1083
  if (_this.state.currentDatastreamId !== undefined) {
1084
+ _this.addDatastream(_this.state.currentDatastreamId);
1085
+ }
1086
+ });
1087
+ _defineProperty(_this, "addDatastream", function (datastreamId) {
1088
+ if (datastreamId !== undefined) {
1084
1089
  _this.setState(function (state) {
1085
1090
  // find next unused color
1086
1091
  var availableColors = new Set(state.graphColors.map(function (color, idx) {
@@ -1104,7 +1109,7 @@ var SensorThingsTool = /*#__PURE__*/function (_React$Component) {
1104
1109
  return {
1105
1110
  graph: _objectSpread(_objectSpread({}, state.graph), {}, {
1106
1111
  datastreams: [].concat(_toConsumableArray(state.graph.datastreams), [{
1107
- id: state.currentDatastreamId,
1112
+ id: datastreamId,
1108
1113
  observations: null,
1109
1114
  loading: false,
1110
1115
  colorIdx: colorIdx,
@@ -1116,7 +1121,7 @@ var SensorThingsTool = /*#__PURE__*/function (_React$Component) {
1116
1121
  }])
1117
1122
  }),
1118
1123
  datastreamOptions: [].concat(_toConsumableArray(state.datastreamOptions), [{
1119
- datastreamId: state.currentDatastreamId,
1124
+ datastreamId: datastreamId,
1120
1125
  showOnSecondYAxis: false,
1121
1126
  showArithmeticMean: false,
1122
1127
  percentilesInput: "",
@@ -1606,10 +1611,32 @@ var SensorThingsTool = /*#__PURE__*/function (_React$Component) {
1606
1611
  if (!_this.state.showDatastreamsFilterWindow || _this.state.currentSensorLocation === null) {
1607
1612
  return null;
1608
1613
  }
1614
+
1615
+ // group datastreams by thing
1616
+ var groupedDatastreams = {};
1617
+ var filteredThings = [];
1618
+ _this.state.currentSensorLocation.filteredDatastreams.forEach(function (datastreamId) {
1619
+ var datastreamInfo = _this.state.datastreams[datastreamId];
1620
+ var thingId = datastreamInfo.thing.id;
1621
+ if (groupedDatastreams[thingId] === undefined) {
1622
+ groupedDatastreams[thingId] = {
1623
+ thing: datastreamInfo.thing,
1624
+ datastreamIds: []
1625
+ };
1626
+ filteredThings.push(datastreamInfo.thing);
1627
+ }
1628
+ groupedDatastreams[thingId].datastreamIds.push(datastreamId);
1629
+ });
1630
+ // order thing IDs by name and description
1631
+ var thingIds = filteredThings.sort(function (a, b) {
1632
+ return a.name.localeCompare(b.name) || a.description.localeCompare(b.description);
1633
+ }).map(function (thing) {
1634
+ return thing.id;
1635
+ });
1609
1636
  return /*#__PURE__*/React.createElement(ResizeableWindow, {
1610
- fitHeight: "true",
1611
1637
  icon: "filter",
1612
- initialWidth: 500,
1638
+ initialHeight: 600,
1639
+ initialWidth: 800,
1613
1640
  initialX: _this.props.windowSize.width + 10,
1614
1641
  initialY: 0,
1615
1642
  key: "SensorThingsDatastreamsFilterWindow",
@@ -1624,7 +1651,9 @@ var SensorThingsTool = /*#__PURE__*/function (_React$Component) {
1624
1651
  role: "body"
1625
1652
  }, /*#__PURE__*/React.createElement("table", {
1626
1653
  className: "sensor-things-datastreams-filter"
1627
- }, /*#__PURE__*/React.createElement("tbody", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, LocaleUtils.tr("sensorthingstool.datastreamsFilter.thing"), ":\xA0"), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement("select", {
1654
+ }, /*#__PURE__*/React.createElement("tbody", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", {
1655
+ className: "sensor-things-datastreams-filter-location"
1656
+ }, LocaleUtils.tr("sensorthingstool.datastreamsFilter.location"), ":\xA0"), /*#__PURE__*/React.createElement("td", null, _this.state.currentSensorLocation.name, ": ", _this.state.currentSensorLocation.description)), /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, LocaleUtils.tr("sensorthingstool.datastreamsFilter.thing"), ":\xA0"), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement("select", {
1628
1657
  onChange: function onChange(ev) {
1629
1658
  return _this.updateDatastreamsFilter('thingId', ev.target.value);
1630
1659
  },
@@ -1660,7 +1689,41 @@ var SensorThingsTool = /*#__PURE__*/function (_React$Component) {
1660
1689
  key: "sensor-things-select-filter-observed-property-" + observedProperty.id,
1661
1690
  value: observedProperty.id
1662
1691
  }, observedProperty.optionText);
1663
- }))))))));
1692
+ })))))), /*#__PURE__*/React.createElement("div", {
1693
+ className: "sensor-things-datastreams-filter-table-wrapper"
1694
+ }, /*#__PURE__*/React.createElement("table", {
1695
+ className: "sensor-things-datastreams-filter-table"
1696
+ }, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("th", null, "ID"), /*#__PURE__*/React.createElement("th", null, LocaleUtils.tr("sensorthingstool.datastreamsFilter.datastream")), /*#__PURE__*/React.createElement("th", null, LocaleUtils.tr("sensorthingstool.datastreamTable.fullPeriod")), /*#__PURE__*/React.createElement("th", null, LocaleUtils.tr("sensorthingstool.datastreamInfo.observedProperty")), /*#__PURE__*/React.createElement("th", null, LocaleUtils.tr("sensorthingstool.datastreamInfo.unit")), /*#__PURE__*/React.createElement("th", null, LocaleUtils.tr("sensorthingstool.datastreamInfo.sensor")), /*#__PURE__*/React.createElement("th", null))), /*#__PURE__*/React.createElement("tbody", null, thingIds.map(function (thingId) {
1697
+ var thing = groupedDatastreams[thingId].thing;
1698
+ var datastreamIds = groupedDatastreams[thingId].datastreamIds;
1699
+ var thingRows = [/*#__PURE__*/React.createElement("tr", {
1700
+ className: "sensor-things-datastreams-filter-table-thing",
1701
+ key: "sensor-things-datastream-filter-list-thing-" + thingId
1702
+ }, /*#__PURE__*/React.createElement("td", null, LocaleUtils.tr("sensorthingstool.datastreamInfo.thing"), ":"), /*#__PURE__*/React.createElement("td", {
1703
+ colSpan: "6"
1704
+ }, /*#__PURE__*/React.createElement("div", null, thing.name), /*#__PURE__*/React.createElement("div", null, thing.description)))];
1705
+ var datastreamRows = datastreamIds.map(function (datastreamId, idx) {
1706
+ var datastreamInfo = _this.state.datastreams[datastreamId];
1707
+ var periodInfo = "-";
1708
+ if (datastreamInfo.period.begin !== null && datastreamInfo.period.end !== null) {
1709
+ var fullPeriodBegin = dayjs(datastreamInfo.period.begin).format(_this.props.timeFormats.tooltip);
1710
+ var fullPeriodEnd = dayjs(datastreamInfo.period.end).format(_this.props.timeFormats.tooltip);
1711
+ periodInfo = /*#__PURE__*/React.createElement("div", null, fullPeriodBegin, /*#__PURE__*/React.createElement("br", null), "- ", fullPeriodEnd);
1712
+ }
1713
+ return /*#__PURE__*/React.createElement("tr", {
1714
+ key: "sensor-things-datastream-filter-list-" + idx
1715
+ }, /*#__PURE__*/React.createElement("td", null, datastreamInfo.id), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement("div", null, datastreamInfo.name), /*#__PURE__*/React.createElement("div", null, datastreamInfo.description)), /*#__PURE__*/React.createElement("td", null, periodInfo), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement("div", null, datastreamInfo.observedProperty.name), /*#__PURE__*/React.createElement("div", null, datastreamInfo.observedProperty.description)), /*#__PURE__*/React.createElement("td", null, datastreamInfo.unitOfMeasurement.symbol), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement("div", null, datastreamInfo.sensor.name), /*#__PURE__*/React.createElement("div", null, datastreamInfo.sensor.description)), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement("button", {
1716
+ className: "button",
1717
+ onClick: function onClick() {
1718
+ return _this.addDatastream(datastreamId);
1719
+ },
1720
+ title: LocaleUtils.tr("sensorthingstool.addDatastream")
1721
+ }, /*#__PURE__*/React.createElement(Icon, {
1722
+ icon: "plus"
1723
+ }))));
1724
+ });
1725
+ return thingRows.concat(datastreamRows);
1726
+ }))))));
1664
1727
  });
1665
1728
  _defineProperty(_this, "toggleDatastreamInfoWindow", function (datastreamIndex) {
1666
1729
  var datastreamInfoWindow = null;
@@ -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;
@@ -177,8 +177,34 @@ table.sensor-things-datastreams-filter td select {
177
177
  width: 100%;
178
178
  text-overflow: ellipsis;
179
179
  }
180
+ table.sensor-things-datastreams-filter td.sensor-things-datastreams-filter-location {
181
+ height: 2em;
182
+ }
183
+ table.sensor-things-datastreams-filter-table {
184
+ width: 100%;
185
+ margin-top: 1em;
186
+ font-size: 85%;
187
+ }
188
+ table.sensor-things-datastreams-filter-table td {
189
+ vertical-align: top;
190
+ padding-top: 0.25em;
191
+ padding-bottom: 0.25em;
192
+ border-bottom: 1px solid var(--border-color);
193
+ }
194
+ table.sensor-things-datastreams-filter-table td div:nth-child(2) {
195
+ color: var(--text-color-disabled);
196
+ }
197
+ table.sensor-things-datastreams-filter-table td:last-child {
198
+ vertical-align: middle;
199
+ }
200
+ table.sensor-things-datastreams-filter-table tr.sensor-things-datastreams-filter-table-thing {
201
+ background-color: var(--button-bg-color);
202
+ }
203
+ table.sensor-things-datastreams-filter-table tr.sensor-things-datastreams-filter-table-thing td:nth-child(1) {
204
+ font-weight: bold;
205
+ }
180
206
 
181
- div.sensor-things-datastream-observations-table-wrapper {
207
+ div.sensor-things-datastream-observations-table-wrapper, div.sensor-things-datastreams-filter-table-wrapper {
182
208
  overflow: auto;
183
209
  margin-bottom: 0.25em;
184
210
  }
@@ -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": {
@@ -672,6 +673,8 @@
672
673
  "value": ""
673
674
  },
674
675
  "datastreamsFilter": {
676
+ "datastream": "",
677
+ "location": "",
675
678
  "observedProperty": "",
676
679
  "sensor": "",
677
680
  "thing": "",
@@ -336,6 +336,7 @@
336
336
  "radius": "Radi"
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": "Titol"
340
341
  },
341
342
  "layerinfo": {
@@ -672,6 +673,8 @@
672
673
  "value": ""
673
674
  },
674
675
  "datastreamsFilter": {
676
+ "datastream": "",
677
+ "location": "",
675
678
  "observedProperty": "",
676
679
  "sensor": "",
677
680
  "thing": "",
@@ -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": {
@@ -672,6 +673,8 @@
672
673
  "value": ""
673
674
  },
674
675
  "datastreamsFilter": {
676
+ "datastream": "",
677
+ "location": "",
675
678
  "observedProperty": "",
676
679
  "sensor": "",
677
680
  "thing": "",
@@ -336,6 +336,7 @@
336
336
  "radius": "Radius"
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": "Ebenenkatalog"
340
341
  },
341
342
  "layerinfo": {
@@ -672,6 +673,8 @@
672
673
  "value": "Wert"
673
674
  },
674
675
  "datastreamsFilter": {
676
+ "datastream": "Datastream",
677
+ "location": "Location",
675
678
  "observedProperty": "Observed Property",
676
679
  "sensor": "Sensor",
677
680
  "thing": "Thing",
@@ -336,6 +336,7 @@
336
336
  "radius": "Radius"
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": "Ebenenkatalog"
340
341
  },
341
342
  "layerinfo": {
@@ -672,6 +673,8 @@
672
673
  "value": "Wert"
673
674
  },
674
675
  "datastreamsFilter": {
676
+ "datastream": "Datastream",
677
+ "location": "Location",
675
678
  "observedProperty": "Observed Property",
676
679
  "sensor": "Sensor",
677
680
  "thing": "Thing",
@@ -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": {
@@ -672,6 +673,8 @@
672
673
  "value": "Value"
673
674
  },
674
675
  "datastreamsFilter": {
676
+ "datastream": "Datastream",
677
+ "location": "Location",
675
678
  "observedProperty": "Observed Property",
676
679
  "sensor": "Sensor",
677
680
  "thing": "Thing",
@@ -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": {
@@ -672,6 +673,8 @@
672
673
  "value": ""
673
674
  },
674
675
  "datastreamsFilter": {
676
+ "datastream": "",
677
+ "location": "",
675
678
  "observedProperty": "",
676
679
  "sensor": "",
677
680
  "thing": "",
@@ -336,6 +336,7 @@
336
336
  "radius": ""
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": ""
340
341
  },
341
342
  "layerinfo": {
@@ -672,6 +673,8 @@
672
673
  "value": ""
673
674
  },
674
675
  "datastreamsFilter": {
676
+ "datastream": "",
677
+ "location": "",
675
678
  "observedProperty": "",
676
679
  "sensor": "",
677
680
  "thing": "",
@@ -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": {
@@ -672,6 +673,8 @@
672
673
  "value": ""
673
674
  },
674
675
  "datastreamsFilter": {
676
+ "datastream": "",
677
+ "location": "",
675
678
  "observedProperty": "",
676
679
  "sensor": "",
677
680
  "thing": "",
@@ -336,6 +336,7 @@
336
336
  "radius": ""
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": ""
340
341
  },
341
342
  "layerinfo": {
@@ -672,6 +673,8 @@
672
673
  "value": ""
673
674
  },
674
675
  "datastreamsFilter": {
676
+ "datastream": "",
677
+ "location": "",
675
678
  "observedProperty": "",
676
679
  "sensor": "",
677
680
  "thing": "",
@@ -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": {
@@ -672,6 +673,8 @@
672
673
  "value": ""
673
674
  },
674
675
  "datastreamsFilter": {
676
+ "datastream": "",
677
+ "location": "",
675
678
  "observedProperty": "",
676
679
  "sensor": "",
677
680
  "thing": "",
@@ -336,6 +336,7 @@
336
336
  "radius": "半径"
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": "レイヤ・カタログ"
340
341
  },
341
342
  "layerinfo": {
@@ -672,6 +673,8 @@
672
673
  "value": ""
673
674
  },
674
675
  "datastreamsFilter": {
676
+ "datastream": "",
677
+ "location": "",
675
678
  "observedProperty": "",
676
679
  "sensor": "",
677
680
  "thing": "",
@@ -336,6 +336,7 @@
336
336
  "radius": "Straal"
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": "Lagencatalogus"
340
341
  },
341
342
  "layerinfo": {
@@ -672,6 +673,8 @@
672
673
  "value": ""
673
674
  },
674
675
  "datastreamsFilter": {
676
+ "datastream": "",
677
+ "location": "",
675
678
  "observedProperty": "",
676
679
  "sensor": "",
677
680
  "thing": "",
@@ -336,6 +336,7 @@
336
336
  "radius": ""
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": ""
340
341
  },
341
342
  "layerinfo": {
@@ -672,6 +673,8 @@
672
673
  "value": ""
673
674
  },
674
675
  "datastreamsFilter": {
676
+ "datastream": "",
677
+ "location": "",
675
678
  "observedProperty": "",
676
679
  "sensor": "",
677
680
  "thing": "",
@@ -336,6 +336,7 @@
336
336
  "radius": ""
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": ""
340
341
  },
341
342
  "layerinfo": {
@@ -672,6 +673,8 @@
672
673
  "value": ""
673
674
  },
674
675
  "datastreamsFilter": {
676
+ "datastream": "",
677
+ "location": "",
675
678
  "observedProperty": "",
676
679
  "sensor": "",
677
680
  "thing": "",
@@ -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": {
@@ -672,6 +673,8 @@
672
673
  "value": ""
673
674
  },
674
675
  "datastreamsFilter": {
676
+ "datastream": "",
677
+ "location": "",
675
678
  "observedProperty": "",
676
679
  "sensor": "",
677
680
  "thing": "",
@@ -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": {
@@ -672,6 +673,8 @@
672
673
  "value": ""
673
674
  },
674
675
  "datastreamsFilter": {
676
+ "datastream": "",
677
+ "location": "",
675
678
  "observedProperty": "",
676
679
  "sensor": "",
677
680
  "thing": "",
@@ -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": {
@@ -672,6 +673,8 @@
672
673
  "value": ""
673
674
  },
674
675
  "datastreamsFilter": {
676
+ "datastream": "",
677
+ "location": "",
675
678
  "observedProperty": "",
676
679
  "sensor": "",
677
680
  "thing": "",
@@ -336,6 +336,7 @@
336
336
  "radius": ""
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": ""
340
341
  },
341
342
  "layerinfo": {
@@ -672,6 +673,8 @@
672
673
  "value": ""
673
674
  },
674
675
  "datastreamsFilter": {
676
+ "datastream": "",
677
+ "location": "",
675
678
  "observedProperty": "",
676
679
  "sensor": "",
677
680
  "thing": "",
@@ -336,6 +336,7 @@
336
336
  "radius": ""
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": ""
340
341
  },
341
342
  "layerinfo": {
@@ -672,6 +673,8 @@
672
673
  "value": ""
673
674
  },
674
675
  "datastreamsFilter": {
676
+ "datastream": "",
677
+ "location": "",
675
678
  "observedProperty": "",
676
679
  "sensor": "",
677
680
  "thing": "",
@@ -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": {
@@ -672,6 +673,8 @@
672
673
  "value": ""
673
674
  },
674
675
  "datastreamsFilter": {
676
+ "datastream": "",
677
+ "location": "",
675
678
  "observedProperty": "",
676
679
  "sensor": "",
677
680
  "thing": "",
@@ -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",
@@ -580,6 +581,8 @@
580
581
  "sensorthingstool.datastreamTable.title",
581
582
  "sensorthingstool.datastreamTable.unit",
582
583
  "sensorthingstool.datastreamTable.value",
584
+ "sensorthingstool.datastreamsFilter.datastream",
585
+ "sensorthingstool.datastreamsFilter.location",
583
586
  "sensorthingstool.datastreamsFilter.observedProperty",
584
587
  "sensorthingstool.datastreamsFilter.sensor",
585
588
  "sensorthingstool.datastreamsFilter.thing",
@@ -336,6 +336,7 @@
336
336
  "radius": ""
337
337
  },
338
338
  "layercatalog": {
339
+ "openlink": "",
339
340
  "windowtitle": ""
340
341
  },
341
342
  "layerinfo": {
@@ -672,6 +673,8 @@
672
673
  "value": ""
673
674
  },
674
675
  "datastreamsFilter": {
676
+ "datastream": "",
677
+ "location": "",
675
678
  "observedProperty": "",
676
679
  "sensor": "",
677
680
  "thing": "",
@@ -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) {