qwc2 2025.10.16 → 2025.10.24

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 (62) hide show
  1. package/actions/locate.js +3 -2
  2. package/components/AttributeTableWidget.js +24 -15
  3. package/components/FeatureAttributesWindow.js +177 -0
  4. package/components/IdentifyViewer.js +80 -39
  5. package/components/LocationRecorder.js +138 -0
  6. package/components/PickFeature.js +87 -26
  7. package/components/PluginsContainer.js +16 -3
  8. package/components/map/OlLayer.js +2 -1
  9. package/components/map3d/HeightProfile3D.js +2 -0
  10. package/components/style/App.css +14 -0
  11. package/components/style/AttributeTableWidget.css +1 -1
  12. package/components/style/FeatureAttributesWindow.css +16 -0
  13. package/components/style/IdentifyViewer.css +5 -0
  14. package/components/style/LocationRecorder.css +10 -0
  15. package/components/style/NumericInputWindow.css +7 -0
  16. package/components/style/PluginsContainer.css +16 -0
  17. package/components/widgets/LayerCatalogWidget.js +40 -16
  18. package/components/widgets/NavBar.js +10 -3
  19. package/icons/circle_full.svg +75 -0
  20. package/package.json +1 -1
  21. package/plugins/AttributeTable.js +4 -0
  22. package/plugins/GeometryDigitizer.js +3 -0
  23. package/plugins/HeightProfile.js +2 -0
  24. package/plugins/Identify.js +7 -3
  25. package/plugins/ObjectList.js +116 -0
  26. package/plugins/Redlining.js +14 -55
  27. package/plugins/map/EditingSupport.js +22 -1
  28. package/plugins/map/LocateSupport.js +8 -1
  29. package/plugins/map/RedliningSupport.js +108 -18
  30. package/plugins/map/SnappingSupport.js +11 -6
  31. package/plugins/map/style/SnappingSupport.css +2 -13
  32. package/reducers/locate.js +4 -2
  33. package/reducers/redlining.js +2 -1
  34. package/static/translations/bg-BG.json +13 -0
  35. package/static/translations/ca-ES.json +13 -0
  36. package/static/translations/cs-CZ.json +13 -0
  37. package/static/translations/de-CH.json +13 -0
  38. package/static/translations/de-DE.json +14 -1
  39. package/static/translations/en-US.json +13 -0
  40. package/static/translations/es-ES.json +13 -0
  41. package/static/translations/fi-FI.json +13 -0
  42. package/static/translations/fr-FR.json +13 -0
  43. package/static/translations/hu-HU.json +13 -0
  44. package/static/translations/it-IT.json +13 -0
  45. package/static/translations/ja-JP.json +13 -0
  46. package/static/translations/nl-NL.json +13 -0
  47. package/static/translations/no-NO.json +13 -0
  48. package/static/translations/pl-PL.json +13 -0
  49. package/static/translations/pt-BR.json +13 -0
  50. package/static/translations/pt-PT.json +13 -0
  51. package/static/translations/ro-RO.json +13 -0
  52. package/static/translations/ru-RU.json +13 -0
  53. package/static/translations/sv-SE.json +13 -0
  54. package/static/translations/tr-TR.json +13 -0
  55. package/static/translations/tsconfig.json +10 -0
  56. package/static/translations/uk-UA.json +13 -0
  57. package/utils/EditingInterface.js +4 -1
  58. package/utils/EditingUtils.js +3 -1
  59. package/utils/MiscUtils.js +65 -0
  60. package/utils/expr_grammar/grammar.js +104 -22
  61. package/utils/expr_grammar/grammar.ne +2 -0
  62. package/utils/expr_grammar/test.js +21 -4
@@ -0,0 +1,75 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <!-- Generated by IcoMoon.io -->
3
+
4
+ <svg
5
+ version="1.1"
6
+ width="24"
7
+ height="24"
8
+ viewBox="0 0 24 24"
9
+ id="svg6"
10
+ sodipodi:docname="record.svg"
11
+ inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
12
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
13
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
14
+ xmlns="http://www.w3.org/2000/svg"
15
+ xmlns:svg="http://www.w3.org/2000/svg"
16
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
17
+ xmlns:cc="http://creativecommons.org/ns#"
18
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
19
+ <metadata
20
+ id="metadata12">
21
+ <rdf:RDF>
22
+ <cc:Work
23
+ rdf:about="">
24
+ <dc:format>image/svg+xml</dc:format>
25
+ <dc:type
26
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
27
+ <dc:title>uniE250</dc:title>
28
+ </cc:Work>
29
+ </rdf:RDF>
30
+ </metadata>
31
+ <defs
32
+ id="defs10" />
33
+ <sodipodi:namedview
34
+ pagecolor="#ffffff"
35
+ bordercolor="#666666"
36
+ borderopacity="1"
37
+ objecttolerance="10"
38
+ gridtolerance="10"
39
+ guidetolerance="10"
40
+ inkscape:pageopacity="0"
41
+ inkscape:pageshadow="2"
42
+ inkscape:window-width="1920"
43
+ inkscape:window-height="1172"
44
+ id="namedview8"
45
+ showgrid="true"
46
+ inkscape:zoom="20.85965"
47
+ inkscape:cx="11.697224"
48
+ inkscape:cy="10.810344"
49
+ inkscape:window-x="0"
50
+ inkscape:window-y="0"
51
+ inkscape:window-maximized="1"
52
+ inkscape:current-layer="svg6"
53
+ inkscape:pagecheckerboard="0"
54
+ inkscape:showpageshadow="2"
55
+ inkscape:deskcolor="#d1d1d1">
56
+ <inkscape:grid
57
+ type="xygrid"
58
+ id="grid823"
59
+ originx="0"
60
+ originy="0"
61
+ spacingy="1"
62
+ spacingx="1"
63
+ units="px" />
64
+ </sodipodi:namedview>
65
+ <title
66
+ id="title2">uniE250</title>
67
+ <rect
68
+ style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stop-color:#000000"
69
+ id="rect866"
70
+ width="18"
71
+ height="18"
72
+ x="3"
73
+ y="3"
74
+ ry="9" />
75
+ </svg>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qwc2",
3
- "version": "2025.10.16",
3
+ "version": "2025.10.24",
4
4
  "description": "QGIS Web Client",
5
5
  "author": "Sourcepole AG",
6
6
  "license": "BSD-2-Clause",
@@ -75,6 +75,7 @@ var AttributeTable = /*#__PURE__*/function (_React$Component) {
75
75
  allowAddForGeometryLayers: this.props.allowAddForGeometryLayers,
76
76
  iface: this.props.iface,
77
77
  initialLayer: (_this$props$taskData = this.props.taskData) === null || _this$props$taskData === void 0 ? void 0 : _this$props$taskData.layer,
78
+ limitToExtent: this.props.limitToExtent,
78
79
  role: "body",
79
80
  showEditFormButton: this.props.showEditFormButton,
80
81
  showHiddenFields: this.props.showHiddenFields,
@@ -90,6 +91,8 @@ _defineProperty(AttributeTable, "propTypes", {
90
91
  allowAddForGeometryLayers: PropTypes.bool,
91
92
  blocked: PropTypes.bool,
92
93
  iface: PropTypes.object,
94
+ /** Whether to limit to the extent by default. */
95
+ limitToExtent: PropTypes.bool,
93
96
  setCurrentTask: PropTypes.func,
94
97
  /** Whether to show a button to open the edit form for selected layer. Requires the Editing plugin to be enabled. */
95
98
  showEditFormButton: PropTypes.bool,
@@ -102,6 +105,7 @@ _defineProperty(AttributeTable, "propTypes", {
102
105
  zoomLevel: PropTypes.number
103
106
  });
104
107
  _defineProperty(AttributeTable, "defaultProps", {
108
+ limitToExtent: false,
105
109
  zoomLevel: 1000,
106
110
  showEditFormButton: true,
107
111
  showHiddenFields: true,
@@ -622,6 +622,9 @@ var GeometryDigitizer = /*#__PURE__*/function (_React$Component) {
622
622
  }), this.renderOutputWindow(), this.state.pickGeomType ? /*#__PURE__*/React.createElement(PickFeature, {
623
623
  featurePicked: this.selectFeature,
624
624
  key: "FeaturePicker",
625
+ layerFilterFunc: function layerFilterFunc(layer) {
626
+ return !layer.id.startsWith("__geomdigitizer");
627
+ },
625
628
  pickGeomType: this.state.pickGeomType
626
629
  }) : null];
627
630
  }
@@ -208,6 +208,8 @@ var HeightProfilePrintDialog_ = /*#__PURE__*/function (_React$PureComponent) {
208
208
  value: function componentDidMount() {
209
209
  var templatePath = MiscUtils.resolveAssetsPath(this.props.templatePath);
210
210
  this.externalWindow = window.open(templatePath, LocaleUtils.tr("heightprofile.title"), "toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes");
211
+ // Inherit API
212
+ this.externalWindow.qwc2 = window.qwc2;
211
213
  this.externalWindow.addEventListener('load', this.setWindowContent, false);
212
214
  this.externalWindow.addEventListener('resize', this.windowResized, false);
213
215
  window.addEventListener('beforeunload', this.closePrintWindow);
@@ -94,7 +94,7 @@ var Identify = /*#__PURE__*/function (_React$Component) {
94
94
  };
95
95
  });
96
96
  if (response) {
97
- _this.parseResult(response, l, request.params.info_format, clickPoint);
97
+ _this.parseResult(response, l, request.params.info_format, clickPoint, _this.props.click.modifiers.ctrl);
98
98
  }
99
99
  });
100
100
  });
@@ -229,6 +229,7 @@ var Identify = /*#__PURE__*/function (_React$Component) {
229
229
  });
230
230
  });
231
231
  _defineProperty(_this, "parseResult", function (response, layer, format, clickPoint) {
232
+ var ctrlPick = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
232
233
  var newResults = IdentifyUtils.parseResponse(response, layer, format, clickPoint, _this.props.map.projection, _this.props.featureInfoReturnsLayerName);
233
234
  // Merge with previous
234
235
  _this.setState(function (state) {
@@ -239,10 +240,13 @@ var Identify = /*#__PURE__*/function (_React$Component) {
239
240
  features = _ref4[1];
240
241
  var key = layer.url + "#" + layername;
241
242
  identifyResults[key] = features.reduce(function (result, feature) {
242
- if (result.find(function (f) {
243
+ var idx = result.findIndex(function (f) {
243
244
  return f.id === feature.id;
244
- }) === undefined) {
245
+ });
246
+ if (idx === -1) {
245
247
  result.push(feature);
248
+ } else if (ctrlPick === true) {
249
+ result.splice(idx, 1);
246
250
  }
247
251
  return result;
248
252
  }, identifyResults[key] || []);
@@ -0,0 +1,116 @@
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 2024 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 PropTypes from 'prop-types';
26
+ import { setCurrentTask } from '../actions/task';
27
+ import AttributeTableWidget from '../components/AttributeTableWidget';
28
+ import ResizeableWindow from '../components/ResizeableWindow';
29
+ import EditingInterface from '../utils/EditingInterface';
30
+ import LocaleUtils from '../utils/LocaleUtils';
31
+
32
+ /**
33
+ * Display layer object lists in a dialog.
34
+ *
35
+ * The object list is similar to the attribute table, but displays only the display field for each object and contains no edit functionality.
36
+ *
37
+ * To make a layer available in the object list, create a a data resource and matching permissions for it in the `qwc-admin-gui`.
38
+ *
39
+ * This plugin queries the dataset via the editing service specified by
40
+ * `editServiceUrl` in `config.json` (by default the `qwc-data-service`).
41
+ */
42
+ var ObjectList = /*#__PURE__*/function (_React$Component) {
43
+ function ObjectList() {
44
+ var _this;
45
+ _classCallCheck(this, ObjectList);
46
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
47
+ args[_key] = arguments[_key];
48
+ }
49
+ _this = _callSuper(this, ObjectList, [].concat(args));
50
+ _defineProperty(_this, "onClose", function () {
51
+ _this.props.setCurrentTask(null);
52
+ });
53
+ return _this;
54
+ }
55
+ _inherits(ObjectList, _React$Component);
56
+ return _createClass(ObjectList, [{
57
+ key: "render",
58
+ value: function render() {
59
+ var _this$props$taskData;
60
+ if (!this.props.active) {
61
+ return null;
62
+ }
63
+ return /*#__PURE__*/React.createElement(ResizeableWindow, {
64
+ dockable: "bottom",
65
+ icon: "editing",
66
+ initialHeight: 480,
67
+ initialWidth: 800,
68
+ initiallyDocked: true,
69
+ onClose: this.onClose,
70
+ splitScreenWhenDocked: true,
71
+ title: LocaleUtils.tr("appmenu.items.ObjectList")
72
+ }, /*#__PURE__*/React.createElement(AttributeTableWidget, {
73
+ iface: this.props.iface,
74
+ initialLayer: (_this$props$taskData = this.props.taskData) === null || _this$props$taskData === void 0 ? void 0 : _this$props$taskData.layer,
75
+ limitToExtent: this.props.limitToExtent,
76
+ readOnly: true,
77
+ role: "body",
78
+ showDisplayFieldOnly: true,
79
+ showEditFormButton: false,
80
+ showHiddenFields: false,
81
+ showLimitToExtent: this.props.showLimitToExtent,
82
+ zoomLevel: this.props.zoomLevel
83
+ }));
84
+ }
85
+ }]);
86
+ }(React.Component);
87
+ _defineProperty(ObjectList, "propTypes", {
88
+ active: PropTypes.bool,
89
+ iface: PropTypes.object,
90
+ /** Whether to limit to the extent by default. */
91
+ limitToExtent: PropTypes.bool,
92
+ setCurrentTask: PropTypes.func,
93
+ /** Whether to show the "Limit to extent" checkbox */
94
+ showLimitToExtent: PropTypes.bool,
95
+ taskData: PropTypes.object,
96
+ /** The zoom level for zooming to point features. */
97
+ zoomLevel: PropTypes.number
98
+ });
99
+ _defineProperty(ObjectList, "defaultProps", {
100
+ limitToExtent: false,
101
+ zoomLevel: 1000,
102
+ showHiddenFields: true,
103
+ showLimitToExtent: true
104
+ });
105
+ export default (function () {
106
+ var iface = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : EditingInterface;
107
+ return connect(function (state) {
108
+ return {
109
+ active: state.task.id === "ObjectList",
110
+ iface: iface,
111
+ taskData: state.task.id === "ObjectList" ? state.task.data : null
112
+ };
113
+ }, {
114
+ setCurrentTask: setCurrentTask
115
+ })(ObjectList);
116
+ });
@@ -34,8 +34,6 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
34
34
 
35
35
  import React from 'react';
36
36
  import { connect } from 'react-redux';
37
- import FileSaver from 'file-saver';
38
- import ol from 'openlayers';
39
37
  import PropTypes from 'prop-types';
40
38
  import { LayerRole, addLayer } from '../actions/layers';
41
39
  import { setSnappingConfig } from '../actions/map';
@@ -51,8 +49,6 @@ import VectorLayerPicker from '../components/widgets/VectorLayerPicker';
51
49
  import ConfigUtils from '../utils/ConfigUtils';
52
50
  import { END_MARKERS } from '../utils/FeatureStyles';
53
51
  import LocaleUtils from '../utils/LocaleUtils';
54
- import MapUtils from '../utils/MapUtils';
55
- import VectorLayerUtils from '../utils/VectorLayerUtils';
56
52
  import './style/Redlining.css';
57
53
 
58
54
  /**
@@ -134,7 +130,7 @@ var Redlining = /*#__PURE__*/function (_React$Component) {
134
130
  geomType: "LineString",
135
131
  text: ""
136
132
  }
137
- }, {
133
+ }, [{
138
134
  key: "Polygon",
139
135
  tooltip: LocaleUtils.tr("redlining.polygon"),
140
136
  icon: "polygon",
@@ -143,7 +139,7 @@ var Redlining = /*#__PURE__*/function (_React$Component) {
143
139
  geomType: "Polygon",
144
140
  text: ""
145
141
  }
146
- }, [toolEnabled("Circle") ? {
142
+ }, toolEnabled("Circle") ? {
147
143
  key: "Circle",
148
144
  tooltip: LocaleUtils.tr("redlining.circle"),
149
145
  icon: "circle",
@@ -238,6 +234,10 @@ var Redlining = /*#__PURE__*/function (_React$Component) {
238
234
  key: "NumericInput",
239
235
  tooltip: LocaleUtils.tr("redlining.numericinput"),
240
236
  icon: "numericinput"
237
+ }, {
238
+ key: "FeatureAttributes",
239
+ tooltip: LocaleUtils.tr("redlining.attributes"),
240
+ icon: "list-alt"
241
241
  }] : [];
242
242
  for (var _i = 0, _Object$values = Object.values(_this.props.plugins || {}); _i < _Object$values.length; _i++) {
243
243
  var plugin = _Object$values[_i];
@@ -300,11 +300,11 @@ var Redlining = /*#__PURE__*/function (_React$Component) {
300
300
  })), /*#__PURE__*/React.createElement("div", {
301
301
  className: "redlining-groupcontrol"
302
302
  }, /*#__PURE__*/React.createElement("div", null, "\xA0"), /*#__PURE__*/React.createElement(ButtonBar, {
303
- active: _this.props.redlining.numericInput ? "NumericInput" : null,
303
+ active: _this.props.redlining.extraAction,
304
304
  buttons: extraButtons,
305
- onClick: function onClick() {
305
+ onClick: function onClick(key) {
306
306
  return _this.props.changeRedliningState({
307
- numericInput: !_this.props.redlining.numericInput
307
+ extraAction: key
308
308
  });
309
309
  }
310
310
  })), toolEnabled("Export") ? /*#__PURE__*/React.createElement("div", {
@@ -325,52 +325,11 @@ var Redlining = /*#__PURE__*/function (_React$Component) {
325
325
  value: "kml"
326
326
  }, "KML"))) : null), controls);
327
327
  });
328
- _defineProperty(_this, "export", function (type) {
329
- if (type === "geojson") {
330
- var layer = _this.props.layers.find(function (l) {
331
- return l.id === _this.props.redlining.layer;
332
- });
333
- if (!layer) {
334
- return;
335
- }
336
- var geojson = JSON.stringify({
337
- type: "FeatureCollection",
338
- features: layer.features.map(function (feature) {
339
- var newFeature = _objectSpread(_objectSpread({}, feature), {}, {
340
- geometry: VectorLayerUtils.reprojectGeometry(feature.geometry, feature.crs || _this.props.mapCrs, 'EPSG:4326')
341
- });
342
- delete newFeature.crs;
343
- return newFeature;
344
- })
345
- }, null, ' ');
346
- FileSaver.saveAs(new Blob([geojson], {
347
- type: "text/plain;charset=utf-8"
348
- }), layer.title + ".json");
349
- } else if (type === "kml") {
350
- var getNativeLayer = MapUtils.getHook(MapUtils.GET_NATIVE_LAYER);
351
- var _layer = _this.props.layers.find(function (l) {
352
- return l.id === _this.props.redlining.layer;
353
- });
354
- var nativeLayer = getNativeLayer(_this.props.redlining.layer);
355
- if (!nativeLayer) {
356
- return;
357
- }
358
- var kmlFormat = new ol.format.KML();
359
- var features = nativeLayer.getSource().getFeatures().map(function (feature) {
360
- // Circle is not supported by kml format
361
- if (feature.getGeometry() instanceof ol.geom.Circle) {
362
- feature = feature.clone();
363
- feature.setGeometry(ol.geom.polygonFromCircle(feature.getGeometry()));
364
- }
365
- return feature;
366
- });
367
- var data = kmlFormat.writeFeatures(features, {
368
- featureProjection: _this.props.mapCrs
369
- });
370
- FileSaver.saveAs(new Blob([data], {
371
- type: "application/vnd.google-earth.kml+xml"
372
- }), _layer.title + ".kml");
373
- }
328
+ _defineProperty(_this, "export", function (format) {
329
+ _this.props.changeRedliningState({
330
+ action: 'Export',
331
+ format: format
332
+ });
374
333
  });
375
334
  _defineProperty(_this, "renderStandardControls", function () {
376
335
  var sizeLabel = LocaleUtils.tr("redlining.line");
@@ -33,6 +33,7 @@ import { connect } from 'react-redux';
33
33
  import ol from 'openlayers';
34
34
  import PropTypes from 'prop-types';
35
35
  import { setEditContext } from '../../actions/editing';
36
+ import LocationRecorder from '../../components/LocationRecorder';
36
37
  import FeatureStyles from "../../utils/FeatureStyles";
37
38
 
38
39
  /**
@@ -43,6 +44,9 @@ var EditingSupport = /*#__PURE__*/function (_React$Component) {
43
44
  var _this;
44
45
  _classCallCheck(this, EditingSupport);
45
46
  _this = _callSuper(this, EditingSupport, [props]);
47
+ _defineProperty(_this, "state", {
48
+ showRecordLocation: false
49
+ });
46
50
  _defineProperty(_this, "editStyle", function () {
47
51
  var geometryFunction = function geometryFunction(feature) {
48
52
  if (feature.getGeometry().getType() === "Point") {
@@ -76,9 +80,10 @@ var EditingSupport = /*#__PURE__*/function (_React$Component) {
76
80
  _defineProperty(_this, "addDrawInteraction", function () {
77
81
  _this.reset();
78
82
  _this.createLayer();
83
+ var geomType = _this.props.editContext.geomType.replace(/Z$/, '');
79
84
  var drawInteraction = new ol.interaction.Draw({
80
85
  stopClick: true,
81
- type: _this.props.editContext.geomType.replace(/Z$/, ''),
86
+ type: geomType,
82
87
  source: _this.layer.getSource(),
83
88
  condition: function condition(event) {
84
89
  return event.originalEvent.buttons === 1;
@@ -89,11 +94,18 @@ var EditingSupport = /*#__PURE__*/function (_React$Component) {
89
94
  _this.currentFeature = evt.feature;
90
95
  }, _this);
91
96
  drawInteraction.on('drawend', function () {
97
+ _this.setState({
98
+ showRecordLocation: false
99
+ });
92
100
  _this.commitCurrentFeature();
93
101
  _this.props.map.removeInteraction(drawInteraction);
102
+ _this.interaction = null;
94
103
  }, _this);
95
104
  _this.props.map.addInteraction(drawInteraction);
96
105
  _this.interaction = drawInteraction;
106
+ _this.setState({
107
+ showRecordLocation: ["Point", "LineString"].includes(geomType)
108
+ });
97
109
  });
98
110
  _defineProperty(_this, "addEditInteraction", function () {
99
111
  _this.reset();
@@ -187,6 +199,15 @@ var EditingSupport = /*#__PURE__*/function (_React$Component) {
187
199
  }, {
188
200
  key: "render",
189
201
  value: function render() {
202
+ if (this.state.showRecordLocation) {
203
+ var geomType = this.props.editContext.geomType.replace(/Z$/, '');
204
+ return /*#__PURE__*/React.createElement(LocationRecorder, {
205
+ drawInteraction: this.interaction,
206
+ geomType: geomType,
207
+ key: "LocationRecorder",
208
+ map: this.props.map
209
+ });
210
+ }
190
211
  return null;
191
212
  }
192
213
  }]);
@@ -42,6 +42,11 @@ var LocateSupport = /*#__PURE__*/function (_React$Component) {
42
42
  _classCallCheck(this, LocateSupport);
43
43
  _this = _callSuper(this, LocateSupport, [props]);
44
44
  _defineProperty(_this, "onLocationError", function (err) {
45
+ // Handle LOCATION_UNAVAILABLE
46
+ if (err.code === 2 && _this.errorCount < 5) {
47
+ _this.errorCount += 1;
48
+ return;
49
+ }
45
50
  _this.props.onLocateError(err.message);
46
51
  // User denied geolocation prompt
47
52
  if (err.code === 1) {
@@ -79,9 +84,10 @@ var LocateSupport = /*#__PURE__*/function (_React$Component) {
79
84
  _this.props.changeLocateState(_this.requestedMode);
80
85
  _this.posLayer.setVisible(true);
81
86
  }
87
+ _this.errorCount = 0;
82
88
  var mapPos = _this.geolocate.getPosition();
83
89
  var wgsPos = CoordinatesUtils.reproject(mapPos, _this.props.projection, "EPSG:4326");
84
- _this.props.changeLocatePosition(wgsPos);
90
+ _this.props.changeLocatePosition(wgsPos, mapPos);
85
91
  var point = new ol.geom.Point(mapPos);
86
92
  if (_this.props.drawCircle) {
87
93
  var circle = new ol.geom.Circle(mapPos, _this.geolocate.getAccuracy());
@@ -181,6 +187,7 @@ var LocateSupport = /*#__PURE__*/function (_React$Component) {
181
187
  _this.posPopup.hidden = true;
182
188
  };
183
189
  _this.requestedMode = 'DISABLED';
190
+ _this.errorCount = 0;
184
191
  return _this;
185
192
  }
186
193
  _inherits(LocateSupport, _React$Component);