@eeacms/volto-arcgis-block 0.1.74 → 0.1.76

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,45 @@ 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.76](https://github.com/eea/volto-arcgis-block/compare/0.1.75...0.1.76) - 25 November 2022
8
+
9
+ #### :rocket: New Features
10
+
11
+ - feat: added legends for WMTS and TMS layers [joewdavies - [`cf24e61`](https://github.com/eea/volto-arcgis-block/commit/cf24e6188430724172ced72d0bda116e08845123)]
12
+ - feat: added legends for WMTS and TMS layers [joewdavies - [`2429361`](https://github.com/eea/volto-arcgis-block/commit/2429361bb9cb6d871575dccbb3e1e38a3c13257f)]
13
+
14
+ #### :hammer_and_wrench: Others
15
+
16
+ - specify volto-ci version in jenkinsfile cypress [joewdavies - [`2e3a641`](https://github.com/eea/volto-arcgis-block/commit/2e3a64155c24e94227254ab3ed2a88328f15f8af)]
17
+ - ESlint fix [joewdavies - [`3f086d0`](https://github.com/eea/volto-arcgis-block/commit/3f086d052d26a3dbf186a00403be5d5a56fe44cc)]
18
+ - specify volto-ci version in jenkinsfile [joewdavies - [`a4756a7`](https://github.com/eea/volto-arcgis-block/commit/a4756a72218295a5d3a4dd645823b1c6b5631032)]
19
+ - specify volto-ci version in jenkinsfile [joewdavies - [`667f02c`](https://github.com/eea/volto-arcgis-block/commit/667f02c640a858d33cd092e26b79ee80900f63a0)]
20
+ - specify volto-ci version in jenkinsfile [joewdavies - [`c8434f2`](https://github.com/eea/volto-arcgis-block/commit/c8434f2157ec72506b746d5d214d87ff3a72c3f4)]
21
+ - specify volto-ci version in jenkinsfile [joewdavies - [`482e770`](https://github.com/eea/volto-arcgis-block/commit/482e77029a1569f149c4674362897e972a961f5c)]
22
+ - specify volto-ci version in jenkinsfile [joewdavies - [`a5d7ad7`](https://github.com/eea/volto-arcgis-block/commit/a5d7ad7d7579c295659105623d1c160ad593d6ee)]
23
+ ### [0.1.75](https://github.com/eea/volto-arcgis-block/compare/0.1.74...0.1.75) - 22 November 2022
24
+
25
+ #### :rocket: New Features
26
+
27
+ - feat: show zoom in message for snow and ice product when zoom level is below 7 - CLMS-1528 [joewdavies - [`7ac9d04`](https://github.com/eea/volto-arcgis-block/commit/7ac9d04ab96b44b22ea8520e7c8677e286df525e)]
28
+ - feat: show zoom in message for snow and ice product when zoom level is below 7 - CLMS-1528 [joewdavies - [`e803695`](https://github.com/eea/volto-arcgis-block/commit/e803695e46fba76a48186ebdf25c7a74f02e3a08)]
29
+ - feat: show zoom in message for snow and ice product when zoom level is below 7 - CLMS-1528 [joewdavies - [`1734f89`](https://github.com/eea/volto-arcgis-block/commit/1734f89ee8bc16dc1bc18d5d76b3131b044796c5)]
30
+ - feat: show zoom in message for snow and ice product when zoom level is below 7 - CLMS-1528 [joewdavies - [`5f12f70`](https://github.com/eea/volto-arcgis-block/commit/5f12f702061b34421302d6037a87e131c19f3b56)]
31
+ - feat: show zoom in message for snow and ice product when zoom level is below 7 - CLMS-1528 [joewdavies - [`d6e4dea`](https://github.com/eea/volto-arcgis-block/commit/d6e4dea9b5030217ca5faad8c33959e65b9d179b)]
32
+ - feat: load TMS layers JSON asynchronosly [joewdavies - [`a36ac9b`](https://github.com/eea/volto-arcgis-block/commit/a36ac9b99deaa1b5ed344fd869589ea0f053aabb)]
33
+
34
+ #### :hammer_and_wrench: Others
35
+
36
+ - prettier fix [joewdavies - [`3855674`](https://github.com/eea/volto-arcgis-block/commit/3855674ce363b58387dc818bf4a86ce50ff7ee38)]
37
+ - prettier fix [joewdavies - [`a900320`](https://github.com/eea/volto-arcgis-block/commit/a9003201ed25be8636c59ca5e075e98f15086b7d)]
38
+ - prettier fix [joewdavies - [`8b4f2d2`](https://github.com/eea/volto-arcgis-block/commit/8b4f2d24815d96c3be14a2455a6a2af844aa16ba)]
39
+ - prettier fix [joewdavies - [`d578f5a`](https://github.com/eea/volto-arcgis-block/commit/d578f5a6fbc54ed3cf24ae2fe9c439daa3b82961)]
40
+ - add default TMS layer if none specified [joewdavies - [`ffbdc0e`](https://github.com/eea/volto-arcgis-block/commit/ffbdc0e4d1e27d0fd886200a9bba29cc5763698c)]
41
+ - ESLint fix [joewdavies - [`a22c35f`](https://github.com/eea/volto-arcgis-block/commit/a22c35f4568c69b654dc414c61b80257d6932430)]
42
+ - attempt to get TMS layer to work with legend widget [joewdavies - [`4271bdd`](https://github.com/eea/volto-arcgis-block/commit/4271bddff97667c7f1a466b53df568b7cb3a3a14)]
43
+ - remove TMS layer correctly [joewdavies - [`9fb63f1`](https://github.com/eea/volto-arcgis-block/commit/9fb63f1983f82fe9452a9830eff640bc136f7137)]
44
+ - remove superfluous logs [joewdavies - [`9b0717b`](https://github.com/eea/volto-arcgis-block/commit/9b0717bed39113b448e10c9ad4e1fecf2d83bb09)]
45
+ - TMS json progress [joewdavies - [`f24c7c7`](https://github.com/eea/volto-arcgis-block/commit/f24c7c7da483221c15a705bf6972075e1f9bc7a6)]
7
46
  ### [0.1.74](https://github.com/eea/volto-arcgis-block/compare/0.1.73...0.1.74) - 27 October 2022
8
47
 
9
48
  ### [0.1.73](https://github.com/eea/volto-arcgis-block/compare/0.1.72...0.1.73) - 26 October 2022
package/Jenkinsfile CHANGED
@@ -6,6 +6,7 @@ pipeline {
6
6
  NAMESPACE = "@eeacms"
7
7
  SONARQUBE_TAGS = "volto.eea.europa.eu,clms.land.copernicus.eu,water.europa.eu-freshwater,clmsdemo.devel6cph.eea.europa.eu"
8
8
  DEPENDENCIES = ""
9
+ VOLTO = "15.16.0"
9
10
  }
10
11
 
11
12
  stages {
@@ -76,8 +77,8 @@ pipeline {
76
77
  node(label: 'docker') {
77
78
  script {
78
79
  try {
79
- sh '''docker pull plone/volto-addon-ci'''
80
- sh '''docker run -i --name="$BUILD_TAG-volto" -e NAMESPACE="$NAMESPACE" -e GIT_NAME=$GIT_NAME -e GIT_BRANCH="$BRANCH_NAME" -e GIT_CHANGE_ID="$CHANGE_ID" plone/volto-addon-ci'''
80
+ sh '''docker pull plone/volto-addon-ci:15.x'''
81
+ sh '''docker run -i --name="$BUILD_TAG-volto" -e NAMESPACE="$NAMESPACE" -e VOLTO=$VOLTO -e GIT_NAME=$GIT_NAME -e GIT_BRANCH="$BRANCH_NAME" -e GIT_CHANGE_ID="$CHANGE_ID" plone/volto-addon-ci:15.x'''
81
82
  sh '''rm -rf xunit-reports'''
82
83
  sh '''mkdir -p xunit-reports'''
83
84
  sh '''docker cp $BUILD_TAG-volto:/opt/frontend/my-volto-project/coverage xunit-reports/'''
@@ -125,7 +126,7 @@ pipeline {
125
126
  script {
126
127
  try {
127
128
  sh '''docker pull plone; docker run -d --rm --name="$BUILD_TAG-plone" -e SITE="Plone" -e PROFILES="profile-plone.restapi:blocks" plone fg'''
128
- sh '''docker pull plone/volto-addon-ci; docker run -i --name="$BUILD_TAG-cypress" --link $BUILD_TAG-plone:plone -e NAMESPACE="$NAMESPACE" -e GIT_NAME=$GIT_NAME -e GIT_BRANCH="$BRANCH_NAME" -e GIT_CHANGE_ID="$CHANGE_ID" -e DEPENDENCIES="$DEPENDENCIES" -e NODE_ENV=test plone/volto-addon-ci cypress'''
129
+ sh '''docker pull plone/volto-addon-ci; docker run -i --name="$BUILD_TAG-cypress" --link $BUILD_TAG-plone:plone -e VOLTO=$VOLTO -e NAMESPACE="$NAMESPACE" -e GIT_NAME=$GIT_NAME -e GIT_BRANCH="$BRANCH_NAME" -e GIT_CHANGE_ID="$CHANGE_ID" -e DEPENDENCIES="$DEPENDENCIES" -e NODE_ENV=test plone/volto-addon-ci cypress'''
129
130
  } finally {
130
131
  try {
131
132
  sh '''rm -rf cypress-reports cypress-results cypress-coverage'''
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-arcgis-block",
3
- "version": "0.1.74",
3
+ "version": "0.1.76",
4
4
  "description": "volto-arcgis-block: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: CodeSyntax",
@@ -1,6 +1,9 @@
1
1
  import React, { createRef } from 'react';
2
2
  import { loadModules } from 'esri-loader';
3
3
  var BasemapGallery;
4
+ // var Basemap;
5
+ // var WebTileLayer;
6
+ // var LocalBasemapsSource;
4
7
 
5
8
  class BasemapWidget extends React.Component {
6
9
  /**
@@ -20,9 +23,17 @@ class BasemapWidget extends React.Component {
20
23
  }
21
24
 
22
25
  loader() {
23
- return loadModules(['esri/widgets/BasemapGallery']).then(
24
- ([_BasemapGallery]) => {
26
+ return loadModules([
27
+ 'esri/widgets/BasemapGallery',
28
+ 'esri/Basemap',
29
+ 'esri/layers/WebTileLayer',
30
+ 'esri/widgets/BasemapGallery/support/LocalBasemapsSource',
31
+ ]).then(
32
+ ([_BasemapGallery, _Basemap, _WebTileLayer, _LocalBasemapsSource]) => {
25
33
  BasemapGallery = _BasemapGallery;
34
+ // Basemap = _Basemap;
35
+ // WebTileLayer = _WebTileLayer;
36
+ // LocalBasemapsSource = _LocalBasemapsSource;
26
37
  },
27
38
  );
28
39
  }
@@ -95,9 +106,30 @@ class BasemapWidget extends React.Component {
95
106
  async componentDidMount() {
96
107
  await this.loader();
97
108
  if (!this.container.current) return;
109
+
110
+ // custom basemaps
111
+ // let basemaps = [Basemap.fromId('topo-vector'), Basemap.fromId('hybrid')];
112
+ // basemaps.push(
113
+ // new Basemap({
114
+ // baseLayers: [
115
+ // new WebTileLayer({
116
+ // urlTemplate:
117
+ // 'https://gisco-services.ec.europa.eu/maps/wmts/OSMCartoV4CompositeEN/EPSG3857/{z}/{x}/{y}.png',
118
+ // }),
119
+ // ],
120
+ // title: 'OSM GISCO',
121
+ // id: 'osm-gisco',
122
+ // }),
123
+ // );
124
+
125
+ // let customSource = new LocalBasemapsSource({
126
+ // basemaps,
127
+ // });
128
+
98
129
  this.basemapGallery = new BasemapGallery({
99
130
  view: this.props.view,
100
131
  container: this.container.current.querySelector('.basemap-panel'),
132
+ // source: customSource
101
133
  });
102
134
  this.props.view.ui.add(this.container.current, 'top-right');
103
135
  }
@@ -297,11 +297,14 @@ class InfoWidget extends React.Component {
297
297
  break;
298
298
  case 'featureLayer':
299
299
  if (data.results.length) {
300
- var graphic = data.results.filter((result) => {
300
+ var graphics = data.results.filter((result) => {
301
301
  return result.graphic.layer === layers[index];
302
- })[0].graphic;
303
- if (graphic) {
304
- properties = graphic.attributes;
302
+ });
303
+ if (graphics[0]) {
304
+ let graphic = graphics[0].graphic;
305
+ if (graphic) {
306
+ properties = graphic.attributes;
307
+ }
305
308
  }
306
309
  }
307
310
  this.infoData[index] = {
@@ -9,7 +9,7 @@ import TimesliderWidget from './TimesliderWidget';
9
9
  import { Toast } from '@plone/volto/components';
10
10
  import { toast } from 'react-toastify';
11
11
  import { UniversalLink } from '@plone/volto/components';
12
- var WMSLayer, WMTSLayer, FeatureLayer;
12
+ var WMSLayer, WMTSLayer, FeatureLayer, BaseTileLayer, esriRequest;
13
13
 
14
14
  const popupSettings = {
15
15
  basic: true,
@@ -412,16 +412,28 @@ class MenuWidget extends React.Component {
412
412
  this.container = createRef();
413
413
  //Initially, we set the state of the component to
414
414
  //not be showing the basemap panel
415
- this.state = { showMapMenu: false };
415
+ this.state = { showMapMenu: false, tms_jsx: null };
416
416
  // call the props of the layers list (mapviewer.jsx)
417
417
  this.compCfg = this.props.conf;
418
418
  this.map = this.props.map;
419
+ this.view = this.props.view;
419
420
  this.menuClass =
420
421
  'esri-icon-drag-horizontal esri-widget--button esri-widget esri-interactive';
421
422
  this.loadFirst = true;
422
423
  this.layers = {};
423
424
  this.activeLayersJSON = {};
424
425
  this.layerGroups = {};
426
+
427
+ // add zoomend listener to map to show/hide zoom in message
428
+ this.view.watch('stationary', (isStationary) => {
429
+ if (isStationary) {
430
+ let node = document.getElementById('snow-and-ice-zoom-message');
431
+ if (node) {
432
+ let zoom = this.view.get('zoom');
433
+ node.style.display = zoom > 6 ? 'none' : 'block';
434
+ }
435
+ }
436
+ });
425
437
  }
426
438
 
427
439
  loader() {
@@ -429,11 +441,53 @@ class MenuWidget extends React.Component {
429
441
  'esri/layers/WMSLayer',
430
442
  'esri/layers/WMTSLayer',
431
443
  'esri/layers/FeatureLayer',
432
- ]).then(([_WMSLayer, _WMTSLayer, _FeatureLayer]) => {
433
- WMSLayer = _WMSLayer;
434
- WMTSLayer = _WMTSLayer;
435
- FeatureLayer = _FeatureLayer;
444
+ 'esri/layers/BaseTileLayer',
445
+ 'esri/request',
446
+ ]).then(
447
+ ([
448
+ _WMSLayer,
449
+ _WMTSLayer,
450
+ _FeatureLayer,
451
+ _BaseTileLayer,
452
+ _esriRequest,
453
+ ]) => {
454
+ WMSLayer = _WMSLayer;
455
+ WMTSLayer = _WMTSLayer;
456
+ FeatureLayer = _FeatureLayer;
457
+ BaseTileLayer = _BaseTileLayer;
458
+ esriRequest = _esriRequest;
459
+ },
460
+ );
461
+ }
462
+
463
+ // get custom TMS layer JSON
464
+ getTMSLayersJSON() {
465
+ let promises = []; // download JSON file calls
466
+ this.compCfg.forEach((component) => {
467
+ component.Products.forEach((product) => {
468
+ product.Datasets.forEach((dataset) => {
469
+ if (dataset.ViewService.endsWith('file')) {
470
+ let promise = fetch(dataset.ViewService, { mode: 'no-cors' })
471
+ .then((response) => {
472
+ if (!response.ok) {
473
+ throw new Error(`HTTP error, status = ${response.status}`);
474
+ }
475
+ return response.json();
476
+ })
477
+ .then((data) => {
478
+ // fill dataset.Layer manually
479
+ dataset.Layer = data.Layers;
480
+ })
481
+ .catch((error) => {
482
+ throw new Error(error);
483
+ });
484
+ promises.push(promise);
485
+ }
486
+ });
487
+ });
436
488
  });
489
+
490
+ return Promise.all(promises);
437
491
  }
438
492
 
439
493
  /**
@@ -505,11 +559,12 @@ class MenuWidget extends React.Component {
505
559
  }
506
560
 
507
561
  /**
508
- * This method is executed after the rener method is executed
562
+ * This method is executed after the render method is executed
509
563
  */
510
564
  async componentDidMount() {
511
565
  loadCss();
512
566
  await this.loader();
567
+ await this.getTMSLayersJSON();
513
568
  this.props.view.ui.add(this.container.current, 'top-left');
514
569
  if (this.props.download) {
515
570
  document.querySelector('.area-panel input:checked').click();
@@ -737,15 +792,23 @@ class MenuWidget extends React.Component {
737
792
  dataset_def.push(idDataset);
738
793
  }
739
794
 
740
- datasets.push(
741
- this.metodProcessDataset(
742
- product.Datasets[i],
743
- index,
744
- inheritedIndexProduct,
745
- checkProduct,
746
- ),
747
- );
748
- index++;
795
+ // CLMS-1545
796
+ if (
797
+ product.Datasets[i].ViewService !==
798
+ 'https://trial.discomap.eea.europa.eu/arcgis/services/CLMS/WorldCountries/MapServer/WmsServer' &&
799
+ product.Datasets[i].ViewService !==
800
+ 'https://trial.discomap.eea.europa.eu/arcgis/services/CLMS/WorldCountries/MapServer/WmsServer?'
801
+ ) {
802
+ datasets.push(
803
+ this.metodProcessDataset(
804
+ product.Datasets[i],
805
+ index,
806
+ inheritedIndexProduct,
807
+ checkProduct,
808
+ ),
809
+ );
810
+ index++;
811
+ }
749
812
  }
750
813
 
751
814
  // Empty vector, add the first dataset
@@ -802,12 +865,38 @@ class MenuWidget extends React.Component {
802
865
  <legend className="ccl-form-legend">
803
866
  {description ? (
804
867
  <Popup
805
- trigger={<span>{product.ProductTitle}</span>}
868
+ trigger={
869
+ product.ProductId ===
870
+ '8474c3b080fa42cc837f1d2338fcf096' ||
871
+ product.ProductTitle === 'Snow and Ice Parameters' ? (
872
+ <div class="zoom-in-message-container">
873
+ <span>{product.ProductTitle}</span>
874
+ <div
875
+ class="zoom-in-message"
876
+ id="snow-and-ice-zoom-message"
877
+ >
878
+ Zoom in to view on map
879
+ </div>
880
+ </div>
881
+ ) : (
882
+ <span>{product.ProductTitle}</span>
883
+ )
884
+ }
806
885
  content={description}
807
886
  basic
808
887
  className="custom"
809
888
  style={{ transform: 'translateX(-4rem)' }}
810
889
  />
890
+ ) : product.ProductId ===
891
+ '8474c3b080fa42cc837f1d2338fcf096' ||
892
+ product.ProductTitle ===
893
+ 'High Resolution Snow and Ice Parameters' ? (
894
+ <div class="zoom-in-message-container">
895
+ <span>{product.ProductTitle}</span>
896
+ <div class="zoom-in-message">
897
+ Zoom in to view on map
898
+ </div>
899
+ </div>
811
900
  ) : (
812
901
  <span>{product.ProductTitle}</span>
813
902
  )}
@@ -860,32 +949,93 @@ class MenuWidget extends React.Component {
860
949
  ? dataset.DatasetDescription.substr(0, 300) + '...'
861
950
  : dataset.DatasetDescription;
862
951
 
952
+ let style = this.props.download
953
+ ? { paddingLeft: dataset.HandlingLevel ? '0' : '1rem' }
954
+ : {};
955
+
863
956
  if (dataset.HandlingLevel) {
864
957
  this.layerGroups[dataset.DatasetId] = [];
865
958
  }
866
- for (var i in dataset.Layer) {
867
- if (dataset.Layer[i].Default_active === true) {
868
- layer_default.push(
869
- dataset.Layer[i].LayerId + '_' + inheritedIndexDataset + '_' + i,
959
+
960
+ // TMS
961
+ if (dataset.ViewService.endsWith('file')) {
962
+ let tmsLayerIndex = 0;
963
+
964
+ dataset.Layer.forEach((layer, sublayerIndex) => {
965
+ if (!layer.LayerId) {
966
+ layer.LayerId = sublayerIndex;
967
+ }
968
+ let inheritedIndexLayer = inheritedIndex + '_' + tmsLayerIndex;
969
+ let checkboxId = layer.LayerId + '_' + inheritedIndexLayer;
970
+
971
+ // add as default
972
+ if (!layer_default.length) {
973
+ layer_default.push(checkboxId);
974
+ }
975
+ // add each sublayer to this.layers
976
+ this.processTMSLayer(layer, checkboxId, dataset);
977
+
978
+ // build TMS DOM nodes for TOC
979
+ layers.push(
980
+ <div
981
+ className="ccl-form-group map-menu-layer"
982
+ id={'layer_' + inheritedIndexLayer}
983
+ key={'a' + tmsLayerIndex}
984
+ data-timeseries={dataset.IsTimeSeries}
985
+ style={style}
986
+ >
987
+ <input
988
+ type="checkbox"
989
+ id={checkboxId}
990
+ parentid={checkIndex}
991
+ layerid={layer.LayerId}
992
+ name="layerCheckbox"
993
+ value="name"
994
+ className="ccl-checkbox ccl-required ccl-form-check-input"
995
+ key={'c' + tmsLayerIndex}
996
+ title={layer.Title}
997
+ onChange={(e) => {
998
+ this.toggleLayer(e.target);
999
+ }}
1000
+ ></input>
1001
+ <label
1002
+ className="ccl-form-check-label"
1003
+ htmlFor={layer.LayerId + '_' + inheritedIndexLayer}
1004
+ key={'d' + tmsLayerIndex}
1005
+ >
1006
+ <span>{layer.Title}</span>
1007
+ </label>
1008
+ </div>,
870
1009
  );
1010
+ tmsLayerIndex++;
1011
+ });
1012
+ } else {
1013
+ for (var i in dataset.Layer) {
1014
+ if (dataset.Layer[i].Default_active === true) {
1015
+ layer_default.push(
1016
+ dataset.Layer[i].LayerId + '_' + inheritedIndexDataset + '_' + i,
1017
+ );
1018
+ }
1019
+ if (dataset.HandlingLevel) {
1020
+ this.layerGroups[dataset.DatasetId].push(dataset.Layer[i].LayerId);
1021
+ }
1022
+
1023
+ layers.push(
1024
+ this.metodProcessLayer(
1025
+ dataset.Layer[i],
1026
+ index,
1027
+ inheritedIndexDataset,
1028
+ dataset.ViewService,
1029
+ dataset.TimeSeriesService,
1030
+ checkIndex,
1031
+ dataset.IsTimeSeries,
1032
+ dataset.DatasetId,
1033
+ dataset.DatasetTitle,
1034
+ dataset.ProductId,
1035
+ ),
1036
+ );
1037
+ index++;
871
1038
  }
872
- if (dataset.HandlingLevel) {
873
- this.layerGroups[dataset.DatasetId].push(dataset.Layer[i].LayerId);
874
- }
875
- layers.push(
876
- this.metodProcessLayer(
877
- dataset.Layer[i],
878
- index,
879
- inheritedIndexDataset,
880
- dataset.ViewService,
881
- dataset.TimeSeriesService,
882
- checkIndex,
883
- dataset.IsTimeSeries,
884
- layer_default,
885
- dataset.HandlingLevel,
886
- ),
887
- );
888
- index++;
889
1039
  }
890
1040
 
891
1041
  if (!layer_default.length) {
@@ -893,9 +1043,6 @@ class MenuWidget extends React.Component {
893
1043
  dataset.Layer[0].LayerId + '_' + inheritedIndexDataset + '_0',
894
1044
  );
895
1045
  }
896
- let style = this.props.download
897
- ? { paddingLeft: dataset.HandlingLevel ? '0' : '1rem' }
898
- : {};
899
1046
 
900
1047
  return (
901
1048
  <div
@@ -1048,28 +1195,32 @@ class MenuWidget extends React.Component {
1048
1195
  layer,
1049
1196
  layerIndex,
1050
1197
  inheritedIndex,
1051
- urlWMS,
1198
+ viewService,
1052
1199
  featureInfoUrl,
1053
1200
  parentIndex,
1054
1201
  isTimeSeries,
1055
- layer_default,
1056
- handlingLevel,
1202
+ DatasetId,
1203
+ DatasetTitle,
1204
+ ProductId,
1057
1205
  ) {
1058
1206
  //For Legend request
1059
1207
  const legendRequest =
1060
1208
  'request=GetLegendGraphic&version=1.0.0&format=image/png&layer=';
1061
1209
  //For each layer
1062
- var inheritedIndexLayer = inheritedIndex + '_' + layerIndex;
1210
+ let inheritedIndexLayer = inheritedIndex + '_' + layerIndex;
1211
+ let style = this.props.download ? { paddingLeft: '4rem' } : {};
1063
1212
  //Add sublayers and popup enabled for layers
1064
1213
  if (
1065
1214
  !this.layers.hasOwnProperty(layer.LayerId + '_' + inheritedIndexLayer)
1066
1215
  ) {
1067
- if (urlWMS.toLowerCase().includes('wms')) {
1068
- urlWMS = urlWMS.endsWith('?') ? urlWMS : urlWMS + '?';
1216
+ if (viewService.toLowerCase().includes('wms')) {
1217
+ viewService = viewService.endsWith('?')
1218
+ ? viewService
1219
+ : viewService + '?';
1069
1220
  this.layers[layer.LayerId + '_' + inheritedIndexLayer] = new WMSLayer({
1070
- url: urlWMS,
1221
+ url: viewService,
1071
1222
  featureInfoFormat: 'text/html',
1072
- featureInfoUrl: urlWMS,
1223
+ featureInfoUrl: viewService,
1073
1224
  //id: layer.LayerId,
1074
1225
  title: '',
1075
1226
  legendEnabled: true,
@@ -1083,16 +1234,20 @@ class MenuWidget extends React.Component {
1083
1234
  legendEnabled: true,
1084
1235
  legendUrl: layer.StaticImageLegend
1085
1236
  ? layer.StaticImageLegend
1086
- : urlWMS + legendRequest + layer.LayerId,
1237
+ : viewService + legendRequest + layer.LayerId,
1087
1238
  featureInfoUrl: featureInfoUrl,
1088
1239
  },
1089
1240
  ],
1090
1241
  isTimeSeries: isTimeSeries,
1091
1242
  fields: layer.Fields,
1243
+ DatasetId: DatasetId,
1244
+ DatasetTitle: DatasetTitle,
1245
+ ProductId: ProductId,
1246
+ ViewService: viewService,
1092
1247
  });
1093
- } else if (urlWMS.toLowerCase().includes('wmts')) {
1248
+ } else if (viewService.toLowerCase().includes('wmts')) {
1094
1249
  this.layers[layer.LayerId + '_' + inheritedIndexLayer] = new WMTSLayer({
1095
- url: urlWMS.endsWith('?') ? urlWMS : urlWMS + '?',
1250
+ url: viewService.endsWith('?') ? viewService : viewService + '?',
1096
1251
  //id: layer.LayerId,
1097
1252
  title: '',
1098
1253
  _wmtsTitle: layer.Title, // CLMS-1105
@@ -1103,22 +1258,35 @@ class MenuWidget extends React.Component {
1103
1258
  },
1104
1259
  isTimeSeries: isTimeSeries,
1105
1260
  fields: layer.Fields,
1261
+ DatasetId: DatasetId,
1262
+ DatasetTitle: DatasetTitle,
1263
+ ProductId: ProductId,
1264
+ ViewService: viewService,
1265
+ StaticImageLegend: layer.StaticImageLegend,
1266
+ LayerTitle: layer.Title,
1106
1267
  });
1107
1268
  } else {
1108
1269
  this.layers[
1109
1270
  layer.LayerId + '_' + inheritedIndexLayer
1110
1271
  ] = new FeatureLayer({
1111
- url: urlWMS + (urlWMS.endsWith('/') ? '' : '/') + layer.LayerId,
1272
+ url:
1273
+ viewService +
1274
+ (viewService.endsWith('/') ? '' : '/') +
1275
+ layer.LayerId,
1112
1276
  id: layer.LayerId,
1113
1277
  title: layer.Title,
1114
1278
  featureInfoUrl: featureInfoUrl,
1115
1279
  popupEnabled: true,
1116
1280
  isTimeSeries: isTimeSeries,
1117
1281
  fields: layer.Fields,
1282
+ DatasetId: DatasetId,
1283
+ DatasetTitle: DatasetTitle,
1284
+ ProductId: ProductId,
1285
+ ViewService: viewService,
1118
1286
  });
1119
1287
  }
1120
1288
  }
1121
- let style = this.props.download ? { paddingLeft: '4rem' } : {};
1289
+
1122
1290
  return (
1123
1291
  <div
1124
1292
  className="ccl-form-group map-menu-layer"
@@ -1152,6 +1320,97 @@ class MenuWidget extends React.Component {
1152
1320
  );
1153
1321
  }
1154
1322
 
1323
+ /**
1324
+ * adds a custom TMS layer to this.layers array
1325
+ * @param {*} checkboxId Is the layers checkbox ID
1326
+ */
1327
+ processTMSLayer(layer, checkboxId, dataset) {
1328
+ const CustomTileLayer = BaseTileLayer.createSubclass({
1329
+ properties: {
1330
+ urlTemplate: null,
1331
+ tms: false,
1332
+ tint: {
1333
+ value: null,
1334
+ },
1335
+ },
1336
+
1337
+ // generate the tile url for a given level, row and column
1338
+ getTileUrl: function (level, row, col) {
1339
+ // si es cero será el maximo. las filas serán el array invertido
1340
+ // tengo que extrarer de alguna manera la cantidad de filas y columnas que se muestran.
1341
+
1342
+ return this.urlTemplate
1343
+ .replace('{z}', level)
1344
+ .replace('{x}', col)
1345
+ .replace('{y}', row);
1346
+ },
1347
+
1348
+ // This method fetches tiles for the specified level and size.
1349
+ // Override this method to process the data returned from the server.
1350
+ fetchTile: function (level, row, col, options) {
1351
+ // call getTileUrl() method to construct the URL to tiles
1352
+ // for a given level, row and col provided by the LayerView
1353
+
1354
+ // Images pyramid formula
1355
+ if (this.tms) {
1356
+ var rowmax = 1 << level; // LEVEL 1 * (2 ** 1) = 1 * (2) = 2 ; LEVEL 2 * (2 ** 2) = 1 * (4) = 4 ; LEVEL 3 * (2 ** 3) = 1 * (8) = 8 . . .
1357
+ row = rowmax - row - 1; // Invert Y axis
1358
+ }
1359
+
1360
+ const url = this.getTileUrl(level, row, col);
1361
+
1362
+ // request for tiles based on the generated url
1363
+ // the signal option ensures that obsolete requests are aborted
1364
+ return esriRequest(url, {
1365
+ responseType: 'image',
1366
+ signal: options && options.signal,
1367
+ }).then(
1368
+ function (response) {
1369
+ // when esri request resolves successfully
1370
+ // get the image from the response
1371
+ const image = response.data;
1372
+ const width = this.tileInfo.size[0];
1373
+ const height = this.tileInfo.size[0];
1374
+ // create a canvas with 2D rendering context
1375
+ const canvas = document.createElement('canvas');
1376
+ const context = canvas.getContext('2d');
1377
+ //canvas
1378
+ canvas.width = width;
1379
+ canvas.height = height;
1380
+
1381
+ // Draw the blended image onto the canvas.
1382
+ context.drawImage(image, 0, 0, width, height);
1383
+
1384
+ return canvas;
1385
+ }.bind(this),
1386
+ );
1387
+ },
1388
+ });
1389
+ // *******************************************************
1390
+ // end of Custom tile layer class code
1391
+ // *******************************************************
1392
+ this.layers[checkboxId] = new CustomTileLayer({
1393
+ id: checkboxId,
1394
+ tms: true, // True establishes Y axis from the south northwards. False establishes tile origin top left and Y from north southwards (Default False)
1395
+ urlTemplate: layer.LayerUrl,
1396
+ // TMS Service.
1397
+ // 'https://s3-eu-west-1.amazonaws.com/vito-lcv/global/2019/cog-full_l0-colored-full/{z}/{x}/{y}.png',
1398
+ // Google/ESRI/OSM tiling style services
1399
+ // "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
1400
+ // "https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}",
1401
+ // "https://stamen-tiles.a.ssl.fastly.net/watercolor/{z}/{x}/{y}.jpg",
1402
+ spatialReference: {
1403
+ wkid: 3857,
1404
+ },
1405
+ title: layer.Title,
1406
+ LayerTitle: layer.Title,
1407
+ DatasetTitle: dataset.DatasetTitle,
1408
+ ViewService: dataset.ViewService,
1409
+ StaticImageLegend: layer.StaticImageLegend,
1410
+ url: dataset.ViewService,
1411
+ });
1412
+ }
1413
+
1155
1414
  /**
1156
1415
  * Method to show/hide a layer. Update checkboxes from dataset and products
1157
1416
  * @param {*} elem Is the checkbox
@@ -1195,6 +1454,9 @@ class MenuWidget extends React.Component {
1195
1454
  } else {
1196
1455
  this.deleteCheckedLayer(elem.id);
1197
1456
  this.layers[elem.id].opacity = 1;
1457
+ this.layers[elem.id].visible = false;
1458
+ let mapLayer = this.map.findLayerById(elem.id);
1459
+ if (mapLayer) mapLayer.destroy();
1198
1460
  this.map.remove(this.layers[elem.id]);
1199
1461
  delete this.activeLayersJSON[elem.id];
1200
1462
  delete this.visibleLayers[elem.id];
@@ -1203,10 +1465,105 @@ class MenuWidget extends React.Component {
1203
1465
  this.updateCheckDataset(parentId);
1204
1466
  this.layersReorder();
1205
1467
  this.checkInfoWidget();
1468
+
1469
+ // toggle custom legend for WMTS and TMS
1470
+ if (
1471
+ this.layers[elem.id].ViewService.toLowerCase().includes('wmts') ||
1472
+ this.layers[elem.id].ViewService.toLowerCase().endsWith('file')
1473
+ ) {
1474
+ this.toggleCustomLegendItem(this.layers[elem.id]);
1475
+ }
1206
1476
  // update DOM
1207
1477
  this.setState({});
1208
1478
  }
1209
1479
 
1480
+ /**
1481
+ * Hide or show a legend image in the legend widget for a WMTS or a TMS layer
1482
+ *
1483
+ * @param Layer
1484
+ */
1485
+ toggleCustomLegendItem(layer) {
1486
+ // check for existing legend item
1487
+ let existingItem = document.getElementById(
1488
+ 'custom-legend-item-' + layer.id,
1489
+ );
1490
+
1491
+ if (layer.visible) {
1492
+ if (!existingItem) {
1493
+ // create one
1494
+ this.addCustomItemToLegend(layer);
1495
+ } else {
1496
+ // show existing one
1497
+ existingItem.style.display = 'block';
1498
+ }
1499
+ } else {
1500
+ // hide legend item
1501
+ if (existingItem) {
1502
+ existingItem.style.display = 'none';
1503
+ }
1504
+ }
1505
+ }
1506
+
1507
+ addCustomItemToLegend(layer) {
1508
+ // Find legend widget node
1509
+ const legendDiv = document.querySelectorAll('.esri-widget.esri-legend')[0];
1510
+ let childDiv = legendDiv.firstChild;
1511
+
1512
+ // create legend element
1513
+ let legendItem = this.createStaticLegendImageNode(
1514
+ layer.id,
1515
+ layer.LayerTitle,
1516
+ layer.StaticImageLegend,
1517
+ );
1518
+
1519
+ // append to Legend widet
1520
+ childDiv.appendChild(legendItem);
1521
+
1522
+ // hide no legend message
1523
+ const noLegendMessage = document.querySelectorAll(
1524
+ '.esri-legend__message',
1525
+ )[0];
1526
+ if (noLegendMessage) {
1527
+ noLegendMessage.style.display = 'none';
1528
+ }
1529
+ }
1530
+
1531
+ createStaticLegendImageNode(id, title, imageURL) {
1532
+ let node = document.createElement('div');
1533
+ node.classList.add('esri-legend__service');
1534
+ node.id = 'custom-legend-item-' + id;
1535
+
1536
+ // Create node
1537
+ let template = `
1538
+ <div class="esri-legend__layer">
1539
+ <div class="esri-legend__layer-table esri-legend__layer-table--size-ramp" >
1540
+ <div class="esri-legend__layer-caption">
1541
+ ${title}
1542
+ </div>
1543
+ <div class="esri-legend__layer-body">
1544
+ <div class="esri-legend__layer-row">
1545
+ <div class="esri-legend__layer-cell esri-legend__layer-cell--symbols" >
1546
+ <div class="esri-legend__symbol">
1547
+ <img crossorigin="anonymous"
1548
+ alt=""
1549
+ src="${imageURL}"
1550
+ style="opacity: 1"
1551
+ />
1552
+ </div>
1553
+ </div>
1554
+ <div
1555
+ class="esri-legend__layer-cell esri-legend__layer-cell--info"
1556
+ ></div>
1557
+ </div>
1558
+ </div>
1559
+ </div>
1560
+ </div>`;
1561
+
1562
+ node.innerHTML = template;
1563
+
1564
+ return node;
1565
+ }
1566
+
1210
1567
  /**
1211
1568
  * Returns the DOM elements for active layers
1212
1569
  * just in the order they were added to map
@@ -1282,6 +1639,7 @@ class MenuWidget extends React.Component {
1282
1639
  } else {
1283
1640
  datasetChecks = document.querySelectorAll(`[parentid=${id}]`);
1284
1641
  }
1642
+
1285
1643
  datasetChecks.forEach((element) => {
1286
1644
  element.checked = value;
1287
1645
  this.toggleDataset(value, element.id, element);
@@ -1006,3 +1006,13 @@ input[type='range']::-ms-track {
1006
1006
  background: transparent;
1007
1007
  box-shadow: none;
1008
1008
  }
1009
+
1010
+ .zoom-in-message {
1011
+ padding: 0.1rem 0.6rem 0.1rem 0.6rem;
1012
+ margin-top: 0.2rem;
1013
+ background: #a0b128;
1014
+ border-radius: 10px;
1015
+ color: white;
1016
+ font-size: 0.875rem;
1017
+ text-align: center;
1018
+ }