@eeacms/volto-arcgis-block 0.1.290 → 0.1.292

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,17 @@ 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.292](https://github.com/eea/volto-arcgis-block/compare/0.1.291...0.1.292) - 28 June 2024
8
+
9
+ #### :hammer_and_wrench: Others
10
+
11
+ - CLMS-3254 (task): clean console statements. [Unai Bolivar - [`7058e29`](https://github.com/eea/volto-arcgis-block/commit/7058e293a6c546496035875bfda1348e3fb97e45)]
12
+ - CLMS-3254 (task): added CSV to file formats supported span text at the bottom of the area widget [Unai Bolivar - [`96fedac`](https://github.com/eea/volto-arcgis-block/commit/96fedac5bf59edba736d56c75b4c467e8f261416)]
13
+ - CLMS-3254 (feat): Completed CSV file upload [Unai Bolivar - [`b828893`](https://github.com/eea/volto-arcgis-block/commit/b828893edc8b147f779b79ed33935b9ab253bf48)]
14
+ - CLMS-3254 (feat): Checking layer for extent and wkid [Unai Bolivar - [`cf6468a`](https://github.com/eea/volto-arcgis-block/commit/cf6468af5ede54807160be32449e7ecdbcfed819)]
15
+ - CLMS-3254 (feat): CSV file upload renders points on map. [Unai Bolivar - [`abf28d1`](https://github.com/eea/volto-arcgis-block/commit/abf28d1c68580623113a059e15b0dd92a7535118)]
16
+ ### [0.1.291](https://github.com/eea/volto-arcgis-block/compare/0.1.290...0.1.291) - 20 June 2024
17
+
7
18
  ### [0.1.290](https://github.com/eea/volto-arcgis-block/compare/0.1.289...0.1.290) - 19 June 2024
8
19
 
9
20
  ### [0.1.289](https://github.com/eea/volto-arcgis-block/compare/0.1.288...0.1.289) - 18 June 2024
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-arcgis-block",
3
- "version": "0.1.290",
3
+ "version": "0.1.292",
4
4
  "description": "volto-arcgis-block: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: CodeSyntax",
@@ -13,7 +13,8 @@ var Graphic,
13
13
  request,
14
14
  SimpleLineSymbol,
15
15
  SimpleFillSymbol,
16
- SpatialReference;
16
+ SpatialReference,
17
+ Polygon;
17
18
 
18
19
  class AreaWidget extends React.Component {
19
20
  /**
@@ -65,6 +66,7 @@ class AreaWidget extends React.Component {
65
66
  'esri/symbols/SimpleLineSymbol',
66
67
  'esri/symbols/SimpleFillSymbol',
67
68
  'esri/geometry/SpatialReference',
69
+ 'esri/geometry/Polygon',
68
70
  ]).then(
69
71
  ([
70
72
  _Graphic,
@@ -79,6 +81,7 @@ class AreaWidget extends React.Component {
79
81
  _SimpleLineSymbol,
80
82
  _SimpleFillSymbol,
81
83
  _SpatialReference,
84
+ _Polygon,
82
85
  ]) => {
83
86
  [
84
87
  Graphic,
@@ -93,6 +96,7 @@ class AreaWidget extends React.Component {
93
96
  SimpleLineSymbol,
94
97
  SimpleFillSymbol,
95
98
  SpatialReference,
99
+ Polygon,
96
100
  ] = [
97
101
  _Graphic,
98
102
  _Extent,
@@ -106,6 +110,7 @@ class AreaWidget extends React.Component {
106
110
  _SimpleLineSymbol,
107
111
  _SimpleFillSymbol,
108
112
  _SpatialReference,
113
+ _Polygon,
109
114
  ];
110
115
  },
111
116
  );
@@ -212,7 +217,7 @@ class AreaWidget extends React.Component {
212
217
  if (document.querySelector('#download_prepackage').checked) {
213
218
  this.setState({
214
219
  showInfoPopup: true,
215
- infoPopupType: 'download',
220
+ infoPopupType: 'prepackage',
216
221
  });
217
222
  } else {
218
223
  this.setState({
@@ -292,6 +297,7 @@ class AreaWidget extends React.Component {
292
297
  // FILE UPLOAD HANDLERS
293
298
 
294
299
  // Trigger the file input click
300
+
295
301
  handleUploadClick = (event) => {
296
302
  event.preventDefault();
297
303
  this.fileInput.current.click();
@@ -299,19 +305,31 @@ class AreaWidget extends React.Component {
299
305
 
300
306
  handleFileUpload = (e) => {
301
307
  //Get the file name
308
+
302
309
  const fileName = e.target.value.toLowerCase();
303
310
 
304
311
  //Get the file size
312
+
305
313
  const fileSize = e.target.files[0].size;
306
314
 
307
315
  //Get the file from the form
316
+
308
317
  const file = document.getElementById('uploadForm');
309
318
 
319
+ //Get the file blob
320
+
321
+ const fileBlob = e.target.files[0];
322
+
323
+ //Create a new file reader
324
+
325
+ let reader = new FileReader();
326
+
310
327
  //List allowed file extensions
311
328
 
312
- let fileExtensions = ['zip', 'geojson'];
329
+ let fileExtensions = ['zip', 'geojson', 'csv'];
313
330
 
314
331
  // Get the file extension
332
+
315
333
  let fileExtension = fileName.split('.').pop();
316
334
 
317
335
  //Check if the file format is not supported
@@ -324,10 +342,13 @@ class AreaWidget extends React.Component {
324
342
  return;
325
343
  }
326
344
 
327
- // Check if the file is a geojson and the file size is over the 10mb file size limit
345
+ // Check if the file format is geojson or csv and the file size is over the 10mb file size limit
328
346
  // or file is a shape file and the file size is over the 2mb file size limit
329
347
 
330
- if (fileSize > 10485760 && fileExtension === 'geojson') {
348
+ if (
349
+ fileSize > 10485760 &&
350
+ (fileExtension === 'geojson' || fileExtension === 'csv')
351
+ ) {
331
352
  this.setState({
332
353
  showInfoPopup: true,
333
354
  infoPopupType: 'fileLimit',
@@ -350,14 +371,17 @@ class AreaWidget extends React.Component {
350
371
  case 'geojson':
351
372
  this.generateFeatureCollection(fileName, file, 'geojson');
352
373
  break;
353
- //case 'csv':
354
- //this.generateFeatureCollection(
355
- // fileName,
356
- // file,
357
- // 'csv',
358
- //);
359
- // reader.readAsText(fileBlob);
360
- // break;
374
+ case 'csv':
375
+ //this.generateFeatureCollection(
376
+ // fileName,
377
+ // file,
378
+ // 'csv',
379
+ //);
380
+ reader.readAsText(fileBlob);
381
+ reader.onload = () => {
382
+ this.handleCsv(reader.result);
383
+ };
384
+ break;
361
385
  default:
362
386
  break;
363
387
  }
@@ -580,7 +604,7 @@ class AreaWidget extends React.Component {
580
604
 
581
605
  //Display CSV on the map
582
606
 
583
- handleCsv(data) {
607
+ async handleCsv(data) {
584
608
  //Create a CSV layer
585
609
  const blob = new Blob([data], {
586
610
  type: 'plain/text',
@@ -594,50 +618,157 @@ class AreaWidget extends React.Component {
594
618
  title: 'uploadLayer',
595
619
  });
596
620
 
597
- //Query all features insisde the CSV layer
598
-
599
- //csvLayer.load().then(function(){
600
- // let query = new Query({
601
- // where: "mag > 5",
602
- // returnGeometry: true
603
- // });
604
- //
605
- // return csvLayer.queryFeatures(query);
606
- //})
607
- //.then(function(results){
608
- // console.log(results);
609
- //})
610
- //.catch(function (error) {
611
- // console.error("From CSV query: ", error);
612
- //});
613
- //Check if the file has the correct spatial reference
614
- if (this.checkWkid(csvLayer?.spatialReference) === false) return;
615
-
616
- //Check if the file extent is larger than the limit
617
- //let geometry = new Extent({
618
- // xmin: data?.features[0]?.geometry.bbox[0],
619
- // xmax: data?.features[0]?.geometry.bbox[1],
620
- // ymin: data?.features[0]?.geometry.bbox[2],
621
- // ymax: data?.features[0]?.geometry.bbox[3],
622
- // spatialReference: { wkid: 4326 },
623
- //});
621
+ // Set a simple renderer on the layer
622
+
623
+ csvLayer.renderer = {
624
+ type: 'simple', // autocasts as new SimpleRenderer()
625
+ symbol: {
626
+ type: 'simple-marker', // autocasts as new SimpleMarkerSymbol()
627
+ size: 6,
628
+ color: 'black',
629
+ outline: {
630
+ // autocasts as new SimpleLineSymbol()
631
+ width: 0.5,
632
+ color: 'white',
633
+ },
634
+ },
635
+ };
624
636
 
625
- //If checkExtent returns false, add the layer to the map
626
- //if (this.checkExtent(geometry)) {
627
- // this.setState({
628
- // showInfoPopup: true,
629
- // infoPopupType: 'fullDataset',
630
- // });
631
- //} else {
632
- this.removeFileUploadedLayer();
633
- this.fileUploadLayer = csvLayer;
634
- this.removeNutsLayers();
635
- this.props.map.add(this.fileUploadLayer);
636
- this.setState({
637
- showInfoPopup: true,
638
- infoPopupType: 'download',
639
- });
640
- //}
637
+ let csvFeatures, csvFeatureCount, csvExtent;
638
+
639
+ //Query the CSV layer
640
+
641
+ try {
642
+ await csvLayer.load();
643
+ const results = await Promise.all([
644
+ csvLayer.queryFeatures(),
645
+ csvLayer.queryFeatureCount(),
646
+ csvLayer.queryExtent(),
647
+ ]);
648
+
649
+ csvFeatures = results[0];
650
+ csvFeatureCount = results[1];
651
+ csvExtent = results[2];
652
+
653
+ //Check if the file has the correct spatial reference
654
+
655
+ if (this.checkWkid(csvLayer?.spatialReference) === false) return;
656
+
657
+ //Check if the file extent is larger than the limit
658
+ //If checkExtent() is false, add the layer to the map
659
+
660
+ if (this.checkExtent(csvExtent.extent)) {
661
+ this.setState({
662
+ showInfoPopup: true,
663
+ infoPopupType: 'fullDataset',
664
+ });
665
+ } else {
666
+ //Draw a polygon around of the CSVlayer Features data
667
+
668
+ let allRings = [];
669
+ let currentRing = [];
670
+ let startingPoint = null;
671
+
672
+ for (let i = 0; i < csvFeatureCount; i++) {
673
+ const currentPoint = [
674
+ csvFeatures.features[i].geometry.x,
675
+ csvFeatures.features[i].geometry.y,
676
+ ];
677
+ if (!startingPoint) {
678
+ startingPoint = currentPoint;
679
+ currentRing.push(currentPoint);
680
+ } else if (
681
+ startingPoint[0] === currentPoint[0] &&
682
+ startingPoint[1] === currentPoint[1]
683
+ ) {
684
+ allRings.push(currentRing);
685
+ currentRing = [];
686
+ startingPoint = null;
687
+ } else {
688
+ currentRing.push(currentPoint);
689
+ }
690
+ }
691
+
692
+ if (currentRing.length > 0) {
693
+ allRings.push(currentRing);
694
+ }
695
+
696
+ let idPolygon = new Polygon({
697
+ isSelfIntersecting: false,
698
+ rings: allRings,
699
+ spatialReference: csvExtent.spatialReference,
700
+ //set type as multi polygon
701
+ });
702
+
703
+ //Draw a graphic using the polyId polygon data as the geometry
704
+
705
+ const polygonSymbol = {
706
+ type: 'simple-fill', // autocasts as new SimpleFillSymbol()
707
+ color: [234, 168, 72, 0.8],
708
+ outline: {
709
+ // autocasts as new SimpleLineSymbol()
710
+ color: '#000000',
711
+ width: 0.1,
712
+ },
713
+ };
714
+
715
+ let polygonGraphic = new Graphic({
716
+ geometry: idPolygon,
717
+ symbol: polygonSymbol,
718
+ });
719
+
720
+ //Clear any previously saved file upload data and save the uploaded layer to the component props for reference
721
+
722
+ this.removeFileUploadedLayer();
723
+ this.fileUploadLayer = {
724
+ layers: CSVLayer,
725
+ sourceGraphics: polygonGraphic,
726
+ };
727
+
728
+ //Clean the map before adding the graphic
729
+
730
+ this.removeNutsLayers();
731
+
732
+ //Add the polygon graphic to the map
733
+
734
+ this.props.view.graphics.add(polygonGraphic);
735
+ //this.props.map.add(this.fileUploadLayer);
736
+
737
+ //Refresh the map view
738
+
739
+ this.props.view.goTo(polygonGraphic).catch((error) => {
740
+ //console.error('From handleCsv function', error);
741
+ });
742
+
743
+ //Send the area to the parent component
744
+
745
+ this.props.updateArea({
746
+ origin: { x: csvExtent.extent.xmin, y: csvExtent.extent.ymin },
747
+ end: { x: csvExtent.extent.xmax, y: csvExtent.extent.ymax },
748
+ });
749
+
750
+ //re order the layer in the map
751
+
752
+ let index = this.getHighestIndex();
753
+ this.props.map.reorder(polygonGraphic, index + 1);
754
+
755
+ //Refresh the map view
756
+
757
+ this.setState({
758
+ showInfoPopup: true,
759
+ infoPopupType: 'download',
760
+ });
761
+
762
+ //Save file upload layer to session storage as a tag for adding item to cart action
763
+
764
+ sessionStorage.setItem(
765
+ 'fileUploadLayer',
766
+ JSON.stringify(this.fileUploadLayer),
767
+ );
768
+ }
769
+ } catch (error) {
770
+ //console.error('Error: ', error);
771
+ }
641
772
  }
642
773
 
643
774
  checkWkid(spatialReference) {
@@ -851,7 +982,9 @@ class AreaWidget extends React.Component {
851
982
  'none';
852
983
  }
853
984
  areaSearch() {
854
- let searchText = document.querySelector('#area-searchtext').value;
985
+ let searchText = document
986
+ .querySelector('#area-searchtext')
987
+ .value.toUpperCase();
855
988
  if (searchText.length <= 2) {
856
989
  this.loadNutsService('nuts0', [0]);
857
990
  this.loadCountriesService('nuts0');
@@ -872,15 +1005,25 @@ class AreaWidget extends React.Component {
872
1005
  }
873
1006
  let found = false;
874
1007
  let count = this.nutsGroupLayer.layers.items.length;
875
- const queryParams = this.nutsGroupLayer.layers.items[0].createQuery();
876
- queryParams.where = `(NUTS_ID = '${searchText}')`;
877
- queryParams.outSpatialReference = this.props.view.spatialReference;
878
1008
  document.querySelector('.no-result-message').style.display = 'none';
879
1009
  this.nutsGroupLayer.layers.items.forEach((item) => {
1010
+ const queryParams = item.createQuery();
1011
+ if (
1012
+ item.url ===
1013
+ 'https://land.discomap.eea.europa.eu/arcgis/rest/services/CLMS_Portal/World_countries_except_EU37/MapServer'
1014
+ ) {
1015
+ queryParams.where = `(ISO_2DIGIT = '${searchText}')`;
1016
+ } else {
1017
+ queryParams.where = `(NUTS_ID = '${searchText}')`;
1018
+ }
1019
+ queryParams.outSpatialReference = this.props.view.spatialReference;
880
1020
  item.queryFeatures(queryParams).then((response) => {
881
1021
  count = count - 1;
882
1022
  response.features.forEach((feature) => {
883
- if (feature.attributes.NUTS_ID === searchText) {
1023
+ if (
1024
+ feature.attributes.NUTS_ID === searchText ||
1025
+ feature.attributes.ISO_2DIGIT === searchText
1026
+ ) {
884
1027
  found = true;
885
1028
  this.props.updateArea(feature);
886
1029
  let symbol = new SimpleFillSymbol(
@@ -1278,7 +1421,9 @@ class AreaWidget extends React.Component {
1278
1421
  >
1279
1422
  <div className="field">
1280
1423
  <label className="file-upload">
1281
- <span>File formats supported: shp(zip), geojson</span>
1424
+ <span>
1425
+ File formats supported: shp(zip), geojson, CSV
1426
+ </span>
1282
1427
  <input
1283
1428
  type="file"
1284
1429
  name="file"
@@ -1327,6 +1472,17 @@ class AreaWidget extends React.Component {
1327
1472
  </div>
1328
1473
  </>
1329
1474
  )}
1475
+ {this.state.infoPopupType === 'prepackage' && (
1476
+ <>
1477
+ <span className="drawRectanglePopup-icon">
1478
+ <FontAwesomeIcon icon={['fas', 'download']} />
1479
+ </span>
1480
+ <div className="drawRectanglePopup-text">
1481
+ Click on the download icon on “Products and datasets” to
1482
+ continue
1483
+ </div>
1484
+ </>
1485
+ )}
1330
1486
  {this.state.infoPopupType === 'fullDataset' && (
1331
1487
  <>
1332
1488
  <span className="drawRectanglePopup-icon">