qwc2 2026.4.23 → 2026.5.6
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.
- package/actions/theme.js +3 -2
- package/components/AutoEditForm.js +4 -3
- package/components/EditComboField.js +7 -1
- package/components/IdentifyViewer.js +3 -0
- package/components/PickFeature.js +2 -1
- package/components/widgets/DateTimeInput.js +1 -0
- package/package.json +2 -2
- package/plugins/API.js +1 -1
- package/plugins/Cyclomedia.js +53 -21
- package/plugins/Editing.js +1 -1
- package/plugins/Help.js +6 -1
- package/plugins/MapExport.js +6 -4
- package/plugins/MapFilter.js +5 -3
- package/plugins/Redlining.js +14 -5
- package/plugins/SensorThingsTool.js +41 -22
- package/plugins/map/EditingSupport.js +72 -30
- package/plugins/map3d/MapExport3D.js +1 -1
- package/plugins/style/SensorThingsTool.css +13 -5
- package/reducers/layers.js +6 -4
- package/reducers/task.js +6 -3
- package/static/translations/bg-BG.json +1 -0
- package/static/translations/ca-ES.json +1 -0
- package/static/translations/cs-CZ.json +1 -0
- package/static/translations/de-CH.json +1 -0
- package/static/translations/de-DE.json +1 -0
- package/static/translations/en-US.json +1 -0
- package/static/translations/es-ES.json +1 -0
- package/static/translations/fi-FI.json +1 -0
- package/static/translations/fr-FR.json +1 -0
- package/static/translations/hu-HU.json +1 -0
- package/static/translations/it-IT.json +1 -0
- package/static/translations/ja-JP.json +1 -0
- package/static/translations/nl-NL.json +1 -0
- package/static/translations/no-NO.json +1 -0
- package/static/translations/pl-PL.json +1 -0
- package/static/translations/pt-BR.json +1 -0
- package/static/translations/pt-PT.json +1 -0
- package/static/translations/ro-RO.json +1 -0
- package/static/translations/ru-RU.json +1 -0
- package/static/translations/sv-SE.json +1 -0
- package/static/translations/tr-TR.json +1 -0
- package/static/translations/tsconfig.json +1 -0
- package/static/translations/uk-UA.json +1 -0
- package/utils/EditingInterface.js +1 -1
- package/utils/LayerUtils.js +2 -1
package/actions/theme.js
CHANGED
|
@@ -53,7 +53,7 @@ export function setThemeLayersList(theme) {
|
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
55
|
export function finishThemeSetup(dispatch, theme, themes, layerConfigs, insertPos, permalinkLayers, externalLayerRestorer, visibleBgLayer, initialTheme, initialTask) {
|
|
56
|
-
var _theme$config;
|
|
56
|
+
var _theme$config$section, _theme$config, _theme$config2;
|
|
57
57
|
// Create layer
|
|
58
58
|
var themeLayer = ThemeUtils.createThemeLayer(theme, themes);
|
|
59
59
|
var layers = [themeLayer];
|
|
@@ -148,7 +148,8 @@ export function finishThemeSetup(dispatch, theme, themes, layerConfigs, insertPo
|
|
|
148
148
|
type: SWITCHING_THEME,
|
|
149
149
|
switching: false
|
|
150
150
|
});
|
|
151
|
-
var
|
|
151
|
+
var section = ConfigUtils.isMobile() ? "mobile" : "desktop";
|
|
152
|
+
var task = initialTask || ((_theme$config$section = theme === null || theme === void 0 || (_theme$config = theme.config) === null || _theme$config === void 0 || (_theme$config = _theme$config[section]) === null || _theme$config === void 0 ? void 0 : _theme$config.startupTask) !== null && _theme$config$section !== void 0 ? _theme$config$section : theme === null || theme === void 0 || (_theme$config2 = theme.config) === null || _theme$config2 === void 0 ? void 0 : _theme$config2.startupTask) || (initialTheme ? ConfigUtils.getConfigProp("startupTask") : null);
|
|
152
153
|
if (task) {
|
|
153
154
|
var mapClickAction = ConfigUtils.getPluginConfig(task.key).mapClickAction;
|
|
154
155
|
dispatch(setCurrentTask(task.key, task.mode, mapClickAction, task.data));
|
|
@@ -50,7 +50,9 @@ var AutoEditForm = /*#__PURE__*/function (_React$Component) {
|
|
|
50
50
|
}
|
|
51
51
|
var input = null;
|
|
52
52
|
var title = field.name + ":";
|
|
53
|
-
if (
|
|
53
|
+
if (constraints.hidden) {
|
|
54
|
+
return null;
|
|
55
|
+
} else if (field.type === "boolean" || field.type === "bool") {
|
|
54
56
|
if (_this.props.touchFriendly) {
|
|
55
57
|
var boolvalue = value === "1" || value === "on" || value === "true" || value === true;
|
|
56
58
|
input = /*#__PURE__*/React.createElement(ToggleSwitch, _extends({
|
|
@@ -87,12 +89,11 @@ var AutoEditForm = /*#__PURE__*/function (_React$Component) {
|
|
|
87
89
|
values: constraints.values
|
|
88
90
|
}));
|
|
89
91
|
} else if (field.type === "number") {
|
|
90
|
-
var precision = constraints.step > 0 ? Math.ceil(-Math.log10(constraints.step)) :
|
|
92
|
+
var precision = constraints.step > 0 ? Math.ceil(-Math.log10(constraints.step)) : 0;
|
|
91
93
|
input = /*#__PURE__*/React.createElement(NumberInput, {
|
|
92
94
|
decimals: precision,
|
|
93
95
|
max: constraints.max,
|
|
94
96
|
min: constraints.min,
|
|
95
|
-
mobile: true,
|
|
96
97
|
name: field.id,
|
|
97
98
|
onChange: function onChange(nr) {
|
|
98
99
|
return _this.props.updateField(field.id, nr);
|
|
@@ -186,7 +186,13 @@ var EditComboField = /*#__PURE__*/function (_React$Component) {
|
|
|
186
186
|
key: "componentDidUpdate",
|
|
187
187
|
value: function componentDidUpdate(prevProps) {
|
|
188
188
|
var _this3 = this;
|
|
189
|
-
if (this.props.
|
|
189
|
+
if (this.props.values && this.props.values !== prevProps.values) {
|
|
190
|
+
// This does not handle the case a selected value has disappeared from values, caller should handle that
|
|
191
|
+
this.setState({
|
|
192
|
+
values: this.props.values,
|
|
193
|
+
showPlaceholder: !this.hasEmptyValue(this.props.values)
|
|
194
|
+
});
|
|
195
|
+
} else if (this.props.keyvalrel && this.props.filterExpr !== prevProps.filterExpr) {
|
|
190
196
|
var _this$props$filterExp3;
|
|
191
197
|
KeyValCache.get(this.props.editIface, this.props.mapPrefix + "." + this.props.keyvalrel, (_this$props$filterExp3 = this.props.filterExpr) !== null && _this$props$filterExp3 !== void 0 ? _this$props$filterExp3 : null).then(function (values) {
|
|
192
198
|
_this3.setState({
|
|
@@ -1155,6 +1155,9 @@ var IdentifyViewer = /*#__PURE__*/function (_React$Component) {
|
|
|
1155
1155
|
var _window$qwc3;
|
|
1156
1156
|
var formatter = _Object$values[_i];
|
|
1157
1157
|
text = formatter(attrName, text, layer, result);
|
|
1158
|
+
if (/*#__PURE__*/React.isValidElement(text)) {
|
|
1159
|
+
return text;
|
|
1160
|
+
}
|
|
1158
1161
|
}
|
|
1159
1162
|
text = _this.props.attributeTransform(attrName, text, layer, result);
|
|
1160
1163
|
text = MiscUtils.addLinkAnchors(text);
|
|
@@ -271,7 +271,8 @@ var PickFeature = /*#__PURE__*/function (_React$Component) {
|
|
|
271
271
|
}
|
|
272
272
|
}, entry.layer + ": " + ((_entry$feature$displa = entry.feature.displayname) !== null && _entry$feature$displa !== void 0 ? _entry$feature$displa : entry.feature.id));
|
|
273
273
|
}) : /*#__PURE__*/React.createElement("div", {
|
|
274
|
-
className: "pick-feature-menu-querying"
|
|
274
|
+
className: "pick-feature-menu-querying",
|
|
275
|
+
key: "spinner"
|
|
275
276
|
}, /*#__PURE__*/React.createElement(Spinner, null), LocaleUtils.tr("pickfeature.querying")));
|
|
276
277
|
}
|
|
277
278
|
return [resultsMenu, /*#__PURE__*/React.createElement(MapSelection, {
|
|
@@ -54,6 +54,7 @@ var DateTimeInput = /*#__PURE__*/function (_React$Component) {
|
|
|
54
54
|
value: function render() {
|
|
55
55
|
var _this2 = this;
|
|
56
56
|
var parts = (this.props.value || "T").split("T");
|
|
57
|
+
parts[1] = (parts[1] || "").replace(/\+[0-9:]+$/, ''); // Strip timezone
|
|
57
58
|
parts[1] = (parts[1] || "").replace(/\.\d+$/, ''); // Strip milliseconds
|
|
58
59
|
return /*#__PURE__*/React.createElement(InputContainer, {
|
|
59
60
|
className: "DateTimeInput"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "qwc2",
|
|
3
|
-
"version": "2026.
|
|
3
|
+
"version": "2026.05.06",
|
|
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.
|
|
20
|
+
"@giro3d/giro3d": "^2.0.2",
|
|
21
21
|
"@kayahr/text-encoding": "^2.1.0",
|
|
22
22
|
"@loaders.gl/core": "^4.3.4",
|
|
23
23
|
"@loaders.gl/shapefile": "^4.3.4",
|
package/plugins/API.js
CHANGED
|
@@ -401,7 +401,7 @@ var API = /*#__PURE__*/function (_React$Component) {
|
|
|
401
401
|
* * `name`: An identifier
|
|
402
402
|
* * `fmtFunc`: The formatter function with signature `function(name, value, layer, feature)`
|
|
403
403
|
*
|
|
404
|
-
* The `fmtFunc` should return a string (which may also be a HTML fragment).
|
|
404
|
+
* The `fmtFunc` should return a string (which may also be a HTML fragment) or a React element.
|
|
405
405
|
*/
|
|
406
406
|
_defineProperty(_this, "addIdentifyAttributeFormatter", function (name, fmtFunc) {
|
|
407
407
|
window.qwc2.__attributeFormatters[name] = fmtFunc;
|
package/plugins/Cyclomedia.js
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
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 _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
|
|
3
|
+
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
4
|
+
function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
|
|
5
|
+
function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
|
|
2
6
|
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
|
3
7
|
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
4
8
|
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
@@ -192,6 +196,10 @@ var Cyclomedia = /*#__PURE__*/function (_React$Component) {
|
|
|
192
196
|
return "\n <!DOCTYPE html>\n <html>\n <head>\n <script nonce=\"".concat((_window$__CSP_NONCE__ = window.__CSP_NONCE__) !== null && _window$__CSP_NONCE__ !== void 0 ? _window$__CSP_NONCE__ : '', "\" type=\"text/javascript\" src=\"https://unpkg.com/react@18.3.1/umd/react.production.min.js\"></script>\n <script nonce=\"").concat((_window$__CSP_NONCE__2 = window.__CSP_NONCE__) !== null && _window$__CSP_NONCE__2 !== void 0 ? _window$__CSP_NONCE__2 : '', "\" type=\"text/javascript\" src=\"https://unpkg.com/react-dom@18.3.1/umd/react-dom.production.min.js\"></script>\n <script nonce=\"").concat((_window$__CSP_NONCE__3 = window.__CSP_NONCE__) !== null && _window$__CSP_NONCE__3 !== void 0 ? _window$__CSP_NONCE__3 : '', "\" type=\"text/javascript\" src=\"https://streetsmart.cyclomedia.com/api/v").concat(_this.props.cyclomediaVersion, "/StreetSmartApi.js\"></script>\n <script nonce=\"").concat((_window$__CSP_NONCE__4 = window.__CSP_NONCE__) !== null && _window$__CSP_NONCE__4 !== void 0 ? _window$__CSP_NONCE__4 : '', "\" type=\"text/javascript\">\n let apiInitialized = false;\n let initCallback = null;\n let posCallback = null;\n let measureCallback = null;\n\n function initApi() {\n StreetSmartApi.init({\n targetElement: document.getElementById(\"streetsmartApi\"),\n username: \"").concat(_this.state.username || undefined, "\",\n password: \"").concat(_this.state.password || undefined, "\",\n apiKey: \"").concat(_this.props.apikey, "\",\n clientId: \"").concat(_this.props.clientId, "\",\n loginOauth: ").concat(loginOauth, ",\n loginRedirectUri: \"").concat(_this.props.loginRedirectUri, "\",\n logoutRedirectUri: \"").concat(_this.props.logoutRedirectUri, "\",\n srs: \"").concat(_this.props.projection, "\",\n locale: \"").concat(lang, "\",\n configurationUrl: 'https://atlas.cyclomedia.com/configuration',\n addressSettings: {\n locale: \"us\",\n database: \"Nokia\"\n }\n }).then(() => {\n apiInitialized = true;\n if (initCallback) {\n initCallback(true);\n }\n }, (e) => {\n apiInitialized = false;\n if (initCallback) {\n initCallback(false, e.message);\n }\n });\n }\n function openImage(posStr, crs) {\n if (!apiInitialized) {\n return;\n }\n StreetSmartApi.open(posStr, {\n viewerType: StreetSmartApi.ViewerType.PANORAMA,\n srs: crs,\n panoramaViewer: {\n closable: false,\n maximizable: true,\n replace: true,\n recordingsVisible: true,\n navbarVisible: true,\n timeTravelVisible: true,\n measureTypeButtonVisible: true,\n measureTypeButtonStart: true,\n measureTypeButtonToggle: true,\n },\n }).then((result) => {\n if (result && result[0]){\n window.panoramaViewer = result[0];\n window.panoramaViewer.on(StreetSmartApi.Events.panoramaViewer.IMAGE_CHANGE, changeView);\n window.panoramaViewer.on(StreetSmartApi.Events.panoramaViewer.VIEW_CHANGE, changeView);\n StreetSmartApi.on(StreetSmartApi.Events.measurement.MEASUREMENT_CHANGED, changeMeasurement);\n StreetSmartApi.on(StreetSmartApi.Events.measurement.MEASUREMENT_STOPPED, stopMeasurement);\n }\n }).catch((reason) => {\n console.log('Failed to create component(s) through API: ' + reason);\n });\n }\n function changeView() {\n if (posCallback) {\n const recording = window.panoramaViewer.getRecording();\n const orientation = window.panoramaViewer.getOrientation();\n const pos = recording.xyz;\n const posData = {\n pos: [pos[0], pos[1]],\n crs: recording.srs,\n yaw: orientation.yaw * Math.PI / 180,\n hFov: orientation.hFov * Math.PI / 180.0\n }\n posCallback(posData);\n }\n }\n function changeMeasurement(e) {\n measureCallback(e.detail.activeMeasurement);\n }\n function stopMeasurement() {\n measureCallback(null);\n }\n function registerCallbacks(_initCallback, _posCallback, _measureCallback) {\n initCallback = _initCallback;\n posCallback = _posCallback;\n measureCallback = _measureCallback;\n }\n </script>\n <style>\n html, body, #streetsmartApi {height: 100%;}\n </style>\n </head>\n <body style=\"margin: 0\">\n <div id=\"streetsmartApi\">\n </div>\n </body>\n </html>\n ");
|
|
193
197
|
});
|
|
194
198
|
_defineProperty(_this, "addRecordingsWFS", function () {
|
|
199
|
+
// Maximum tile size in map CRS units to avoid exceeding the feature limit per request.
|
|
200
|
+
// ~1000 m in metric CRS, ~0.01° (≈ 1000 m) in geographic CRS, ~3280 ft in imperial CRS.
|
|
201
|
+
var crsUnits = CoordinatesUtils.getUnits(_this.props.mapCrs);
|
|
202
|
+
var MAX_TILE_SIZE = crsUnits === 'degrees' ? 0.01 : crsUnits === 'ft' ? 3280 : 1000;
|
|
195
203
|
var layer = {
|
|
196
204
|
id: 'cyclomedia-recordings',
|
|
197
205
|
type: 'wfs',
|
|
@@ -202,38 +210,62 @@ var Cyclomedia = /*#__PURE__*/function (_React$Component) {
|
|
|
202
210
|
miny = _CoordinatesUtils$rep2[1],
|
|
203
211
|
maxx = _CoordinatesUtils$rep2[2],
|
|
204
212
|
maxy = _CoordinatesUtils$rep2[3];
|
|
205
|
-
|
|
206
|
-
var
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
//
|
|
210
|
-
|
|
211
|
-
//
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
var
|
|
213
|
+
var width = maxx - minx;
|
|
214
|
+
var height = maxy - miny;
|
|
215
|
+
// Cyclomedia WFS only returns up to 3000 points per request.
|
|
216
|
+
// Split the bbox into tiles so that no tile exceeds MAX_TILE_SIZE in each dimension.
|
|
217
|
+
// Each tile is expanded by OVERLAP on every side so that features on tile borders
|
|
218
|
+
// are reliably included. Duplicate features are removed afterwards via their id.
|
|
219
|
+
var OVERLAP = MAX_TILE_SIZE * 0.05; // 5 % of tile size
|
|
220
|
+
var cols = Math.max(1, Math.ceil(width / MAX_TILE_SIZE));
|
|
221
|
+
var rows = Math.max(1, Math.ceil(height / MAX_TILE_SIZE));
|
|
222
|
+
var tileW = width / cols;
|
|
223
|
+
var tileH = height / rows;
|
|
224
|
+
var tiles = [];
|
|
225
|
+
for (var row = 0; row < rows; row++) {
|
|
226
|
+
for (var col = 0; col < cols; col++) {
|
|
227
|
+
tiles.push([minx + col * tileW - OVERLAP, miny + row * tileH - OVERLAP, minx + (col + 1) * tileW + OVERLAP, miny + (row + 1) * tileH + OVERLAP]);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
var authHeader = "Basic " + btoa(_this.state.username + ":" + _this.state.password);
|
|
231
|
+
var onError = function onError() {
|
|
232
|
+
vectorSource.removeLoadedExtent(extent);
|
|
233
|
+
failure();
|
|
234
|
+
};
|
|
235
|
+
var completed = 0;
|
|
236
|
+
var hasError = false;
|
|
237
|
+
var allFeatures = [];
|
|
238
|
+
tiles.forEach(function (tile) {
|
|
239
|
+
var bboxstr = tile.join(",");
|
|
240
|
+
var reqUrl = "https://atlasapi.cyclomedia.com/api/recording/wfs?service=WFS&version=1.1.0&request=GetFeature&typename=atlas:Recording&srsname=".concat(_this.props.mapCrs, "&bbox=").concat(bboxstr, "&maxFeatures=10000");
|
|
219
241
|
var xhr = new XMLHttpRequest();
|
|
220
242
|
xhr.open('GET', reqUrl);
|
|
221
|
-
xhr.setRequestHeader("Authorization",
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
243
|
+
xhr.setRequestHeader("Authorization", authHeader);
|
|
244
|
+
xhr.onerror = function () {
|
|
245
|
+
if (!hasError) {
|
|
246
|
+
hasError = true;
|
|
247
|
+
onError();
|
|
248
|
+
}
|
|
225
249
|
};
|
|
226
|
-
xhr.onerror = onError;
|
|
227
250
|
xhr.onload = function () {
|
|
251
|
+
if (hasError) {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
228
254
|
if (xhr.status === 200) {
|
|
229
255
|
var features = vectorSource.getFormat().readFeatures(xhr.responseText, {
|
|
230
256
|
dataProjection: _this.props.mapCrs,
|
|
231
257
|
featureProjection: projection.getCode()
|
|
232
258
|
});
|
|
233
|
-
|
|
234
|
-
success(features);
|
|
259
|
+
allFeatures.push.apply(allFeatures, _toConsumableArray(features));
|
|
235
260
|
} else {
|
|
261
|
+
hasError = true;
|
|
236
262
|
onError();
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
completed++;
|
|
266
|
+
if (completed === tiles.length) {
|
|
267
|
+
vectorSource.addFeatures(allFeatures);
|
|
268
|
+
success(allFeatures);
|
|
237
269
|
}
|
|
238
270
|
};
|
|
239
271
|
xhr.send();
|
package/plugins/Editing.js
CHANGED
|
@@ -532,7 +532,7 @@ var Editing = /*#__PURE__*/function (_React$Component) {
|
|
|
532
532
|
if (match) {
|
|
533
533
|
var oldvisibility = match.sublayer.visibility;
|
|
534
534
|
if (oldvisibility !== visibility && visibility !== null) {
|
|
535
|
-
var recurseDirection = !oldvisibility ? "
|
|
535
|
+
var recurseDirection = !oldvisibility ? "parents" : null;
|
|
536
536
|
_this.props.changeLayerProperty(match.layer.id, "visibility", visibility, match.path, recurseDirection);
|
|
537
537
|
}
|
|
538
538
|
return oldvisibility;
|
package/plugins/Help.js
CHANGED
|
@@ -60,8 +60,13 @@ var Help = /*#__PURE__*/function (_React$Component) {
|
|
|
60
60
|
return _createClass(Help, [{
|
|
61
61
|
key: "componentDidMount",
|
|
62
62
|
value: function componentDidMount() {
|
|
63
|
+
this.componentDidUpdate({});
|
|
64
|
+
}
|
|
65
|
+
}, {
|
|
66
|
+
key: "componentDidUpdate",
|
|
67
|
+
value: function componentDidUpdate(prevProps) {
|
|
63
68
|
var _this2 = this;
|
|
64
|
-
if (this.props.bodyContentsFragmentUrl) {
|
|
69
|
+
if (this.props.bodyContentsFragmentUrl && this.props.bodyContentsFragmentUrl !== prevProps.bodyContentsFragmentUrl) {
|
|
65
70
|
axios.get(this.props.bodyContentsFragmentUrl).then(function (response) {
|
|
66
71
|
_this2.setState({
|
|
67
72
|
body: response.data.replace('$VERSION$', process.env.BuildDate)
|
package/plugins/MapExport.js
CHANGED
|
@@ -351,6 +351,7 @@ var MapExport = /*#__PURE__*/function (_React$Component) {
|
|
|
351
351
|
params.WIDTH = width;
|
|
352
352
|
params.HEIGHT = height;
|
|
353
353
|
params.filename = fileName;
|
|
354
|
+
params.FILTER_GEOM = VectorLayerUtils.geoJSONGeomToWkt(VectorLayerUtils.reprojectGeometry(_this.props.filter.filterGeom, _this.props.map.projection, crs));
|
|
354
355
|
|
|
355
356
|
// Dimension values
|
|
356
357
|
_this.props.layers.forEach(function (layer) {
|
|
@@ -464,15 +465,14 @@ var MapExport = /*#__PURE__*/function (_React$Component) {
|
|
|
464
465
|
var _layer$mapFormats;
|
|
465
466
|
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
467
|
}).reverse().map(function (layer) {
|
|
467
|
-
var _layer$params$FILTER
|
|
468
|
+
var _layer$params$FILTER;
|
|
468
469
|
return {
|
|
469
470
|
layer: layer,
|
|
470
471
|
params: _objectSpread(_objectSpread({}, baseParams), {}, {
|
|
471
472
|
LAYERS: layer.params.LAYERS,
|
|
472
473
|
OPACITIES: layer.params.OPACITIES,
|
|
473
474
|
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_ : ''
|
|
475
|
+
FILTER: (_layer$params$FILTER = layer.params.FILTER) !== null && _layer$params$FILTER !== void 0 ? _layer$params$FILTER : ''
|
|
476
476
|
})
|
|
477
477
|
};
|
|
478
478
|
});
|
|
@@ -596,6 +596,7 @@ _defineProperty(MapExport, "propTypes", {
|
|
|
596
596
|
exportExternalLayers: PropTypes.bool,
|
|
597
597
|
/** Template for the name of the generated files when downloading. Can contain the placeholders `{username}`, `{tenant}`, `{theme}`, `{themeTitle}`, `{timestamp}`. */
|
|
598
598
|
fileNameTemplate: PropTypes.string,
|
|
599
|
+
filter: PropTypes.object,
|
|
599
600
|
/** Formats to force as available even if the map capabilities report otherwise. Useful if a serviceUrl is defined in a format configuration. */
|
|
600
601
|
forceAvailableFormats: PropTypes.array,
|
|
601
602
|
/** 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.
|
|
@@ -640,7 +641,8 @@ var selector = function selector(state) {
|
|
|
640
641
|
return {
|
|
641
642
|
theme: state.theme.current,
|
|
642
643
|
map: state.map,
|
|
643
|
-
layers: state.layers.flat
|
|
644
|
+
layers: state.layers.flat,
|
|
645
|
+
filter: state.layers.filter
|
|
644
646
|
};
|
|
645
647
|
};
|
|
646
648
|
export default connect(selector, {
|
package/plugins/MapFilter.js
CHANGED
|
@@ -383,8 +383,10 @@ var MapFilter = /*#__PURE__*/function (_React$Component) {
|
|
|
383
383
|
});
|
|
384
384
|
_defineProperty(_this, "renderPredefinedFilters", function () {
|
|
385
385
|
var predefinedFilters = _this.collectPredefinedFilters(_this.props.layers);
|
|
386
|
-
return Object.values(predefinedFilters).
|
|
387
|
-
|
|
386
|
+
return Object.values(predefinedFilters).filter(function (filter) {
|
|
387
|
+
return filter.id in _this.state.filters;
|
|
388
|
+
}).map(function (config) {
|
|
389
|
+
var _config$title;
|
|
388
390
|
return /*#__PURE__*/React.createElement("div", {
|
|
389
391
|
className: "map-filter-entry",
|
|
390
392
|
key: config.id
|
|
@@ -393,7 +395,7 @@ var MapFilter = /*#__PURE__*/function (_React$Component) {
|
|
|
393
395
|
}, /*#__PURE__*/React.createElement("span", {
|
|
394
396
|
className: "map-filter-entry-title"
|
|
395
397
|
}, (_config$title = config.title) !== null && _config$title !== void 0 ? _config$title : LocaleUtils.tr(config.titlemsgid)), /*#__PURE__*/React.createElement(ToggleSwitch, {
|
|
396
|
-
active:
|
|
398
|
+
active: _this.state.filters[config.id].active,
|
|
397
399
|
onChange: function onChange(active) {
|
|
398
400
|
return _this.toggleFilter(config.id, active);
|
|
399
401
|
}
|
package/plugins/Redlining.js
CHANGED
|
@@ -35,7 +35,7 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
|
|
|
35
35
|
import React from 'react';
|
|
36
36
|
import { connect } from 'react-redux';
|
|
37
37
|
import PropTypes from 'prop-types';
|
|
38
|
-
import { LayerRole, addLayer } from '../actions/layers';
|
|
38
|
+
import { LayerRole, addLayer, changeLayerProperty } from '../actions/layers';
|
|
39
39
|
import { setSnappingConfig } from '../actions/map';
|
|
40
40
|
import { changeRedliningState, resetRedliningState } from '../actions/redlining';
|
|
41
41
|
import Icon from '../components/Icon';
|
|
@@ -70,13 +70,18 @@ var Redlining = /*#__PURE__*/function (_React$Component) {
|
|
|
70
70
|
geomType: (_data$geomType = data === null || data === void 0 ? void 0 : data.geomType) !== null && _data$geomType !== void 0 ? _data$geomType : null
|
|
71
71
|
}, _this.redliningStateDefaults()));
|
|
72
72
|
_this.props.setSnappingConfig(_this.props.snapping, _this.props.snappingActive);
|
|
73
|
+
var layer = null;
|
|
73
74
|
if (data && data.layerId) {
|
|
74
|
-
|
|
75
|
+
layer = _this.props.layers.find(function (l) {
|
|
75
76
|
return l.id === data.layerId;
|
|
76
77
|
});
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
} else {
|
|
79
|
+
layer = _this.props.layers.find(function (l) {
|
|
80
|
+
return l.id === _this.props.redlining.layer;
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
if (layer) {
|
|
84
|
+
_this.changeRedliningLayer(layer);
|
|
80
85
|
}
|
|
81
86
|
});
|
|
82
87
|
_defineProperty(_this, "onHide", function () {
|
|
@@ -550,6 +555,8 @@ var Redlining = /*#__PURE__*/function (_React$Component) {
|
|
|
550
555
|
layerTitle: layer.title,
|
|
551
556
|
action: action
|
|
552
557
|
});
|
|
558
|
+
// Ensure layer is visible
|
|
559
|
+
_this.props.changeLayerProperty(layer.id, "visibility", true);
|
|
553
560
|
});
|
|
554
561
|
_this.labelInput = null;
|
|
555
562
|
_this.dashIcons = {};
|
|
@@ -617,6 +624,7 @@ _defineProperty(Redlining, "propTypes", {
|
|
|
617
624
|
addLayer: PropTypes.func,
|
|
618
625
|
/** Whether to allow labeling geometric figures. */
|
|
619
626
|
allowGeometryLabels: PropTypes.bool,
|
|
627
|
+
changeLayerProperty: PropTypes.func,
|
|
620
628
|
changeRedliningState: PropTypes.func,
|
|
621
629
|
/** Default area unit. Options: `metric`, `imperial`, `sqm`, `ha`, `sqkm`, `sqft`, `acre`, `sqmi` */
|
|
622
630
|
defaultAreaUnit: PropTypes.string,
|
|
@@ -675,6 +683,7 @@ export default (function (plugins) {
|
|
|
675
683
|
};
|
|
676
684
|
}, {
|
|
677
685
|
changeRedliningState: changeRedliningState,
|
|
686
|
+
changeLayerProperty: changeLayerProperty,
|
|
678
687
|
addLayer: addLayer,
|
|
679
688
|
resetRedliningState: resetRedliningState,
|
|
680
689
|
setSnappingConfig: setSnappingConfig
|
|
@@ -235,9 +235,9 @@ var SensorThingsTool = /*#__PURE__*/function (_React$Component) {
|
|
|
235
235
|
showLocationInfoWindow: false,
|
|
236
236
|
// currently selected Datastreams filter options
|
|
237
237
|
currentDatastreamsFilter: {
|
|
238
|
-
thingId: -1,
|
|
239
|
-
sensorId: -1,
|
|
240
|
-
observedPropertyId: -1
|
|
238
|
+
thingId: '-1',
|
|
239
|
+
sensorId: '-1',
|
|
240
|
+
observedPropertyId: '-1'
|
|
241
241
|
},
|
|
242
242
|
// show Datastreams filter window for currently selected Location if true
|
|
243
243
|
showDatastreamsFilterWindow: false,
|
|
@@ -666,7 +666,7 @@ var SensorThingsTool = /*#__PURE__*/function (_React$Component) {
|
|
|
666
666
|
locationSelect = /*#__PURE__*/React.createElement("div", null, LocaleUtils.tr("sensorthingstool.locationLabel"), ":\xA0", /*#__PURE__*/React.createElement("select", {
|
|
667
667
|
onChange: function onChange(ev) {
|
|
668
668
|
return _this.setState({
|
|
669
|
-
currentLocationId:
|
|
669
|
+
currentLocationId: ev.target.value
|
|
670
670
|
});
|
|
671
671
|
},
|
|
672
672
|
value: _this.state.currentLocationId
|
|
@@ -693,14 +693,14 @@ var SensorThingsTool = /*#__PURE__*/function (_React$Component) {
|
|
|
693
693
|
icon: "trash"
|
|
694
694
|
}));
|
|
695
695
|
if (_this.state.currentSensorLocation !== null) {
|
|
696
|
-
var datastreamsFilterActive = _this.state.currentDatastreamsFilter.thingId !== -1 || _this.state.currentDatastreamsFilter.sensorId !== -1 || _this.state.currentDatastreamsFilter.observedPropertyId !== -1;
|
|
696
|
+
var datastreamsFilterActive = _this.state.currentDatastreamsFilter.thingId !== '-1' || _this.state.currentDatastreamsFilter.sensorId !== '-1' || _this.state.currentDatastreamsFilter.observedPropertyId !== '-1';
|
|
697
697
|
if (_this.state.currentSensorLocation.filteredDatastreams.length > 0) {
|
|
698
698
|
datastreamSelect = /*#__PURE__*/React.createElement("div", {
|
|
699
699
|
className: "sensor-things-location-datastreams"
|
|
700
700
|
}, LocaleUtils.tr("sensorthingstool.datastreamLabel"), ":\xA0", /*#__PURE__*/React.createElement("select", {
|
|
701
701
|
onChange: function onChange(ev) {
|
|
702
702
|
return _this.setState({
|
|
703
|
-
currentDatastreamId:
|
|
703
|
+
currentDatastreamId: ev.target.value
|
|
704
704
|
});
|
|
705
705
|
},
|
|
706
706
|
value: _this.state.currentDatastreamId
|
|
@@ -929,14 +929,30 @@ var SensorThingsTool = /*#__PURE__*/function (_React$Component) {
|
|
|
929
929
|
// show popup with list of Locations at picking pos, cf. MapInfoTooltip
|
|
930
930
|
var pixel = MapUtils.getHook(MapUtils.GET_PIXEL_FROM_COORDINATES_HOOK)(_this.state.pickGeom.coordinates);
|
|
931
931
|
var style = {
|
|
932
|
-
left: pixel[0] +
|
|
932
|
+
left: pixel[0] + 32 + "px",
|
|
933
933
|
top: pixel[1] + "px"
|
|
934
934
|
};
|
|
935
935
|
return /*#__PURE__*/React.createElement("div", {
|
|
936
936
|
className: "sensor-things-location-select",
|
|
937
937
|
key: "SensorThingsLocationSelectPopup",
|
|
938
938
|
style: style
|
|
939
|
-
}, /*#__PURE__*/React.createElement("
|
|
939
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
940
|
+
className: "sensor-things-location-select-header"
|
|
941
|
+
}, /*#__PURE__*/React.createElement("b", null, LocaleUtils.tr("sensorthingstool.selectLocation")), /*#__PURE__*/React.createElement("div", {
|
|
942
|
+
className: "sensor-things-toolbar-spacer"
|
|
943
|
+
}), /*#__PURE__*/React.createElement("button", {
|
|
944
|
+
className: "button",
|
|
945
|
+
onClick: function onClick() {
|
|
946
|
+
return _this.setState({
|
|
947
|
+
locationsAtPoint: []
|
|
948
|
+
});
|
|
949
|
+
},
|
|
950
|
+
title: LocaleUtils.tr("common.close")
|
|
951
|
+
}, /*#__PURE__*/React.createElement(Icon, {
|
|
952
|
+
icon: "remove"
|
|
953
|
+
}))), /*#__PURE__*/React.createElement("div", {
|
|
954
|
+
className: "sensor-things-location-select-list"
|
|
955
|
+
}, _this.state.locationsAtPoint.map(function (location, idx) {
|
|
940
956
|
return /*#__PURE__*/React.createElement("div", {
|
|
941
957
|
key: "select-location-" + idx,
|
|
942
958
|
onClickCapture: function onClickCapture() {
|
|
@@ -953,7 +969,7 @@ var SensorThingsTool = /*#__PURE__*/function (_React$Component) {
|
|
|
953
969
|
});
|
|
954
970
|
}
|
|
955
971
|
}, location.name, ": ", location.description);
|
|
956
|
-
}));
|
|
972
|
+
})));
|
|
957
973
|
} else {
|
|
958
974
|
return null;
|
|
959
975
|
}
|
|
@@ -1053,9 +1069,9 @@ var SensorThingsTool = /*#__PURE__*/function (_React$Component) {
|
|
|
1053
1069
|
currentLocationId: nextSelectedLocationId,
|
|
1054
1070
|
currentSensorLocation: null,
|
|
1055
1071
|
currentDatastreamsFilter: {
|
|
1056
|
-
thingId: -1,
|
|
1057
|
-
sensorId: -1,
|
|
1058
|
-
observedPropertyId: -1
|
|
1072
|
+
thingId: '-1',
|
|
1073
|
+
sensorId: '-1',
|
|
1074
|
+
observedPropertyId: '-1'
|
|
1059
1075
|
},
|
|
1060
1076
|
currentDatastreamId: null,
|
|
1061
1077
|
datastreams: nextDatastreams,
|
|
@@ -1075,7 +1091,7 @@ var SensorThingsTool = /*#__PURE__*/function (_React$Component) {
|
|
|
1075
1091
|
_defineProperty(_this, "updateDatastreamsFilter", function (field, value) {
|
|
1076
1092
|
_this.setState(function (state) {
|
|
1077
1093
|
return {
|
|
1078
|
-
currentDatastreamsFilter: _objectSpread(_objectSpread({}, state.currentDatastreamsFilter), {}, _defineProperty({}, field,
|
|
1094
|
+
currentDatastreamsFilter: _objectSpread(_objectSpread({}, state.currentDatastreamsFilter), {}, _defineProperty({}, field, value))
|
|
1079
1095
|
};
|
|
1080
1096
|
});
|
|
1081
1097
|
});
|
|
@@ -2236,9 +2252,9 @@ var SensorThingsTool = /*#__PURE__*/function (_React$Component) {
|
|
|
2236
2252
|
filteredDatastreams: datastreamIds
|
|
2237
2253
|
},
|
|
2238
2254
|
currentDatastreamsFilter: {
|
|
2239
|
-
thingId: -1,
|
|
2240
|
-
sensorId: -1,
|
|
2241
|
-
observedPropertyId: -1
|
|
2255
|
+
thingId: '-1',
|
|
2256
|
+
sensorId: '-1',
|
|
2257
|
+
observedPropertyId: '-1'
|
|
2242
2258
|
},
|
|
2243
2259
|
currentDatastreamId: datastreamIds[0],
|
|
2244
2260
|
datastreams: _objectSpread(_objectSpread({}, state.datastreams), datastreamsLookup)
|
|
@@ -2252,22 +2268,25 @@ var SensorThingsTool = /*#__PURE__*/function (_React$Component) {
|
|
|
2252
2268
|
_defineProperty(_this, "filterLocationDatastreams", function () {
|
|
2253
2269
|
if (_this.state.currentSensorLocation !== null) {
|
|
2254
2270
|
var filteredDatastreams = _this.state.currentSensorLocation.datastreams;
|
|
2255
|
-
|
|
2271
|
+
|
|
2272
|
+
// NOTE: entity IDs may be integer or UUID strings, so compare them as string
|
|
2273
|
+
|
|
2274
|
+
if (_this.state.currentDatastreamsFilter.thingId !== '-1') {
|
|
2256
2275
|
// filter by Thing
|
|
2257
2276
|
filteredDatastreams = filteredDatastreams.filter(function (datastreamId) {
|
|
2258
|
-
return _this.state.datastreams[datastreamId].thing.id === _this.state.currentDatastreamsFilter.thingId;
|
|
2277
|
+
return _this.state.datastreams[datastreamId].thing.id.toString() === _this.state.currentDatastreamsFilter.thingId;
|
|
2259
2278
|
});
|
|
2260
2279
|
}
|
|
2261
|
-
if (_this.state.currentDatastreamsFilter.sensorId !== -1) {
|
|
2280
|
+
if (_this.state.currentDatastreamsFilter.sensorId !== '-1') {
|
|
2262
2281
|
// filter by Sensor
|
|
2263
2282
|
filteredDatastreams = filteredDatastreams.filter(function (datastreamId) {
|
|
2264
|
-
return _this.state.datastreams[datastreamId].sensor.id === _this.state.currentDatastreamsFilter.sensorId;
|
|
2283
|
+
return _this.state.datastreams[datastreamId].sensor.id.toString() === _this.state.currentDatastreamsFilter.sensorId;
|
|
2265
2284
|
});
|
|
2266
2285
|
}
|
|
2267
|
-
if (_this.state.currentDatastreamsFilter.observedPropertyId !== -1) {
|
|
2286
|
+
if (_this.state.currentDatastreamsFilter.observedPropertyId !== '-1') {
|
|
2268
2287
|
// filter by ObservedProperty
|
|
2269
2288
|
filteredDatastreams = filteredDatastreams.filter(function (datastreamId) {
|
|
2270
|
-
return _this.state.datastreams[datastreamId].observedProperty.id === _this.state.currentDatastreamsFilter.observedPropertyId;
|
|
2289
|
+
return _this.state.datastreams[datastreamId].observedProperty.id.toString() === _this.state.currentDatastreamsFilter.observedPropertyId;
|
|
2271
2290
|
});
|
|
2272
2291
|
}
|
|
2273
2292
|
_this.setState(function (state) {
|
|
@@ -37,7 +37,9 @@ import { setEditContext } from '../../actions/editing';
|
|
|
37
37
|
import LocationRecorder from '../../components/LocationRecorder';
|
|
38
38
|
import MeasureSwitcher from '../../components/MeasureSwitcher';
|
|
39
39
|
import { BottomToolPortalContext } from '../../components/PluginsContainer';
|
|
40
|
+
import ButtonBar from '../../components/widgets/ButtonBar';
|
|
40
41
|
import FeatureStyles from "../../utils/FeatureStyles";
|
|
42
|
+
import LocaleUtils from '../../utils/LocaleUtils';
|
|
41
43
|
import MeasureUtils from '../../utils/MeasureUtils';
|
|
42
44
|
|
|
43
45
|
/**
|
|
@@ -49,6 +51,7 @@ var EditingSupport = /*#__PURE__*/function (_React$Component) {
|
|
|
49
51
|
_classCallCheck(this, EditingSupport);
|
|
50
52
|
_this = _callSuper(this, EditingSupport, [props]);
|
|
51
53
|
_defineProperty(_this, "state", {
|
|
54
|
+
activeEditTool: 'Node',
|
|
52
55
|
showRecordLocation: false,
|
|
53
56
|
measurements: {
|
|
54
57
|
showmeasurements: false,
|
|
@@ -56,6 +59,11 @@ var EditingSupport = /*#__PURE__*/function (_React$Component) {
|
|
|
56
59
|
areaUnit: 'metric'
|
|
57
60
|
}
|
|
58
61
|
});
|
|
62
|
+
_defineProperty(_this, "setEditMode", function (action) {
|
|
63
|
+
_this.setState({
|
|
64
|
+
activeEditTool: action
|
|
65
|
+
}, _this.setEditInteraction);
|
|
66
|
+
});
|
|
59
67
|
_defineProperty(_this, "changeMeasurementState", function (diff) {
|
|
60
68
|
_this.setState(function (state) {
|
|
61
69
|
return {
|
|
@@ -95,7 +103,7 @@ var EditingSupport = /*#__PURE__*/function (_React$Component) {
|
|
|
95
103
|
}
|
|
96
104
|
_this.currentLayer = _this.layers[_this.props.editContext.id];
|
|
97
105
|
});
|
|
98
|
-
_defineProperty(_this, "
|
|
106
|
+
_defineProperty(_this, "setDrawInteraction", function () {
|
|
99
107
|
_this.reset();
|
|
100
108
|
_this.setCurrentLayer();
|
|
101
109
|
var geomType = _this.props.editContext.geomType.replace(/Z$/, '');
|
|
@@ -126,7 +134,7 @@ var EditingSupport = /*#__PURE__*/function (_React$Component) {
|
|
|
126
134
|
showRecordLocation: ["Point", "LineString", "MultiPoint", "MultiLineString"].includes(geomType)
|
|
127
135
|
});
|
|
128
136
|
});
|
|
129
|
-
_defineProperty(_this, "
|
|
137
|
+
_defineProperty(_this, "setEditInteraction", function () {
|
|
130
138
|
var _this$props$editConte;
|
|
131
139
|
_this.reset();
|
|
132
140
|
_this.setCurrentLayer();
|
|
@@ -135,26 +143,42 @@ var EditingSupport = /*#__PURE__*/function (_React$Component) {
|
|
|
135
143
|
_this.currentFeature.on('change', _this.updateMeasurements);
|
|
136
144
|
_this.updateMeasurements();
|
|
137
145
|
_this.currentLayer.getSource().addFeature(_this.currentFeature);
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
_this.commitCurrentFeature
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
_this.
|
|
157
|
-
|
|
146
|
+
if (_this.state.activeEditTool === "Node") {
|
|
147
|
+
var modifyInteraction = new ol.interaction.Modify({
|
|
148
|
+
features: new ol.Collection([_this.currentFeature]),
|
|
149
|
+
condition: function condition(event) {
|
|
150
|
+
return event.originalEvent.buttons === 1;
|
|
151
|
+
},
|
|
152
|
+
deleteCondition: function deleteCondition(event) {
|
|
153
|
+
// delete vertices on SHIFT + click
|
|
154
|
+
if (event.type === "pointerdown" && ol.events.condition.shiftKeyOnly(event)) {
|
|
155
|
+
_this.props.map.setIgnoreNextClick(true);
|
|
156
|
+
}
|
|
157
|
+
return ol.events.condition.shiftKeyOnly(event) && ol.events.condition.singleClick(event);
|
|
158
|
+
},
|
|
159
|
+
style: FeatureStyles.sketchInteraction()
|
|
160
|
+
});
|
|
161
|
+
modifyInteraction.on('modifyend', _this.commitCurrentFeature);
|
|
162
|
+
_this.interaction = modifyInteraction;
|
|
163
|
+
_this.props.map.addInteraction(_this.interaction);
|
|
164
|
+
} else if (_this.state.activeEditTool === "Transform") {
|
|
165
|
+
var transformInteraction = new ol.interaction.Transform({
|
|
166
|
+
stretch: false,
|
|
167
|
+
keepAspectRatio: function keepAspectRatio(ev) {
|
|
168
|
+
return ol.events.condition.shiftKeyOnly(ev);
|
|
169
|
+
},
|
|
170
|
+
layers: [_this.currentLayer],
|
|
171
|
+
translateFeature: true,
|
|
172
|
+
selection: false
|
|
173
|
+
});
|
|
174
|
+
transformInteraction.on('rotateend', _this.commitCurrentFeature);
|
|
175
|
+
transformInteraction.on('translateend', _this.commitCurrentFeature);
|
|
176
|
+
transformInteraction.on('scaleend', _this.commitCurrentFeature);
|
|
177
|
+
_this.interaction = transformInteraction;
|
|
178
|
+
_this.props.map.addInteraction(_this.interaction);
|
|
179
|
+
_this.interaction.setSelection([_this.currentFeature]);
|
|
180
|
+
}
|
|
181
|
+
_this.interaction.setActive(_this.props.editContext.geomType && _this.props.editContext.permissions.updatable && ((_this$props$editConte = _this.props.editContext.editConfig) === null || _this$props$editConte === void 0 || (_this$props$editConte = _this$props$editConte.permissions) === null || _this$props$editConte === void 0 ? void 0 : _this$props$editConte.updatable) === true && !_this.props.editContext.geomReadOnly && !_this.props.editContext.geomNonZeroZ);
|
|
158
182
|
});
|
|
159
183
|
_defineProperty(_this, "updateMeasurements", function () {
|
|
160
184
|
var _this$state$measureme;
|
|
@@ -237,16 +261,16 @@ var EditingSupport = /*#__PURE__*/function (_React$Component) {
|
|
|
237
261
|
} else if (curContext.action === 'Pick' && curContext.feature) {
|
|
238
262
|
// If a feature without geometry was picked, enter draw mode, otherwise enter edit mode
|
|
239
263
|
if (!curContext.feature.geometry && curContext.geomType) {
|
|
240
|
-
this.
|
|
264
|
+
this.setDrawInteraction();
|
|
241
265
|
} else {
|
|
242
|
-
this.
|
|
266
|
+
this.setEditInteraction();
|
|
243
267
|
}
|
|
244
268
|
} else if (curContext.action === 'Draw' && curContext.geomType) {
|
|
245
269
|
// Usually, draw mode starts without a feature, but draw also can start with a pre-set geometry
|
|
246
270
|
if (!(curContext.feature || {}).geometry || prevContext.id === curContext.id && prevContext.geomType !== curContext.geomType) {
|
|
247
|
-
this.
|
|
271
|
+
this.setDrawInteraction();
|
|
248
272
|
} else if ((curContext.feature || {}).geometry) {
|
|
249
|
-
this.
|
|
273
|
+
this.setEditInteraction();
|
|
250
274
|
}
|
|
251
275
|
} else {
|
|
252
276
|
this.reset();
|
|
@@ -261,9 +285,28 @@ var EditingSupport = /*#__PURE__*/function (_React$Component) {
|
|
|
261
285
|
}, {
|
|
262
286
|
key: "render",
|
|
263
287
|
value: function render() {
|
|
264
|
-
var _this$props$editConte2;
|
|
288
|
+
var _this$props$editConte2, _this$props$editConte3;
|
|
289
|
+
var toolbar = null;
|
|
265
290
|
var locationRecorder = null;
|
|
266
291
|
var measureSwitcher = null;
|
|
292
|
+
if ((_this$props$editConte2 = this.props.editContext.feature) !== null && _this$props$editConte2 !== void 0 && _this$props$editConte2.geometry) {
|
|
293
|
+
var editButtons = [{
|
|
294
|
+
key: "Node",
|
|
295
|
+
tooltip: LocaleUtils.tr("redlining.draw"),
|
|
296
|
+
icon: "nodetool"
|
|
297
|
+
}, {
|
|
298
|
+
key: "Transform",
|
|
299
|
+
tooltip: LocaleUtils.tr("redlining.transform"),
|
|
300
|
+
icon: "transformtool"
|
|
301
|
+
}];
|
|
302
|
+
toolbar = /*#__PURE__*/ReactDOM.createPortal(/*#__PURE__*/React.createElement(ButtonBar, {
|
|
303
|
+
active: this.state.activeEditTool,
|
|
304
|
+
buttons: editButtons,
|
|
305
|
+
key: "ButtonBar",
|
|
306
|
+
onClick: this.setEditMode,
|
|
307
|
+
tooltipPos: "top"
|
|
308
|
+
}), this.context);
|
|
309
|
+
}
|
|
267
310
|
if (this.state.showRecordLocation && this.props.editContext.geomType) {
|
|
268
311
|
var geomType = this.props.editContext.geomType.replace(/Z$/, '');
|
|
269
312
|
locationRecorder = /*#__PURE__*/React.createElement(LocationRecorder, {
|
|
@@ -273,16 +316,15 @@ var EditingSupport = /*#__PURE__*/function (_React$Component) {
|
|
|
273
316
|
map: this.props.map
|
|
274
317
|
});
|
|
275
318
|
}
|
|
276
|
-
if (this.props.editContext.action === "Draw" || (_this$props$
|
|
319
|
+
if (this.props.editContext.action === "Draw" || (_this$props$editConte3 = this.props.editContext.feature) !== null && _this$props$editConte3 !== void 0 && _this$props$editConte3.geometry) {
|
|
277
320
|
measureSwitcher = /*#__PURE__*/ReactDOM.createPortal(/*#__PURE__*/React.createElement(MeasureSwitcher, {
|
|
278
321
|
changeMeasureState: this.changeMeasurementState,
|
|
279
322
|
geomType: this.props.editContext.geomType,
|
|
280
|
-
iconSize: "large",
|
|
281
323
|
key: "MeasureSwitcher",
|
|
282
324
|
measureState: this.state.measurements
|
|
283
325
|
}), this.context);
|
|
284
326
|
}
|
|
285
|
-
return [measureSwitcher, locationRecorder];
|
|
327
|
+
return [toolbar, measureSwitcher, locationRecorder];
|
|
286
328
|
}
|
|
287
329
|
}]);
|
|
288
330
|
}(React.Component);
|
|
@@ -352,7 +352,7 @@ var MapExport3D = /*#__PURE__*/function (_React$Component) {
|
|
|
352
352
|
var exportScale = _this.state.exportScaleFactor / 100;
|
|
353
353
|
if (_this.state.selectedFormat === "application/pdf") {
|
|
354
354
|
var mapWidthMM = _this.state.layout.map.width;
|
|
355
|
-
var exportWidthPx = _this.state.width;
|
|
355
|
+
var exportWidthPx = _this.state.frame.width;
|
|
356
356
|
exportScale = Math.min(5, _this.state.exportDpi / (exportWidthPx * 25.4 / mapWidthMM));
|
|
357
357
|
}
|
|
358
358
|
_this.setState({
|
|
@@ -150,18 +150,26 @@ table.sensor-things-datastream-statistics-table td.sensor-things-datastream-stat
|
|
|
150
150
|
}
|
|
151
151
|
|
|
152
152
|
div.sensor-things-location-select {
|
|
153
|
-
max-height: 16em;
|
|
154
|
-
overflow-y: auto;
|
|
155
|
-
padding: 0.25em;
|
|
156
153
|
position: fixed;
|
|
157
154
|
background-color: var(--container-bg-color);
|
|
158
155
|
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.75);
|
|
159
156
|
z-index: 2;
|
|
160
157
|
}
|
|
161
|
-
div.sensor-things-location-select
|
|
158
|
+
div.sensor-things-location-select-header {
|
|
159
|
+
display: flex;
|
|
160
|
+
padding-left: 0.25em;
|
|
161
|
+
align-items: center;
|
|
162
|
+
background-color: var(--button-bg-color);
|
|
163
|
+
}
|
|
164
|
+
div.sensor-things-location-select-list {
|
|
165
|
+
padding: 0.25em;
|
|
166
|
+
max-height: 16em;
|
|
167
|
+
overflow-y: auto;
|
|
168
|
+
}
|
|
169
|
+
div.sensor-things-location-select-list div {
|
|
162
170
|
padding-top: 0.25em;
|
|
163
171
|
}
|
|
164
|
-
div.sensor-things-location-select div:hover {
|
|
172
|
+
div.sensor-things-location-select-list div:hover {
|
|
165
173
|
font-weight: bold;
|
|
166
174
|
cursor: pointer;
|
|
167
175
|
}
|
package/reducers/layers.js
CHANGED
|
@@ -150,7 +150,7 @@ export default function layers() {
|
|
|
150
150
|
}
|
|
151
151
|
case ADD_LAYER:
|
|
152
152
|
{
|
|
153
|
-
var _action$layer$srcid, _action$layer$visibil, _action$layer$opacity, _action$options, _action$options2;
|
|
153
|
+
var _action$layer$srcid, _action$layer$visibil, _action$layer$opacity, _ref, _action$options$layer, _action$options, _action$options2, _action$options3;
|
|
154
154
|
var _newLayers2 = (state.flat || []).concat();
|
|
155
155
|
var layerId = action.layer.id || uuidv4();
|
|
156
156
|
var newLayer = _objectSpread(_objectSpread({}, action.layer), {}, {
|
|
@@ -161,9 +161,9 @@ export default function layers() {
|
|
|
161
161
|
queryable: action.layer.queryable || false,
|
|
162
162
|
visibility: (_action$layer$visibil = action.layer.visibility) !== null && _action$layer$visibil !== void 0 ? _action$layer$visibil : true,
|
|
163
163
|
opacity: (_action$layer$opacity = action.layer.opacity) !== null && _action$layer$opacity !== void 0 ? _action$layer$opacity : 255,
|
|
164
|
-
layertreehidden: action.layer.layertreehidden
|
|
164
|
+
layertreehidden: (_ref = (_action$options$layer = (_action$options = action.options) === null || _action$options === void 0 ? void 0 : _action$options.layertreehidden) !== null && _action$options$layer !== void 0 ? _action$options$layer : action.layer.layertreehidden) !== null && _ref !== void 0 ? _ref : action.layer.role > LayerRole.USERLAYER
|
|
165
165
|
});
|
|
166
|
-
if ((_action$
|
|
166
|
+
if ((_action$options2 = action.options) !== null && _action$options2 !== void 0 && _action$options2.beforeLayerName || (_action$options3 = action.options) !== null && _action$options3 !== void 0 && _action$options3.afterLayerName) {
|
|
167
167
|
_newLayers2 = LayerUtils.insertLayer(_newLayers2, newLayer, "name", action.options.beforeLayerName || action.options.afterLayerName, action.options.afterLayerName ? true : false);
|
|
168
168
|
} else {
|
|
169
169
|
var inspos = 0;
|
|
@@ -315,6 +315,7 @@ export default function layers() {
|
|
|
315
315
|
return layer.id === _layerId;
|
|
316
316
|
});
|
|
317
317
|
if (idx === -1) {
|
|
318
|
+
var _action$layer$srcid2;
|
|
318
319
|
var newFeatures = action.features.map(function (f) {
|
|
319
320
|
return _objectSpread(_objectSpread({}, f), {}, {
|
|
320
321
|
id: f.id || (f.properties || {}).id || uuidv4()
|
|
@@ -330,7 +331,8 @@ export default function layers() {
|
|
|
330
331
|
visibility: action.layer.visibility || true,
|
|
331
332
|
opacity: action.layer.opacity || 255,
|
|
332
333
|
layertreehidden: action.layer.layertreehidden || action.layer.role > LayerRole.USERLAYER,
|
|
333
|
-
bbox: VectorLayerUtils.computeFeaturesBBox(action.features)
|
|
334
|
+
bbox: VectorLayerUtils.computeFeaturesBBox(action.features),
|
|
335
|
+
srcid: (_action$layer$srcid2 = action.layer.srcid) !== null && _action$layer$srcid2 !== void 0 ? _action$layer$srcid2 : uuidv4()
|
|
334
336
|
});
|
|
335
337
|
var _inspos = 0;
|
|
336
338
|
for (; _inspos < _newLayers6.length && _newLayer2.role < _newLayers6[_inspos].role; ++_inspos);
|
package/reducers/task.js
CHANGED
|
@@ -19,7 +19,8 @@ var defaultState = {
|
|
|
19
19
|
data: null,
|
|
20
20
|
blocked: false,
|
|
21
21
|
unsetOnMapClick: false,
|
|
22
|
-
identifyEnabled: true
|
|
22
|
+
identifyEnabled: true,
|
|
23
|
+
unblockedIdentifyEnabled: true
|
|
23
24
|
};
|
|
24
25
|
export default function task() {
|
|
25
26
|
var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : defaultState;
|
|
@@ -35,13 +36,15 @@ export default function task() {
|
|
|
35
36
|
mode: action.mode,
|
|
36
37
|
data: action.data,
|
|
37
38
|
unsetOnMapClick: action.unsetOnMapClick,
|
|
38
|
-
identifyEnabled: action.identifyEnabled
|
|
39
|
+
identifyEnabled: action.identifyEnabled,
|
|
40
|
+
unblockedIdentifyEnabled: action.identifyEnabled
|
|
39
41
|
});
|
|
40
42
|
}
|
|
41
43
|
case SET_CURRENT_TASK_BLOCKED:
|
|
42
44
|
{
|
|
43
45
|
return _objectSpread(_objectSpread({}, state), {}, {
|
|
44
|
-
blocked: action.blocked
|
|
46
|
+
blocked: action.blocked,
|
|
47
|
+
identifyEnabled: action.blocked ? false : state.unblockedIdentifyEnabled
|
|
45
48
|
});
|
|
46
49
|
}
|
|
47
50
|
default:
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"FeatureSearch": "Търсене на функции",
|
|
44
44
|
"GeometryDigitizer": "Дигитайзер на геометрия",
|
|
45
45
|
"IdentifyPoint": "Идентифициране на точка",
|
|
46
|
+
"IdentifyRadius": "",
|
|
46
47
|
"IdentifyRegion": "Определяне на региона",
|
|
47
48
|
"LayerCatalog": "Каталог на слоевете",
|
|
48
49
|
"Login": "Вход",
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"FeatureSearch": "Objektsuche",
|
|
44
44
|
"GeometryDigitizer": "Geometriedigitalisierung",
|
|
45
45
|
"IdentifyPoint": "Punkt abfragen",
|
|
46
|
+
"IdentifyRadius": "Radius abfragen",
|
|
46
47
|
"IdentifyRegion": "Region abfragen",
|
|
47
48
|
"LayerCatalog": "Ebenenkatalog",
|
|
48
49
|
"Login": "Anmelden",
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"FeatureSearch": "Objektsuche",
|
|
44
44
|
"GeometryDigitizer": "Geometriedigitalisierung",
|
|
45
45
|
"IdentifyPoint": "Punkt abfragen",
|
|
46
|
+
"IdentifyRadius": "Radius abfragen",
|
|
46
47
|
"IdentifyRegion": "Region abfragen",
|
|
47
48
|
"LayerCatalog": "Ebenenkatalog",
|
|
48
49
|
"Login": "Anmelden",
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"FeatureSearch": "Búsqueda de elemento",
|
|
44
44
|
"GeometryDigitizer": "Digitalizador de geometría",
|
|
45
45
|
"IdentifyPoint": "Identificar punto",
|
|
46
|
+
"IdentifyRadius": "",
|
|
46
47
|
"IdentifyRegion": "Identificar zona",
|
|
47
48
|
"LayerCatalog": "Capa catálogo",
|
|
48
49
|
"Login": "Inicio de sesión",
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"FeatureSearch": "Recherche objet",
|
|
44
44
|
"GeometryDigitizer": "Digitalisation des géométries",
|
|
45
45
|
"IdentifyPoint": "Interroger point",
|
|
46
|
+
"IdentifyRadius": "Interroger dans un rayon",
|
|
46
47
|
"IdentifyRegion": "Interroger la région",
|
|
47
48
|
"LayerCatalog": "Catalogue des couches",
|
|
48
49
|
"Login": "Connexion",
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"FeatureSearch": "Ricerca oggetto",
|
|
44
44
|
"GeometryDigitizer": "Digitalizzazione geometrie",
|
|
45
45
|
"IdentifyPoint": "Identifica punto",
|
|
46
|
+
"IdentifyRadius": "Identifica in un raggio",
|
|
46
47
|
"IdentifyRegion": "Identifica in un poligono",
|
|
47
48
|
"LayerCatalog": "Catalogo livelli",
|
|
48
49
|
"Login": "Accedi",
|
|
@@ -374,7 +374,7 @@ var EditingInterface = {
|
|
|
374
374
|
* @param editConfig The edit config of the feature dataset
|
|
375
375
|
* @param featureId The feature ID
|
|
376
376
|
* @param mapCrs The CRS of the map, as an EPSG code
|
|
377
|
-
* @param tables Comma separated string of relation table
|
|
377
|
+
* @param tables Comma separated string of relation table references in the form `<table_name>:<fk_name>:<sort_col>`
|
|
378
378
|
* @param editConfigs The theme editConfig block, containing all theme dataset edit configs
|
|
379
379
|
* @param callback Callback invoked with the relation values, taking `{<tablename>: {<relation_values>}}` on success and `{}` on failure
|
|
380
380
|
*/
|
package/utils/LayerUtils.js
CHANGED
|
@@ -163,7 +163,8 @@ var LayerUtils = {
|
|
|
163
163
|
type: "separator",
|
|
164
164
|
title: title,
|
|
165
165
|
role: LayerRole.USERLAYER,
|
|
166
|
-
id: uuidv4()
|
|
166
|
+
id: uuidv4(),
|
|
167
|
+
srcid: uuidv4()
|
|
167
168
|
}]);
|
|
168
169
|
},
|
|
169
170
|
createExternalLayerPlaceholder: function createExternalLayerPlaceholder(layerConfig, externalLayers, id) {
|