@eeacms/volto-arcgis-block 0.1.478 → 0.1.479

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,19 @@ 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.479](https://github.com/eea/volto-arcgis-block/compare/0.1.478...0.1.479) - 8 September 2026
8
+
9
+ #### :hammer_and_wrench: Others
10
+
11
+ - (lint): lint and prettified [Unai Bolivar - [`89001ca`](https://github.com/eea/volto-arcgis-block/commit/89001ca4c7c5bad39c2eeaed0ffd03ecd3fcfbe1)]
12
+ - (lint): lint and prettified [Unai Bolivar - [`f3a2e36`](https://github.com/eea/volto-arcgis-block/commit/f3a2e3602eba3e5279d2a2e080cf8f52cc26690d)]
13
+ - (lint): lint and prettified [Unai Bolivar - [`3ea38aa`](https://github.com/eea/volto-arcgis-block/commit/3ea38aa798a8ac6df3db03651f8f9e02c1b5d9a5)]
14
+ - (lint): lint and prettified [Unai Bolivar - [`5d96946`](https://github.com/eea/volto-arcgis-block/commit/5d969465ba1e55a1048c647d121d82081677daa3)]
15
+ - (bug): finished implementing changes to hot spot widget [Unai Bolivar - [`2bf933b`](https://github.com/eea/volto-arcgis-block/commit/2bf933bc2e0ef57c0df2308ec90c903f643ee27f)]
16
+ - (bug): switched to drop down for the date selection in hot spot widget [Unai Bolivar - [`5c83990`](https://github.com/eea/volto-arcgis-block/commit/5c839901bbb0637a716aaac4f48011622b5325ca)]
17
+ - (bug): improve hotspot widget behavior for new json data. create a reference land cover selection box only for new data [Unai Bolivar - [`d73f58f`](https://github.com/eea/volto-arcgis-block/commit/d73f58ff1addcb06ac61e8947e64e34a2bc29647)]
18
+ - (bug): improve hotspot widget behavior for new json data [Unai Bolivar - [`643c95d`](https://github.com/eea/volto-arcgis-block/commit/643c95d93f375b90c39e16774b866daffa5f11aa)]
19
+ - (bug): improve hotspot server calls to avoid sql injection rejection warning from servers [Unai Bolivar - [`4c76cbf`](https://github.com/eea/volto-arcgis-block/commit/4c76cbf1d78ac2db6225a1b001e02badbd852133)]
7
20
  ### [0.1.478](https://github.com/eea/volto-arcgis-block/compare/0.1.477...0.1.478) - 3 September 2026
8
21
 
9
22
  #### :house: Internal changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-arcgis-block",
3
- "version": "0.1.478",
3
+ "version": "0.1.479",
4
4
  "description": "volto-arcgis-block: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: CodeSyntax",
@@ -18,8 +18,10 @@ class HotspotWidget extends React.Component {
18
18
  showMapMenu: false,
19
19
  activeLayers: {},
20
20
  selectedArea: null,
21
+ referenceLcYear: null,
21
22
  lcYear: null,
22
23
  lccYear: null,
24
+ hasMultipleLcDates: false,
23
25
  activeLayersArray: [],
24
26
  };
25
27
  this.menuClass =
@@ -46,8 +48,10 @@ class HotspotWidget extends React.Component {
46
48
  this.handleApplyFilter = this.handleApplyFilter.bind(this);
47
49
  this.filteredLayersToHotspotData =
48
50
  this.filteredLayersToHotspotData.bind(this);
51
+ this.resetHotspotWidgetFilters = this.resetHotspotWidgetFilters.bind(this);
49
52
  this.mapCfg = this.props.mapCfg;
50
53
  this.selectedArea = null;
54
+ this.referenceLcYear = null;
51
55
  this.lcYear = null;
52
56
  this.lccYear = null;
53
57
  this.urls = this.props.urls;
@@ -56,6 +60,235 @@ class HotspotWidget extends React.Component {
56
60
  this._isMounted = false;
57
61
  }
58
62
 
63
+ parseKeymapInfo(rawKeymapInfo) {
64
+ if (typeof rawKeymapInfo === 'string') {
65
+ try {
66
+ return JSON.parse(rawKeymapInfo) || {};
67
+ } catch (e) {
68
+ return {};
69
+ }
70
+ }
71
+ if (rawKeymapInfo && typeof rawKeymapInfo === 'object') {
72
+ return rawKeymapInfo;
73
+ }
74
+ return {};
75
+ }
76
+
77
+ getDateOptionsForNode(node) {
78
+ const keyMapInfoObj = this.parseKeymapInfo(node?.keymap_info);
79
+ let lccDateList = [];
80
+ let lcDateList = [];
81
+ let lccDatesByLcYear = {};
82
+
83
+ if (Array.isArray(keyMapInfoObj.dates)) {
84
+ keyMapInfoObj.dates.forEach((entry) => {
85
+ const lccDate = Number(
86
+ entry && typeof entry === 'object' ? entry?.date : entry,
87
+ );
88
+ const lcDate = Number(
89
+ entry && typeof entry === 'object' ? entry?.lc_date : undefined,
90
+ );
91
+ if (Number.isFinite(lccDate)) {
92
+ lccDateList.push(lccDate);
93
+ }
94
+ if (Number.isFinite(lcDate)) {
95
+ lcDateList.push(lcDate);
96
+ if (!lccDatesByLcYear[lcDate]) {
97
+ lccDatesByLcYear[lcDate] = [];
98
+ }
99
+ if (Number.isFinite(lccDate)) {
100
+ lccDatesByLcYear[lcDate].push(lccDate);
101
+ }
102
+ }
103
+ });
104
+ }
105
+
106
+ if (Array.isArray(keyMapInfoObj.multiple_lc_dates)) {
107
+ lcDateList = lcDateList.concat(
108
+ keyMapInfoObj.multiple_lc_dates
109
+ .map((yearEntry) =>
110
+ Number(
111
+ yearEntry && typeof yearEntry === 'object'
112
+ ? yearEntry?.date
113
+ : yearEntry,
114
+ ),
115
+ )
116
+ .filter((year) => Number.isFinite(year)),
117
+ );
118
+ }
119
+
120
+ const dynamicYearValues = Object.keys(keyMapInfoObj)
121
+ .filter((key) => /^year\d+$/.test(key))
122
+ .map((key) => Number(keyMapInfoObj[key]))
123
+ .filter((year) => Number.isFinite(year));
124
+ if (dynamicYearValues.length) {
125
+ lccDateList = lccDateList.concat(dynamicYearValues);
126
+ }
127
+
128
+ const presentLcYearFromKeymap = Number(keyMapInfoObj.year_present_lc);
129
+ if (Number.isFinite(presentLcYearFromKeymap)) {
130
+ lcDateList.push(presentLcYearFromKeymap);
131
+ }
132
+
133
+ if (!lccDateList.length && Number.isFinite(Number(node?.lcc_year))) {
134
+ lccDateList = [Number(node?.lcc_year)];
135
+ }
136
+ if (!lcDateList.length && Number.isFinite(Number(node?.present_lc_year))) {
137
+ lcDateList = [Number(node?.present_lc_year)];
138
+ }
139
+
140
+ lccDateList = Array.from(new Set(lccDateList)).sort((a, b) => a - b);
141
+ lcDateList = Array.from(new Set(lcDateList)).sort((a, b) => a - b);
142
+
143
+ Object.keys(lccDatesByLcYear).forEach((lcDateKey) => {
144
+ lccDatesByLcYear[lcDateKey] = Array.from(
145
+ new Set(lccDatesByLcYear[lcDateKey]),
146
+ ).sort((a, b) => a - b);
147
+ });
148
+
149
+ return {
150
+ keyMapInfoObj,
151
+ lccDateList,
152
+ lcDateList,
153
+ lccDatesByLcYear,
154
+ };
155
+ }
156
+
157
+ getSelectedNodeByArea(selectedArea) {
158
+ if (!selectedArea || !Array.isArray(this.dataJSONNames)) {
159
+ return null;
160
+ }
161
+
162
+ return this.dataJSONNames.find(
163
+ (entry) => entry?.node?.klc_name === selectedArea,
164
+ )?.node;
165
+ }
166
+
167
+ isReferenceSelectionKlcCode(klcCode) {
168
+ return klcCode === 'CAF_02' || klcCode === 'CAF_05';
169
+ }
170
+
171
+ getReferenceLcYearSelection(lcDateList) {
172
+ const selectedReferenceLcYear = Number(this.state.referenceLcYear);
173
+ if (
174
+ Number.isFinite(selectedReferenceLcYear) &&
175
+ lcDateList.includes(selectedReferenceLcYear)
176
+ ) {
177
+ return selectedReferenceLcYear;
178
+ }
179
+ return null;
180
+ }
181
+
182
+ setPresentLandCoverVisibility(shouldShow) {
183
+ const presentLandCoverContainer = this.container.current?.querySelector(
184
+ '.presentLandCoverContainer',
185
+ );
186
+ if (presentLandCoverContainer) {
187
+ presentLandCoverContainer.style.display = shouldShow ? 'block' : 'none';
188
+ }
189
+ }
190
+
191
+ isHotspotLayerKey(layerKey) {
192
+ if (typeof layerKey !== 'string') return false;
193
+ return (
194
+ layerKey.includes('all_present_lc_') ||
195
+ layerKey.includes('all_lcc_') ||
196
+ layerKey.includes('cop_klc') ||
197
+ layerKey.includes('protected_areas') ||
198
+ layerKey.endsWith('_filter')
199
+ );
200
+ }
201
+
202
+ removeLayerFromMap(layer) {
203
+ if (!layer || !this.props.map) return;
204
+ try {
205
+ this.props.map.remove(layer);
206
+ } catch (e) {}
207
+ if (layer.visible !== undefined) {
208
+ layer.visible = false;
209
+ }
210
+ }
211
+
212
+ clearHotspotLayersFromMap() {
213
+ const layerRefs = [];
214
+ if (this.layers && typeof this.layers === 'object') {
215
+ Object.keys(this.layers).forEach((layerKey) => {
216
+ if (this.isHotspotLayerKey(layerKey) && this.layers[layerKey]) {
217
+ layerRefs.push(this.layers[layerKey]);
218
+ }
219
+ });
220
+ }
221
+
222
+ const hotspotData = this.props.hotspotData || {};
223
+ const activeLayers = hotspotData.activeLayers || {};
224
+ const filteredLayers = hotspotData.filteredLayers || {};
225
+
226
+ Object.keys(activeLayers).forEach((layerKey) => {
227
+ if (this.isHotspotLayerKey(layerKey) && activeLayers[layerKey]) {
228
+ layerRefs.push(activeLayers[layerKey]);
229
+ }
230
+ });
231
+ Object.keys(filteredLayers).forEach((layerKey) => {
232
+ if (this.isHotspotLayerKey(layerKey) && filteredLayers[layerKey]) {
233
+ layerRefs.push(filteredLayers[layerKey]);
234
+ }
235
+ });
236
+
237
+ Array.from(new Set(layerRefs)).forEach((layer) => {
238
+ this.removeLayerFromMap(layer);
239
+ });
240
+ }
241
+
242
+ resetHotspotViewState() {
243
+ if (this.props.view && this.props.view.popup) {
244
+ this.props.view.popup.close();
245
+ }
246
+ if (this.props.view && this.props.view.graphics) {
247
+ this.props.view.graphics.removeAll();
248
+ }
249
+ }
250
+
251
+ resetHotspotWidgetFilters() {
252
+ const selectBox = document.getElementById('select-klc-area');
253
+ const selectBoxLcTime = document.getElementById('select-klc-lcTime');
254
+ const selectBoxLccTime = document.getElementById('select-klc-lccTime');
255
+
256
+ if (selectBox) {
257
+ selectBox.value = 'default';
258
+ }
259
+
260
+ if (selectBoxLcTime) {
261
+ this.removeOptions(selectBoxLcTime);
262
+ selectBoxLcTime.options.add(
263
+ new Option('Select a year', 'default', true, true),
264
+ );
265
+ selectBoxLcTime.options[0].disabled = true;
266
+ }
267
+
268
+ if (selectBoxLccTime) {
269
+ this.removeOptions(selectBoxLccTime);
270
+ selectBoxLccTime.options.add(
271
+ new Option('Select a year', 'default', true, true),
272
+ );
273
+ selectBoxLccTime.options[0].disabled = true;
274
+ }
275
+
276
+ this.setPresentLandCoverVisibility(false);
277
+
278
+ this.selectedArea = null;
279
+ this.referenceLcYear = null;
280
+ this.lcYear = null;
281
+ this.lccYear = null;
282
+
283
+ this.setState({
284
+ selectedArea: null,
285
+ referenceLcYear: null,
286
+ lcYear: null,
287
+ lccYear: null,
288
+ hasMultipleLcDates: false,
289
+ });
290
+ }
291
+
59
292
  loader() {
60
293
  return loadModules([
61
294
  'esri/layers/WMSLayer',
@@ -185,8 +418,7 @@ class HotspotWidget extends React.Component {
185
418
  }
186
419
 
187
420
  buildCqlFilter(klcCode, date) {
188
- const baseFilter =
189
- "klc_code LIKE '" + klcCode + "' AND in_pa LIKE 'not_defined'";
421
+ const baseFilter = "klc_code='" + klcCode + "' AND in_pa='not_defined'";
190
422
  if (!Number.isFinite(Number(date))) {
191
423
  return baseFilter;
192
424
  }
@@ -208,38 +440,13 @@ class HotspotWidget extends React.Component {
208
440
  };
209
441
  }
210
442
 
211
- resolveLccDateOptions(
212
- klcCode,
213
- selectedLcYear,
214
- lccDatesByLcYear,
215
- lccDateList,
216
- ) {
217
- const klcLcDateMap = {
218
- CAF_02: {
219
- 2016: [2000, 2019],
220
- 2019: [2024],
221
- },
222
- CAF_05: {
223
- 2015: [2000, 2019],
224
- 2019: [2024],
225
- },
226
- };
227
-
228
- const mappedByKlc = klcLcDateMap[klcCode] || null;
229
- if (mappedByKlc && Number.isFinite(Number(selectedLcYear))) {
230
- const mapped = mappedByKlc[Number(selectedLcYear)];
231
- if (Array.isArray(mapped) && mapped.length) {
232
- return Array.from(new Set(mapped)).sort((a, b) => a - b);
233
- }
234
- }
235
-
443
+ getLccDateOptionsFromData(selectedLcYear, lccDatesByLcYear, lccDateList) {
236
444
  const mappedByData = Number.isFinite(Number(selectedLcYear))
237
445
  ? lccDatesByLcYear[Number(selectedLcYear)]
238
446
  : null;
239
447
  if (Array.isArray(mappedByData) && mappedByData.length) {
240
448
  return mappedByData;
241
449
  }
242
-
243
450
  return lccDateList;
244
451
  }
245
452
 
@@ -358,6 +565,11 @@ class HotspotWidget extends React.Component {
358
565
  }
359
566
 
360
567
  async handleApplyFilter(typeFilter) {
568
+ await Promise.all([this.getLayerParameters(), this.getBBoxData()]);
569
+ this.clearHotspotLayersFromMap();
570
+ this.resetHotspotViewState();
571
+ this.layerModelInit();
572
+
361
573
  let typeLegend;
362
574
  let title;
363
575
  let activeLayers =
@@ -495,7 +707,7 @@ class HotspotWidget extends React.Component {
495
707
  } else {
496
708
  this.esriLayer_klc.customLayerParameters =
497
709
  this.buildWmsCustomLayerParameters(
498
- "klc_code LIKE '" + this.dataKlc_code + "'",
710
+ "klc_code='" + this.dataKlc_code + "'",
499
711
  );
500
712
  }
501
713
  filterLayer = this.esriLayer_klc;
@@ -519,7 +731,7 @@ class HotspotWidget extends React.Component {
519
731
  } else {
520
732
  this.esriLayer_pa.customLayerParameters =
521
733
  this.buildWmsCustomLayerParameters(
522
- "klc_code LIKE '" + this.dataKlc_code + "'",
734
+ "klc_code='" + this.dataKlc_code + "'",
523
735
  );
524
736
  }
525
737
  filterLayer = this.esriLayer_pa;
@@ -537,8 +749,6 @@ class HotspotWidget extends React.Component {
537
749
  if (layerId !== undefined) this.layers[layerId].visible = false;
538
750
  let layer = this.props.map.findLayerById(layerId);
539
751
  if (layer !== undefined) {
540
- layer.clear();
541
- layer.destroy();
542
752
  this.props.map.remove(layer);
543
753
  }
544
754
  });
@@ -549,8 +759,6 @@ class HotspotWidget extends React.Component {
549
759
  if (layerId !== undefined) this.layers[layerId].visible = false;
550
760
  let layer = this.props.map.findLayerById(layerId);
551
761
  if (layer !== undefined) {
552
- layer.clear();
553
- layer.destroy();
554
762
  this.props.map.remove(layer);
555
763
  }
556
764
  });
@@ -628,6 +836,7 @@ class HotspotWidget extends React.Component {
628
836
 
629
837
  openMenu() {
630
838
  if (this.state.showMapMenu) {
839
+ this.resetHotspotWidgetFilters();
631
840
  this.props.mapViewer.setActiveWidget();
632
841
  this.container.current.querySelector('.right-panel').style.display =
633
842
  'none';
@@ -660,7 +869,7 @@ class HotspotWidget extends React.Component {
660
869
  const url =
661
870
  window.location.href.replace(window.location.pathname.substring(3), '') +
662
871
  this.props.urls.all_geo_klc;
663
- fetch(url)
872
+ return fetch(url)
664
873
  .then((data) => {
665
874
  if (data.status === 200) {
666
875
  return data.json();
@@ -680,18 +889,24 @@ class HotspotWidget extends React.Component {
680
889
  this.props.hotspotData && this.props.hotspotData['activeLayers']
681
890
  ? Object.keys(this.props.hotspotData['activeLayers'])
682
891
  : [];
892
+ const hasActivePresentLcLayer = activeLayers.some(
893
+ (layer) =>
894
+ layer.includes('all_present_lc_a_pol') ||
895
+ layer.includes('all_present_lc_b_pol') ||
896
+ layer.includes('lc_filter'),
897
+ );
898
+ const hasActiveLccLayer = activeLayers.some(
899
+ (layer) =>
900
+ layer.includes('all_lcc_a_pol') ||
901
+ layer.includes('all_lcc_b_pol') ||
902
+ layer.includes('lcc_filter'),
903
+ );
683
904
 
684
- if (
685
- this.container.current.querySelector('.presentLandCoverContainer').style
686
- .display === 'block'
687
- ) {
905
+ if (hasActivePresentLcLayer) {
688
906
  typeFilter.push('lc');
689
907
  }
690
908
 
691
- if (
692
- this.container.current.querySelector('.landCoverChangeContainer').style
693
- .display === 'block'
694
- ) {
909
+ if (hasActiveLccLayer) {
695
910
  typeFilter.push('lcc');
696
911
  }
697
912
  activeLayers.forEach((layer) => {
@@ -789,22 +1004,16 @@ class HotspotWidget extends React.Component {
789
1004
  selectBoxLccTime = document.getElementById('select-klc-lccTime');
790
1005
  selectBoxLcTime = document.getElementById('select-klc-lcTime');
791
1006
 
1007
+ let hasMultipleLcDatesForSelection = false;
1008
+ let hasSelectedAreaOption = false;
1009
+
792
1010
  //this.selectedArea = selectedOption;
793
1011
 
794
1012
  for (let i = 0; i < data.length; i++) {
795
1013
  var option = data[i].node.klc_name;
796
1014
 
797
1015
  let rawKeymapInfo = data[i].node.keymap_info;
798
- let keyMapInfoObj = {};
799
- if (typeof rawKeymapInfo === 'string') {
800
- try {
801
- keyMapInfoObj = JSON.parse(rawKeymapInfo) || {};
802
- } catch (e) {
803
- keyMapInfoObj = {};
804
- }
805
- } else if (rawKeymapInfo && typeof rawKeymapInfo === 'object') {
806
- keyMapInfoObj = rawKeymapInfo;
807
- }
1016
+ let keyMapInfoObj = this.parseKeymapInfo(rawKeymapInfo);
808
1017
 
809
1018
  if (keyMapInfoObj.b_classes === true) {
810
1019
  modularKLCAreas.push(option);
@@ -830,102 +1039,47 @@ class HotspotWidget extends React.Component {
830
1039
  selectBoxLccTime.options[0].disabled = true;
831
1040
  }
832
1041
 
833
- let lccDateList = [];
834
- let lcDateList = [];
835
- let lccDatesByLcYear = {};
836
-
837
- if (Array.isArray(keyMapInfoObj.dates)) {
838
- keyMapInfoObj.dates.forEach((entry) => {
839
- const lccDate = Number(
840
- entry && typeof entry === 'object' ? entry?.date : entry,
841
- );
842
- const lcDate = Number(
843
- entry && typeof entry === 'object' ? entry?.lc_date : undefined,
844
- );
845
- if (Number.isFinite(lccDate)) {
846
- lccDateList.push(lccDate);
847
- }
848
- if (Number.isFinite(lcDate)) {
849
- lcDateList.push(lcDate);
850
- if (!lccDatesByLcYear[lcDate]) {
851
- lccDatesByLcYear[lcDate] = [];
852
- }
853
- if (Number.isFinite(lccDate)) {
854
- lccDatesByLcYear[lcDate].push(lccDate);
855
- }
856
- }
857
- });
858
- }
1042
+ const { lccDateList, lcDateList, lccDatesByLcYear } =
1043
+ this.getDateOptionsForNode(data[i].node);
859
1044
 
860
- if (Array.isArray(keyMapInfoObj.multiple_lc_dates)) {
861
- lcDateList = lcDateList.concat(
862
- keyMapInfoObj.multiple_lc_dates
863
- .map((yearEntry) =>
864
- Number(
865
- yearEntry && typeof yearEntry === 'object'
866
- ? yearEntry?.date
867
- : yearEntry,
868
- ),
869
- )
870
- .filter((year) => Number.isFinite(year)),
871
- );
872
- }
873
-
874
- const dynamicYearValues = Object.keys(keyMapInfoObj)
875
- .filter((key) => /^year\d+$/.test(key))
876
- .map((key) => Number(keyMapInfoObj[key]))
877
- .filter((year) => Number.isFinite(year));
878
- if (dynamicYearValues.length) {
879
- lccDateList = lccDateList.concat(dynamicYearValues);
880
- }
881
-
882
- const presentLcYearFromKeymap = Number(keyMapInfoObj.year_present_lc);
883
- if (Number.isFinite(presentLcYearFromKeymap)) {
884
- lcDateList.push(presentLcYearFromKeymap);
885
- }
886
-
887
- if (
888
- !lccDateList.length &&
889
- Number.isFinite(Number(data[i].node.lcc_year))
890
- ) {
891
- lccDateList = [Number(data[i].node.lcc_year)];
892
- }
893
- if (
894
- !lcDateList.length &&
895
- Number.isFinite(Number(data[i].node.present_lc_year))
896
- ) {
897
- lcDateList = [Number(data[i].node.present_lc_year)];
898
- }
1045
+ const isReferenceSelectionArea = this.isReferenceSelectionKlcCode(
1046
+ data[i].node.klc_code,
1047
+ );
1048
+ const selectedReferenceLcYear = isReferenceSelectionArea
1049
+ ? this.getReferenceLcYearSelection(lcDateList)
1050
+ : null;
899
1051
 
900
- lccDateList = Array.from(new Set(lccDateList)).sort((a, b) => a - b);
901
- lcDateList = Array.from(new Set(lcDateList)).sort((a, b) => a - b);
1052
+ hasMultipleLcDatesForSelection = lcDateList.length > 1;
1053
+ hasSelectedAreaOption = true;
902
1054
 
903
- Object.keys(lccDatesByLcYear).forEach((lcDateKey) => {
904
- lccDatesByLcYear[lcDateKey] = Array.from(
905
- new Set(lccDatesByLcYear[lcDateKey]),
906
- ).sort((a, b) => a - b);
907
- });
1055
+ const lcDateOptionsToUse =
1056
+ isReferenceSelectionArea && Number.isFinite(selectedReferenceLcYear)
1057
+ ? [selectedReferenceLcYear]
1058
+ : isReferenceSelectionArea
1059
+ ? []
1060
+ : lcDateList;
908
1061
 
909
- lcDateList.forEach((element) => {
1062
+ lcDateOptionsToUse.forEach((element) => {
910
1063
  selectBoxLcTime.options.add(new Option(element, element, element));
911
1064
  });
912
1065
 
913
- if (this.state.lcYear !== null) {
914
- const hasLcYearOption = Array.from(selectBoxLcTime.options).some(
915
- (option) => option.value === this.state.lcYear,
916
- );
917
- selectBoxLcTime.value = hasLcYearOption
918
- ? this.state.lcYear
919
- : 'default';
920
- }
921
-
922
- const selectedLcYear = Number(this.state.lcYear);
923
- const lccOptionsToUse = this.resolveLccDateOptions(
924
- data[i].node.klc_code,
925
- selectedLcYear,
926
- lccDatesByLcYear,
927
- lccDateList,
928
- );
1066
+ const selectedLcYear =
1067
+ isReferenceSelectionArea && Number.isFinite(selectedReferenceLcYear)
1068
+ ? selectedReferenceLcYear
1069
+ : Number(selectBoxLcTime.value);
1070
+ const lccOptionsToUse = hasMultipleLcDatesForSelection
1071
+ ? Number.isFinite(selectedLcYear)
1072
+ ? this.getLccDateOptionsFromData(
1073
+ selectedLcYear,
1074
+ lccDatesByLcYear,
1075
+ lccDateList,
1076
+ )
1077
+ : []
1078
+ : this.getLccDateOptionsFromData(
1079
+ selectedLcYear,
1080
+ lccDatesByLcYear,
1081
+ lccDateList,
1082
+ );
929
1083
 
930
1084
  lccOptionsToUse.forEach((element) => {
931
1085
  selectBoxLccTime.options.add(new Option(element, element, element));
@@ -944,12 +1098,14 @@ class HotspotWidget extends React.Component {
944
1098
  );
945
1099
  selectBox.options[0].disabled = true;
946
1100
  }
1101
+ let hasDatasetSpecificKlcOptions = false;
947
1102
  if (activeLayers.length) {
948
1103
  for (let a = 0; a < activeLayers.length; a++) {
949
1104
  if (
950
1105
  activeLayers[a].includes('all_lcc_b_pol') ||
951
1106
  activeLayers[a].includes('all_present_lc_b_pol')
952
1107
  ) {
1108
+ hasDatasetSpecificKlcOptions = true;
953
1109
  for (let i = 0; i < modularKLCAreas.length; i++) {
954
1110
  let option = modularKLCAreas[i];
955
1111
  selectBox.options.add(new Option(option, option, option));
@@ -960,22 +1116,6 @@ class HotspotWidget extends React.Component {
960
1116
  continue;
961
1117
  } else {
962
1118
  selectBox.value = this.state.selectedArea;
963
- if (this.state.lcYear !== null) {
964
- const hasLcYearOption = Array.from(
965
- selectBoxLcTime.options,
966
- ).some((option) => option.value === this.state.lcYear);
967
- selectBoxLcTime.value = hasLcYearOption
968
- ? this.state.lcYear
969
- : 'default';
970
- }
971
- if (this.state.lccYear !== null) {
972
- const hasLccYearOption = Array.from(
973
- selectBoxLccTime.options,
974
- ).some((option) => option.value === this.state.lccYear);
975
- selectBoxLccTime.value = hasLccYearOption
976
- ? this.state.lccYear
977
- : 'default';
978
- }
979
1119
  break; // move break statement inside the if block
980
1120
  }
981
1121
  }
@@ -984,6 +1124,7 @@ class HotspotWidget extends React.Component {
984
1124
  activeLayers[a].includes('all_lcc_a_pol') ||
985
1125
  activeLayers[a].includes('all_present_lc_a_pol')
986
1126
  ) {
1127
+ hasDatasetSpecificKlcOptions = true;
987
1128
  for (let i = 0; i < dichotomousKLCAreas.length; i++) {
988
1129
  let option = dichotomousKLCAreas[i];
989
1130
  selectBox.options.add(new Option(option, option, option));
@@ -994,29 +1135,15 @@ class HotspotWidget extends React.Component {
994
1135
  continue;
995
1136
  } else {
996
1137
  selectBox.value = this.state.selectedArea;
997
- if (this.state.lcYear !== null) {
998
- const hasLcYearOption = Array.from(
999
- selectBoxLcTime.options,
1000
- ).some((option) => option.value === this.state.lcYear);
1001
- selectBoxLcTime.value = hasLcYearOption
1002
- ? this.state.lcYear
1003
- : 'default';
1004
- }
1005
- if (this.state.lccYear !== null) {
1006
- const hasLccYearOption = Array.from(
1007
- selectBoxLccTime.options,
1008
- ).some((option) => option.value === this.state.lccYear);
1009
- selectBoxLccTime.value = hasLccYearOption
1010
- ? this.state.lccYear
1011
- : 'default';
1012
- }
1013
1138
  break;
1014
1139
  }
1015
1140
  }
1016
1141
  break;
1017
1142
  }
1018
1143
  }
1019
- } else if (selectBox) {
1144
+ }
1145
+
1146
+ if (!hasDatasetSpecificKlcOptions && selectBox) {
1020
1147
  const allKLCAreas = Array.from(
1021
1148
  new Set(modularKLCAreas.concat(dichotomousKLCAreas)),
1022
1149
  ).sort((a, b) => a.localeCompare(b));
@@ -1034,20 +1161,60 @@ class HotspotWidget extends React.Component {
1034
1161
  }
1035
1162
  }
1036
1163
  if (selectBox.value === 'default') {
1164
+ hasMultipleLcDatesForSelection = false;
1037
1165
  if (selectBoxLcTime) {
1038
1166
  this.removeOptions(selectBoxLcTime);
1039
1167
  selectBoxLcTime.options.add(
1040
- new Option('Select a region first', 'default', true, true),
1168
+ new Option('Select a year', 'default', true, true),
1041
1169
  );
1042
1170
  selectBoxLcTime.options[0].disabled = true;
1043
1171
  }
1044
1172
  if (selectBoxLccTime) {
1045
1173
  this.removeOptions(selectBoxLccTime);
1046
1174
  selectBoxLccTime.options.add(
1047
- new Option('Select a region first', 'default', true, true),
1175
+ new Option('Select a year', 'default', true, true),
1048
1176
  );
1049
1177
  selectBoxLccTime.options[0].disabled = true;
1050
1178
  }
1179
+
1180
+ if (
1181
+ this.state.selectedArea !== null ||
1182
+ this.state.referenceLcYear !== null ||
1183
+ this.state.lcYear !== null ||
1184
+ this.state.lccYear !== null
1185
+ ) {
1186
+ this.setState({
1187
+ selectedArea: null,
1188
+ referenceLcYear: null,
1189
+ lcYear: null,
1190
+ lccYear: null,
1191
+ });
1192
+ }
1193
+ }
1194
+
1195
+ if (
1196
+ selectBox &&
1197
+ this.state.selectedArea !== null &&
1198
+ Array.from(selectBox.options).some(
1199
+ (option) => option.value === this.state.selectedArea,
1200
+ )
1201
+ ) {
1202
+ selectBox.value = this.state.selectedArea;
1203
+ hasSelectedAreaOption = true;
1204
+ }
1205
+
1206
+ const hasActivePresentLcLayer = activeLayers.some(
1207
+ (layer) =>
1208
+ layer.includes('all_present_lc_a_pol') ||
1209
+ layer.includes('all_present_lc_b_pol') ||
1210
+ layer.includes('lc_filter'),
1211
+ );
1212
+
1213
+ const shouldShowPresentLandCoverDropdown =
1214
+ hasSelectedAreaOption && hasActivePresentLcLayer;
1215
+ this.setPresentLandCoverVisibility(shouldShowPresentLandCoverDropdown);
1216
+ if (this.state.hasMultipleLcDates !== hasMultipleLcDatesForSelection) {
1217
+ this.setState({ hasMultipleLcDates: hasMultipleLcDatesForSelection });
1051
1218
  }
1052
1219
  }
1053
1220
 
@@ -1079,69 +1246,21 @@ class HotspotWidget extends React.Component {
1079
1246
  return;
1080
1247
  }
1081
1248
 
1082
- let rawKeymapInfo = selectedNode.keymap_info;
1083
- let keyMapInfoObj = {};
1084
- if (typeof rawKeymapInfo === 'string') {
1085
- try {
1086
- keyMapInfoObj = JSON.parse(rawKeymapInfo) || {};
1087
- } catch (e) {
1088
- keyMapInfoObj = {};
1089
- }
1090
- } else if (rawKeymapInfo && typeof rawKeymapInfo === 'object') {
1091
- keyMapInfoObj = rawKeymapInfo;
1092
- }
1249
+ const { lccDateList, lcDateList, lccDatesByLcYear } =
1250
+ this.getDateOptionsForNode(selectedNode);
1093
1251
 
1094
- let lccDateList = [];
1095
- let lccDatesByLcYear = {};
1096
-
1097
- if (Array.isArray(keyMapInfoObj.dates)) {
1098
- keyMapInfoObj.dates.forEach((entry) => {
1099
- const lccDate = Number(
1100
- entry && typeof entry === 'object' ? entry?.date : entry,
1101
- );
1102
- const lcDate = Number(
1103
- entry && typeof entry === 'object' ? entry?.lc_date : undefined,
1104
- );
1105
- if (Number.isFinite(lccDate)) {
1106
- lccDateList.push(lccDate);
1107
- }
1108
- if (Number.isFinite(lcDate)) {
1109
- if (!lccDatesByLcYear[lcDate]) {
1110
- lccDatesByLcYear[lcDate] = [];
1111
- }
1112
- if (Number.isFinite(lccDate)) {
1113
- lccDatesByLcYear[lcDate].push(lccDate);
1114
- }
1115
- }
1116
- });
1117
- }
1118
-
1119
- const dynamicYearValues = Object.keys(keyMapInfoObj)
1120
- .filter((key) => /^year\d+$/.test(key))
1121
- .map((key) => Number(keyMapInfoObj[key]))
1122
- .filter((year) => Number.isFinite(year));
1123
- if (dynamicYearValues.length) {
1124
- lccDateList = lccDateList.concat(dynamicYearValues);
1125
- }
1126
-
1127
- if (!lccDateList.length && Number.isFinite(Number(selectedNode.lcc_year))) {
1128
- lccDateList = [Number(selectedNode.lcc_year)];
1129
- }
1130
-
1131
- lccDateList = Array.from(new Set(lccDateList)).sort((a, b) => a - b);
1132
- Object.keys(lccDatesByLcYear).forEach((lcDateKey) => {
1133
- lccDatesByLcYear[lcDateKey] = Array.from(
1134
- new Set(lccDatesByLcYear[lcDateKey]),
1135
- ).sort((a, b) => a - b);
1136
- });
1137
-
1138
- const selectedLcYear = Number(this.state.lcYear);
1139
- const lccOptionsToUse = this.resolveLccDateOptions(
1140
- selectedNode.klc_code,
1141
- selectedLcYear,
1142
- lccDatesByLcYear,
1143
- lccDateList,
1144
- );
1252
+ const selectedLcYear = this.isReferenceSelectionKlcCode(
1253
+ selectedNode?.klc_code,
1254
+ )
1255
+ ? this.getReferenceLcYearSelection(lcDateList)
1256
+ : Number(this.state.lcYear);
1257
+ const lccOptionsToUse = Number.isFinite(Number(selectedLcYear))
1258
+ ? this.getLccDateOptionsFromData(
1259
+ selectedLcYear,
1260
+ lccDatesByLcYear,
1261
+ lccDateList,
1262
+ )
1263
+ : [];
1145
1264
 
1146
1265
  this.removeOptions(selectBoxLccTime);
1147
1266
  selectBoxLccTime.options.add(
@@ -1188,6 +1307,84 @@ class HotspotWidget extends React.Component {
1188
1307
  );
1189
1308
  }
1190
1309
 
1310
+ renderReferenceLandCoverSelection() {
1311
+ const selectedNode = this.getSelectedNodeByArea(this.state.selectedArea);
1312
+ if (
1313
+ !selectedNode ||
1314
+ !this.isReferenceSelectionKlcCode(selectedNode.klc_code)
1315
+ ) {
1316
+ return null;
1317
+ }
1318
+
1319
+ const { lcDateList } = this.getDateOptionsForNode(selectedNode);
1320
+ if (!lcDateList.length) {
1321
+ return null;
1322
+ }
1323
+
1324
+ const selectedReferenceLcYear = this.state.referenceLcYear || 'default';
1325
+
1326
+ return (
1327
+ <div className="measurement-dropdown-container hotspot-reference-selection">
1328
+ <div className="esri-print__form-section-container">
1329
+ <label>
1330
+ Select first the reference land cover date you want to visualize
1331
+ <select
1332
+ id="select-klc-reference-lc-time"
1333
+ className="esri-select"
1334
+ value={selectedReferenceLcYear}
1335
+ onBlur={() => {}}
1336
+ onChange={(e) => {
1337
+ const nextReferenceLcYear = e.target.value;
1338
+ if (nextReferenceLcYear === 'default') {
1339
+ this.setState(
1340
+ {
1341
+ referenceLcYear: null,
1342
+ lcYear: null,
1343
+ lccYear: null,
1344
+ },
1345
+ () => {
1346
+ this.getKLCNames(
1347
+ this.dataJSONNames,
1348
+ this.state.selectedArea,
1349
+ );
1350
+ this.updateLccOptionsForSelectedLc();
1351
+ this.disableButton();
1352
+ },
1353
+ );
1354
+ return;
1355
+ }
1356
+ this.setState(
1357
+ {
1358
+ referenceLcYear: nextReferenceLcYear,
1359
+ lcYear: nextReferenceLcYear,
1360
+ lccYear: null,
1361
+ },
1362
+ () => {
1363
+ this.getKLCNames(
1364
+ this.dataJSONNames,
1365
+ this.state.selectedArea,
1366
+ );
1367
+ this.updateLccOptionsForSelectedLc();
1368
+ this.disableButton();
1369
+ },
1370
+ );
1371
+ }}
1372
+ >
1373
+ <option value="default" disabled>
1374
+ Select a year
1375
+ </option>
1376
+ {lcDateList.map((year) => (
1377
+ <option key={year} value={String(year)}>
1378
+ {year}
1379
+ </option>
1380
+ ))}
1381
+ </select>
1382
+ </label>
1383
+ </div>
1384
+ </div>
1385
+ );
1386
+ }
1387
+
1191
1388
  render() {
1192
1389
  let divs = [
1193
1390
  {
@@ -1270,6 +1467,7 @@ class HotspotWidget extends React.Component {
1270
1467
  onChange={(e) => {
1271
1468
  this.setState({
1272
1469
  selectedArea: e.target.value,
1470
+ referenceLcYear: null,
1273
1471
  lcYear: null,
1274
1472
  lccYear: null,
1275
1473
  });
@@ -1280,6 +1478,7 @@ class HotspotWidget extends React.Component {
1280
1478
  </label>
1281
1479
  </div>
1282
1480
  </div>
1481
+ {this.renderReferenceLandCoverSelection()}
1283
1482
  <div>
1284
1483
  {divs.map((div, i) => (
1285
1484
  <div key={i} className={div.className}>
@@ -1361,7 +1560,12 @@ class HotspotWidget extends React.Component {
1361
1560
  this.lccYear = null;
1362
1561
  this.selectedArea = null;
1363
1562
  if (this._isMounted) {
1364
- this.setState({ lcYear: null, lccYear: null, selectedArea: null });
1563
+ this.setState({
1564
+ lcYear: null,
1565
+ lccYear: null,
1566
+ selectedArea: null,
1567
+ referenceLcYear: null,
1568
+ });
1365
1569
  }
1366
1570
  shouldUpdate = true;
1367
1571
  }
@@ -1398,9 +1602,7 @@ class HotspotWidget extends React.Component {
1398
1602
  return '';
1399
1603
  }
1400
1604
  return Object.keys(activeLayers)
1401
- .filter(
1402
- (key) => key.includes('all_present_lc_') || key.includes('all_lcc_'),
1403
- )
1605
+ .filter((key) => this.isHotspotLayerKey(key))
1404
1606
  .sort()
1405
1607
  .join('|');
1406
1608
  }
@@ -1413,17 +1615,16 @@ class HotspotWidget extends React.Component {
1413
1615
  this.props.hotspotData,
1414
1616
  );
1415
1617
 
1416
- if (
1417
- prevHotspotLayerSignature !== nextHotspotLayerSignature &&
1418
- (this.state.selectedArea !== null ||
1419
- this.state.lcYear !== null ||
1420
- this.state.lccYear !== null)
1421
- ) {
1422
- this.setState({
1423
- selectedArea: null,
1424
- lcYear: null,
1425
- lccYear: null,
1426
- });
1618
+ if (prevHotspotLayerSignature !== nextHotspotLayerSignature) {
1619
+ this.clearHotspotLayersFromMap();
1620
+ this.resetHotspotViewState();
1621
+ const newHotspotData = {
1622
+ ...(this.props.hotspotData || {}),
1623
+ filteredLayers: {},
1624
+ filteredLayersData: {},
1625
+ };
1626
+ this.props.hotspotDataHandler(newHotspotData);
1627
+ this.resetHotspotWidgetFilters();
1427
1628
  return;
1428
1629
  }
1429
1630
 
@@ -1437,6 +1638,9 @@ class HotspotWidget extends React.Component {
1437
1638
  if (prevState.lcYear !== this.state.lcYear) {
1438
1639
  this.disableButton();
1439
1640
  }
1641
+ if (prevState.referenceLcYear !== this.state.referenceLcYear) {
1642
+ this.disableButton();
1643
+ }
1440
1644
  }
1441
1645
  }
1442
1646
  export default HotspotWidget;
@@ -7358,33 +7358,78 @@ class MenuWidget extends React.Component {
7358
7358
  this.hideOnClickOutsideOpacity();
7359
7359
  }
7360
7360
 
7361
+ getHotspotFilterLayerId(layerId, options = {}) {
7362
+ const { requireActive = false } = options;
7363
+ if (!layerId || typeof layerId !== 'string') {
7364
+ return null;
7365
+ }
7366
+ let filterLayerId = null;
7367
+ if (layerId === 'lcc_filter' || layerId.includes('all_lcc')) {
7368
+ filterLayerId = 'lcc_filter';
7369
+ } else if (layerId === 'lc_filter' || layerId.includes('all_present')) {
7370
+ filterLayerId = 'lc_filter';
7371
+ } else if (layerId === 'klc_filter' || layerId.includes('cop_klc')) {
7372
+ filterLayerId = 'klc_filter';
7373
+ } else if (layerId === 'pa_filter' || layerId.includes('protected_areas')) {
7374
+ filterLayerId = 'pa_filter';
7375
+ }
7376
+
7377
+ if (!filterLayerId) {
7378
+ return null;
7379
+ }
7380
+
7381
+ if (!requireActive || layerId === filterLayerId) {
7382
+ return filterLayerId;
7383
+ }
7384
+
7385
+ const hotspotFilteredLayers =
7386
+ this.props.hotspotData &&
7387
+ this.props.hotspotData.filteredLayers &&
7388
+ typeof this.props.hotspotData.filteredLayers === 'object'
7389
+ ? this.props.hotspotData.filteredLayers
7390
+ : {};
7391
+ const hasFilteredEntry = Object.prototype.hasOwnProperty.call(
7392
+ hotspotFilteredLayers,
7393
+ filterLayerId,
7394
+ );
7395
+ const mapLayer =
7396
+ this.map && typeof this.map.findLayerById === 'function'
7397
+ ? this.map.findLayerById(filterLayerId)
7398
+ : null;
7399
+ const hasVisibleFilterLayer =
7400
+ (this.layers[filterLayerId] && this.layers[filterLayerId].visible) ||
7401
+ (mapLayer && mapLayer.visible);
7402
+
7403
+ if (hasFilteredEntry && (mapLayer || hasVisibleFilterLayer)) {
7404
+ return filterLayerId;
7405
+ }
7406
+
7407
+ return null;
7408
+ }
7409
+
7361
7410
  setOpacity() {
7362
7411
  let layer = document.querySelector('.opacity-slider input').dataset.layer;
7363
7412
  let value = document.querySelector('.opacity-panel input').value;
7364
7413
 
7365
- if (this.layers['lcc_filter'] && layer.includes('all_lcc')) {
7366
- this.layers['lcc_filter'].opacity = value / 100;
7367
- this.saveOpacity(this.layers['lcc_filter'], value / 100);
7368
- } else if (this.layers['lc_filter'] && layer.includes('all_present')) {
7369
- this.layers['lc_filter'].opacity = value / 100;
7370
- this.saveOpacity(this.layers['lc_filter'], value / 100);
7371
- } else if (this.layers['klc_filter'] && layer.includes('cop_klc')) {
7372
- this.layers['klc_filter'].opacity = value / 100;
7373
- this.saveOpacity(this.layers['klc_filter'], value / 100);
7374
- } else if (this.layers['pa_filter'] && layer.includes('protected_areas')) {
7375
- this.layers['pa_filter'].opacity = value / 100;
7376
- this.saveOpacity(this.layers['pa_filter'], value / 100);
7377
- }
7378
- this.layers[layer].opacity = value / 100;
7379
- this.saveOpacity(layer, value / 100);
7380
- if (
7381
- this.map.findLayerById(layer) &&
7382
- this.map.findLayerById(layer) !== null &&
7383
- (this.map.findLayerById(layer).opacity ||
7384
- this.map.findLayerById(layer).opacity === 0)
7385
- ) {
7386
- this.map.findLayerById(layer).opacity = value / 100;
7414
+ const filterLayerId = this.getHotspotFilterLayerId(layer, {
7415
+ requireActive: true,
7416
+ });
7417
+ const targetLayerId =
7418
+ filterLayerId && this.layers[filterLayerId] ? filterLayerId : layer;
7419
+ if (!this.layers[targetLayerId]) {
7420
+ return;
7387
7421
  }
7422
+ this.layers[targetLayerId].opacity = value / 100;
7423
+ this.saveOpacity(targetLayerId, value / 100);
7424
+
7425
+ const mapLayer =
7426
+ this.map && typeof this.map.findLayerById === 'function'
7427
+ ? this.map.findLayerById(targetLayerId)
7428
+ : null;
7429
+ if (mapLayer && (mapLayer.opacity || mapLayer.opacity === 0)) {
7430
+ mapLayer.opacity = value / 100;
7431
+ }
7432
+
7388
7433
  document.querySelector(
7389
7434
  '.active-layer[layer-id="' + layer + '"] .active-layer-opacity',
7390
7435
  ).dataset.opacity = value;
@@ -7589,46 +7634,31 @@ class MenuWidget extends React.Component {
7589
7634
  if (!isUserServiceLayer) {
7590
7635
  this.findCheckedDataset(elem);
7591
7636
  }
7637
+
7638
+ const filterLayerId = this.getHotspotFilterLayerId(elem.id, {
7639
+ requireActive: true,
7640
+ });
7641
+ const targetLayerId =
7642
+ filterLayerId && this.layers[filterLayerId] ? filterLayerId : elem.id;
7643
+
7644
+ if (!this.layers[targetLayerId]) {
7645
+ return;
7646
+ }
7647
+
7592
7648
  if (
7593
7649
  !this.visibleLayers[elem.id] ||
7594
7650
  this.visibleLayers[elem.id][1] === 'eye'
7595
7651
  ) {
7596
- this.layers[elem.id].visible = false;
7652
+ this.layers[targetLayerId].visible = false;
7597
7653
  this.visibleLayers[elem.id] = ['fas', 'eye-slash'];
7598
- if (this.layers['lcc_filter'] && elem.id.includes('all_lcc')) {
7599
- this.map.remove(this.layers['lcc_filter']);
7600
- this.layers['lcc_filter'].visible = false;
7601
- } else if (this.layers['lc_filter'] && elem.id.includes('all_present')) {
7602
- this.map.remove(this.layers['lc_filter']);
7603
- this.layers['lc_filter'].visible = false;
7604
- } else if (this.layers['klc_filter'] && elem.id.includes('cop_klc')) {
7605
- this.map.remove(this.layers['klc_filter']);
7606
- this.layers['klc_filter'].visible = false;
7607
- } else if (
7608
- this.layers['pa_filter'] &&
7609
- elem.id.includes('protected_areas')
7610
- ) {
7611
- this.map.remove(this.layers['pa_filter']);
7612
- this.layers['pa_filter'].visible = false;
7654
+ if (targetLayerId !== elem.id && this.layers[elem.id]) {
7655
+ this.layers[elem.id].visible = false;
7613
7656
  }
7657
+ this.map.remove(this.layers[targetLayerId]);
7614
7658
  } else {
7615
- if (this.layers['lcc_filter'] && elem.id.includes('all_lcc')) {
7616
- this.map.add(this.layers['lcc_filter']);
7617
- this.layers['lcc_filter'].visible = true;
7618
- } else if (this.layers['lc_filter'] && elem.id.includes('all_present')) {
7619
- this.map.add(this.layers['lc_filter']);
7620
- this.layers['lc_filter'].visible = true;
7621
- } else if (this.layers['klc_filter'] && elem.id.includes('cop_klc')) {
7622
- this.map.add(this.layers['klc_filter']);
7623
- this.layers['klc_filter'].visible = true;
7624
- } else if (
7625
- this.layers['pa_filter'] &&
7626
- elem.id.includes('protected_areas')
7627
- ) {
7628
- this.map.add(this.layers['pa_filter']);
7629
- this.layers['pa_filter'].visible = true;
7630
- } else {
7631
- this.map.add(this.layers[elem.id]);
7659
+ this.map.add(this.layers[targetLayerId]);
7660
+ this.layers[targetLayerId].visible = true;
7661
+ if (targetLayerId !== elem.id && this.layers[elem.id]) {
7632
7662
  this.layers[elem.id].visible = true;
7633
7663
  }
7634
7664
  this.visibleLayers[elem.id] = ['fas', 'eye'];
@@ -7883,6 +7913,26 @@ class MenuWidget extends React.Component {
7883
7913
  * @param {*} id id from elem
7884
7914
  */
7885
7915
  deleteCrossEvent(elem) {
7916
+ if (
7917
+ elem.id === 'lcc_filter' ||
7918
+ elem.id === 'lc_filter' ||
7919
+ elem.id === 'klc_filter' ||
7920
+ elem.id === 'pa_filter'
7921
+ ) {
7922
+ this.deleteFilteredLayer(elem.id);
7923
+ delete this.activeLayersJSON[elem.id];
7924
+ if (this.visibleLayers && this.visibleLayers[elem.id]) {
7925
+ delete this.visibleLayers[elem.id];
7926
+ }
7927
+ if (this.timeLayers && this.timeLayers[elem.id]) {
7928
+ delete this.timeLayers[elem.id];
7929
+ }
7930
+ this.layersReorder();
7931
+ this.saveLayerOrder();
7932
+ this.checkInfoWidget();
7933
+ this.setState({});
7934
+ return;
7935
+ }
7886
7936
  elem.checked = false;
7887
7937
  this.toggleLayer(elem);
7888
7938
  delete this.activeLayersJSON[elem.id];
@@ -8018,16 +8068,13 @@ class MenuWidget extends React.Component {
8018
8068
 
8019
8069
  deleteFilteredLayer(layer) {
8020
8070
  if (!layer || !this.props || !this.props.map) return;
8021
- if (
8022
- !(
8023
- layer.includes('all_lcc') ||
8024
- layer.includes('all_present') ||
8025
- layer.includes('cop_klc') ||
8026
- layer.includes('protected_areas')
8027
- )
8028
- )
8071
+ const filterLayerId =
8072
+ this.getHotspotFilterLayerId(layer, {
8073
+ requireActive: true,
8074
+ }) || this.getHotspotFilterLayerId(layer);
8075
+ if (!filterLayerId) {
8029
8076
  return;
8030
- let filterLayer;
8077
+ }
8031
8078
  let updatedHotspotData = this.props.hotspotData || {};
8032
8079
  let updatedFilteredLayers =
8033
8080
  updatedHotspotData &&
@@ -8035,60 +8082,19 @@ class MenuWidget extends React.Component {
8035
8082
  typeof updatedHotspotData['filteredLayers'] === 'object'
8036
8083
  ? updatedHotspotData['filteredLayers']
8037
8084
  : {};
8038
- if (this.layers['lcc_filter'] && layer.includes('all_lcc')) {
8039
- this.layers['lcc_filter'].visible = false;
8040
- filterLayer = this.props.map.findLayerById('lcc_filter');
8041
- if (filterLayer !== undefined) {
8042
- filterLayer.clear();
8043
- filterLayer.destroy();
8044
- this.props.map.remove(filterLayer);
8045
- }
8046
- delete updatedFilteredLayers['lcc_filter'];
8047
- delete this.layers['lcc_filter'];
8048
- } else if (this.layers['lc_filter'] && layer.includes('all_present_lc')) {
8049
- this.layers['lc_filter'].visible = false;
8050
- filterLayer = this.props.map.findLayerById('lc_filter');
8051
- if (filterLayer !== undefined) {
8052
- filterLayer.clear();
8053
- filterLayer.destroy();
8054
- this.props.map.remove(filterLayer);
8055
- }
8056
- delete updatedFilteredLayers['lc_filter'];
8057
- delete this.layers['lc_filter'];
8058
- } else if (
8059
- this.layers['klc_filter'] !== undefined &&
8060
- layer.includes('cop_klc')
8061
- ) {
8062
- this.layers['klc_filter'].visible = false;
8063
- if (this.layers[layer]) {
8064
- this.layers[layer].visible = false;
8065
- }
8066
- filterLayer = this.props.map.findLayerById('klc_filter');
8067
- if (filterLayer !== undefined) {
8068
- // temp = filterLayer;
8069
- filterLayer.clear();
8070
- filterLayer.destroy();
8071
- this.props.map.remove(filterLayer);
8072
- }
8073
- delete updatedFilteredLayers['klc_filter'];
8074
- //delete this.layers['klc_filter'];
8075
- } else if (
8076
- this.layers['pa_filter'] !== undefined &&
8077
- layer.includes('protected_areas')
8078
- ) {
8079
- this.layers['pa_filter'].visible = false;
8080
- if (this.layers[layer]) {
8081
- this.layers[layer].visible = false;
8082
- }
8083
- filterLayer = this.props.map.findLayerById('pa_filter');
8084
- if (filterLayer !== undefined) {
8085
- // temp = filterLayer;
8086
- filterLayer.clear();
8087
- filterLayer.destroy();
8088
- this.props.map.remove(filterLayer);
8085
+ if (this.layers[filterLayerId]) {
8086
+ this.layers[filterLayerId].visible = false;
8087
+ this.props.map.remove(this.layers[filterLayerId]);
8088
+ const mapFilterLayer = this.props.map.findLayerById(filterLayerId);
8089
+ if (mapFilterLayer) {
8090
+ this.props.map.remove(mapFilterLayer);
8089
8091
  }
8090
- delete updatedFilteredLayers['pa_filter'];
8091
8092
  }
8093
+ if (this.layers[layer]) {
8094
+ this.layers[layer].visible = false;
8095
+ }
8096
+ delete updatedFilteredLayers[filterLayerId];
8097
+ delete this.layers[filterLayerId];
8092
8098
  this.props.mapLayersHandler(this.layers);
8093
8099
  if (this.props.hotspotDataHandler) {
8094
8100
  updatedHotspotData['filteredLayers'] = updatedFilteredLayers;
@@ -1975,6 +1975,17 @@ div.map-container.popup-block {
1975
1975
  cursor: not-allowed;
1976
1976
  }
1977
1977
 
1978
+ .hotspot-reference-selection {
1979
+ padding: 8px;
1980
+ margin-top: 10px;
1981
+ margin-bottom: 10px;
1982
+ background: rgba(160, 177, 40, 0.15);
1983
+ }
1984
+
1985
+ .hotspot-reference-selection .esri-select {
1986
+ margin-top: 8px;
1987
+ }
1988
+
1978
1989
  /*.hotspot-container .esri-select{
1979
1990
  font-family:Helvetica, sans-serif;
1980
1991
  font-size:20px;