@eeacms/volto-arcgis-block 0.1.207 → 0.1.209

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.209](https://github.com/eea/volto-arcgis-block/compare/0.1.208...0.1.209) - 3 October 2023
8
+
9
+ #### :hammer_and_wrench: Others
10
+
11
+ - ready to upload hotpsot bug fixes [ujbolivar - [`0799ca8`](https://github.com/eea/volto-arcgis-block/commit/0799ca8028bec5a15ececdbe4504fbb83c065603)]
12
+ - setting up hotspot bug fixes for latest dev update before pushing [ujbolivar - [`f117e0e`](https://github.com/eea/volto-arcgis-block/commit/f117e0e7ee37e35e7b6ae77549d92d44289d8328)]
13
+ - hotspotstate is updated with activelayers for hotspot widget [ujbolivar - [`b36f4a5`](https://github.com/eea/volto-arcgis-block/commit/b36f4a5362604188497b5bb0d080219d1ebf44b9)]
14
+ ### [0.1.208](https://github.com/eea/volto-arcgis-block/compare/0.1.207...0.1.208) - 2 October 2023
15
+
16
+ #### :hammer_and_wrench: Others
17
+
18
+ - info widget bug when activate/deactivate LLC layer fixed [masanchez85 - [`6cb51a9`](https://github.com/eea/volto-arcgis-block/commit/6cb51a9739718817bc81c860c95c93aeec5f708b)]
19
+ - CLMS-2349, BBOX fixing and text to hyperlink adaptation [masanchez85 - [`7d8dfa2`](https://github.com/eea/volto-arcgis-block/commit/7d8dfa2e0fdd036dad132ef53494314a13fcca9e)]
7
20
  ### [0.1.207](https://github.com/eea/volto-arcgis-block/compare/0.1.206...0.1.207) - 27 September 2023
8
21
 
9
22
  ### [0.1.206](https://github.com/eea/volto-arcgis-block/compare/0.1.205...0.1.206) - 26 September 2023
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-arcgis-block",
3
- "version": "0.1.207",
3
+ "version": "0.1.209",
4
4
  "description": "volto-arcgis-block: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: CodeSyntax",
@@ -194,13 +194,21 @@ class AreaWidget extends React.Component {
194
194
  }
195
195
 
196
196
  checkExtent(extent) {
197
+ let extentToCHeck = new Extent({
198
+ xmin: -4957196.074387185,
199
+ xmax: 8896862.428240843,
200
+ ymin: 2252343.9407090154,
201
+ ymax: 12114555.078173038,
202
+ spatialReference: { wkid: 102100 },
203
+ });
197
204
  if (
198
- extent.xmin < -31.27 &&
199
- extent.xmax > 44.82 &&
200
- extent.ymin < 27.64 &&
201
- extent.ymax > 80.83
205
+ extent.xmin < extentToCHeck.xmin &&
206
+ extent.xmax > extentToCHeck.xmax &&
207
+ extent.ymin < extentToCHeck.ymin &&
208
+ extent.ymax > extentToCHeck.ymax
202
209
  )
203
210
  return true;
211
+ else return false;
204
212
  }
205
213
 
206
214
  rectanglehandler() {
@@ -565,8 +573,17 @@ class AreaWidget extends React.Component {
565
573
  <FontAwesomeIcon icon={['fas', 'info-circle']} />
566
574
  </span>
567
575
  <div className="drawRectanglePopupWarning-text">
568
- Full dataset's only downloadable through the M2M API,
569
- AOI isn't sent to cart
576
+ <a
577
+ style={{ color: 'black', cursor: 'pointer' }}
578
+ className="drawRectanglePopupWarning"
579
+ id="drawRectanglePopupWarning"
580
+ href="https://clmsdemo.devel6cph.eea.europa.eu/en/how-to-guides/how-to-download-spatial-data/how-to-download-m2m"
581
+ target="_blank"
582
+ rel="noreferrer"
583
+ >
584
+ To download the full dataset consult the "How to
585
+ download M2M" How to guide.
586
+ </a>
570
587
  </div>
571
588
  </>
572
589
  )}
@@ -16,6 +16,7 @@ class HotspotWidget extends React.Component {
16
16
  //not be showing the basemap panel
17
17
  this.state = {
18
18
  showMapMenu: false,
19
+ activeLayers: {},
19
20
  };
20
21
  this.menuClass =
21
22
  'esri-icon-filter esri-widget--button esri-widget esri-interactive';
@@ -183,7 +184,7 @@ class HotspotWidget extends React.Component {
183
184
 
184
185
  async handleApplyFilter(typeFilter) {
185
186
  let typeLegend;
186
-
187
+ const activeLayers = Object.keys(this.props.hotspotData['activeLayers']);
187
188
  this.props.loadingHandler(true);
188
189
 
189
190
  if (this.props.selectedLayers) {
@@ -247,8 +248,8 @@ class HotspotWidget extends React.Component {
247
248
  .value.match(/\d+/g)
248
249
  .map(Number)[0];
249
250
 
250
- for (let i = 0; i < this.state.activeLayers.length; i++) {
251
- let layer = this.state.activeLayers[i];
251
+ for (let i = 0; activeLayers[i]; i++) {
252
+ let layer = activeLayers[i];
252
253
  if (layer.includes('all_lcc_a_pol')) {
253
254
  typeLegend = 'all_lcc_a_pol';
254
255
  break;
@@ -283,8 +284,8 @@ class HotspotWidget extends React.Component {
283
284
  }
284
285
  }
285
286
  if (type === 'lc') {
286
- for (let i = 0; i < this.state.activeLayers.length; i++) {
287
- let layer = this.state.activeLayers[i];
287
+ for (let i = 0; i < activeLayers.length; i++) {
288
+ let layer = activeLayers[i];
288
289
  if (layer.includes('all_present_lc_a_pol')) {
289
290
  typeLegend = 'all_present_lc_a_pol';
290
291
  break;
@@ -354,6 +355,7 @@ class HotspotWidget extends React.Component {
354
355
  }
355
356
  this.layerModelInit();
356
357
  this.setBBoxCoordinates(this.dataBBox);
358
+ //this.setState({ activeLayers: {[type+'_filter']: this.props.selectedLayers[type+'_filter']}})
357
359
  });
358
360
  //set sessionStorage value to keep the widget open
359
361
  sessionStorage.setItem('hotspotFilterApplied', 'true');
@@ -387,7 +389,7 @@ class HotspotWidget extends React.Component {
387
389
 
388
390
  openMenu() {
389
391
  if (this.state.showMapMenu) {
390
- this.getKLCNames(this.dataJSONNames, this.selectedArea);
392
+ //this.getKLCNames(this.dataJSONNames, this.selectedArea);
391
393
  this.props.mapViewer.setActiveWidget();
392
394
  this.container.current.querySelector('.right-panel').style.display =
393
395
  'none';
@@ -401,9 +403,9 @@ class HotspotWidget extends React.Component {
401
403
  // and ensure that the component is rendered again
402
404
  this.setState({ showMapMenu: false });
403
405
  } else {
404
- this.getLayerParameters();
405
- if (this.getLayerParameters.length !== 0)
406
- this.getKLCNames(this.dataJSONNames, this.selectedArea);
406
+ //this.getLayerParameters();
407
+ //if (this.getLayerParameters.length !== 0)
408
+ //this.getKLCNames(this.dataJSONNames, this.selectedArea);
407
409
  this.props.mapViewer.setActiveWidget(this);
408
410
  this.container.current.querySelector('.right-panel').style.display =
409
411
  'flex';
@@ -433,7 +435,6 @@ class HotspotWidget extends React.Component {
433
435
  //if (this.selectedArea == null) {
434
436
  // this.selectedArea = data.nodes[0].node.klc_name;
435
437
  //}
436
- this.getKLCNames(data.nodes, this.selectedArea);
437
438
  })
438
439
  .catch(function (error) {
439
440
  /* console.log('error while getting data'); */
@@ -442,6 +443,7 @@ class HotspotWidget extends React.Component {
442
443
 
443
444
  renderApplyFilterButton() {
444
445
  let typeFilter = [];
446
+ const activeLayers = Object.keys(this.props.hotspotData['activeLayers']);
445
447
 
446
448
  if (
447
449
  this.container.current.querySelector('.presentLandCoverContainer').style
@@ -456,7 +458,7 @@ class HotspotWidget extends React.Component {
456
458
  ) {
457
459
  typeFilter.push('lcc');
458
460
  }
459
- this.state.activeLayers.forEach((layer) => {
461
+ activeLayers.forEach((layer) => {
460
462
  if (layer.match('cop_klc')) {
461
463
  typeFilter.push('klc');
462
464
  }
@@ -527,6 +529,13 @@ class HotspotWidget extends React.Component {
527
529
  var selectBoxLccTime;
528
530
  let modularKLCAreas = [];
529
531
  let dichotomousKLCAreas = [];
532
+ let activeLayers = [];
533
+
534
+ if (this.props.hotspotData['activeLayers'] === undefined) return;
535
+
536
+ activeLayers = Object.keys(this.props.hotspotData['activeLayers']);
537
+
538
+ if (selectedOption === undefined) return;
530
539
 
531
540
  selectBox = document.getElementById('select-klc-area');
532
541
  selectBoxLccTime = document.getElementById('select-klc-lccTime');
@@ -612,11 +621,11 @@ class HotspotWidget extends React.Component {
612
621
  );
613
622
  selectBox.options[0].disabled = true;
614
623
  }
615
- if (this.state.activeLayers.length) {
616
- for (let a = 0; a < this.state.activeLayers.length; a++) {
624
+ if (activeLayers.length) {
625
+ for (let a = 0; a < activeLayers.length; a++) {
617
626
  if (
618
- this.state.activeLayers[a].includes('all_lcc_b_pol') ||
619
- this.state.activeLayers[a].includes('all_present_lc_b_pol')
627
+ activeLayers[a].includes('all_lcc_b_pol') ||
628
+ activeLayers[a].includes('all_present_lc_b_pol')
620
629
  ) {
621
630
  for (let i = 0; i < modularKLCAreas.length; i++) {
622
631
  let option = modularKLCAreas[i];
@@ -634,13 +643,13 @@ class HotspotWidget extends React.Component {
634
643
  if (this.lccYear !== null) {
635
644
  selectBoxLccTime.value = this.lccYear;
636
645
  }
646
+ break; // move break statement inside the if block
637
647
  }
638
- break;
639
648
  }
640
649
  break;
641
650
  } else if (
642
- this.state.activeLayers[a].includes('all_lcc_a_pol') ||
643
- this.state.activeLayers[a].includes('all_present_lc_a_pol')
651
+ activeLayers[a].includes('all_lcc_a_pol') ||
652
+ activeLayers[a].includes('all_present_lc_a_pol')
644
653
  ) {
645
654
  for (let i = 0; i < dichotomousKLCAreas.length; i++) {
646
655
  let option = dichotomousKLCAreas[i];
@@ -658,12 +667,11 @@ class HotspotWidget extends React.Component {
658
667
  if (this.lccYear !== null) {
659
668
  selectBoxLccTime.value = this.lccYear;
660
669
  }
670
+ break; // move break statement inside the if block
661
671
  }
662
- break;
663
672
  }
664
673
  break;
665
674
  }
666
- break;
667
675
  }
668
676
  }
669
677
  if (selectBox.value === 'default') {
@@ -803,25 +811,13 @@ class HotspotWidget extends React.Component {
803
811
  this.props.view.ui.add(this.container.current, 'top-right');
804
812
  this.layerModelInit();
805
813
  this.getBBoxData();
806
- // Listen for changes to sessionStorage
807
- window.addEventListener('storage', this.handleStorageChange);
808
814
  }
809
815
 
810
- componentDidUpdate(prevState) {
811
- if (prevState.activeLayers !== this.state.activeLayers) {
816
+ componentDidUpdate(prevState, prevProps) {
817
+ if (prevProps.hotspotData !== this.props.hotspotData) {
812
818
  this.getKLCNames(this.dataJSONNames, this.selectedArea);
813
819
  this.disableButton();
814
820
  }
815
821
  }
816
-
817
- componentWillUnmount() {
818
- // Remove the event listener when the component is unmounted
819
- window.removeEventListener('storage', this.handleStorageChange);
820
- }
821
-
822
- handleStorageChange = () => {
823
- this.setState({ activeLayers: JSON.parse(sessionStorage.checkedLayers) });
824
- this.forceUpdate();
825
- };
826
822
  }
827
823
  export default HotspotWidget;
@@ -919,6 +919,7 @@ class InfoWidget extends React.Component {
919
919
  render() {
920
920
  let noData = true;
921
921
  if (this.state.pixelInfo) {
922
+ /* debugger */
922
923
  noData = this.infoData[this.state.layerIndex].data.data
923
924
  ? this.infoData[this.state.layerIndex].data.data.values.map((a) => {
924
925
  return a[
@@ -927,6 +928,7 @@ class InfoWidget extends React.Component {
927
928
  }).length === 0
928
929
  : true;
929
930
  } else if (this.state.popup) {
931
+ /* debugger */
930
932
  noData = this.infoData[this.state.layerIndex].data.length === 0 && true;
931
933
  }
932
934
  return (
@@ -56,7 +56,9 @@ class LegendWidget extends React.Component {
56
56
  if (!(img.complete && img.naturalHeight !== 0)) {
57
57
  // If img src returns a broken link
58
58
  if (img?.src?.includes('all_present_lc_a_pol')) {
59
- img.src = this.urls.all_present_lc_a_pol;
59
+ img.src = this.props.hotspotData.all_present_lc[
60
+ 'all_present_lc_a_pol'
61
+ ].FilterStaticImageLegend;
60
62
 
61
63
  img.parentNode.parentNode.parentNode.parentNode.firstElementChild.textContent =
62
64
  'Dichotomous Present Land Cover in selected hot spots';
@@ -83,7 +85,9 @@ class LegendWidget extends React.Component {
83
85
  /*img.parentNode.parentNode.parentNode.parentNode.firstElementChild.textContent =
84
86
  'Modular Present Land Cover in selected hot spots';*/
85
87
  } else if (img?.src?.includes('all_lcc_a_pol')) {
86
- img.src = this.urls.all_lcc_a_pol;
88
+ img.src = this.props.hotspotData.all_lcc[
89
+ 'all_lcc_a_pol'
90
+ ].FilterStaticImageLegend;
87
91
 
88
92
  img.parentNode.parentNode.parentNode.parentNode.firstElementChild.textContent =
89
93
  'Dichotomous Land Cover Change in selected hot spots';
@@ -172,6 +176,11 @@ class LegendWidget extends React.Component {
172
176
  }
173
177
 
174
178
  imageFixWithTimer() {
179
+ let newHotspotData = this.props.hotspotData;
180
+ if (this.props.hotspotData?.layerViewError !== undefined) {
181
+ delete newHotspotData['layerViewError'];
182
+ }
183
+ this.props.hotspotDataHandler(newHotspotData);
175
184
  this.setState({ loading: true });
176
185
  setTimeout(() => {
177
186
  this.brokenLegendImagePatch();
@@ -200,6 +209,11 @@ class LegendWidget extends React.Component {
200
209
  });
201
210
  }
202
211
 
212
+ componentDidUpdate(prevProps) {
213
+ if (this.props.hotspotData?.layerViewError !== undefined) {
214
+ this.imageFixWithTimer();
215
+ }
216
+ }
203
217
  /**
204
218
  * This method renders the component
205
219
  * @returns jsx
@@ -11,6 +11,7 @@ import { useIntl } from 'react-intl';
11
11
  import BasemapWidget from './BasemapWidget';
12
12
  import MeasurementWidget from './MeasurementWidget';
13
13
  import PrintWidget from './PrintWidget';
14
+ import SwipeWidget from './SwipeWidget';
14
15
  import AreaWidget from './AreaWidget';
15
16
  import ScaleWidget from './ScaleWidget';
16
17
  import LegendWidget from './LegendWidget';
@@ -62,12 +63,20 @@ class MapViewer extends React.Component {
62
63
  this.cfgUrls = this.props.cfg.Urls;
63
64
  this.userID = null;
64
65
  this.loadingHandler = this.loadingHandler.bind(this);
66
+ this.hotspotDataHandler = this.hotspotDataHandler.bind(this);
65
67
  }
66
68
 
67
69
  loadingHandler(bool) {
68
70
  this.setState({ layerLoading: bool });
69
71
  }
70
72
 
73
+ hotspotDataHandler(newHotspotData) {
74
+ if (!this.state.hotspotData) {
75
+ this.setState({ hotspotData: {} });
76
+ }
77
+ this.setState({ hotspotData: newHotspotData });
78
+ }
79
+
71
80
  activeLayersHandler(newActiveLayers) {
72
81
  this.activeLayers = newActiveLayers;
73
82
  mapStatus.activeLayers = newActiveLayers;
@@ -235,7 +244,12 @@ class MapViewer extends React.Component {
235
244
  }
236
245
 
237
246
  componentDidUpdate(prevProps, prevState) {
238
- if (this.props.Download || (this.location && this.location.search !== '')) {
247
+ if (
248
+ this.props.Download ||
249
+ (this.location &&
250
+ (this.location.search.includes('product=') ||
251
+ this.location.search.includes('dataset=')))
252
+ ) {
239
253
  let toc_panel_scrolls = sessionStorage.getItem('toc_panel_scrolls');
240
254
  sessionStorage.clear();
241
255
  sessionStorage.setItem('toc_panel_scrolls', toc_panel_scrolls);
@@ -293,6 +307,8 @@ class MapViewer extends React.Component {
293
307
  mapViewer={this}
294
308
  download={this.props.mapviewer_config.Download}
295
309
  urls={this.cfgUrls}
310
+ hotspotData={this.state.hotspotData}
311
+ hotspotDataHandler={this.hotspotDataHandler}
296
312
  />
297
313
  );
298
314
  }
@@ -308,6 +324,12 @@ class MapViewer extends React.Component {
308
324
  if (this.view) return <PrintWidget view={this.view} mapViewer={this} />;
309
325
  }
310
326
 
327
+ renderSwipe() {
328
+ if (this.props.mapviewer_config.Download) return;
329
+ if (this.view)
330
+ return <SwipeWidget view={this.view} mapViewer={this} map={this.map} />;
331
+ }
332
+
311
333
  renderArea() {
312
334
  if (this.props.mapviewer_config.Download) return;
313
335
  if (this.view) {
@@ -341,6 +363,8 @@ class MapViewer extends React.Component {
341
363
  mapCfg={this.mapCfg}
342
364
  urls={this.cfgUrls}
343
365
  loadingHandler={this.loadingHandler}
366
+ hotspotData={this.state.hotspotData}
367
+ hotspotDataHandler={this.hotspotDataHandler}
344
368
  />
345
369
  );
346
370
  }
@@ -361,6 +385,8 @@ class MapViewer extends React.Component {
361
385
  activeLayersHandler={this.activeLayersHandler}
362
386
  urls={this.cfgUrls}
363
387
  loadingHandler={this.loadingHandler}
388
+ hotspotDataHandler={this.hotspotDataHandler}
389
+ hotspotData={this.state.hotspotData}
364
390
  />
365
391
  ); //call conf
366
392
  }
@@ -402,6 +428,7 @@ class MapViewer extends React.Component {
402
428
  {this.renderLegend()}
403
429
  {this.renderMeasurement()}
404
430
  {this.renderPrint()}
431
+ {this.renderSwipe()}
405
432
  {this.renderArea()}
406
433
  {this.renderPan()}
407
434
  {this.renderScale()}
@@ -259,7 +259,8 @@ class MenuWidget extends React.Component {
259
259
  this.xml = null;
260
260
  this.dataBBox = null;
261
261
  this.extentInitiated = false;
262
-
262
+ this.prepareHotspotLayers = this.prepareHotspotLayers.bind(this);
263
+ this.activeLayersToHotspotData = this.activeLayersToHotspotData.bind(this);
263
264
  // add zoomend listener to map to show/hide zoom in message
264
265
  this.view.watch('stationary', (isStationary) => {
265
266
  let snowAndIceInSessionStorage = sessionStorage.getItem('snowAndIce');
@@ -351,6 +352,56 @@ class MenuWidget extends React.Component {
351
352
  );
352
353
  }
353
354
 
355
+ stringMatch(str1, str2) {
356
+ let matchingPart = '';
357
+ for (let i = 0; i < str1.length; i++) {
358
+ if (str1[i] === str2[i]) {
359
+ matchingPart += str1[i];
360
+ } else {
361
+ break;
362
+ }
363
+ }
364
+ return matchingPart;
365
+ }
366
+
367
+ prepareHotspotLayers() {
368
+ this.compCfg.forEach((component) => {
369
+ const hotspotProduct = component.Products.find(
370
+ (product) => product.ProductId === 'd764e020485a402598551fa461bf1db2',
371
+ );
372
+
373
+ if (hotspotProduct !== undefined) {
374
+ const datasetObj = {};
375
+ hotspotProduct.Datasets.forEach((dataset) => {
376
+ const layerObj = {};
377
+ dataset.Layer.forEach((layer) => {
378
+ layerObj[layer.LayerId] = layer;
379
+ });
380
+ let key;
381
+ if (dataset.Layer.length === 1) {
382
+ key = dataset.Layer[0].LayerId;
383
+ } else if (dataset.Layer.length === 2) {
384
+ key = this.stringMatch(
385
+ dataset.Layer[0].LayerId,
386
+ dataset.Layer[1].LayerId,
387
+ );
388
+ if (key.endsWith('_')) {
389
+ key = key.slice(0, -1);
390
+ }
391
+ } else if (dataset.Layer.length > 2) {
392
+ key = dataset.DatasetTitle.toLowerCase()
393
+ .split(' ')
394
+ .join('_')
395
+ .split('_(')[0]
396
+ .split('_for')[0];
397
+ }
398
+ datasetObj[key] = layerObj;
399
+ });
400
+ return this.props.hotspotDataHandler(datasetObj);
401
+ }
402
+ });
403
+ }
404
+
354
405
  // get custom TMS layer JSON
355
406
  getTMSLayersJSON() {
356
407
  let promises = []; // download JSON file calls
@@ -589,6 +640,7 @@ class MenuWidget extends React.Component {
589
640
  loadCss();
590
641
  await this.loader();
591
642
  await this.getTMSLayersJSON();
643
+ this.prepareHotspotLayers();
592
644
  this.props.view.ui.add(this.container.current, 'top-left');
593
645
  if (this.props.download) {
594
646
  setTimeout(() => {
@@ -1542,6 +1594,8 @@ class MenuWidget extends React.Component {
1542
1594
  */
1543
1595
 
1544
1596
  checkForHotspots(elem, productContainerId) {
1597
+ if (!(elem.id.includes('all_present') || elem.id.includes('all_lcc')))
1598
+ return;
1545
1599
  let elemContainer = document
1546
1600
  .getElementById(elem.id)
1547
1601
  .closest('.ccl-form-group');
@@ -1718,15 +1772,15 @@ class MenuWidget extends React.Component {
1718
1772
  .getElementById(parentId)
1719
1773
  .closest('.map-menu-product-dropdown')
1720
1774
  .getAttribute('productid');
1721
- /*let modularLC;
1722
- if (elem.id.includes('all_present_lc_b_pol')) {
1723
- modularLC = elem.id;
1724
- }*/
1725
1775
 
1726
1776
  let group = this.getGroup(elem);
1727
1777
  if (elem.checked) {
1728
1778
  this.props.loadingHandler(true);
1729
- if (this.props.download || this.location.search !== '') {
1779
+ if (
1780
+ this.props.download ||
1781
+ this.location.search.includes('product=') ||
1782
+ this.location.search.includes('dataset=')
1783
+ ) {
1730
1784
  if (
1731
1785
  this.extentInitiated === false &&
1732
1786
  productContainerId !== 'd764e020485a402598551fa461bf1db2' // hotspot
@@ -1747,13 +1801,7 @@ class MenuWidget extends React.Component {
1747
1801
  } else {
1748
1802
  this.map.add(this.layers[elem.id]);
1749
1803
  }
1750
- } /*else if (this.layers[modularLC]) {
1751
- let previousElem = document
1752
- .getElementById(elem.id)
1753
- .closest('.ccl-form-group')
1754
- .previousElementSibling.querySelector('input');
1755
- this.map.add(this.layers[previousElem.id]);
1756
- } */ else {
1804
+ } else {
1757
1805
  this.map.add(this.layers[elem.id]);
1758
1806
  }
1759
1807
  if (this.layers[elem.id] === undefined) return;
@@ -1783,13 +1831,25 @@ class MenuWidget extends React.Component {
1783
1831
  if (nuts) {
1784
1832
  this.map.reorder(nuts, this.map.layers.items.length + 1);
1785
1833
  }
1786
- this.props.view.whenLayerView(this.layers[elem.id]).then((layerView) => {
1787
- layerView.watch('updating', (isUpdating) => {
1788
- if (!isUpdating) {
1789
- this.props.loadingHandler(false);
1790
- }
1834
+ this.props.view
1835
+ .whenLayerView(this.layers[elem.id])
1836
+ .then((layerView) => {
1837
+ layerView.watch('updating', (isUpdating) => {
1838
+ if (!isUpdating) {
1839
+ this.props.loadingHandler(false);
1840
+ } else {
1841
+ }
1842
+ });
1843
+ })
1844
+ .catch((error) => {
1845
+ let newHotspotData = this.props.hotspotData;
1846
+ let LayerId = elem.id.replace(/\d+\D*/g, '').slice(0, -1);
1847
+ let errObj = {};
1848
+ errObj[LayerId] = error;
1849
+ newHotspotData['layerViewError'] = errObj;
1850
+ this.props.hotspotDataHandler(newHotspotData);
1851
+ this.props.loadingHandler(false);
1791
1852
  });
1792
- });
1793
1853
  this.checkForHotspots(elem, productContainerId);
1794
1854
  } else {
1795
1855
  sessionStorage.removeItem('downloadButtonClicked');
@@ -1815,10 +1875,44 @@ class MenuWidget extends React.Component {
1815
1875
  ) {
1816
1876
  this.toggleCustomLegendItem(this.layers[elem.id]);
1817
1877
  }
1878
+ this.activeLayersToHotspotData(elem.id);
1818
1879
  // update DOM
1819
- this.setState({});
1880
+ //this.setState({});
1820
1881
  }
1821
1882
 
1883
+ activeLayersToHotspotData(layerId) {
1884
+ let layer = Object.entries(this.layers).find(
1885
+ ([key, value]) => key === layerId,
1886
+ )?.[1];
1887
+ let hotspotLayersIds = [];
1888
+ let updatedActiveLayers = this.props.hotspotData['activeLayers'] || {};
1889
+ let newHotspotData = this.props.hotspotData;
1890
+
1891
+ Object.keys(this.props.hotspotData).forEach((key) => {
1892
+ let dataset = this.props.hotspotData[key];
1893
+ Object.keys(dataset).forEach((layerKey) => {
1894
+ hotspotLayersIds.push(layerKey);
1895
+ });
1896
+ });
1897
+
1898
+ for (let i = 0; i < hotspotLayersIds.length; i++) {
1899
+ const id = hotspotLayersIds[i];
1900
+ if (!layerId.includes(id)) continue;
1901
+ else if (layerId.includes(id)) {
1902
+ if (layer.visible === true) {
1903
+ updatedActiveLayers[id] = layer;
1904
+ } else if (layer.visible === false) {
1905
+ if (updatedActiveLayers[id]) {
1906
+ delete updatedActiveLayers[id];
1907
+ }
1908
+ }
1909
+ break;
1910
+ }
1911
+ }
1912
+
1913
+ newHotspotData['activeLayers'] = updatedActiveLayers;
1914
+ return this.props.hotspotDataHandler(newHotspotData);
1915
+ }
1822
1916
  //CLMS-1634 - This shows the zoom message for the checked dataset under the Snow and Ice Parameters Products dropdown only.
1823
1917
 
1824
1918
  showZoomMessageOnDataset(dataset) {
@@ -2849,16 +2943,15 @@ class MenuWidget extends React.Component {
2849
2943
  layers.push(layer);
2850
2944
  }
2851
2945
  });
2946
+ if (layers.length === 0 && document.querySelector('.info-container')) {
2947
+ document.querySelector('.info-container').style.display = 'none';
2948
+ } else if (layers.length > 0) {
2949
+ document.querySelector('.info-container').style.display = 'flex';
2950
+ }
2852
2951
  if (!sessionStorage.getItem('hotspotFilterApplied')) {
2853
- if (layers.length === 0 && document.querySelector('.info-container')) {
2854
- this.props.mapViewer.closeActiveWidget();
2855
- document.querySelector('.info-container').style.display = 'none';
2856
- } else if (layers.length > 0) {
2857
- document.querySelector('.info-container').style.display = 'flex';
2858
- }
2952
+ this.props.mapViewer.closeActiveWidget();
2859
2953
  }
2860
2954
  this.renderHotspot();
2861
- /**/
2862
2955
  }
2863
2956
 
2864
2957
  getLayerTitle(layer) {
@@ -3246,10 +3339,8 @@ class MenuWidget extends React.Component {
3246
3339
  deleteFilteredLayer(layer) {
3247
3340
  let layers = this.layers;
3248
3341
  if (layers['lcc_filter'] && layer.includes('all_lcc')) {
3249
- layers['lcc_filter'].visible = false;
3250
3342
  delete layers['lcc_filter'];
3251
3343
  } else if (layers['lc_filter'] && layer.includes('all_present_lc')) {
3252
- layers['lc_filter'].visible = false;
3253
3344
  delete layers['lc_filter'];
3254
3345
  } else if (layers['klc_filter'] && layer.includes('cop_klc')) {
3255
3346
  layers['klc_filter'].visible = false;
@@ -0,0 +1,238 @@
1
+ import React, { createRef } from 'react';
2
+ //import "@arcgis/core/assets/esri/css/main.css";
3
+ //import "./css/ArcgisMap.css";
4
+ import { loadModules } from 'esri-loader';
5
+ var Swipe;
6
+
7
+ class SwipeWidget extends React.Component {
8
+ /**
9
+ * Creator of the Measurement widget class
10
+ * @param {*} props
11
+ */
12
+ constructor(props) {
13
+ super(props);
14
+ //We create a reference to a DOM element to be mounted
15
+ this.container = createRef();
16
+ //Initially, we set the state of the component to
17
+ //not be showing the basemap panel
18
+ this.state = { showMapMenu: false };
19
+ this.menuClass =
20
+ 'esri-icon-swap esri-widget--button esri-widget esri-interactive';
21
+ this.titleMaxLength = 50;
22
+ this.authorMaxLength = 60;
23
+ this.textMaxLength = 180;
24
+ this.sizeMax = 15000;
25
+ this.dpiMax = 1200;
26
+ this.scaleMax = 600000000;
27
+ this.map = this.props.map;
28
+ this.visibleSavedLayers = [];
29
+ }
30
+
31
+ loader() {
32
+ return loadModules(['esri/widgets/Swipe']).then(([_Swipe]) => {
33
+ Swipe = _Swipe;
34
+ });
35
+ }
36
+
37
+ /**
38
+ * Method that will be invoked when the
39
+ * button is clicked. It controls the open
40
+ * and close actions of the component
41
+ */
42
+ openMenu() {
43
+ if (this.state.showMapMenu) {
44
+ // CLOSE
45
+ this.props.mapViewer.setActiveWidget();
46
+ this.container.current
47
+ .querySelector('.esri-widget--button')
48
+ .classList.remove('active-widget');
49
+ document
50
+ .querySelector('.esri-ui-top-right.esri-ui-corner')
51
+ .classList.remove('show-panel');
52
+ this.loadVisibleLayers();
53
+ this.swipe.leadingLayers.removeAll();
54
+ this.swipe.trailingLayers.removeAll();
55
+ this.props.view.ui.remove(this.swipe);
56
+ this.container.current.querySelector('.right-panel').style.display =
57
+ 'none';
58
+ this.setState({ showMapMenu: false });
59
+ } else {
60
+ // OPEN
61
+ this.props.mapViewer.setActiveWidget(this);
62
+ this.container.current.querySelector('.right-panel').style.display =
63
+ 'flex';
64
+ this.container.current
65
+ .querySelector('.esri-widget--button')
66
+ .classList.add('active-widget');
67
+ document
68
+ .querySelector('.esri-ui-top-right.esri-ui-corner')
69
+ .classList.add('show-panel');
70
+ // By invoking the setState, we notify the state we want to reach
71
+ // and ensure that the component is rendered again
72
+ this.loadOptions();
73
+ this.map.layers.on('change', () => {
74
+ this.loadVisibleLayers();
75
+ this.swipe.leadingLayers.removeAll();
76
+ this.swipe.trailingLayers.removeAll();
77
+ this.props.view.ui.remove(this.swipe);
78
+ this.loadOptions();
79
+ });
80
+ this.setState({ showMapMenu: true });
81
+ }
82
+ }
83
+ /**
84
+ * This method is executed after the rener method is executed
85
+ */
86
+ async componentDidMount() {
87
+ this.props.view.ui.add(this.container.current, 'top-right');
88
+ await this.loader();
89
+ this.swipe = new Swipe({
90
+ view: this.props.view,
91
+ position: 50,
92
+ });
93
+ }
94
+
95
+ getLayerTitle(layer) {
96
+ let title;
97
+ if (layer.url.toLowerCase().includes('wmts')) {
98
+ title = layer._wmtsTitle;
99
+ } else {
100
+ if (layer.sublayers) {
101
+ title = layer.sublayers.items[0].title;
102
+ } else if (layer.activeLayer) {
103
+ title = layer.activeLayer.title;
104
+ } else {
105
+ title = layer.title;
106
+ }
107
+ }
108
+ return title;
109
+ }
110
+ loadOptions() {
111
+ var selectLeadingLayer = document.getElementById('select-leading-layer');
112
+ var selectTrailingLayer = document.getElementById('select-trailing-layer');
113
+ this.removeOptions(selectLeadingLayer);
114
+ this.removeOptions(selectTrailingLayer);
115
+ selectLeadingLayer.options.add(
116
+ new Option('Select a leading layer', 'default', true, true),
117
+ );
118
+ selectLeadingLayer.options[0].disabled = true;
119
+ selectTrailingLayer.options.add(
120
+ new Option('Select a trailing layer', 'default', true, true),
121
+ );
122
+ selectTrailingLayer.options[0].disabled = true;
123
+ this.map.layers.forEach((layer) => {
124
+ selectLeadingLayer.options.add(
125
+ new Option(this.getLayerTitle(layer), layer.id, layer.id),
126
+ );
127
+ selectTrailingLayer.options.add(
128
+ new Option(this.getLayerTitle(layer), layer.id, layer.id),
129
+ );
130
+ });
131
+ }
132
+ removeOptions(selectElement) {
133
+ if (selectElement.options.length > 0) {
134
+ var i,
135
+ L = selectElement.options.length - 1;
136
+ for (i = L; i >= 0; i--) {
137
+ selectElement.remove(i);
138
+ }
139
+ }
140
+ }
141
+ renderApplySwipeButton() {
142
+ if (this.visibleSavedLayers.length === 0) {
143
+ this.saveVisibleLayers();
144
+ }
145
+ this.props.view.ui.remove(this.swipe);
146
+ this.props.view.ui.add(this.swipe);
147
+ let selectedLeadingLayer = document.getElementById('select-leading-layer')
148
+ .value;
149
+ let selectedTrailingLayer = document.getElementById('select-trailing-layer')
150
+ .value;
151
+ this.swipe.leadingLayers.removeAll();
152
+ this.swipe.trailingLayers.removeAll();
153
+ this.map.layers.forEach((layer) => {
154
+ layer.visible = false;
155
+ if (layer.id === selectedLeadingLayer) {
156
+ layer.visible = true;
157
+ this.swipe.leadingLayers.add(layer);
158
+ }
159
+ if (layer.id === selectedTrailingLayer) {
160
+ layer.visible = true;
161
+ this.swipe.trailingLayers.add(layer);
162
+ }
163
+ });
164
+ }
165
+ saveVisibleLayers() {
166
+ this.visibleSavedLayers.push('default');
167
+ this.map.layers.forEach((layer) => {
168
+ if (layer.visible) {
169
+ this.visibleSavedLayers.push(layer.id);
170
+ }
171
+ });
172
+ }
173
+ loadVisibleLayers() {
174
+ this.map.layers.forEach((layer) => {
175
+ this.visibleSavedLayers.forEach((visibleLayerId) => {
176
+ if (layer.id === visibleLayerId) {
177
+ layer.visible = true;
178
+ }
179
+ });
180
+ });
181
+ this.visibleSavedLayers = [];
182
+ }
183
+ /**
184
+ * This method renders the component
185
+ * @returns jsx
186
+ */
187
+ render() {
188
+ return (
189
+ <>
190
+ <div ref={this.container} className="swipe-container">
191
+ <div tooltip="Swipe" direction="left" type="widget">
192
+ <div
193
+ className={this.menuClass}
194
+ id="map_swipe_button"
195
+ aria-label="Swipe"
196
+ onClick={this.openMenu.bind(this)} //aqui deberían ir ocultar panel y mas abajo cerrar (pasar a 3d)
197
+ onKeyDown={this.openMenu.bind(this)}
198
+ tabIndex="0"
199
+ role="button"
200
+ ></div>
201
+ </div>
202
+ {/* Al final el IF lo añadiremos aqui en estos OpenMenu */}
203
+ <div className="right-panel">
204
+ <div className="right-panel-header">
205
+ <span>Swipe</span>
206
+ <span
207
+ className="map-menu-icon esri-icon-close"
208
+ onClick={this.openMenu.bind(this)}
209
+ onKeyDown={this.openMenu.bind(this)}
210
+ tabIndex="0"
211
+ role="button"
212
+ ></span>
213
+ </div>
214
+ <div className="right-panel-content">
215
+ <div className="swipe-panel">
216
+ <span>Leading Layer</span>
217
+ <select id="select-leading-layer" class="esri-select"></select>
218
+ <br></br>
219
+ <span>Trailing Layer</span>
220
+ <select id="select-trailing-layer" class="esri-select"></select>
221
+ <br></br>
222
+ <button
223
+ id="applySwipeButton"
224
+ class="esri-button"
225
+ onClick={() => this.renderApplySwipeButton()}
226
+ >
227
+ Swipe
228
+ </button>
229
+ </div>
230
+ </div>
231
+ </div>
232
+ </div>
233
+ </>
234
+ );
235
+ }
236
+ }
237
+
238
+ export default SwipeWidget;
@@ -1371,3 +1371,16 @@ div.map-container.popup-block {
1371
1371
  align-items:center;
1372
1372
  }
1373
1373
  */
1374
+
1375
+ /*Swipe*/
1376
+
1377
+ .swipe-container .esri-button {
1378
+ border: none;
1379
+ background-color: #a0b128;
1380
+ }
1381
+
1382
+ .swipe-container .esri-button:hover {
1383
+ border-color: #a0b128;
1384
+ background-color: white;
1385
+ color: #a0b128;
1386
+ }