@eeacms/volto-arcgis-block 0.1.402 → 0.1.403

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,8 @@ 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.403](https://github.com/eea/volto-arcgis-block/compare/0.1.402...0.1.403) - 4 November 2025
8
+
7
9
  ### [0.1.402](https://github.com/eea/volto-arcgis-block/compare/0.1.401...0.1.402) - 3 November 2025
8
10
 
9
11
  #### :hammer_and_wrench: Others
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-arcgis-block",
3
- "version": "0.1.402",
3
+ "version": "0.1.403",
4
4
  "description": "volto-arcgis-block: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: CodeSyntax",
@@ -142,7 +142,24 @@ class InfoWidget extends React.Component {
142
142
  title = this.getLayerTitle(layer);
143
143
  }
144
144
  if (layer?.isTimeSeries) {
145
- if (layer.url.toLowerCase().includes('wms')) {
145
+ if (
146
+ !!layer.ViewService &&
147
+ ['/ogc/', '/cdse/'].some((s) =>
148
+ layer.ViewService.toLowerCase().includes(s),
149
+ )
150
+ ) {
151
+ layerTypes.push({
152
+ isTimeSeries: true,
153
+ type: 'wmts',
154
+ title: title,
155
+ fields: layer.fields,
156
+ });
157
+ promises.push(
158
+ this.cdseCapabilities(layer.ViewService, layer).then((xml) =>
159
+ this.identifyCDSE(xml, layer),
160
+ ),
161
+ );
162
+ } else if (layer.url.toLowerCase().includes('wms')) {
146
163
  layerTypes.push({
147
164
  isTimeSeries: true,
148
165
  type: 'wms',
@@ -293,6 +310,15 @@ class InfoWidget extends React.Component {
293
310
  };
294
311
  break;
295
312
  case 'wmts':
313
+ if (
314
+ layers[index]?.ViewService &&
315
+ layers[index].ViewService.toLowerCase().includes(
316
+ 'cdse',
317
+ )
318
+ ) {
319
+ properties = data;
320
+ }
321
+ properties = data;
296
322
  this.infoData[index] = {
297
323
  title: layer.title,
298
324
  data: properties,
@@ -444,7 +470,9 @@ class InfoWidget extends React.Component {
444
470
 
445
471
  getLayerTitle(layer) {
446
472
  let title;
447
- if (layer.url.toLowerCase().includes('wmts')) {
473
+ if (layer.ViewService && layer.ViewService.toLowerCase().includes('cdse')) {
474
+ title = layer.title;
475
+ } else if (layer.url.toLowerCase().includes('wmts')) {
448
476
  // CLMS-1105
449
477
  title = layer._wmtsTitle;
450
478
  } else if (layer.url.toLowerCase().toLowerCase().endsWith('mapserver')) {
@@ -562,6 +590,109 @@ class InfoWidget extends React.Component {
562
590
  });
563
591
  }
564
592
 
593
+ async cdseCapabilities(url, layer) {
594
+ if (!url) return {};
595
+ try {
596
+ const res = await fetch(url);
597
+ const text = await res.text();
598
+ let parser = new DOMParser();
599
+ let xml = parser.parseFromString(text, 'text/html');
600
+ return xml;
601
+ } catch (e) {
602
+ return {};
603
+ }
604
+ }
605
+
606
+ identifyCDSE(xml, layer) {
607
+ let values = { timeFields: {}, data: {}, variables: {}, tableData: {} };
608
+ if (!xml || !xml.querySelector) {
609
+ values.timeFields['start'] = 'time';
610
+ values.variables = { options: ['value'], selected: 'value' };
611
+ values.tableData['fields'] = ['time', 'value'];
612
+ values.timeFields['values'] = [];
613
+ values.data['outFields'] = 'value';
614
+ values.data['values'] = [];
615
+ values.tableData['values'] = [];
616
+ return values;
617
+ }
618
+ let layerId = this.getLayerName(layer);
619
+ let layers = Array.from(xml.querySelectorAll('Layer'));
620
+ let lyr =
621
+ layers.find((l) => {
622
+ let id =
623
+ l.querySelector('ows\\:Identifier') || l.querySelector('Identifier');
624
+ return id && id.textContent === layerId;
625
+ }) || layers[0];
626
+ let timeValues = [];
627
+ if (lyr) {
628
+ let dimNodes = Array.from(lyr.querySelectorAll('Dimension'));
629
+ let timeDim =
630
+ dimNodes.find((d) => {
631
+ let n = d.getAttribute('name') || d.getAttribute('identifier') || '';
632
+ return n.toLowerCase() === 'time';
633
+ }) ||
634
+ dimNodes.find((d) => {
635
+ let idn =
636
+ d.querySelector('ows\\:Identifier') ||
637
+ d.querySelector('Identifier');
638
+ return idn && idn.textContent.toLowerCase() === 'time';
639
+ });
640
+ if (timeDim) {
641
+ let valNodes = Array.from(timeDim.querySelectorAll('Value'));
642
+ if (valNodes.length) {
643
+ timeValues = valNodes
644
+ .map((v) => v.textContent.trim())
645
+ .filter((t) => t);
646
+ } else {
647
+ let txt = (timeDim.textContent || '').trim();
648
+ if (txt) {
649
+ if (txt.includes(',')) {
650
+ timeValues = txt.split(',').map((s) => s.trim());
651
+ } else if (txt.includes('/')) {
652
+ timeValues = this.expandTimeRange(txt);
653
+ }
654
+ }
655
+ let def = timeDim.getAttribute('default') || '';
656
+ if (!timeValues.length && def) timeValues = [def];
657
+ }
658
+ }
659
+ }
660
+ values.timeFields['start'] = 'time';
661
+ values.variables = { options: ['value'], selected: 'value' };
662
+ values.tableData['fields'] = ['time', 'value'];
663
+ values.timeFields['values'] = timeValues.map((t) => {
664
+ let obj = {};
665
+ obj['time'] = t;
666
+ return obj;
667
+ });
668
+ values.data['outFields'] = 'value';
669
+ values.data['values'] = [];
670
+ values.tableData['values'] = timeValues.map((t) => {
671
+ return [
672
+ ['time', t],
673
+ ['value', ''],
674
+ ];
675
+ });
676
+ return values;
677
+ }
678
+
679
+ expandTimeRange(range) {
680
+ let parts = range.split('/');
681
+ if (parts.length !== 3) return parts.filter((p) => p);
682
+ let start = new Date(parts[0]);
683
+ let end = new Date(parts[1]);
684
+ let step = parts[2];
685
+ let out = [];
686
+ if (step === 'P1D') {
687
+ for (let d = new Date(start); d <= end; d.setDate(d.getDate() + 1)) {
688
+ out.push(new Date(d).toISOString().split('T')[0]);
689
+ }
690
+ return out;
691
+ } else {
692
+ return [parts[0], parts[1]];
693
+ }
694
+ }
695
+
565
696
  parseCapabilities(xml, tag) {
566
697
  let result = xml.getElementsByTagName(tag);
567
698