@eeacms/volto-arcgis-block 0.1.399 → 0.1.401

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,16 @@ 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.401](https://github.com/eea/volto-arcgis-block/compare/0.1.400...0.1.401) - 29 October 2025
8
+
9
+ #### :hammer_and_wrench: Others
10
+
11
+ - (bug): HOTPSOT widget bugs corrected for sentry and loading mapviewer without downloading unecessary files if widget is not in use [Unai Bolivar - [`d83bcdf`](https://github.com/eea/volto-arcgis-block/commit/d83bcdfafe6979e012ac848362269fe23277bd5b)]
12
+ ### [0.1.400](https://github.com/eea/volto-arcgis-block/compare/0.1.399...0.1.400) - 29 October 2025
13
+
14
+ #### :hammer_and_wrench: Others
15
+
16
+ - CLMS-293307+CLMS-289791+CLMS-289790 (feat): Bookmark download/load function added [Urkorue - [`1a9888d`](https://github.com/eea/volto-arcgis-block/commit/1a9888d6163828e712d52cba52ea1d34adc74390)]
7
17
  ### [0.1.399](https://github.com/eea/volto-arcgis-block/compare/0.1.398...0.1.399) - 27 October 2025
8
18
 
9
19
  #### :hammer_and_wrench: Others
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-arcgis-block",
3
- "version": "0.1.399",
3
+ "version": "0.1.401",
4
4
  "description": "volto-arcgis-block: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: CodeSyntax",
@@ -35,6 +35,7 @@ class BookmarkWidget extends React.Component {
35
35
  this.boundLimitMaxLenth = this.limitMaxLenth.bind(this);
36
36
  this._isMounted = false;
37
37
  this._skipNextChangePersist = true;
38
+ this.fileInput = createRef();
38
39
  }
39
40
 
40
41
  loader() {
@@ -246,6 +247,18 @@ class BookmarkWidget extends React.Component {
246
247
  this.sessionBookmarks.push(bookmark);
247
248
  });
248
249
  this.Bookmarks.when(() => {
250
+ document
251
+ .querySelectorAll('.esri-bookmarks__bookmark')
252
+ .forEach((bookmark) => {
253
+ let download_button = document.createElement('button');
254
+ download_button.className = 'esri-button download-bookmark-button';
255
+ download_button.innerText = '⭳';
256
+ download_button.bookmarkName = bookmark.innerText;
257
+ download_button.addEventListener('click', (e) => {
258
+ this.downloadBookmark(e.currentTarget.bookmarkName);
259
+ });
260
+ bookmark.insertBefore(download_button, bookmark.childNodes[2]);
261
+ });
249
262
  this.arcgisEventHandles.push(
250
263
  this.Bookmarks.bookmarks.on('change', (e) => {
251
264
  if (!this._isMounted) return;
@@ -312,6 +325,28 @@ class BookmarkWidget extends React.Component {
312
325
  ) {
313
326
  this.sessionBookmarkHotspot.splice(index, 1);
314
327
  }
328
+ if (this.sessionBookmarks.length === 0) {
329
+ if (this.userID !== null) {
330
+ const storageKey = 'user_' + this.userID;
331
+ let userObj;
332
+ try {
333
+ userObj =
334
+ JSON.parse(localStorage.getItem(storageKey)) || {};
335
+ } catch (e) {
336
+ userObj = {};
337
+ }
338
+ if (userObj.bookmarks) {
339
+ userObj.bookmarks = {};
340
+ }
341
+ localStorage.setItem(storageKey, JSON.stringify(userObj));
342
+ try {
343
+ localStorage.setItem(
344
+ storageKey + '_bookmarks_backup',
345
+ {},
346
+ );
347
+ } catch (e) {}
348
+ }
349
+ }
315
350
  shouldUpdate = true;
316
351
  break;
317
352
  }
@@ -769,6 +804,20 @@ class BookmarkWidget extends React.Component {
769
804
  );
770
805
  });
771
806
  });
807
+ document
808
+ .querySelectorAll('.esri-bookmarks__bookmark')
809
+ .forEach((bookmark) => {
810
+ if (bookmark.childNodes.length < 4) {
811
+ let download_button = document.createElement('button');
812
+ download_button.className = 'esri-button download-bookmark-button';
813
+ download_button.innerText = '⭳';
814
+ download_button.bookmarkName = bookmark.innerText;
815
+ download_button.addEventListener('click', (e) => {
816
+ this.downloadBookmark(e.currentTarget.bookmarkName);
817
+ });
818
+ bookmark.insertBefore(download_button, bookmark.childNodes[2]);
819
+ }
820
+ });
772
821
  }
773
822
  componentWillUnmount() {
774
823
  this._isMounted = false;
@@ -951,6 +1000,122 @@ class BookmarkWidget extends React.Component {
951
1000
  );
952
1001
  } catch (e) {}
953
1002
  }
1003
+ downloadBookmark(name) {
1004
+ if (this.userID == null) return;
1005
+ const storageKey = 'user_' + this.userID;
1006
+ let userObj;
1007
+ try {
1008
+ userObj = JSON.parse(localStorage.getItem(storageKey)) || {};
1009
+ } catch (e) {
1010
+ userObj = {};
1011
+ }
1012
+ let bookmarks =
1013
+ userObj && userObj.bookmarks && typeof userObj.bookmarks === 'object'
1014
+ ? userObj.bookmarks
1015
+ : null;
1016
+ if (!bookmarks) {
1017
+ try {
1018
+ bookmarks = JSON.parse(
1019
+ localStorage.getItem(storageKey + '_bookmarks_backup'),
1020
+ );
1021
+ } catch (e) {
1022
+ return;
1023
+ }
1024
+ }
1025
+ if (!bookmarks) return;
1026
+ let index = 0;
1027
+ for (index; index < bookmarks.items.length; index++) {
1028
+ if (bookmarks.items[index].name === name) {
1029
+ break;
1030
+ }
1031
+ }
1032
+ let selectedBookmark = {
1033
+ items: Array.isArray(bookmarks.items) ? bookmarks.items[index] : [],
1034
+ layers: Array.isArray(bookmarks.layers) ? bookmarks.layers[index] : [],
1035
+ opacity: Array.isArray(bookmarks.opacity) ? bookmarks.opacity[index] : [],
1036
+ visible: Array.isArray(bookmarks.visible) ? bookmarks.visible[index] : [],
1037
+ hotspot: Array.isArray(bookmarks.hotspot) ? bookmarks.hotspot[index] : [],
1038
+ selectedHotspotFilter:
1039
+ bookmarks.selectedHotspotFilter != null
1040
+ ? bookmarks.selectedHotspotFilter
1041
+ : null,
1042
+ };
1043
+ let filename = 'bookmark_' + selectedBookmark.items.name;
1044
+ //const JSONToFile = (userObj, filename) => {
1045
+ const blob = new Blob([JSON.stringify(selectedBookmark)], {
1046
+ type: 'application/json',
1047
+ });
1048
+ const url = URL.createObjectURL(blob);
1049
+ const a = document.createElement('a');
1050
+ a.href = url;
1051
+ a.download = `${filename}.json`;
1052
+ a.click();
1053
+ URL.revokeObjectURL(url);
1054
+ }
1055
+ handleUploadClick(event) {
1056
+ event.preventDefault();
1057
+ this.fileInput.current.click();
1058
+ }
1059
+ handleFileUpload(e) {
1060
+ const file = e.target.files[0];
1061
+ if (file) {
1062
+ if (this.userID == null) return;
1063
+ const storageKey = 'user_' + this.userID;
1064
+ let userObj;
1065
+ try {
1066
+ userObj = JSON.parse(localStorage.getItem(storageKey)) || {};
1067
+ } catch (e) {
1068
+ userObj = {};
1069
+ }
1070
+ if (userObj.bookmarks == null) {
1071
+ userObj.bookmarks = {
1072
+ items: [],
1073
+ layers: [],
1074
+ opacity: [],
1075
+ visible: [],
1076
+ hotspot: [],
1077
+ selectedHotspotFilter: null,
1078
+ };
1079
+ }
1080
+ const reader = new FileReader();
1081
+ reader.onload = (e) => {
1082
+ try {
1083
+ const data = JSON.parse(e.target.result);
1084
+ userObj.bookmarks.items.push(data.items);
1085
+ userObj.bookmarks.layers.push(data.layers);
1086
+ userObj.bookmarks.opacity.push(data.opacity);
1087
+ userObj.bookmarks.visible.push(data.visible);
1088
+ userObj.bookmarks.hotspot.push(data.hotspot);
1089
+ userObj.bookmarks.selectedHotspotFilter = data.selectedHotspotFilter;
1090
+ } catch (e) {}
1091
+ localStorage.setItem(storageKey, JSON.stringify(userObj));
1092
+ try {
1093
+ localStorage.setItem(
1094
+ storageKey + '_bookmarks_backup',
1095
+ JSON.stringify(userObj.bookmarks),
1096
+ );
1097
+ } catch (e) {}
1098
+ this.loadBookmarksToWidget();
1099
+ this.Bookmarks.bookmarks = this.sessionBookmarks.map((bm) => {
1100
+ if (bm.extent) {
1101
+ const { extent, ...rest } = bm;
1102
+ let geometry;
1103
+ if (extent && typeof extent === 'object') {
1104
+ geometry = extent.type ? extent : new Extent(extent);
1105
+ }
1106
+ return {
1107
+ ...rest,
1108
+ viewpoint: {
1109
+ targetGeometry: geometry,
1110
+ },
1111
+ };
1112
+ }
1113
+ return bm;
1114
+ });
1115
+ };
1116
+ reader.readAsText(file);
1117
+ }
1118
+ }
954
1119
  /**
955
1120
  * This method renders the component
956
1121
  * @returns jsx
@@ -1005,6 +1170,25 @@ class BookmarkWidget extends React.Component {
1005
1170
  </div>
1006
1171
  <div className="right-panel-content">
1007
1172
  <div className="bookmark-panel"></div>
1173
+ <input
1174
+ type="file"
1175
+ name="file"
1176
+ id="inFile"
1177
+ ref={this.fileInput}
1178
+ style={{ display: 'none' }}
1179
+ onChange={(e) => {
1180
+ this.handleFileUpload(e);
1181
+ }}
1182
+ />
1183
+ <button
1184
+ className="esri-button upload-bookmark-button"
1185
+ onClick={(e) => {
1186
+ this.handleUploadClick(e);
1187
+ }}
1188
+ type="submit"
1189
+ >
1190
+ Upload file
1191
+ </button>
1008
1192
  </div>
1009
1193
  </div>
1010
1194
  </div>
@@ -75,14 +75,37 @@ class HotspotWidget extends React.Component {
75
75
  this.props.urls.klc_bbox;
76
76
  return esriRequest(url, {
77
77
  responseType: 'json',
78
- }).then((response) => {
79
- const responseJSON = response.data;
80
- this.dataBBox = responseJSON;
81
- });
78
+ })
79
+ .then((response) => {
80
+ const responseJSON = response.data;
81
+ if (Array.isArray(responseJSON)) {
82
+ this.dataBBox = responseJSON;
83
+ } else {
84
+ this.dataBBox = [];
85
+ }
86
+ })
87
+ .catch(async () => {
88
+ try {
89
+ const res = await fetch(url, { credentials: 'same-origin' });
90
+ const text = await res.text();
91
+ const start = text.indexOf('[');
92
+ const end = text.lastIndexOf(']');
93
+ if (start !== -1 && end !== -1) {
94
+ const json = JSON.parse(text.substring(start, end + 1));
95
+ this.dataBBox = Array.isArray(json) ? json : [];
96
+ } else {
97
+ this.dataBBox = [];
98
+ }
99
+ } catch (_) {
100
+ this.dataBBox = [];
101
+ }
102
+ });
82
103
  };
83
104
 
84
105
  setBBoxCoordinates = (data) => {
106
+ if (!data || !Array.isArray(data)) return;
85
107
  let klc_array = data.find((e) => e.klc_code === this.dataKlc_code);
108
+ if (!klc_array || !klc_array.bbox) return;
86
109
  let klc_bbox_coordinates = klc_array.bbox.split(',');
87
110
  let xmin_ymin = klc_bbox_coordinates[0].split(' ');
88
111
  let xmax_ymax = klc_bbox_coordinates[1].split(' ');
@@ -92,10 +115,6 @@ class HotspotWidget extends React.Component {
92
115
  ymin: this.mapCfg.geometryZoomIn.ymin,
93
116
  xmax: this.mapCfg.geometryZoomIn.xmax,
94
117
  ymax: this.mapCfg.geometryZoomIn.ymax,
95
- // xmin: -200,
96
- // ymin: -85,
97
- // xmax: 200,
98
- // ymax: 85,
99
118
  spatialReference: 4326,
100
119
  });
101
120
  this.props.view.constraints.geometry = constraintExtent;
@@ -205,19 +224,15 @@ class HotspotWidget extends React.Component {
205
224
  typeLegend,
206
225
  selectBoxTime,
207
226
  ) {
208
- //sweep the old filtered data
227
+ if (!bboxData || !Array.isArray(bboxData)) return;
209
228
  if (filteredLayersData[typeLegend] !== undefined) {
210
229
  delete filteredLayersData[typeLegend];
211
230
  }
212
- //Find the bbox data for the chosen region
213
231
  let klc_array = bboxData.find((e) => e.klc_code === this.dataKlc_code);
214
-
215
- //Parse the bbox data into finer detail
232
+ if (!klc_array || !klc_array.bbox) return;
216
233
  let klc_bbox_coordinates = klc_array.bbox.split(',');
217
234
  let xmin_ymin = klc_bbox_coordinates[0].split(' ');
218
235
  let xmax_ymax = klc_bbox_coordinates[1].split(' ');
219
-
220
- //Add the filtered data to the filteredLayersData object
221
236
  filteredLayersData[typeLegend] = {
222
237
  klc_code: this.dataKlc_code,
223
238
  year: selectBoxTime,
@@ -242,7 +257,9 @@ class HotspotWidget extends React.Component {
242
257
  this.props.hotspotData && this.props.hotspotData['filteredLayers']
243
258
  ? Object.keys(this.props.hotspotData['filteredLayers'])
244
259
  : [];
245
- let filteredLayersData = this.props.hotspotData['filteredLayerData'] || [];
260
+ let filteredLayersData =
261
+ (this.props.hotspotData && this.props.hotspotData['filteredLayerData']) ||
262
+ [];
246
263
  let layersToAdd = {};
247
264
  let bookmarkHotspotFilter = JSON.parse(
248
265
  localStorage.getItem('bookmarkHotspotFilter'),
@@ -441,9 +458,14 @@ class HotspotWidget extends React.Component {
441
458
  }
442
459
 
443
460
  filteredLayersToHotspotData(layerIds, layersData) {
444
- let updatedFilteredLayers = this.props.hotspotData['filteredLayers'] || {};
445
- let filteredLayersData = this.props.hotspotData['filteredLayersData'] || {};
446
- let newHotspotData = this.props.hotspotData;
461
+ let updatedFilteredLayers =
462
+ (this.props.hotspotData && this.props.hotspotData['filteredLayers']) ||
463
+ {};
464
+ let filteredLayersData =
465
+ (this.props.hotspotData &&
466
+ this.props.hotspotData['filteredLayersData']) ||
467
+ {};
468
+ let newHotspotData = this.props.hotspotData || {};
447
469
  layerIds.forEach((layerId) => {
448
470
  let layer = Object.entries(this.layers).find(
449
471
  ([key, value]) => key === layerId,
@@ -536,7 +558,10 @@ class HotspotWidget extends React.Component {
536
558
 
537
559
  renderApplyFilterButton() {
538
560
  let typeFilter = [];
539
- const activeLayers = Object.keys(this.props.hotspotData['activeLayers']);
561
+ const activeLayers =
562
+ this.props.hotspotData && this.props.hotspotData['activeLayers']
563
+ ? Object.keys(this.props.hotspotData['activeLayers'])
564
+ : [];
540
565
 
541
566
  if (
542
567
  this.container.current.querySelector('.presentLandCoverContainer').style
@@ -289,6 +289,27 @@
289
289
  color: white !important;
290
290
  }
291
291
 
292
+ .upload-bookmark-button {
293
+ width: 16rem !important;
294
+ justify-content: start !important;
295
+ border-color: #a0b128 !important;
296
+ margin-left: 0.65rem;
297
+ background-color: white !important;
298
+ color: #a0b128 !important;
299
+ }
300
+
301
+ .upload-bookmark-button:hover {
302
+ background-color: #a0b128 !important;
303
+ color: white !important;
304
+ }
305
+
306
+ .download-bookmark-button {
307
+ width: 25px !important;
308
+ height: 30px !important;
309
+ border-color: white !important;
310
+ font-size: 30px !important;
311
+ }
312
+
292
313
  body.section-map-viewer
293
314
  #page-document.ui.container
294
315
  .esri-widget__content--empty