@eeacms/volto-arcgis-block 0.1.406 → 0.1.407
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/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file. Dates are d
|
|
|
4
4
|
|
|
5
5
|
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
6
6
|
|
|
7
|
+
### [0.1.407](https://github.com/eea/volto-arcgis-block/compare/0.1.406...0.1.407) - 19 November 2025
|
|
8
|
+
|
|
9
|
+
#### :hammer_and_wrench: Others
|
|
10
|
+
|
|
11
|
+
- (feat): Rebased develop with this branch [Unai Bolivar - [`dae3e96`](https://github.com/eea/volto-arcgis-block/commit/dae3e96d56bd21d54a348267289932d299ba67b2)]
|
|
12
|
+
- (feat): Linting and prettifying before push [Unai Bolivar - [`455aa13`](https://github.com/eea/volto-arcgis-block/commit/455aa133d4da07949f3751d099c3f9ccddd4d971)]
|
|
13
|
+
- (feat): Error Report widget added user instructions and style changes [Unai Bolivar - [`3e69a69`](https://github.com/eea/volto-arcgis-block/commit/3e69a690467e1a66552a0ff8579b30eaabb5b95e)]
|
|
14
|
+
- (feat): Error Report widget added functionality, fixed bugs in css styles. [Unai Bolivar - [`1c833b2`](https://github.com/eea/volto-arcgis-block/commit/1c833b2b62e279fee1adbac0233f8d1cc5f2f559)]
|
|
15
|
+
- (feat): Error Report widget creation [Unai Bolivar - [`47ad31e`](https://github.com/eea/volto-arcgis-block/commit/47ad31e724279be223f3bdd3d8d619db32c24293)]
|
|
7
16
|
### [0.1.406](https://github.com/eea/volto-arcgis-block/compare/0.1.405...0.1.406) - 19 November 2025
|
|
8
17
|
|
|
9
18
|
#### :hammer_and_wrench: Others
|
package/package.json
CHANGED
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import React, { createRef } from 'react';
|
|
2
|
+
import { loadModules } from 'esri-loader';
|
|
3
|
+
|
|
4
|
+
class ErrorReport extends React.Component {
|
|
5
|
+
constructor(props) {
|
|
6
|
+
super(props);
|
|
7
|
+
this.container = createRef();
|
|
8
|
+
this.state = {
|
|
9
|
+
showMapMenu: false,
|
|
10
|
+
latlong: null,
|
|
11
|
+
selecting: false,
|
|
12
|
+
datasets: [],
|
|
13
|
+
instructionsText: 'First select a pixel in the data viewer',
|
|
14
|
+
};
|
|
15
|
+
this.menuClass =
|
|
16
|
+
'esri-icon-notice-round esri-widget--button esri-widget esri-interactive';
|
|
17
|
+
this.helpdeskUrl = 'https://land.copernicus.eu/en/contact-service-helpdesk';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
loader() {
|
|
21
|
+
return loadModules([]).then(() => {});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
openMenu() {
|
|
25
|
+
if (this.state.showMapMenu) {
|
|
26
|
+
this.props.mapViewer.setActiveWidget();
|
|
27
|
+
this.container.current.querySelector('.right-panel').style.display =
|
|
28
|
+
'none';
|
|
29
|
+
this.container.current
|
|
30
|
+
.querySelector('.esri-widget--button')
|
|
31
|
+
.classList.remove('active-widget');
|
|
32
|
+
document
|
|
33
|
+
.querySelector('.esri-ui-top-right.esri-ui-corner')
|
|
34
|
+
.classList.remove('show-panel');
|
|
35
|
+
this.setState({ showMapMenu: false });
|
|
36
|
+
this.resetData();
|
|
37
|
+
} else {
|
|
38
|
+
this.props.mapViewer.setActiveWidget(this);
|
|
39
|
+
this.container.current.querySelector('.right-panel').style.display =
|
|
40
|
+
'flex';
|
|
41
|
+
this.container.current
|
|
42
|
+
.querySelector('.esri-widget--button')
|
|
43
|
+
.classList.add('active-widget');
|
|
44
|
+
document
|
|
45
|
+
.querySelector('.esri-ui-top-right.esri-ui-corner')
|
|
46
|
+
.classList.add('show-panel');
|
|
47
|
+
this.setState({ showMapMenu: true });
|
|
48
|
+
this.startSelection();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
startSelection() {
|
|
53
|
+
if (this.state.selecting) return;
|
|
54
|
+
var handler = this.props.view.on(
|
|
55
|
+
'pointer-down',
|
|
56
|
+
function (evt) {
|
|
57
|
+
let pt = this.props.view.toMap({ x: evt.x, y: evt.y });
|
|
58
|
+
let ds = this.getCheckedDatasets();
|
|
59
|
+
let message =
|
|
60
|
+
'Selected coordinate: Lat ' +
|
|
61
|
+
pt.latitude.toFixed(4) +
|
|
62
|
+
' Lon ' +
|
|
63
|
+
pt.longitude.toFixed(4) +
|
|
64
|
+
'. Active datasets: ' +
|
|
65
|
+
ds.join(', ');
|
|
66
|
+
try {
|
|
67
|
+
if (
|
|
68
|
+
navigator &&
|
|
69
|
+
navigator.clipboard &&
|
|
70
|
+
navigator.clipboard.writeText
|
|
71
|
+
) {
|
|
72
|
+
navigator.clipboard.writeText(message);
|
|
73
|
+
} else {
|
|
74
|
+
let ta = document.createElement('textarea');
|
|
75
|
+
ta.value = message;
|
|
76
|
+
ta.setAttribute('readonly', '');
|
|
77
|
+
ta.style.position = 'absolute';
|
|
78
|
+
ta.style.left = '-9999px';
|
|
79
|
+
document.body.appendChild(ta);
|
|
80
|
+
ta.select();
|
|
81
|
+
document.execCommand('copy');
|
|
82
|
+
document.body.removeChild(ta);
|
|
83
|
+
}
|
|
84
|
+
} catch {}
|
|
85
|
+
this.setState({
|
|
86
|
+
latlong: { x: pt.latitude.toFixed(4), y: pt.longitude.toFixed(4) },
|
|
87
|
+
selecting: false,
|
|
88
|
+
datasets: ds,
|
|
89
|
+
instructionsText:
|
|
90
|
+
"The error report data has been added to your clipboard. Click the 'Service Desk' button and paste the clipboard content inside the Helpdesk's message box",
|
|
91
|
+
});
|
|
92
|
+
handler.remove();
|
|
93
|
+
}.bind(this),
|
|
94
|
+
);
|
|
95
|
+
this.setState({ selecting: handler });
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
getCheckedDatasets() {
|
|
99
|
+
try {
|
|
100
|
+
let uid = sessionStorage.getItem('mv_hydrated_for');
|
|
101
|
+
let key = uid ? 'user_' + uid : 'user_anonymous';
|
|
102
|
+
let raw = localStorage.getItem(key);
|
|
103
|
+
if (raw) {
|
|
104
|
+
let obj = JSON.parse(raw);
|
|
105
|
+
let cl = obj && obj.checkedLayers;
|
|
106
|
+
if (typeof cl === 'string') {
|
|
107
|
+
try {
|
|
108
|
+
cl = JSON.parse(cl);
|
|
109
|
+
} catch {}
|
|
110
|
+
}
|
|
111
|
+
if (Array.isArray(cl)) {
|
|
112
|
+
return [...new Set(cl)].filter((v) => v);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
} catch {}
|
|
116
|
+
try {
|
|
117
|
+
let ss = sessionStorage.getItem('checkedLayers');
|
|
118
|
+
if (ss) {
|
|
119
|
+
let cl = ss;
|
|
120
|
+
if (typeof ss === 'string') {
|
|
121
|
+
try {
|
|
122
|
+
cl = JSON.parse(ss);
|
|
123
|
+
} catch {}
|
|
124
|
+
}
|
|
125
|
+
if (Array.isArray(cl)) {
|
|
126
|
+
return [...new Set(cl)].filter((v) => v);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
} catch {}
|
|
130
|
+
let layers = [];
|
|
131
|
+
this.props.view.map.layers.forEach(function (l) {
|
|
132
|
+
if (l.visible) {
|
|
133
|
+
layers.push(l.title || l.id || 'layer');
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
return layers;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
serviceDeskRedirect() {
|
|
140
|
+
if (!this.state.latlong) return;
|
|
141
|
+
let datasets =
|
|
142
|
+
this.state.datasets && this.state.datasets.length > 0
|
|
143
|
+
? this.state.datasets
|
|
144
|
+
: this.getCheckedDatasets();
|
|
145
|
+
let message =
|
|
146
|
+
'Selected coordinate: Lat ' +
|
|
147
|
+
this.state.latlong.x +
|
|
148
|
+
' Lon ' +
|
|
149
|
+
this.state.latlong.y +
|
|
150
|
+
'. Active datasets: ' +
|
|
151
|
+
datasets.join(', ');
|
|
152
|
+
try {
|
|
153
|
+
if (navigator && navigator.clipboard && navigator.clipboard.writeText) {
|
|
154
|
+
navigator.clipboard.writeText(message);
|
|
155
|
+
} else {
|
|
156
|
+
let ta = document.createElement('textarea');
|
|
157
|
+
ta.value = message;
|
|
158
|
+
ta.setAttribute('readonly', '');
|
|
159
|
+
ta.style.position = 'absolute';
|
|
160
|
+
ta.style.left = '-9999px';
|
|
161
|
+
document.body.appendChild(ta);
|
|
162
|
+
ta.select();
|
|
163
|
+
document.execCommand('copy');
|
|
164
|
+
document.body.removeChild(ta);
|
|
165
|
+
}
|
|
166
|
+
} catch {}
|
|
167
|
+
window.open(this.helpdeskUrl, '_blank');
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
resetData() {
|
|
171
|
+
if (this.state.selecting) {
|
|
172
|
+
this.state.selecting.remove();
|
|
173
|
+
}
|
|
174
|
+
this.setState({
|
|
175
|
+
latlong: null,
|
|
176
|
+
selecting: false,
|
|
177
|
+
datasets: [],
|
|
178
|
+
instructionsText: 'First select a pixel in the data viewer',
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
async componentDidMount() {
|
|
183
|
+
await this.loader();
|
|
184
|
+
if (!this.container.current) return;
|
|
185
|
+
this.props.view.when(() => {
|
|
186
|
+
if (!this.container.current) return;
|
|
187
|
+
var group = document.querySelector('.esri-ui-top-right.esri-ui-corner');
|
|
188
|
+
var addSelf = () => {
|
|
189
|
+
this.props.view.ui.add(this.container.current, {
|
|
190
|
+
position: 'top-right',
|
|
191
|
+
// index: 9999,
|
|
192
|
+
});
|
|
193
|
+
};
|
|
194
|
+
if (group && group.children && group.children.length > 0) {
|
|
195
|
+
addSelf();
|
|
196
|
+
} else if (group) {
|
|
197
|
+
var observer = new MutationObserver((m) => {
|
|
198
|
+
if (group.children.length > 0) {
|
|
199
|
+
addSelf();
|
|
200
|
+
observer.disconnect();
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
observer.observe(group, { childList: true });
|
|
204
|
+
} else {
|
|
205
|
+
addSelf();
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
render() {
|
|
211
|
+
return (
|
|
212
|
+
<>
|
|
213
|
+
<div ref={this.container} className="error-report-container">
|
|
214
|
+
<div tooltip="Report an issue" direction="left" type="widget">
|
|
215
|
+
<div
|
|
216
|
+
className={this.menuClass}
|
|
217
|
+
id="map_error_report_button"
|
|
218
|
+
aria-label="Report an issue"
|
|
219
|
+
onClick={this.openMenu.bind(this)}
|
|
220
|
+
onKeyDown={(e) => {
|
|
221
|
+
if (
|
|
222
|
+
!e.altKey &&
|
|
223
|
+
e.code !== 'Tab' &&
|
|
224
|
+
!e.ctrlKey &&
|
|
225
|
+
e.code !== 'Delete' &&
|
|
226
|
+
!e.shiftKey &&
|
|
227
|
+
!e.code.startsWith('F')
|
|
228
|
+
) {
|
|
229
|
+
this.openMenu(this);
|
|
230
|
+
}
|
|
231
|
+
}}
|
|
232
|
+
tabIndex="0"
|
|
233
|
+
role="button"
|
|
234
|
+
></div>
|
|
235
|
+
</div>
|
|
236
|
+
<div className="right-panel">
|
|
237
|
+
<div className="right-panel-header">
|
|
238
|
+
<span>Report an issue</span>
|
|
239
|
+
<span
|
|
240
|
+
className="map-menu-icon esri-icon-close"
|
|
241
|
+
onClick={this.openMenu.bind(this)}
|
|
242
|
+
onKeyDown={(e) => {
|
|
243
|
+
if (
|
|
244
|
+
!e.altKey &&
|
|
245
|
+
e.code !== 'Tab' &&
|
|
246
|
+
!e.ctrlKey &&
|
|
247
|
+
e.code !== 'Delete' &&
|
|
248
|
+
!e.shiftKey &&
|
|
249
|
+
!e.code.startsWith('F')
|
|
250
|
+
) {
|
|
251
|
+
this.openMenu(this);
|
|
252
|
+
}
|
|
253
|
+
}}
|
|
254
|
+
tabIndex="0"
|
|
255
|
+
role="button"
|
|
256
|
+
></span>
|
|
257
|
+
</div>
|
|
258
|
+
<div className="right-panel-content">
|
|
259
|
+
<div className="error-report-panel">
|
|
260
|
+
<div className="error-report-instructions">
|
|
261
|
+
{this.state.instructionsText}
|
|
262
|
+
</div>
|
|
263
|
+
<button
|
|
264
|
+
className="error-report-button"
|
|
265
|
+
disabled={!this.state.latlong}
|
|
266
|
+
onClick={this.serviceDeskRedirect.bind(this)}
|
|
267
|
+
>
|
|
268
|
+
Service desk
|
|
269
|
+
</button>
|
|
270
|
+
{this.state.latlong && (
|
|
271
|
+
<>
|
|
272
|
+
<h3 className="error-report-coords-heading">Coordinates</h3>
|
|
273
|
+
<div className="error-report-coords">
|
|
274
|
+
Lat {this.state.latlong.x} Lon {this.state.latlong.y}
|
|
275
|
+
</div>
|
|
276
|
+
</>
|
|
277
|
+
)}
|
|
278
|
+
{this.state.datasets && this.state.datasets.length > 0 && (
|
|
279
|
+
<>
|
|
280
|
+
<div className="error-report-datasets-title">
|
|
281
|
+
Active datasets
|
|
282
|
+
</div>
|
|
283
|
+
<ul className="error-report-datasets">
|
|
284
|
+
{this.state.datasets.map((d, i) => (
|
|
285
|
+
<li key={i}>{d}</li>
|
|
286
|
+
))}
|
|
287
|
+
</ul>
|
|
288
|
+
</>
|
|
289
|
+
)}
|
|
290
|
+
</div>
|
|
291
|
+
</div>
|
|
292
|
+
</div>
|
|
293
|
+
</div>
|
|
294
|
+
</>
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export default ErrorReport;
|
|
@@ -30,6 +30,7 @@ import PanWidget from './PanWidget';
|
|
|
30
30
|
import BookmarkWidget from './BookmarkWidget';
|
|
31
31
|
import LoadingSpinner from './LoadingSpinner';
|
|
32
32
|
import UploadWidget from './UploadWidget';
|
|
33
|
+
import ErrorReportWidget from './ErrorReportWidget';
|
|
33
34
|
import { injectLazyLibs } from '@plone/volto/helpers/Loadable';
|
|
34
35
|
import { getTaxonomy } from '@eeacms/volto-taxonomy/actions';
|
|
35
36
|
import { fetchCatalogApiDates } from '../../actions';
|
|
@@ -1016,6 +1017,10 @@ class MapViewer extends React.Component {
|
|
|
1016
1017
|
/>
|
|
1017
1018
|
);
|
|
1018
1019
|
}
|
|
1020
|
+
renderErrorReport() {
|
|
1021
|
+
if (this.view)
|
|
1022
|
+
return <ErrorReportWidget view={this.view} mapViewer={this} />;
|
|
1023
|
+
}
|
|
1019
1024
|
/**
|
|
1020
1025
|
* This method renders the map viewer, invoking if necessary the methods
|
|
1021
1026
|
* to render the other widgets to display
|
|
@@ -1048,6 +1053,7 @@ class MapViewer extends React.Component {
|
|
|
1048
1053
|
{this.renderLoadingSpinner()}
|
|
1049
1054
|
<CheckUserID reference={this} />
|
|
1050
1055
|
{this.renderUploadService()}
|
|
1056
|
+
{this.renderErrorReport()}
|
|
1051
1057
|
</div>
|
|
1052
1058
|
</div>
|
|
1053
1059
|
);
|
|
@@ -313,6 +313,34 @@ button.upload-bookmark-button {
|
|
|
313
313
|
font-size: 30px !important;
|
|
314
314
|
}
|
|
315
315
|
|
|
316
|
+
/* Error report */
|
|
317
|
+
.error-report-button {
|
|
318
|
+
display: block;
|
|
319
|
+
width: 100%;
|
|
320
|
+
box-sizing: border-box;
|
|
321
|
+
padding: 0.75rem 1rem;
|
|
322
|
+
border: 1px solid #a0b128 !important;
|
|
323
|
+
margin: 1rem 0;
|
|
324
|
+
background-color: white !important;
|
|
325
|
+
color: #a0b128 !important;
|
|
326
|
+
cursor: pointer;
|
|
327
|
+
text-align: center;
|
|
328
|
+
transition: all 0.3s ease-out;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.error-report-button:hover {
|
|
332
|
+
border-color: #a0b128 !important;
|
|
333
|
+
background-color: #a0b128 !important;
|
|
334
|
+
color: white !important;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
.error-report-datasets-title {
|
|
338
|
+
margin-top: 1em;
|
|
339
|
+
margin-bottom: 0.5em;
|
|
340
|
+
font-size: 1.17em;
|
|
341
|
+
font-weight: bold;
|
|
342
|
+
}
|
|
343
|
+
|
|
316
344
|
body.section-map-viewer
|
|
317
345
|
#page-document.ui.container
|
|
318
346
|
.esri-widget__content--empty
|