qwc2 2025.12.4 → 2025.12.17

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 (57) hide show
  1. package/components/IdentifyViewer.js +89 -35
  2. package/components/ResizeableWindow.js +8 -0
  3. package/components/SearchBox.js +12 -5
  4. package/components/SideBar.js +4 -0
  5. package/components/style/IdentifyViewer.css +7 -5
  6. package/components/widgets/EditableSelect.js +2 -1
  7. package/components/widgets/LayerCatalogWidget.js +25 -14
  8. package/components/widgets/MenuButton.js +7 -2
  9. package/components/widgets/NavBar.js +4 -2
  10. package/components/widgets/PopupMenu.js +44 -13
  11. package/components/widgets/SearchWidget.js +39 -50
  12. package/components/widgets/style/SearchWidget.css +3 -19
  13. package/icons/oblique.svg +53 -0
  14. package/package.json +3 -2
  15. package/plugins/Cyclomedia.js +2 -1
  16. package/plugins/HeightProfile.js +4 -1
  17. package/plugins/Identify.js +4 -0
  18. package/plugins/LayerTree.js +5 -1
  19. package/plugins/Measure.js +5 -1
  20. package/plugins/ObliqueView.js +410 -0
  21. package/plugins/Print.js +1 -1
  22. package/plugins/TopBar.js +2 -0
  23. package/plugins/map/MeasurementSupport.js +1 -0
  24. package/plugins/map/RedliningSupport.js +7 -5
  25. package/plugins/style/Map.css +4 -2
  26. package/plugins/style/ObliqueView.css +112 -0
  27. package/reducers/layers.js +18 -36
  28. package/reducers/measurement.js +2 -1
  29. package/scripts/themesConfig.js +1 -0
  30. package/scripts/themesConfig.py +2 -0
  31. package/scripts/wmts_config_generator.py +1 -1
  32. package/static/translations/bg-BG.json +11 -1
  33. package/static/translations/ca-ES.json +11 -1
  34. package/static/translations/cs-CZ.json +11 -1
  35. package/static/translations/de-CH.json +11 -1
  36. package/static/translations/de-DE.json +11 -1
  37. package/static/translations/en-US.json +11 -1
  38. package/static/translations/es-ES.json +11 -1
  39. package/static/translations/fi-FI.json +11 -1
  40. package/static/translations/fr-FR.json +12 -2
  41. package/static/translations/hu-HU.json +11 -1
  42. package/static/translations/it-IT.json +11 -1
  43. package/static/translations/ja-JP.json +11 -1
  44. package/static/translations/nl-NL.json +11 -1
  45. package/static/translations/no-NO.json +11 -1
  46. package/static/translations/pl-PL.json +11 -1
  47. package/static/translations/pt-BR.json +11 -1
  48. package/static/translations/pt-PT.json +11 -1
  49. package/static/translations/ro-RO.json +11 -1
  50. package/static/translations/ru-RU.json +11 -1
  51. package/static/translations/sv-SE.json +11 -1
  52. package/static/translations/tr-TR.json +11 -1
  53. package/static/translations/tsconfig.json +8 -0
  54. package/static/translations/uk-UA.json +11 -1
  55. package/utils/FeatureStyles.js +5 -2
  56. package/utils/MiscUtils.js +2 -1
  57. package/utils/VectorLayerUtils.js +14 -5
@@ -0,0 +1,410 @@
1
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
+ function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
3
+ function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } }
4
+ function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
5
+ function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
6
+ function _possibleConstructorReturn(t, e) { if (e && ("object" == _typeof(e) || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); }
7
+ function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; }
8
+ function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
9
+ function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); }
10
+ function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); }
11
+ function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); }
12
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
13
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
14
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
15
+ /**
16
+ * Copyright 2025 Sourcepole AG
17
+ * All rights reserved.
18
+ *
19
+ * This source code is licensed under the BSD-style license found in the
20
+ * LICENSE file in the root directory of this source tree.
21
+ */
22
+
23
+ import React from 'react';
24
+ import { connect } from 'react-redux';
25
+ import axios from 'axios';
26
+ import ol from 'openlayers';
27
+ import PropTypes from 'prop-types';
28
+ import { setCurrentTask } from '../actions/task';
29
+ import Icon from '../components/Icon';
30
+ import ResizeableWindow from '../components/ResizeableWindow';
31
+ import LayerRegistry from '../components/map/layers/index';
32
+ import InputContainer from '../components/widgets/InputContainer';
33
+ import ConfigUtils from '../utils/ConfigUtils';
34
+ import LayerUtils from '../utils/LayerUtils';
35
+ import LocaleUtils from '../utils/LocaleUtils';
36
+ import MapUtils from '../utils/MapUtils';
37
+ import MiscUtils from '../utils/MiscUtils';
38
+ import './style/ObliqueView.css';
39
+
40
+ /**
41
+ * Display oblique satellite imagery.
42
+ */
43
+ var ObliqueView = /*#__PURE__*/function (_React$Component) {
44
+ function ObliqueView(props) {
45
+ var _this;
46
+ _classCallCheck(this, ObliqueView);
47
+ _this = _callSuper(this, ObliqueView, [props]);
48
+ _defineProperty(_this, "onClose", function () {
49
+ _this.setState(ObliqueView.defaultState);
50
+ });
51
+ _defineProperty(_this, "renderScaleChooser", function () {
52
+ return /*#__PURE__*/React.createElement("div", {
53
+ className: "obliqueview-scalechooser"
54
+ }, /*#__PURE__*/React.createElement("span", null, LocaleUtils.tr("bottombar.scale_label"), ":\xA0"), /*#__PURE__*/React.createElement(InputContainer, null, /*#__PURE__*/React.createElement("span", {
55
+ role: "prefix"
56
+ }, " 1 : "), /*#__PURE__*/React.createElement("select", {
57
+ onChange: function onChange(ev) {
58
+ return _this.setState({
59
+ currentZoom: parseInt(ev.target.value, 10)
60
+ });
61
+ },
62
+ role: "input",
63
+ value: _this.state.currentZoom
64
+ }, _this.props.scales.map(function (item, index) {
65
+ return /*#__PURE__*/React.createElement("option", {
66
+ key: index,
67
+ value: index
68
+ }, LocaleUtils.toLocaleFixed(item, 0));
69
+ }))));
70
+ });
71
+ _defineProperty(_this, "changeZoom", function (delta) {
72
+ _this.setState(function (state) {
73
+ return {
74
+ currentZoom: Math.max(0, Math.min(state.currentZoom + delta, _this.props.scales.length - 1))
75
+ };
76
+ });
77
+ });
78
+ _defineProperty(_this, "queryDatasetConfig", function () {
79
+ var obliqueImageryServiceUrl = ConfigUtils.getConfigProp('obliqueImageryServiceUrl');
80
+ if (_this.state.selectedDataset && obliqueImageryServiceUrl) {
81
+ var reqUrl = obliqueImageryServiceUrl.replace(/\/$/, '') + "/".concat(_this.state.selectedDataset, "/config");
82
+ axios.get(reqUrl).then(function (response) {
83
+ var datasetConfig = response.data;
84
+ var direction = 'n' in datasetConfig.image_centers ? 'n' : Object.keys(datasetConfig.image_centers)[0];
85
+ _this.setState({
86
+ datasetConfig: datasetConfig,
87
+ currentDirection: direction
88
+ });
89
+ })["catch"](function () {
90
+ /* eslint-disable-next-line */
91
+ console.warn("Failed to load dataset config");
92
+ });
93
+ }
94
+ });
95
+ _defineProperty(_this, "setupLayer", function () {
96
+ var datasetConfig = _this.state.datasetConfig;
97
+ var projection = new ol.proj.Projection({
98
+ code: datasetConfig.crs,
99
+ extent: datasetConfig.extent,
100
+ units: "m"
101
+ });
102
+ var targetScale = _this.props.initialScale;
103
+ var zoom = _this.props.scales.reduce(function (best, v, i) {
104
+ return Math.abs(v - targetScale) < Math.abs(_this.props.scales[best] - targetScale) ? i : best;
105
+ }, 0);
106
+ _this.map.setView(new ol.View({
107
+ projection: projection,
108
+ // extent: datasetConfig.extent,
109
+ center: ol.extent.getCenter(datasetConfig.extent),
110
+ rotation: _this.getRotation() / 180 * Math.PI,
111
+ zoom: zoom,
112
+ resolutions: MapUtils.getResolutionsForScales(_this.props.scales, datasetConfig.crs),
113
+ constrainResolution: true
114
+ // showFullExtent: true
115
+ }));
116
+ _this.setState({
117
+ currentZoom: zoom
118
+ });
119
+ _this.map.on('moveend', function () {
120
+ _this.setState(function (state) {
121
+ var newZoom = _this.map.getView().getZoom();
122
+ if (newZoom !== state.currentZoom) {
123
+ return {
124
+ currentZoom: newZoom
125
+ };
126
+ }
127
+ return null;
128
+ });
129
+ });
130
+ var layers = [];
131
+ var themeConfig = _this.props.theme.obliqueDatasets.find(function (entry) {
132
+ return entry.name === _this.state.selectedDataset;
133
+ });
134
+ if (themeConfig.backgroundLayer) {
135
+ var _themeConfig$backgrou;
136
+ var layerConfig = LayerUtils.splitLayerUrlParam(themeConfig.backgroundLayer);
137
+ layerConfig.version = _this.props.themes.defaultWMSVersion || "1.3.0";
138
+ layerConfig.opacity = (_themeConfig$backgrou = themeConfig.backgroundOpacity) !== null && _themeConfig$backgrou !== void 0 ? _themeConfig$backgrou : 127;
139
+ var layerCreator = LayerRegistry[layerConfig.type];
140
+ if (layerCreator) {
141
+ layers.push(layerCreator.create(layerConfig, _this.map));
142
+ }
143
+ }
144
+ _this.obliqueImageryLayer = new ol.layer.Tile({
145
+ source: new ol.source.XYZ({
146
+ projection: projection,
147
+ tileGrid: new ol.tilegrid.TileGrid({
148
+ extent: datasetConfig.extent,
149
+ resolutions: datasetConfig.resolutions,
150
+ tileSize: datasetConfig.tileSize,
151
+ origin: datasetConfig.origin
152
+ }),
153
+ url: datasetConfig.url,
154
+ crossOrigin: "anonymous",
155
+ tileLoadFunction: function tileLoadFunction(tile, src) {
156
+ var _this$closestImage;
157
+ if (((_this$closestImage = _this.closestImage) !== null && _this$closestImage !== void 0 ? _this$closestImage : null) !== null) {
158
+ src += "?img=" + _this.closestImage;
159
+ }
160
+ tile.getImage().src = src.replace('{direction}', _this.state.currentDirection);
161
+ }
162
+ })
163
+ });
164
+ layers.push(_this.obliqueImageryLayer);
165
+ _this.map.setLayers(layers);
166
+ });
167
+ _defineProperty(_this, "searchClosestImage", function () {
168
+ var _this$state$datasetCo;
169
+ var best = null;
170
+ var imageCenters = (_this$state$datasetCo = _this.state.datasetConfig) === null || _this$state$datasetCo === void 0 || (_this$state$datasetCo = _this$state$datasetCo.image_centers) === null || _this$state$datasetCo === void 0 ? void 0 : _this$state$datasetCo[_this.state.currentDirection];
171
+ if (imageCenters) {
172
+ var center = _this.map.getView().getCenter();
173
+ var dsqr = function dsqr(p, q) {
174
+ return (p[0] - q[0]) * (p[0] - q[0]) + (p[1] - q[1]) * (p[1] - q[1]);
175
+ };
176
+ best = 0;
177
+ var bestDist = dsqr(center, imageCenters[0]);
178
+ for (var i = 1; i < imageCenters.length; ++i) {
179
+ var dist = dsqr(center, imageCenters[i]);
180
+ if (dist < bestDist) {
181
+ bestDist = dist;
182
+ best = i;
183
+ }
184
+ }
185
+ }
186
+ if (best !== _this.closestImage) {
187
+ if (_this.obliqueImageryLayer) {
188
+ _this.obliqueImageryLayer.getSource().refresh();
189
+ }
190
+ _this.closestImage = best;
191
+ }
192
+ });
193
+ _defineProperty(_this, "getRotation", function () {
194
+ return {
195
+ n: 0,
196
+ w: 90,
197
+ e: -90,
198
+ s: 180
199
+ }[_this.state.currentDirection];
200
+ });
201
+ var controls = ol.control.defaults({
202
+ zoom: false,
203
+ attribution: false,
204
+ rotate: false
205
+ });
206
+ var interactions = ol.interaction.defaults({
207
+ onFocusOnly: false
208
+ });
209
+ _this.map = new ol.Map({
210
+ controls: controls,
211
+ interactions: interactions
212
+ });
213
+ _this.map.on('moveend', _this.searchClosestImage);
214
+ _this.map.on('rotateend', _this.searchClosestImage);
215
+ _this.closestImage = null;
216
+ _this.obliqueImageryLayer = null;
217
+ _this.state = ObliqueView.defaultState;
218
+ return _this;
219
+ }
220
+ _inherits(ObliqueView, _React$Component);
221
+ return _createClass(ObliqueView, [{
222
+ key: "componentDidUpdate",
223
+ value: function componentDidUpdate(prevProps, prevState) {
224
+ if (this.props.active && !prevProps.active) {
225
+ this.setState({
226
+ active: true
227
+ });
228
+ this.props.setCurrentTask(null);
229
+ }
230
+ if (this.props.active && this.props.theme && this.props.theme !== prevProps.theme || this.props.active && !prevProps.active) {
231
+ var _datasets$find$name, _datasets$find, _datasets$;
232
+ var datasets = this.props.theme.obliqueDatasets || [];
233
+ var defaultDataset = (_datasets$find$name = (_datasets$find = datasets.find(function (entry) {
234
+ return entry["default"];
235
+ })) === null || _datasets$find === void 0 ? void 0 : _datasets$find.name) !== null && _datasets$find$name !== void 0 ? _datasets$find$name : (_datasets$ = datasets[0]) === null || _datasets$ === void 0 ? void 0 : _datasets$.name;
236
+ this.setState({
237
+ selectedDataset: defaultDataset,
238
+ datasetConfig: null,
239
+ currentDirection: null
240
+ });
241
+ }
242
+ if (this.state.selectedDataset !== prevState.selectedDataset) {
243
+ this.closestImage = null;
244
+ this.obliqueImageryLayer = null;
245
+ this.queryDatasetConfig();
246
+ }
247
+ if (this.state.datasetConfig && this.state.datasetConfig !== prevState.datasetConfig) {
248
+ this.setupLayer();
249
+ }
250
+ if (this.state.datasetConfig && this.state.currentDirection !== prevState.currentDirection) {
251
+ var _this$obliqueImageryL, _this$obliqueImageryL2, _this$obliqueImageryL3, _this$map$getView, _this$map$getView$set;
252
+ (_this$obliqueImageryL = this.obliqueImageryLayer) === null || _this$obliqueImageryL === void 0 || (_this$obliqueImageryL2 = _this$obliqueImageryL.getSource) === null || _this$obliqueImageryL2 === void 0 || (_this$obliqueImageryL2 = _this$obliqueImageryL2.call(_this$obliqueImageryL)) === null || _this$obliqueImageryL2 === void 0 || (_this$obliqueImageryL3 = _this$obliqueImageryL2.refresh) === null || _this$obliqueImageryL3 === void 0 || _this$obliqueImageryL3.call(_this$obliqueImageryL2);
253
+ (_this$map$getView = this.map.getView()) === null || _this$map$getView === void 0 || (_this$map$getView$set = _this$map$getView.setRotation) === null || _this$map$getView$set === void 0 || _this$map$getView$set.call(_this$map$getView, this.getRotation() / 180 * Math.PI);
254
+ }
255
+ if (this.state.datasetConfig && this.state.currentZoom !== prevState.currentZoom) {
256
+ var _this$map$getView2, _this$map$getView2$se;
257
+ (_this$map$getView2 = this.map.getView()) === null || _this$map$getView2 === void 0 || (_this$map$getView2$se = _this$map$getView2.setZoom) === null || _this$map$getView2$se === void 0 || _this$map$getView2$se.call(_this$map$getView2, this.state.currentZoom);
258
+ }
259
+ }
260
+ }, {
261
+ key: "render",
262
+ value: function render() {
263
+ var _this2 = this;
264
+ if (!this.state.active) {
265
+ return null;
266
+ }
267
+ var rot = this.getRotation();
268
+ return /*#__PURE__*/React.createElement(ResizeableWindow, {
269
+ dockable: this.props.geometry.side,
270
+ icon: "oblique",
271
+ initialHeight: this.props.geometry.initialHeight,
272
+ initialWidth: this.props.geometry.initialWidth,
273
+ initialX: this.props.geometry.initialX,
274
+ initialY: this.props.geometry.initialY,
275
+ initiallyDocked: this.props.geometry.initiallyDocked,
276
+ onClose: this.onClose,
277
+ splitScreenWhenDocked: true,
278
+ splitTopAndBottomBar: true,
279
+ title: LocaleUtils.tr("obliqueview.title")
280
+ }, /*#__PURE__*/React.createElement("div", {
281
+ className: "obliqueview-body"
282
+ }, /*#__PURE__*/React.createElement("div", {
283
+ className: "obliqueview-map",
284
+ ref: function ref(el) {
285
+ return _this2.map.setTarget(el);
286
+ },
287
+ tabIndex: 0
288
+ }), !this.state.selectedDataset && /*#__PURE__*/React.createElement("div", {
289
+ className: "obliqueview-empty-overlay"
290
+ }, LocaleUtils.tr("obliqueview.nodataset")), /*#__PURE__*/React.createElement("div", {
291
+ className: "obliqueview-nav-rotate",
292
+ style: {
293
+ transform: "rotate(".concat(rot, "deg)")
294
+ }
295
+ }, /*#__PURE__*/React.createElement("span", null), /*#__PURE__*/React.createElement("span", {
296
+ className: "obliqueview-nav-dir",
297
+ onClick: function onClick() {
298
+ return _this2.setState({
299
+ currentDirection: "n"
300
+ });
301
+ },
302
+ onKeyDown: MiscUtils.checkKeyActivate,
303
+ style: {
304
+ transform: "rotate(".concat(-rot, "deg)")
305
+ },
306
+ tabIndex: 0
307
+ }, "N"), /*#__PURE__*/React.createElement("span", null), /*#__PURE__*/React.createElement("span", {
308
+ className: "obliqueview-nav-dir",
309
+ onClick: function onClick() {
310
+ return _this2.setState({
311
+ currentDirection: "w"
312
+ });
313
+ },
314
+ onKeyDown: MiscUtils.checkKeyActivate,
315
+ style: {
316
+ transform: "rotate(".concat(-rot, "deg)")
317
+ },
318
+ tabIndex: 0
319
+ }, "W"), /*#__PURE__*/React.createElement("span", null), /*#__PURE__*/React.createElement("span", {
320
+ className: "obliqueview-nav-dir",
321
+ onClick: function onClick() {
322
+ return _this2.setState({
323
+ currentDirection: "e"
324
+ });
325
+ },
326
+ onKeyDown: MiscUtils.checkKeyActivate,
327
+ style: {
328
+ transform: "rotate(".concat(-rot, "deg)")
329
+ },
330
+ tabIndex: 0
331
+ }, "E"), /*#__PURE__*/React.createElement("span", null), /*#__PURE__*/React.createElement("span", {
332
+ className: "obliqueview-nav-dir",
333
+ onClick: function onClick() {
334
+ return _this2.setState({
335
+ currentDirection: "s"
336
+ });
337
+ },
338
+ onKeyDown: MiscUtils.checkKeyActivate,
339
+ style: {
340
+ transform: "rotate(".concat(-rot, "deg)")
341
+ },
342
+ tabIndex: 0
343
+ }, "S"), /*#__PURE__*/React.createElement("span", null)), /*#__PURE__*/React.createElement("div", {
344
+ className: "obliqueview-nav-zoom"
345
+ }, /*#__PURE__*/React.createElement(Icon, {
346
+ icon: "plus",
347
+ onClick: function onClick() {
348
+ return _this2.changeZoom(+1);
349
+ }
350
+ }), /*#__PURE__*/React.createElement(Icon, {
351
+ icon: "minus",
352
+ onClick: function onClick() {
353
+ return _this2.changeZoom(-1);
354
+ }
355
+ })), /*#__PURE__*/React.createElement("div", {
356
+ className: "obliqueview-bottombar"
357
+ }, this.renderScaleChooser())));
358
+ }
359
+ }]);
360
+ }(React.Component);
361
+ _defineProperty(ObliqueView, "propTypes", {
362
+ active: PropTypes.bool,
363
+ /** Default window geometry with size, position and docking status. Positive position values (including '0') are related to top (InitialY) and left (InitialX), negative values (including '-0') to bottom (InitialY) and right (InitialX). */
364
+ geometry: PropTypes.shape({
365
+ initialWidth: PropTypes.number,
366
+ initialHeight: PropTypes.number,
367
+ initialX: PropTypes.number,
368
+ initialY: PropTypes.number,
369
+ initiallyDocked: PropTypes.bool,
370
+ side: PropTypes.string
371
+ }),
372
+ /** The initial map scale. */
373
+ initialScale: PropTypes.number,
374
+ mapBbox: PropTypes.object,
375
+ projection: PropTypes.string,
376
+ /** A list of allowed map scales, in decreasing order. */
377
+ scales: PropTypes.arrayOf(PropTypes.number),
378
+ setCurrentTask: PropTypes.func,
379
+ theme: PropTypes.object,
380
+ themes: PropTypes.object
381
+ });
382
+ _defineProperty(ObliqueView, "defaultProps", {
383
+ geometry: {
384
+ initialWidth: 480,
385
+ initialHeight: 640,
386
+ initialX: 0,
387
+ initialY: 0,
388
+ initiallyDocked: true,
389
+ side: 'left'
390
+ },
391
+ initialScale: 1000,
392
+ scales: [20000, 10000, 5000, 2500, 1000, 500, 250]
393
+ });
394
+ _defineProperty(ObliqueView, "defaultState", {
395
+ active: false,
396
+ selectedDataset: null,
397
+ datasetConfig: null,
398
+ currentDirection: null,
399
+ currentZoom: 0
400
+ });
401
+ export default connect(function (state) {
402
+ return {
403
+ active: state.task.id === "ObliqueView",
404
+ mapBbox: state.map.bbox,
405
+ theme: state.theme.current,
406
+ themes: state.theme.themes
407
+ };
408
+ }, {
409
+ setCurrentTask: setCurrentTask
410
+ })(ObliqueView);
package/plugins/Print.js CHANGED
@@ -1196,7 +1196,7 @@ _defineProperty(Print, "propTypes", {
1196
1196
  printExternalLayers: PropTypes.bool,
1197
1197
  /** Whether to print highlights on the map, e.g. selected features or redlining. */
1198
1198
  printMapHighlights: PropTypes.bool,
1199
- /** Restrict print scale to list of predefine print scales, if any. */
1199
+ /** Restrict print scale to list of predefined print scales, if any. */
1200
1200
  restrictToPrintScales: PropTypes.bool,
1201
1201
  /** Scale factor to apply to line widths, font sizes, ... of redlining drawings passed to GetPrint. */
1202
1202
  scaleFactor: PropTypes.number,
package/plugins/TopBar.js CHANGED
@@ -243,6 +243,8 @@ _defineProperty(TopBar, "propTypes", {
243
243
  searchOptions: PropTypes.shape({
244
244
  /** Whether to show the search filter widget. */
245
245
  allowSearchFilters: PropTypes.bool,
246
+ /** Whether to focus the search field on startup. */
247
+ focusOnStartup: PropTypes.bool,
246
248
  /** Whether to hide the result labels on the map. */
247
249
  hideResultLabels: PropTypes.bool,
248
250
  /** The style used for highlighting search result geometries. */
@@ -179,6 +179,7 @@ var MeasurementSupport = /*#__PURE__*/function (_React$Component) {
179
179
  opts.headmarker = _this.props.measurement.bearingHeadMarker;
180
180
  opts.tailmarker = _this.props.measurement.bearingTailMarker;
181
181
  }
182
+ opts.markerscale = _this.props.measurement.markerScale;
182
183
  return [].concat(_toConsumableArray(FeatureStyles.measureInteraction(feature, opts)), [FeatureStyles.measureInteractionVertex({
183
184
  geometryFunction: geometryFunction
184
185
  })]);
@@ -181,7 +181,7 @@ var RedliningSupport = /*#__PURE__*/function (_React$Component) {
181
181
  var isText = feature.get("shape") === "Text";
182
182
  var styleName = isText ? "text" : "default";
183
183
  var opts = _this.styleOptions(styleProps, isText);
184
- if (!feature.get('measurements')) {
184
+ if (!feature.get('measurements') && _this.selectedFeatures.length <= 1 && !(isText && !styleProps.text)) {
185
185
  feature.set('label', styleProps.text);
186
186
  }
187
187
  feature.set('styleName', styleName);
@@ -559,7 +559,6 @@ var RedliningSupport = /*#__PURE__*/function (_React$Component) {
559
559
  cloneIds.push(featureObj.id);
560
560
  return featureObj;
561
561
  });
562
- _this.updateRedliningState(true);
563
562
  var layer = {
564
563
  id: _this.props.redlining.layer,
565
564
  title: _this.props.redlining.layerTitle,
@@ -570,7 +569,7 @@ var RedliningSupport = /*#__PURE__*/function (_React$Component) {
570
569
  var features = cloneIds.map(function (id) {
571
570
  return l.getSource().getFeatureById(id);
572
571
  });
573
- _this.selectFeatures(features);
572
+ _this.selectFeatures(features, false);
574
573
  while (_this.interactions.length > 0) {
575
574
  _this.props.map.removeInteraction(_this.interactions.shift());
576
575
  }
@@ -606,13 +605,16 @@ var RedliningSupport = /*#__PURE__*/function (_React$Component) {
606
605
  }
607
606
  });
608
607
  _defineProperty(_this, "selectFeatures", function (features) {
608
+ var updateState = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
609
609
  var firstSelection = isEmpty(_this.selectedFeatures);
610
610
  features.forEach(function (feature) {
611
611
  feature.setStyle(_this.styleFunction);
612
612
  feature.on('change', _this.updateMeasurements);
613
613
  _this.selectedFeatures.push(feature);
614
614
  });
615
- _this.updateRedliningState(firstSelection);
615
+ if (updateState) {
616
+ _this.updateRedliningState(firstSelection);
617
+ }
616
618
  });
617
619
  _defineProperty(_this, "deselectFeature", function (feature, updateState) {
618
620
  var styleName = feature.get("shape") === "Text" ? "text" : "default";
@@ -655,7 +657,7 @@ var RedliningSupport = /*#__PURE__*/function (_React$Component) {
655
657
  return featureObj;
656
658
  }).filter(Boolean);
657
659
  if (isEmpty(featureObjects)) {
658
- return null;
660
+ return [];
659
661
  }
660
662
  var layer = {
661
663
  id: redliningProps.layer,
@@ -9,8 +9,10 @@ div.map-contents {
9
9
  /* Move and re-style rotation reset button */
10
10
  div.ol-rotate {
11
11
  padding: 0;
12
- top: 4em!important;
13
- right: 0.5em!important;
12
+ bottom: 2.75em!important;
13
+ left: 0.5em!important;
14
+ right: initial!important;
15
+ top: initial!important;
14
16
  }
15
17
 
16
18
  div.ol-rotate button {
@@ -0,0 +1,112 @@
1
+ div.obliqueview-body {
2
+ position: absolute;
3
+ left: 0;
4
+ right: 0;
5
+ top: 0;
6
+ bottom: 0;
7
+ }
8
+
9
+ div.obliqueview-empty-overlay {
10
+ position: absolute;
11
+ left: 0;
12
+ right: 0;
13
+ top: 0;
14
+ bottom: 0;
15
+ display: flex;
16
+ align-items: center;
17
+ justify-content: center;
18
+ background-color: rgba(200, 200, 200);
19
+ z-index: 4;
20
+ }
21
+
22
+ div.obliqueview-map {
23
+ height: 100%;
24
+ }
25
+
26
+ div.obliqueview-nav-rotate {
27
+ position: absolute;
28
+ right: 1em;
29
+ top: 1em;
30
+ display: flex;
31
+ align-items: center;
32
+ justify-content: center;
33
+ flex-wrap: wrap;
34
+ width: 4em;
35
+ height: 4em;
36
+ border-radius: 3em;
37
+ color: var(--map-button-text-color);
38
+ background-color: var(--map-button-bg-color);
39
+ box-shadow: 0px 5px 10px rgba(136, 136, 136, 0.5);
40
+ margin-bottom: 0.5em;
41
+ transition: transform 0.5s;
42
+ }
43
+
44
+ div.obliqueview-nav-rotate > span {
45
+ flex: 0 0 1.25em;
46
+ }
47
+
48
+ span.obliqueview-nav-dir {
49
+ display: flex;
50
+ align-items: center;
51
+ justify-content: center;
52
+ font-weight: bold;
53
+ cursor: pointer;
54
+ transition: transform 0.5s;
55
+ }
56
+
57
+ div.obliqueview-nav-zoom {
58
+ position: absolute;
59
+ right: 0.5em;
60
+ top: 6em;
61
+ width: 2em;
62
+ display: flex;
63
+ align-items: center;
64
+ justify-content: center;
65
+ color: var(--map-button-text-color);
66
+ background-color: var(--map-button-bg-color);
67
+ box-shadow: 0px 5px 10px rgba(136, 136, 136, 0.5);
68
+ border-radius: 4px;
69
+ cursor: pointer;
70
+ transition: background-color 0.5s, color 0.5s;
71
+ flex-direction: column;
72
+ margin: 0 1.5em 0.5em 1em;
73
+ }
74
+
75
+ div.obliqueview-nav-zoom > span {
76
+ height: 2em;
77
+ width: 1.5em;
78
+ display: flex;
79
+ align-items: center;
80
+ justify-content: center;
81
+ }
82
+
83
+ div.obliqueview-nav-zoom > span:first-child {
84
+ border-bottom: 1px solid var(--map-button-text-color);
85
+ }
86
+
87
+ div.obliqueview-bottombar {
88
+ position: absolute;
89
+ left: 0;
90
+ right: 0;
91
+ bottom: 0;
92
+ height: 3em;
93
+ z-index: 100;
94
+ color: var(--panel-text-color);
95
+ background-color: var(--panel-bg-color);
96
+ box-shadow: 0 -2px 4px rgba(136, 136, 136, 0.5);
97
+ backdrop-filter: blur(3px);
98
+ font-size: 75%;
99
+ display: flex;
100
+ align-items: center;
101
+ justify-content: center;
102
+ }
103
+
104
+ div.obliqueview-scalechooser {
105
+ width: 10em;
106
+ display: flex;
107
+ align-items: center;
108
+ }
109
+
110
+ div.obliqueview-scalechooser > div.input-container {
111
+ flex: 1 1 auto;
112
+ }