qwc2 2026.6.23 → 2026.6.26

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 CHANGED
@@ -125,11 +125,9 @@ export function finishThemeSetup(dispatch, theme, themes, layerConfigs, preserve
125
125
  } finally {
126
126
  _iterator.f();
127
127
  }
128
- if (!actuallyVisibleBgLayer) {
129
- UrlParams.updateParams({
130
- bl: ""
131
- });
132
- }
128
+ UrlParams.updateParams({
129
+ bl: actuallyVisibleBgLayer !== null && actuallyVisibleBgLayer !== void 0 ? actuallyVisibleBgLayer : ""
130
+ });
133
131
  var _iterator2 = _createForOfIteratorHelper(layers.reverse()),
134
132
  _step2;
135
133
  try {
@@ -316,7 +314,9 @@ export function setCurrentTheme(theme, themes) {
316
314
  };
317
315
  }
318
316
  export function setBlankTheme(themes) {
317
+ var initialExtent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
318
+ var visibleBgLayer = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
319
319
  return setCurrentTheme({
320
320
  id: ""
321
- }, themes);
321
+ }, themes, false, initialExtent, null, visibleBgLayer);
322
322
  }
@@ -168,9 +168,7 @@ var AttributeForm = /*#__PURE__*/function (_React$Component) {
168
168
  action: "",
169
169
  className: "attrib-form-parent-form",
170
170
  onSubmit: _this.onSubmit,
171
- ref: function ref(el) {
172
- _this.form = el;
173
- }
171
+ ref: _this.setRef
174
172
  }, editConfig.form ? /*#__PURE__*/React.createElement(QtDesignerForm, {
175
173
  addRelationRecord: _this.addRelationRecord,
176
174
  editConfig: editConfig,
@@ -199,6 +197,9 @@ var AttributeForm = /*#__PURE__*/function (_React$Component) {
199
197
  values: _this.props.editContext.feature.properties
200
198
  }), captchaButton, commitBar), deleteBar, busyDiv, childAttributeForm);
201
199
  });
200
+ _defineProperty(_this, "setRef", function (el) {
201
+ _this.form = el;
202
+ });
202
203
  _defineProperty(_this, "setFormBusy", function (busy) {
203
204
  _this.setState({
204
205
  busy: busy
@@ -93,7 +93,7 @@ var LayerInfoWindow = /*#__PURE__*/function (_React$Component) {
93
93
  }
94
94
  var legend = null;
95
95
  var scale = MapUtils.computeForZoom(this.props.map.scales, this.props.map.zoom);
96
- var legendUrl = LayerUtils.getLegendUrl(this.props.layer, this.props.sublayer, scale, this.props.map, this.props.bboxDependentLegend, this.props.scaleDependentLegend);
96
+ var legendUrl = LayerUtils.getLegendUrl(this.props.layer, this.props.sublayer, scale, this.props.map, this.props.bboxDependentLegend, this.props.scaleDependentLegend, this.props.extraLegendParameters);
97
97
  if (legendUrl) {
98
98
  legend = /*#__PURE__*/React.createElement(Image, {
99
99
  className: "layer-info-window-legend",
@@ -130,6 +130,7 @@ var LayerInfoWindow = /*#__PURE__*/function (_React$Component) {
130
130
  }(React.Component);
131
131
  _defineProperty(LayerInfoWindow, "propTypes", {
132
132
  bboxDependentLegend: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
133
+ extraLegendParameters: PropTypes.string,
133
134
  layer: PropTypes.object,
134
135
  layerInfoGeometry: PropTypes.object,
135
136
  map: PropTypes.object,
@@ -1,5 +1,4 @@
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 _readOnlyError(r) { throw new TypeError('"' + r + '" is read-only'); }
3
2
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
3
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
5
4
  function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
@@ -28,21 +27,31 @@ import ReactDOM from 'react-dom';
28
27
  import { connect } from 'react-redux';
29
28
  import classnames from 'classnames';
30
29
  import PropTypes from 'prop-types';
30
+ import { v4 as uuidv4 } from 'uuid';
31
31
  import { setCurrentTask } from '../actions/task';
32
+ import { setSplitScreen } from '../actions/windows';
32
33
  import Icon from './Icon';
33
34
  import { MapContainerPortalContext } from './PluginsContainer';
34
35
  import { Swipeable } from './Swipeable';
35
36
  import './style/SideBar.css';
36
37
  var SideBar = /*#__PURE__*/function (_React$Component) {
37
38
  function SideBar(props) {
39
+ var _props$currentTask;
38
40
  var _this;
39
41
  _classCallCheck(this, SideBar);
40
42
  _this = _callSuper(this, SideBar, [props]);
41
43
  _defineProperty(_this, "state", {
42
- render: false
44
+ visible: false,
45
+ render: false,
46
+ width: '15em',
47
+ widthProp: '15em',
48
+ height: ''
43
49
  });
44
50
  _defineProperty(_this, "closeClicked", function () {
45
- if (_this.props.currentTask.id === _this.props.id) {
51
+ var _this$props$currentTa;
52
+ if (_this.props.visible) {
53
+ _this.props.onHide();
54
+ } else if (((_this$props$currentTa = _this.props.currentTask) === null || _this$props$currentTa === void 0 ? void 0 : _this$props$currentTa.id) === _this.props.id) {
46
55
  _this.props.setCurrentTask(null);
47
56
  }
48
57
  });
@@ -59,12 +68,16 @@ var SideBar = /*#__PURE__*/function (_React$Component) {
59
68
  var startWidth = _this.sidebar.offsetWidth;
60
69
  var startMouseX = ev.clientX;
61
70
  var sign = _this.props.side === 'left' ? -1 : 1;
71
+ _this.sidebar.style.transition = 'none';
62
72
  var resizeSidebar = function resizeSidebar(event) {
63
- _this.sidebar.style.width = startWidth + sign * (startMouseX - event.clientX) + 'px';
73
+ _this.setState({
74
+ width: startWidth + sign * (startMouseX - event.clientX) + "px"
75
+ });
64
76
  };
65
77
  ev.view.document.body.style.userSelect = 'none';
66
78
  ev.view.addEventListener("pointermove", resizeSidebar);
67
79
  ev.view.addEventListener("pointerup", function () {
80
+ _this.sidebar.style.transition = '';
68
81
  ev.view.document.body.style.userSelect = '';
69
82
  ev.view.removeEventListener("pointermove", resizeSidebar);
70
83
  }, {
@@ -75,7 +88,9 @@ var SideBar = /*#__PURE__*/function (_React$Component) {
75
88
  var startHeight = _this.sidebar.offsetHeight;
76
89
  var startMouseY = ev.clientY;
77
90
  var resizeSidebar = function resizeSidebar(event) {
78
- _this.sidebar.style.height = Math.max(64, startHeight + (event.clientY - startMouseY)) + 'px';
91
+ _this.setState({
92
+ height: Math.max(64, startHeight + (event.clientY - startMouseY)) + "px"
93
+ });
79
94
  };
80
95
  ev.view.document.body.style.userSelect = 'none';
81
96
  ev.view.addEventListener("pointermove", resizeSidebar);
@@ -86,84 +101,107 @@ var SideBar = /*#__PURE__*/function (_React$Component) {
86
101
  once: true
87
102
  });
88
103
  });
89
- _this.state.render = props.currentTask && props.currentTask.id === props.id;
104
+ _this.state.visible = props.visible || ((_props$currentTask = props.currentTask) === null || _props$currentTask === void 0 ? void 0 : _props$currentTask.id) === props.id;
105
+ _this.state.render = _this.state.visible;
106
+ _this.state.width = _this.state.widthProp = props.width;
90
107
  _this.sidebar = null;
108
+ _this.id = uuidv4();
91
109
  return _this;
92
110
  }
93
111
  _inherits(SideBar, _React$Component);
94
112
  return _createClass(SideBar, [{
95
113
  key: "componentDidUpdate",
96
- value: function componentDidUpdate(prevProps) {
97
- var _this2 = this;
98
- var newVisible = this.props.currentTask && this.props.currentTask.id === this.props.id;
99
- var oldVisible = prevProps.currentTask && prevProps.currentTask.id === prevProps.id;
100
- if (newVisible && (!oldVisible || this.props.currentTask.mode !== prevProps.currentTask.mode)) {
114
+ value: function componentDidUpdate(prevProps, prevState) {
115
+ var _this$props$currentTa2,
116
+ _prevProps$currentTas,
117
+ _this2 = this;
118
+ if (this.state.visible && (!prevState.visible || ((_this$props$currentTa2 = this.props.currentTask) === null || _this$props$currentTa2 === void 0 ? void 0 : _this$props$currentTa2.mode) !== ((_prevProps$currentTas = prevProps.currentTask) === null || _prevProps$currentTas === void 0 ? void 0 : _prevProps$currentTas.mode))) {
101
119
  this.setState({
102
120
  render: true
103
121
  }, function () {
104
122
  var _this2$sidebar$queryS, _this2$sidebar$queryS2;
105
- // Set focus to first focusable element
106
- (_this2$sidebar$queryS = _this2.sidebar.querySelector('[tabindex="0"]')) === null || _this2$sidebar$queryS === void 0 || (_this2$sidebar$queryS2 = _this2$sidebar$queryS.focus) === null || _this2$sidebar$queryS2 === void 0 || _this2$sidebar$queryS2.call(_this2$sidebar$queryS);
123
+ return (_this2$sidebar$queryS = _this2.sidebar.querySelector('[tabindex="0"]')) === null || _this2$sidebar$queryS === void 0 || (_this2$sidebar$queryS2 = _this2$sidebar$queryS.focus) === null || _this2$sidebar$queryS2 === void 0 ? void 0 : _this2$sidebar$queryS2.call(_this2$sidebar$queryS);
107
124
  });
108
125
  this.props.onShow(this.props.currentTask.mode);
109
- } else if (!newVisible && oldVisible) {
126
+ if (this.sidebar && this.state.visible && this.props.splitScreen) {
127
+ this.props.setSplitScreen(this.id, this.props.side, this.sidebar.clientWidth, false);
128
+ }
129
+ } else if (!this.state.visible && prevState.visible) {
110
130
  this.props.onHide();
111
131
  // Hide the element after the transition period (see SideBar.css)
112
132
  setTimeout(function () {
113
- _this2.setState({
133
+ return _this2.setState({
114
134
  render: false
115
135
  });
116
136
  }, 300);
137
+ if (this.props.splitScreen) {
138
+ this.props.setSplitScreen(this.id, null, null, false);
139
+ }
117
140
  }
118
141
  if (!this.props.heightResizeable && prevProps.heightResizeable) {
119
- this.sidebar.style.height = '';
142
+ this.setState({
143
+ height: ''
144
+ });
145
+ }
146
+ if (this.props.splitScreen && this.state.visible && this.sidebar && this.state.width !== prevState.width) {
147
+ // Since the sidebar width transition is animated, we cannot measure its width, as it still might be changing
148
+ // Hence measure the pixel width on a dummy element
149
+ var div = document.createElement("div");
150
+ this.sidebar.parentElement.appendChild(div);
151
+ div.style.width = this.state.width;
152
+ div.style.minWidth = this.sidebar.style.minWidth;
153
+ div.style.maxWidth = this.sidebar.style.maxWidth;
154
+ this.props.setSplitScreen(this.id, this.props.side, div.offsetWidth, false);
155
+ this.sidebar.parentElement.removeChild(div);
120
156
  }
121
157
  }
122
158
  }, {
123
159
  key: "render",
124
160
  value: function render() {
125
- var visible = this.props.currentTask.id === this.props.id;
126
- var render = visible || this.state.render;
127
161
  var style = {
128
- width: this.props.width,
162
+ top: this.props.splitScreen ? this.props.topbarHeight + 'px' : undefined,
163
+ bottom: this.props.splitScreen ? this.props.bottombarHeight + 'px' : undefined,
164
+ width: this.state.width,
165
+ height: this.props.splitScreen ? undefined : this.state.height,
129
166
  minWidth: this.props.minWidth,
130
- zIndex: visible ? 5 : 4
167
+ maxWidth: this.props.maxWidth,
168
+ zIndex: this.state.visible ? 5 : 4
131
169
  };
132
170
  var isLeftSide = this.props.side === "left";
133
171
  var classes = classnames({
134
172
  "sidebar": true,
135
- "sidebar-open": visible,
173
+ "sidebar-open": this.state.visible,
136
174
  "sidebar-left": isLeftSide,
137
175
  "sidebar-right": !isLeftSide
138
176
  });
139
177
  var closeIcon = isLeftSide ? "chevron-left" : "chevron-right";
140
178
  var body = null;
141
179
  var extra = null;
142
- if (render) {
180
+ if (this.state.visible) {
143
181
  body = this.renderRole("body");
144
182
  extra = this.renderRole("extra");
145
183
  }
146
- return /*#__PURE__*/ReactDOM.createPortal(/*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Swipeable, {
184
+ var result = /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Swipeable, {
147
185
  delta: 30,
148
186
  onSwipedRight: this.closeClicked
149
187
  }, /*#__PURE__*/React.createElement("div", {
150
188
  className: "".concat(classes, " ").concat(this.props.extraClasses),
151
189
  id: this.props.id,
152
- inert: !visible,
190
+ inert: !this.state.visible,
153
191
  ref: this.setRef,
154
192
  style: style
155
- }, /*#__PURE__*/React.createElement("div", {
193
+ }, this.props.widthResizeable ? /*#__PURE__*/React.createElement("div", {
156
194
  className: "sidebar-resize-handle sidebar-resize-handle-" + this.props.side,
157
195
  onPointerDown: this.startSidebarResize
158
- }), /*#__PURE__*/React.createElement("div", {
196
+ }) : null, /*#__PURE__*/React.createElement("div", {
159
197
  className: "sidebar-titlebar"
160
- }, this.state.render ? this.props.extraBeforeContent : null, this.props.icon ? /*#__PURE__*/React.createElement(Icon, {
198
+ }, this.state.visible ? this.props.extraBeforeContent : null, this.props.icon ? /*#__PURE__*/React.createElement(Icon, {
161
199
  className: "sidebar-titlebar-icon",
162
200
  icon: this.props.icon,
163
201
  size: "large"
164
202
  }) : null, /*#__PURE__*/React.createElement("span", {
165
203
  className: "sidebar-titlebar-title"
166
- }, this.props.title), this.state.render ? this.props.extraTitlebarContent : null, /*#__PURE__*/React.createElement("span", {
204
+ }, this.props.title), this.state.visible ? this.props.extraTitlebarContent : null, /*#__PURE__*/React.createElement("span", {
167
205
  className: "sidebar-titlebar-spacer"
168
206
  }), /*#__PURE__*/React.createElement(Icon, {
169
207
  className: "sidebar-titlebar-closeicon",
@@ -171,15 +209,31 @@ var SideBar = /*#__PURE__*/function (_React$Component) {
171
209
  onClick: this.closeClicked
172
210
  })), /*#__PURE__*/React.createElement("div", {
173
211
  className: "sidebar-body"
174
- }, body), this.props.heightResizeable ? /*#__PURE__*/React.createElement("div", {
212
+ }, body), this.props.heightResizeable && !this.props.splitScreen ? /*#__PURE__*/React.createElement("div", {
175
213
  className: "sidebar-resize-handle-bottom",
176
214
  onPointerDown: this.startSidebarBottomResize
177
- }) : null)), extra), this.context);
215
+ }) : null)), extra);
216
+ return this.props.splitScreen ? result : /*#__PURE__*/ReactDOM.createPortal(result, this.context);
217
+ }
218
+ }], [{
219
+ key: "getDerivedStateFromProps",
220
+ value: function getDerivedStateFromProps(nextProps, state) {
221
+ var _nextProps$currentTas;
222
+ var newState = {};
223
+ if (nextProps.width !== state.widthProp) {
224
+ newState.widthProp = newState.width = nextProps.width;
225
+ }
226
+ var visible = nextProps.visible || ((_nextProps$currentTas = nextProps.currentTask) === null || _nextProps$currentTas === void 0 ? void 0 : _nextProps$currentTas.id) === nextProps.id;
227
+ if (visible !== state.visible) {
228
+ newState.visible = visible;
229
+ }
230
+ return newState;
178
231
  }
179
232
  }]);
180
233
  }(React.Component);
181
234
  _defineProperty(SideBar, "contextType", MapContainerPortalContext);
182
235
  _defineProperty(SideBar, "propTypes", {
236
+ bottombarHeight: PropTypes.number,
183
237
  children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
184
238
  currentTask: PropTypes.object,
185
239
  extraBeforeContent: PropTypes.object,
@@ -188,15 +242,22 @@ _defineProperty(SideBar, "propTypes", {
188
242
  heightResizeable: PropTypes.bool,
189
243
  icon: PropTypes.string,
190
244
  id: PropTypes.string.isRequired,
245
+ maxWidth: PropTypes.string,
191
246
  minWidth: PropTypes.string,
192
247
  onHide: PropTypes.func,
193
248
  onShow: PropTypes.func,
194
249
  setCurrentTask: PropTypes.func,
250
+ setSplitScreen: PropTypes.func,
195
251
  side: PropTypes.string,
252
+ splitScreen: PropTypes.bool,
196
253
  title: PropTypes.string,
197
- width: PropTypes.string
254
+ topbarHeight: PropTypes.number,
255
+ visible: PropTypes.bool,
256
+ width: PropTypes.string,
257
+ widthResizeable: PropTypes.bool
198
258
  });
199
259
  _defineProperty(SideBar, "defaultProps", {
260
+ widthResizeable: true,
200
261
  extraClasses: '',
201
262
  onShow: function onShow() {},
202
263
  onHide: function onHide() {},
@@ -207,8 +268,11 @@ _defineProperty(SideBar, "defaultProps", {
207
268
  });
208
269
  export default connect(function (state) {
209
270
  return {
210
- currentTask: state.task
271
+ currentTask: state.task,
272
+ topbarHeight: state.windows.topbarHeight,
273
+ bottombarHeight: state.windows.bottombarHeight
211
274
  };
212
275
  }, {
213
- setCurrentTask: setCurrentTask
276
+ setCurrentTask: setCurrentTask,
277
+ setSplitScreen: setSplitScreen
214
278
  })(SideBar);
@@ -166,7 +166,8 @@ var AppContainerComponent = /*#__PURE__*/function (_React$Component) {
166
166
  var initialTaskParam = params.task ? JSON.parse(decodeURIComponent(params.task)) : null;
167
167
  _this.props.setCurrentTheme(theme, themes, false, initialExtent, layerParams, (_params$bl = params.bl) !== null && _params$bl !== void 0 ? _params$bl : null, state.layers, _this.props.appConfig.themeLayerRestorer, _this.props.appConfig.externalLayerRestorer, initialTaskParam, state.visibilityPreset);
168
168
  } else if (ConfigUtils.getConfigProp("dontLoadDefaultTheme")) {
169
- _this.props.setBlankTheme(themes);
169
+ var _params$bl2;
170
+ _this.props.setBlankTheme(themes, null, (_params$bl2 = params.bl) !== null && _params$bl2 !== void 0 ? _params$bl2 : null);
170
171
  } else if (!ConfigUtils.havePlugin("Portal")) {
171
172
  _this.props.showNotification("missingdefaulttheme", LocaleUtils.tr("app.missingdefaulttheme", params.t), NotificationType.WARN, true);
172
173
  }
@@ -3,7 +3,7 @@ div.sidebar {
3
3
  top: 0;
4
4
  max-height: 100%;
5
5
  background-color: var(--container-bg-color);
6
- transition: transform 0.25s;
6
+ transition: transform 0.25s, width 0.25s;
7
7
  box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.75);
8
8
  display: flex;
9
9
  flex-direction: column;
@@ -55,8 +55,7 @@ var GroupSelect = /*#__PURE__*/function (_Component) {
55
55
  value: this.props.value
56
56
  }, this.props.placeholder !== null ? /*#__PURE__*/React.createElement("option", {
57
57
  disabled: true,
58
- hidden: true,
59
- selected: true
58
+ value: ""
60
59
  }, this.props.placeholder) : null, this.props.defaultOption !== null ? /*#__PURE__*/React.createElement("option", {
61
60
  key: this.props.defaultOption[0],
62
61
  value: this.props.defaultOption[0]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "qwc2",
3
- "version": "2026.06.23",
3
+ "version": "2026.06.26",
4
4
  "description": "QGIS Web Client",
5
5
  "author": "Sourcepole AG",
6
6
  "license": "BSD-2-Clause",
@@ -152,7 +152,7 @@ var FeatureForm = /*#__PURE__*/function (_React$Component) {
152
152
  _defineProperty(_this, "onWindowClose", function () {
153
153
  if (!_this.props.editContext.changed) {
154
154
  _this.clearResults();
155
- if (_this.props.exitTaskOnResultsClose) {
155
+ if (_this.props.exitTaskOnResultsClose && _this.props.currentTask === "FeatureForm") {
156
156
  _this.props.setCurrentTask(null);
157
157
  }
158
158
  }
@@ -314,6 +314,7 @@ _defineProperty(FeatureForm, "propTypes", {
314
314
  clearEditContext: PropTypes.func,
315
315
  click: PropTypes.object,
316
316
  currentEditContext: PropTypes.string,
317
+ currentTask: PropTypes.string,
317
318
  editConfigs: PropTypes.object,
318
319
  editContext: PropTypes.object,
319
320
  enabled: PropTypes.bool,
@@ -356,8 +357,9 @@ _defineProperty(FeatureForm, "defaultState", {
356
357
  export default (function () {
357
358
  var iface = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : EditingInterface;
358
359
  return connect(function (state) {
359
- var enabled = state.task.id === "FeatureForm" || state.task.identifyEnabled && ConfigUtils.getConfigProp("identifyTool", state.theme.current, "Identify") === "FeatureForm";
360
+ var enabled = state.task.id === "FeatureForm" || (!state.task.id || state.task.identifyEnabled) && ConfigUtils.getConfigProp("identifyTool", state.theme.current, "Identify") === "FeatureForm";
360
361
  return {
362
+ currentTask: state.task.id,
361
363
  click: state.map.click || {
362
364
  modifiers: {}
363
365
  },
@@ -579,7 +579,7 @@ _defineProperty(Identify, "defaultProps", {
579
579
  });
580
580
  export default connect(function (state) {
581
581
  var _state$layers$filter;
582
- var enabled = state.task.id === "Identify" || state.task.identifyEnabled && ConfigUtils.getConfigProp("identifyTool", state.theme.current, "Identify") === "Identify";
582
+ var enabled = state.task.id === "Identify" || (!state.task.id || state.task.identifyEnabled) && ConfigUtils.getConfigProp("identifyTool", state.theme.current, "Identify") === "Identify";
583
583
  return {
584
584
  click: state.map.click || {
585
585
  modifiers: {}
@@ -1139,6 +1139,7 @@ var LayerTree = /*#__PURE__*/function (_React$Component) {
1139
1139
  };
1140
1140
  }), legendTooltip, this.renderLegendPrintWindow(), /*#__PURE__*/React.createElement(LayerInfoWindow, {
1141
1141
  bboxDependentLegend: this.props.bboxDependentLegend,
1142
+ extraLegendParameters: this.props.extraLegendParameters,
1142
1143
  layerInfoGeometry: this.props.layerInfoGeometry,
1143
1144
  scaleDependentLegend: this.props.scaleDependentLegend
1144
1145
  }), /*#__PURE__*/React.createElement(ServiceInfoWindow, {
@@ -231,8 +231,8 @@ var SensorThingsTool = /*#__PURE__*/function (_React$Component) {
231
231
  * }
232
232
  */
233
233
  currentSensorLocation: null,
234
- // automatically add all Datastreams of currently selected Location if true
235
- addCurrentLocationDatastreams: false,
234
+ // automatically add first or all Datastreams of currently selected Location if 'first' or 'all'
235
+ addCurrentLocationDatastreamsMode: null,
236
236
  // show currently selected Location info window if true
237
237
  showLocationInfoWindow: false,
238
238
  // currently selected Datastreams filter options
@@ -971,7 +971,7 @@ var SensorThingsTool = /*#__PURE__*/function (_React$Component) {
971
971
  }
972
972
  }, /*#__PURE__*/React.createElement("td", {
973
973
  onClickCapture: function onClickCapture() {
974
- return _this.addLocation(location);
974
+ return _this.addBasicLocation(location);
975
975
  },
976
976
  title: "".concat(location.name, ": ").concat(location.description)
977
977
  }, location.name, ": ", location.description), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement("div", {
@@ -979,7 +979,7 @@ var SensorThingsTool = /*#__PURE__*/function (_React$Component) {
979
979
  }, /*#__PURE__*/React.createElement("button", {
980
980
  className: "button",
981
981
  onClick: function onClick() {
982
- return _this.addLocation(location);
982
+ return _this.addBasicLocation(location);
983
983
  },
984
984
  title: LocaleUtils.tr("sensorthingstool.addLocation")
985
985
  }, /*#__PURE__*/React.createElement(Icon, {
@@ -1032,6 +1032,16 @@ var SensorThingsTool = /*#__PURE__*/function (_React$Component) {
1032
1032
  });
1033
1033
  }
1034
1034
  });
1035
+ _defineProperty(_this, "addBasicLocation", function (location) {
1036
+ // add selected Location
1037
+ _this.addLocation(location);
1038
+ if (_this.props.autoAddFirstDatastream) {
1039
+ // set flag to automatically add first Datastream of selected Location once ready
1040
+ _this.setState({
1041
+ addCurrentLocationDatastreamsMode: 'first'
1042
+ });
1043
+ }
1044
+ });
1035
1045
  _defineProperty(_this, "addFullLocation", function (location) {
1036
1046
  // remove current Datastreams
1037
1047
  _this.removeAllDatastreams();
@@ -1039,7 +1049,7 @@ var SensorThingsTool = /*#__PURE__*/function (_React$Component) {
1039
1049
  _this.addLocation(location);
1040
1050
  // set flag to automatically add all Datastreams of selected Location once ready
1041
1051
  _this.setState({
1042
- addCurrentLocationDatastreams: true
1052
+ addCurrentLocationDatastreamsMode: 'all'
1043
1053
  });
1044
1054
  });
1045
1055
  _defineProperty(_this, "removeSelectedLocation", function () {
@@ -1129,6 +1139,24 @@ var SensorThingsTool = /*#__PURE__*/function (_React$Component) {
1129
1139
  };
1130
1140
  });
1131
1141
  });
1142
+ _defineProperty(_this, "removeAllLocations", function () {
1143
+ _this.removeAllDatastreams();
1144
+ _this.setState({
1145
+ selectedLocations: {},
1146
+ selectedLocationsOptions: [],
1147
+ currentLocationId: null,
1148
+ currentSensorLocation: null,
1149
+ showLocationInfoWindow: false,
1150
+ currentDatastreamsFilter: {
1151
+ thingId: '-1',
1152
+ sensorId: '-1',
1153
+ observedPropertyId: '-1'
1154
+ },
1155
+ showDatastreamsFilterWindow: false,
1156
+ currentDatastreamId: null,
1157
+ datastreams: {}
1158
+ });
1159
+ });
1132
1160
  _defineProperty(_this, "addSelectedDatastream", function () {
1133
1161
  if (_this.state.currentDatastreamId !== undefined) {
1134
1162
  _this.addDatastream(_this.state.currentDatastreamId);
@@ -1156,8 +1184,37 @@ var SensorThingsTool = /*#__PURE__*/function (_React$Component) {
1156
1184
  // use random color
1157
1185
  color = [Math.round(Math.random() * 255), Math.round(Math.random() * 255), Math.round(Math.random() * 255)];
1158
1186
  }
1187
+ var periodAdjustment = {};
1188
+ if (_this.props.autoAdjustPeriod.intervalBefore !== undefined) {
1189
+ // find earliest last Observation of all visible Datastreams incl. this one
1190
+ var earliestPeriodEnd = state.datastreams[datastreamId].period.end;
1191
+ state.graph.datastreams.forEach(function (datastream) {
1192
+ if (datastream.observations) {
1193
+ var datastreamInfo = state.datastreams[datastream.id];
1194
+ earliestPeriodEnd = Math.min(datastreamInfo.period.end, earliestPeriodEnd || datastreamInfo.period.end);
1195
+ }
1196
+ });
1197
+ if (earliestPeriodEnd !== null) {
1198
+ periodAdjustment = {
1199
+ // show period from intervalBefore before earliest last Observation up to now
1200
+ x: _objectSpread(_objectSpread({}, state.graph.x), {}, {
1201
+ min: earliestPeriodEnd - _this.props.autoAdjustPeriod.intervalBefore * 1000,
1202
+ max: Date.now()
1203
+ }),
1204
+ // NOTE: reset range of y-axes to auto
1205
+ y: _objectSpread(_objectSpread({}, state.graph.y), {}, {
1206
+ min: null,
1207
+ max: null
1208
+ }),
1209
+ y2: _objectSpread(_objectSpread({}, state.graph.y2), {}, {
1210
+ min: null,
1211
+ max: null
1212
+ })
1213
+ };
1214
+ }
1215
+ }
1159
1216
  return {
1160
- graph: _objectSpread(_objectSpread({}, state.graph), {}, {
1217
+ graph: _objectSpread(_objectSpread(_objectSpread({}, state.graph), periodAdjustment), {}, {
1161
1218
  datastreams: [].concat(_toConsumableArray(state.graph.datastreams), [{
1162
1219
  id: datastreamId,
1163
1220
  observations: null,
@@ -2083,6 +2140,12 @@ var SensorThingsTool = /*#__PURE__*/function (_React$Component) {
2083
2140
  });
2084
2141
  }
2085
2142
  });
2143
+ _defineProperty(_this, "closeMainWindow", function () {
2144
+ if (_this.props.clearAllOnClose) {
2145
+ _this.removeAllLocations();
2146
+ }
2147
+ _this.props.setCurrentTask(null);
2148
+ });
2086
2149
  _defineProperty(_this, "queryAtPoint", function (point) {
2087
2150
  var _this$props$theme$plu;
2088
2151
  _this.setState({
@@ -3022,12 +3085,17 @@ var SensorThingsTool = /*#__PURE__*/function (_React$Component) {
3022
3085
  } else if (prevState.currentSensorLocation && !this.state.currentSensorLocation) {
3023
3086
  this.props.removeLayer("sensorThingsSelection");
3024
3087
  }
3025
- if (this.state.addCurrentLocationDatastreams && this.state.currentSensorLocation && this.state.currentSensorLocation.id === this.state.currentLocationId) {
3026
- // add all Datastreams of current Location
3027
- this.addDatastreams(this.state.currentSensorLocation.datastreams);
3088
+ if (this.state.addCurrentLocationDatastreamsMode !== null && this.state.currentSensorLocation && this.state.currentSensorLocation.id === this.state.currentLocationId) {
3089
+ if (this.state.addCurrentLocationDatastreamsMode === 'first' && this.state.currentSensorLocation.datastreams.length > 0) {
3090
+ // add first Datastream of current Location
3091
+ this.addDatastream(this.state.currentSensorLocation.datastreams[0]);
3092
+ } else {
3093
+ // add all Datastreams of current Location
3094
+ this.addDatastreams(this.state.currentSensorLocation.datastreams);
3095
+ }
3028
3096
  // reset flag
3029
3097
  this.setState({
3030
- addCurrentLocationDatastreams: false
3098
+ addCurrentLocationDatastreamsMode: null
3031
3099
  });
3032
3100
  }
3033
3101
  if (this.state.currentDatastreamsFilter !== prevState.currentDatastreamsFilter) {
@@ -3085,9 +3153,7 @@ var SensorThingsTool = /*#__PURE__*/function (_React$Component) {
3085
3153
  initialX: 0,
3086
3154
  initialY: 0,
3087
3155
  key: "SensorThingsInfoWindow",
3088
- onClose: function onClose() {
3089
- return _this3.props.setCurrentTask(null);
3090
- },
3156
+ onClose: this.closeMainWindow,
3091
3157
  title: LocaleUtils.tr("sensorthingstool.title"),
3092
3158
  usePortal: false
3093
3159
  }, this.renderBody()), this.renderLocationSelectPopup(), this.renderLocationInfoWindow(), this.renderDatastreamsFilterWindow(), this.renderDatastreamInfoWindow(), this.renderDatastreamTableWindow(), /*#__PURE__*/React.createElement(MapSelection, {
@@ -3108,6 +3174,18 @@ var SensorThingsTool = /*#__PURE__*/function (_React$Component) {
3108
3174
  }(React.Component);
3109
3175
  _defineProperty(SensorThingsTool, "propTypes", {
3110
3176
  addLayerFeatures: PropTypes.func,
3177
+ /** Automatically add the first Datastream when selecting a Location in the map. */
3178
+ autoAddFirstDatastream: PropTypes.bool,
3179
+ /** Automatically adjust the visible period when adding a Datastream. Set `null` to disable.
3180
+ * Sets the period begin to `intervalBefore` before the earliest last Observation of all visible Datastreams.
3181
+ * Sets the period end to now.
3182
+ */
3183
+ autoAdjustPeriod: PropTypes.shape({
3184
+ /** Interval in seconds.*/
3185
+ intervalBefore: PropTypes.number
3186
+ }),
3187
+ /** Remove all Locations and Datastreams when closing the main window. */
3188
+ clearAllOnClose: PropTypes.bool,
3111
3189
  currentTask: PropTypes.string,
3112
3190
  map: PropTypes.object,
3113
3191
  /** Map picking tolerance in pixels */
@@ -3133,6 +3211,9 @@ _defineProperty(SensorThingsTool, "propTypes", {
3133
3211
  zoomRectMinSize: PropTypes.object
3134
3212
  });
3135
3213
  _defineProperty(SensorThingsTool, "defaultProps", {
3214
+ autoAddFirstDatastream: false,
3215
+ autoAdjustPeriod: {},
3216
+ clearAllOnClose: false,
3136
3217
  queryTolerance: 16,
3137
3218
  sensorThingsApiUrls: [],
3138
3219
  timeFormats: {
@@ -1,5 +1,6 @@
1
1
  div.themebrowser-body {
2
2
  background-color: var(--list-bg-color);
3
+ padding: 0.25em;
3
4
  }
4
5
 
5
6
  div.themebrowser-theme-container {
@@ -13,6 +14,7 @@ div.themebrowser-theme-container:not(:last-child) {
13
14
  div.themebrowser-theme {
14
15
  background-color: var(--button-bg-color);
15
16
  color: var(--button-text-color);
17
+ border-radius: 0.5em;
16
18
  font-weight: bold;
17
19
  padding: 0 0.5em;
18
20
  display: flex;
@@ -65,22 +67,29 @@ div.themebrowser-tree-entry-detailsvisible {
65
67
  border-bottom-right-radius: 0;
66
68
  }
67
69
 
70
+ .themebrowser-tree-entry-plus {
71
+ transition: transform 0.25s;
72
+ }
73
+
74
+ .themebrowser-tree-entry-plus-remove {
75
+ transform: rotate(45deg);
76
+ }
77
+
68
78
  span.themebrowser-tree-entry-title {
69
- cursor: pointer;
70
79
  padding-left: 0.5em;
71
80
  white-space: nowrap;
72
81
  overflow: hidden;
73
82
  text-overflow: ellipsis;
83
+ flex: 1 1 auto;
74
84
  }
75
85
 
76
- span.themebrowser-tree-entry-spacer {
77
- flex: 1 1 auto;
78
- height: 100%;
86
+ div.themebrowser-tree-entry-transparent > span.themebrowser-tree-entry-title {
87
+ cursor: ew-resize;
79
88
  }
80
89
 
81
- span.themebrowser-tree-entry-arrows {
82
- display: none;
90
+ span.themebrowser-tree-entry-opacity {
83
91
  cursor: ew-resize;
92
+ display: none;
84
93
  }
85
94
 
86
95
  span.themebrowser-tree-entry-drag {
@@ -88,8 +97,8 @@ span.themebrowser-tree-entry-drag {
88
97
  padding: 0 0.5em;
89
98
  }
90
99
 
91
- div.themebrowser-tree-entry:focus > span.themebrowser-tree-entry-arrows,
92
- div.themebrowser-tree-entry:hover > span.themebrowser-tree-entry-arrows {
100
+ div.themebrowser-tree-entry:focus > span.themebrowser-tree-entry-opacity,
101
+ div.themebrowser-tree-entry:hover > span.themebrowser-tree-entry-opacity {
93
102
  display: initial;
94
103
  }
95
104
 
@@ -36,7 +36,7 @@ import { setCurrentTask } from '../actions/task';
36
36
  import { setBlankTheme, setCurrentTheme } from '../actions/theme';
37
37
  import Icon from '../components/Icon';
38
38
  import ImportLayer from '../components/ImportLayer';
39
- import ResizeableWindow from '../components/ResizeableWindow';
39
+ import SideBar from '../components/SideBar';
40
40
  import { Image } from '../components/widgets/Primitives';
41
41
  import ConfigUtils from '../utils/ConfigUtils';
42
42
  import LayerUtils from '../utils/LayerUtils';
@@ -59,23 +59,9 @@ var ThemeBrowser = /*#__PURE__*/function (_React$Component) {
59
59
  _defineProperty(_this, "state", {
60
60
  active: false,
61
61
  expandedEntries: new ToggleSet(),
62
- showDelete: false
63
- });
64
- _defineProperty(_this, "setRndRef", function (el) {
65
- _this.rnd = el;
66
- _this.updateWindowSize();
67
- });
68
- _defineProperty(_this, "updateWindowSize", function () {
69
- if (_this.rnd && _this.maxLayerTitleLength !== undefined) {
70
- var _sizes$find;
71
- var width = _this.maxLayerTitleLength + MiscUtils.convertEmToPx(6.5);
72
- var sizes = [200, 300, 500];
73
- _this.rnd.updateSize({
74
- width: (_sizes$find = sizes.find(function (size) {
75
- return size > width;
76
- })) !== null && _sizes$find !== void 0 ? _sizes$find : width
77
- });
78
- }
62
+ showDelete: false,
63
+ width: '15em',
64
+ maxWidth: '50%'
79
65
  });
80
66
  _defineProperty(_this, "renderThemes", function (group) {
81
67
  var _group$items, _group$subdirs;
@@ -103,7 +89,7 @@ var ThemeBrowser = /*#__PURE__*/function (_React$Component) {
103
89
  size: "large"
104
90
  })) : null);
105
91
  });
106
- ((_group$subdirs = group.subdirs) !== null && _group$subdirs !== void 0 ? _group$subdirs : []).map(function (subdir) {
92
+ ((_group$subdirs = group === null || group === void 0 ? void 0 : group.subdirs) !== null && _group$subdirs !== void 0 ? _group$subdirs : []).map(function (subdir) {
107
93
  return children.push.apply(children, _toConsumableArray(_this.renderThemes(subdir)));
108
94
  });
109
95
  return children;
@@ -167,18 +153,20 @@ var ThemeBrowser = /*#__PURE__*/function (_React$Component) {
167
153
  var opacity = LayerUtils.computeLayerOpacity(entry);
168
154
  var entryClasses = classNames({
169
155
  "themebrowser-tree-entry": true,
156
+ "themebrowser-tree-entry-transparent": entry.visibility && opacity < 255,
170
157
  "themebrowser-tree-entry-visible": entry.visibility,
171
158
  "themebrowser-tree-entry-inactive": !parentVisibility,
172
159
  "themebrowser-tree-entry-detailsvisible": _this.state.expandedEntries.has(layer.id + ":" + entry.name)
173
160
  });
161
+ var plusClasses = classNames({
162
+ "themebrowser-tree-entry-plus": true,
163
+ "themebrowser-tree-entry-plus-remove": entry.visibility
164
+ });
174
165
  var entryStyle = {
175
166
  backgroundColor: entry.visibility ? "rgb(from var(--border-color) r g b / ".concat(opacity / 255, ")") : '',
176
167
  color: entry.visibility && opacity > 96 ? "white" : "var(--border-color)"
177
168
  };
178
- var spacerStyle = {
179
- cursor: entry.opacity < 255 ? 'ew-resize' : ''
180
- };
181
- _this.maxLayerTitleLength = Math.max(_this.maxLayerTitleLength, _this.measureContext.measureText(entry.title).width + path.length * MiscUtils.convertEmToPx(1));
169
+ _this.maxLayerTitleLength = Math.max(_this.maxLayerTitleLength, _this.measureContext.measureText(entry.title).width + path.length * MiscUtils.convertEmToPx(1) + MiscUtils.convertEmToPx(6));
182
170
  return /*#__PURE__*/React.createElement("div", {
183
171
  className: "themebrowser-tree-entry-container",
184
172
  "data-id": JSON.stringify({
@@ -197,8 +185,9 @@ var ThemeBrowser = /*#__PURE__*/function (_React$Component) {
197
185
  style: entryStyle,
198
186
  tabIndex: 0
199
187
  }, /*#__PURE__*/React.createElement(Icon, {
200
- icon: entry.visibility ? "remove" : "plus",
201
- onClick: function onClick() {
188
+ className: plusClasses,
189
+ icon: "plus",
190
+ onPointerDown: function onPointerDown() {
202
191
  return _this.toggleEntryVisibility(entry, layer.id, path);
203
192
  }
204
193
  }), /*#__PURE__*/React.createElement("span", {
@@ -207,16 +196,11 @@ var ThemeBrowser = /*#__PURE__*/function (_React$Component) {
207
196
  onPointerDown: function onPointerDown(ev) {
208
197
  return _this.toggleEntryExpanded(ev, entry, layer.id, path);
209
198
  },
210
- tabIndex: 0
211
- }, entry.title), /*#__PURE__*/React.createElement("span", {
212
- className: "themebrowser-tree-entry-spacer",
213
- style: spacerStyle
214
- }), /*#__PURE__*/React.createElement(Icon, {
215
- className: "themebrowser-tree-entry-arrows",
216
- icon: "middle_h"
217
- }), /*#__PURE__*/React.createElement("span", {
199
+ tabIndex: 0,
200
+ title: entry.title
201
+ }, entry.title), entry.visibility ? /*#__PURE__*/React.createElement("span", {
218
202
  className: "themebrowser-tree-entry-opacity"
219
- }), /*#__PURE__*/React.createElement("span", {
203
+ }, Math.round(opacity / 255 * 100) + "%") : null, /*#__PURE__*/React.createElement("span", {
220
204
  className: "themebrowser-tree-entry-drag",
221
205
  onKeyDown: function onKeyDown(ev) {
222
206
  return _this.onKeySort(ev, layer.id, path);
@@ -313,11 +297,9 @@ var ThemeBrowser = /*#__PURE__*/function (_React$Component) {
313
297
  return;
314
298
  }
315
299
  // Only adjust opacities when dragging from areas other than the opacity arrows icon if entry is not fully opaque
316
- if (ev.type === "pointerdown" && entry.opacity === 255 && !ev.target.matches('.themebrowser-tree-entry-arrows')) {
300
+ if (ev.type === "pointerdown" && entry.opacity === 255 && !ev.target.matches('.themebrowser-tree-entry-opacity')) {
317
301
  return;
318
302
  }
319
- var arrowsEl = ev.currentTarget.getElementsByClassName("themebrowser-tree-entry-arrows")[0];
320
- var opacityEl = ev.currentTarget.getElementsByClassName("themebrowser-tree-entry-opacity")[0];
321
303
  var startOpacity = LayerUtils.computeLayerOpacity(entry);
322
304
  if (ev.type === "keydown" && (ev.key === "ArrowLeft" || ev.key === "ArrowRight")) {
323
305
  _this.adjusting = true;
@@ -325,17 +307,12 @@ var ThemeBrowser = /*#__PURE__*/function (_React$Component) {
325
307
  var newOpacity = startOpacity;
326
308
  var adjustInterval = null;
327
309
  var startTimeout = setTimeout(function () {
328
- arrowsEl.style.display = 'none';
329
- opacityEl.innerText = Math.round(newOpacity / 255 * 100) + "%";
330
310
  adjustInterval = setInterval(function () {
331
311
  newOpacity = Math.max(0, Math.min(255, newOpacity + delta));
332
- opacityEl.innerText = Math.round(newOpacity / 255 * 100) + "%";
333
312
  _this.props.changeLayerProperty(layerId, "opacity", newOpacity, path, "children");
334
313
  }, 15);
335
314
  }, 100);
336
315
  ev.view.addEventListener('keyup', function () {
337
- arrowsEl.style.display = '';
338
- opacityEl.innerText = '';
339
316
  clearTimeout(startTimeout);
340
317
  clearInterval(adjustInterval);
341
318
  _this.adjusting = false;
@@ -348,23 +325,16 @@ var ThemeBrowser = /*#__PURE__*/function (_React$Component) {
348
325
  var _newOpacity = startOpacity;
349
326
  var computeNewOpacity = function computeNewOpacity(event) {
350
327
  _newOpacity = Math.max(0, Math.min(255, startOpacity + (event.clientX - startMouseX)));
351
- opacityEl.innerText = Math.round(_newOpacity / 255 * 100) + "%";
352
328
  _this.props.changeLayerProperty(layerId, "opacity", _newOpacity, path, "children");
353
329
  };
354
330
  var resizeOverlay = document.createElement('div');
355
331
  resizeOverlay.className = 'themebrowser-resize-overlay';
356
332
  ev.view.document.body.appendChild(resizeOverlay);
357
333
  ev.view.document.body.style.userSelect = 'none';
358
- // ev.view.document.body.style.setProperty('cursor', 'ew-resize', 'important');
359
- arrowsEl.style.display = 'none';
360
- opacityEl.innerText = Math.round(startOpacity / 255 * 100) + "%";
361
334
  ev.view.addEventListener("pointermove", computeNewOpacity);
362
335
  ev.view.addEventListener("pointerup", function () {
363
336
  ev.view.document.body.removeChild(resizeOverlay);
364
337
  ev.view.document.body.style.userSelect = '';
365
- // ev.view.document.body.style.removeProperty('cursor');
366
- arrowsEl.style.display = '';
367
- opacityEl.innerText = '';
368
338
  ev.view.removeEventListener("pointermove", computeNewOpacity);
369
339
  _this.adjusting = false;
370
340
  }, {
@@ -383,7 +353,7 @@ var ThemeBrowser = /*#__PURE__*/function (_React$Component) {
383
353
  });
384
354
  _defineProperty(_this, "onDragStart", function (layer, path) {
385
355
  _this.dragging = true;
386
- if (layer.role !== LayerRole.THEME) {
356
+ if (layer.role !== LayerRole.THEME || _this.props.allowRemovingThemeLayers) {
387
357
  _this.setState({
388
358
  showDelete: true
389
359
  });
@@ -417,7 +387,7 @@ var ThemeBrowser = /*#__PURE__*/function (_React$Component) {
417
387
  }
418
388
  });
419
389
  _this.maxLayerTitleLength = undefined;
420
- _this.rnd = null;
390
+ _this.sidebar = null;
421
391
  return _this;
422
392
  }
423
393
  _inherits(ThemeBrowser, _React$Component);
@@ -441,35 +411,35 @@ var ThemeBrowser = /*#__PURE__*/function (_React$Component) {
441
411
  }, {
442
412
  key: "render",
443
413
  value: function render() {
444
- if (!this.state.active) {
445
- return null;
446
- }
447
414
  this.maxLayerTitleLength = 0;
448
415
  this.measureCanvas = document.createElement('canvas');
449
416
  this.measureContext = this.measureCanvas.getContext('2d');
450
417
  this.measureContext.font = getComputedStyle(document.body).font;
451
- var result = /*#__PURE__*/React.createElement(ResizeableWindow, {
452
- detachable: false,
453
- dockable: "right",
454
- hideDockIcon: true,
455
- initialHeight: 640,
456
- initialWidth: 640,
457
- initialX: 0,
458
- initialY: 0,
459
- initiallyDocked: true,
460
- maximizeable: false,
461
- onClose: this.onClose,
462
- scrollable: true,
463
- setRef: this.setRndRef,
464
- splitScreenWhenDocked: true,
465
- title: LocaleUtils.tr("appmenu.items.ThemeBrowser")
418
+ var result = /*#__PURE__*/React.createElement(SideBar, {
419
+ icon: "list-alt",
420
+ id: "ThemeBrowser",
421
+ maxWidth: this.props.fillIfWiderThanPerc ? undefined : this.props.maxWidth,
422
+ onHide: this.onClose,
423
+ side: this.props.side,
424
+ splitScreen: true,
425
+ title: LocaleUtils.tr("appmenu.items.ThemeBrowser"),
426
+ visible: this.state.active,
427
+ width: this.state.width
466
428
  }, /*#__PURE__*/React.createElement("div", {
467
429
  className: "themebrowser-body",
468
430
  role: "body"
469
431
  }, this.renderThemes(this.props.themes)));
432
+ var width = this.maxLayerTitleLength + "px";
433
+ if (this.props.fillIfWiderThanPerc && this.maxLayerTitleLength > window.innerWidth * this.props.fillIfWiderThanPerc / 100) {
434
+ width = '100%';
435
+ }
470
436
  this.measureCanvas = undefined;
471
437
  this.measureContext = undefined;
472
- this.updateWindowSize();
438
+ if (width !== this.state.width) {
439
+ this.setState({
440
+ width: width
441
+ });
442
+ }
473
443
  return result;
474
444
  }
475
445
  }]);
@@ -477,13 +447,19 @@ var ThemeBrowser = /*#__PURE__*/function (_React$Component) {
477
447
  _defineProperty(ThemeBrowser, "propTypes", {
478
448
  active: PropTypes.bool,
479
449
  activeTheme: PropTypes.string,
450
+ /** Whether to allow removing theme layers. */
451
+ allowRemovingThemeLayers: PropTypes.bool,
480
452
  /** Whether to display a BBOX dependent legend. Can be `true|false|"theme"`, latter means only for theme layers. */
481
453
  bboxDependentLegend: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
482
454
  changeLayerProperty: PropTypes.func,
483
455
  /** Whether to use the fallback logic for drag-and-drop. */
484
456
  fallbackDrag: PropTypes.bool,
457
+ /** Make panel fill screen width if wider than the specified screen width percentage. */
458
+ fillIfWiderThanPerc: PropTypes.number,
485
459
  layers: PropTypes.array,
486
460
  map: PropTypes.object,
461
+ /** Maximum width of panel (ignored `fillIfWiderThanPerc` is set). */
462
+ maxWidth: PropTypes.string,
487
463
  removeLayer: PropTypes.func,
488
464
  reorderLayer: PropTypes.func,
489
465
  /** Whether to display a scale dependent legend. Can be `true|false|"theme"`, latter means only for theme layers. */
@@ -491,8 +467,13 @@ _defineProperty(ThemeBrowser, "propTypes", {
491
467
  setBlankTheme: PropTypes.func,
492
468
  setCurrentTask: PropTypes.func,
493
469
  setCurrentTheme: PropTypes.func,
470
+ /** The side of the application on which to display the sidebar. */
471
+ side: PropTypes.string,
494
472
  themes: PropTypes.array
495
473
  });
474
+ _defineProperty(ThemeBrowser, "defaultProps", {
475
+ side: 'right'
476
+ });
496
477
  var selector = function selector(state) {
497
478
  var _state$theme$current;
498
479
  return {
@@ -1,4 +1,12 @@
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 _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; } }
5
+ function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
6
+ function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); }
7
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
8
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
9
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
2
10
  function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); }
3
11
  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
12
  function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; }
@@ -37,8 +45,11 @@ var BackgroundSwitcher3D = /*#__PURE__*/function (_React$Component) {
37
45
  return _createClass(BackgroundSwitcher3D, [{
38
46
  key: "render",
39
47
  value: function render() {
48
+ var backgroundLayers = Object.values(this.props.sceneContext.baseLayers.reduce(function (res, l) {
49
+ return _objectSpread(_objectSpread({}, res), {}, _defineProperty({}, "_" + (l.group || l.name), l.group ? [].concat(_toConsumableArray(res["_" + l.group] || []), [l]) : l));
50
+ }, {}));
40
51
  return /*#__PURE__*/React.createElement(BackgroundSwitcher, {
41
- backgroundLayers: this.props.sceneContext.baseLayers,
52
+ backgroundLayers: backgroundLayers,
42
53
  buttonClickAction: this.props.buttonClickAction,
43
54
  buttonDisplayMode: this.props.buttonDisplayMode,
44
55
  changeLayerVisibility: this.props.sceneContext.setBaseLayer,
@@ -1511,11 +1511,11 @@ var LayerUtils = {
1511
1511
  },
1512
1512
  computeVisibilityPreset: function computeVisibilityPreset(layers) {
1513
1513
  var result = {};
1514
- var _collectLayerVisibilities = function collectLayerVisibilities(layer, path, parentVisible) {
1514
+ var _collectLayerVisibilities = function collectLayerVisibilities(layer, path) {
1515
1515
  if (layer.sublayers) {
1516
1516
  var istoplevel = !!layer.url;
1517
1517
  layer.sublayers.forEach(function (sublayer) {
1518
- return _collectLayerVisibilities(sublayer, !istoplevel ? path + layer.name + "/" : "", parentVisible && layer.visibility);
1518
+ return _collectLayerVisibilities(sublayer, !istoplevel ? path + layer.name + "/" : "");
1519
1519
  });
1520
1520
  if (layer.visibility && !istoplevel) {
1521
1521
  result[path + layer.name] = {
@@ -1530,14 +1530,13 @@ var LayerUtils = {
1530
1530
  } else {
1531
1531
  result[path + layer.name] = {
1532
1532
  checked: layer.visibility,
1533
- style: layer.style,
1534
- visible: layer.visibility && parentVisible
1533
+ style: layer.style
1535
1534
  };
1536
1535
  }
1537
1536
  };
1538
1537
  layers.forEach(function (layer) {
1539
1538
  if (layer.role === LayerRole.THEME) {
1540
- _collectLayerVisibilities(layer, "", layer.visibility);
1539
+ _collectLayerVisibilities(layer, "");
1541
1540
  }
1542
1541
  });
1543
1542
  return result;