@eeacms/volto-arcgis-block 0.1.30 → 0.1.31

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,8 +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.31](https://github.com/eea/volto-arcgis-block/compare/0.1.30...0.1.31)
8
+
9
+ - First commit [`#97`](https://github.com/eea/volto-arcgis-block/pull/97)
10
+ - REFACT: Delete comments [`a7a9296`](https://github.com/eea/volto-arcgis-block/commit/a7a929647749280ccf92d97ea17a3d743f1cfa20)
11
+ - FIX: Watch event on Time Extent for props and services. TimeSlider disabled if no time dimension [`2af7f50`](https://github.com/eea/volto-arcgis-block/commit/2af7f50d2ae1d5e033606d690bab0dffaa83b79e)
12
+
7
13
  #### [0.1.30](https://github.com/eea/volto-arcgis-block/compare/0.1.29...0.1.30)
8
14
 
15
+ > 10 February 2022
16
+
17
+ - Develop [`#99`](https://github.com/eea/volto-arcgis-block/pull/99)
9
18
  - Bugs n improvements [`#98`](https://github.com/eea/volto-arcgis-block/pull/98)
10
19
  - ESLint fix [`4b23a15`](https://github.com/eea/volto-arcgis-block/commit/4b23a15d924a671ded144b453d5864884394a277)
11
20
  - Download functionality [`457fddd`](https://github.com/eea/volto-arcgis-block/commit/457fdddac4082d9706458d0a9421e64fca1e6ab6)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-arcgis-block",
3
- "version": "0.1.30",
3
+ "version": "0.1.31",
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,8 @@
1
1
  import React, { createRef } from 'react';
2
2
  import { loadModules } from 'esri-loader';
3
3
  var TimeSlider;
4
+ var TimeExtent;
5
+ var timeDict = {};
4
6
 
5
7
  class TimesliderWidget extends React.Component {
6
8
  /**
@@ -19,15 +21,175 @@ class TimesliderWidget extends React.Component {
19
21
  };
20
22
  this.map = this.props.map;
21
23
  this.layer = this.props.layer;
24
+ if (this.layer.type === 'feature') {
25
+ this.layerName = this.layer.id; //FEATURE
26
+ } else if (this.layer.type === 'wms') {
27
+ this.layerName = this.layer.sublayers.items[0].name;
28
+ } else if (this.layer.type === 'wmts') {
29
+ this.layerName = this.layer.activeLayer.id; //WMTS
30
+ }
22
31
  this.drag = {};
23
32
  }
24
33
 
25
34
  loader() {
26
- return loadModules(['esri/widgets/TimeSlider']).then(([_TimeSlider]) => {
27
- [TimeSlider] = [_TimeSlider];
28
- });
35
+ return loadModules(['esri/widgets/TimeSlider', 'esri/TimeExtent']).then(
36
+ ([_TimeSlider, _TimeExtent]) => {
37
+ [TimeSlider] = [_TimeSlider];
38
+ [TimeExtent] = [_TimeExtent];
39
+ },
40
+ );
41
+ }
42
+
43
+ xmlToJson(xml) {
44
+ // Create the return object
45
+ var obj = {};
46
+
47
+ if (xml.nodeType === 1) {
48
+ // element
49
+ // do attributes
50
+ if (xml.attributes.length > 0) {
51
+ obj['@attributes'] = {};
52
+ for (var j = 0; j < xml.attributes.length; j++) {
53
+ var attribute = xml.attributes.item(j);
54
+ obj['@attributes'][attribute.nodeName] = attribute.nodeValue;
55
+ }
56
+ }
57
+ } else if (xml.nodeType === 3) {
58
+ // text
59
+ obj = xml.nodeValue;
60
+ }
61
+
62
+ // do children
63
+ if (xml.hasChildNodes()) {
64
+ for (var i = 0; i < xml.childNodes.length; i++) {
65
+ var item = xml.childNodes.item(i);
66
+ var nodeName = item.nodeName;
67
+ if (typeof obj[nodeName] == 'undefined') {
68
+ obj[nodeName] = this.xmlToJson(item);
69
+ } else {
70
+ if (typeof obj[nodeName].push == 'undefined') {
71
+ var old = obj[nodeName];
72
+ obj[nodeName] = [];
73
+ obj[nodeName].push(old);
74
+ }
75
+ obj[nodeName].push(this.xmlToJson(item));
76
+ }
77
+ }
78
+ }
79
+ return obj;
29
80
  }
30
81
 
82
+ getTime(esriLayer, layerName) {
83
+ let getCapabilitiesUrl = '';
84
+
85
+ if (esriLayer.type === 'wms') {
86
+ // WMS
87
+ getCapabilitiesUrl =
88
+ esriLayer.url + '?request=GetCapabilities&service=WMS';
89
+ return fetch(getCapabilitiesUrl)
90
+ .then((response) => response.text())
91
+ .then((str) => new window.DOMParser().parseFromString(str, 'text/xml'))
92
+ .then((data) => {
93
+ let cap = this.xmlToJson(data);
94
+ let layers = cap.WMS_Capabilities.Capability.Layer.Layer;
95
+
96
+ let layerMetadata = {};
97
+ if (Array.isArray(layers)) {
98
+ layerMetadata = layers.filter(
99
+ (l) => l['Name']['#text'] === layerName,
100
+ )[0];
101
+ } else {
102
+ layerMetadata = layers;
103
+ }
104
+
105
+ if (layerMetadata.hasOwnProperty('Dimension')) {
106
+ const timeString = layerMetadata.Dimension['#text'];
107
+ return this.parserTimeDimensionWMS(timeString);
108
+ } else {
109
+ return false;
110
+ }
111
+ });
112
+ } else if (esriLayer.type === 'wmts') {
113
+ // WMTS
114
+ getCapabilitiesUrl =
115
+ esriLayer.url + '?request=GetCapabilities&service=WMTS';
116
+
117
+ return fetch(getCapabilitiesUrl)
118
+ .then((response) => response.text())
119
+ .then((str) => new window.DOMParser().parseFromString(str, 'text/xml'))
120
+ .then((data) => {
121
+ let cap = this.xmlToJson(data);
122
+ let layers = cap.Capabilities.Contents.Layer;
123
+ let layerMetadata = {};
124
+
125
+ if (Array.isArray(layers)) {
126
+ layerMetadata = layers.filter(
127
+ (l) => l['ows:Identifier']['#text'] === layerName,
128
+ )[0];
129
+ } else {
130
+ layerMetadata = layers;
131
+ }
132
+ if (layerMetadata.hasOwnProperty('Dimension')) {
133
+ return this.parserTimeDimensionWMTileS(
134
+ layerMetadata.Dimension.Value,
135
+ );
136
+ } else {
137
+ return false;
138
+ }
139
+ });
140
+ }
141
+ } // getTime
142
+
143
+ parserTimeDimensionWMS(timeString) {
144
+ if (timeString.includes('/P')) {
145
+ const [startDate, endDate, period] = timeString
146
+ .replace(/\s/g, '')
147
+ .split('/');
148
+ return {
149
+ start: startDate,
150
+ end: endDate,
151
+ period: period,
152
+ };
153
+ } else if (timeString.includes(',')) {
154
+ const datesArray = timeString.replace(/\s/g, '').split(',');
155
+ return { array: datesArray.map((e) => e) };
156
+ }
157
+ } // parserTimeDimensionWMS
158
+
159
+ parserTimeDimensionWMTileS(timeString) {
160
+ // [ TO CHECK ] cambiar timeString por un nombre de variable mas entendible
161
+ if (timeString.includes('/P')) {
162
+ const [startDate, endDate, period] = timeString
163
+ .replace(/\s/g, '')
164
+ .split('/');
165
+ return {
166
+ start: startDate,
167
+ end: endDate,
168
+ period: period,
169
+ };
170
+ } else if (Array.isArray(timeString)) {
171
+ const datesArray = timeString.map((e) => e['#text'].replace(/\s/g, ''));
172
+ return { array: datesArray };
173
+ }
174
+ } // parserTimeDimensionWMTS
175
+
176
+ parserPeriod(iso8601Duration) {
177
+ var iso8601DurationRegex = /(-)?P(?:([.,\d]+)Y)?(?:([.,\d]+)M)?(?:([.,\d]+)W)?(?:([.,\d]+)D)?T?(?:([.,\d]+)H)?(?:([.,\d]+)M)?(?:([.,\d]+)S)?/;
178
+
179
+ var matches = iso8601Duration.match(iso8601DurationRegex);
180
+
181
+ return {
182
+ sign: matches[1] === undefined ? '+' : '-',
183
+ years: parseInt(matches[2] === undefined ? 0 : matches[2]),
184
+ months: parseInt(matches[3] === undefined ? 0 : matches[3]),
185
+ weeks: parseInt(matches[4] === undefined ? 0 : matches[4]),
186
+ days: parseInt(matches[5] === undefined ? 0 : matches[5]),
187
+ hours: parseInt(matches[6] === undefined ? 0 : matches[6]),
188
+ minutes: parseInt(matches[7] === undefined ? 0 : matches[7]),
189
+ seconds: parseFloat(matches[8] === undefined ? 0 : matches[8]),
190
+ };
191
+ } // parserPeriod
192
+
31
193
  /**
32
194
  * This method is executed after the rener method is executed
33
195
  */
@@ -48,32 +210,99 @@ class TimesliderWidget extends React.Component {
48
210
  this.props.view.ui.add(this.container.current, 'bottom-right');
49
211
  this.container.current.style.display = 'block';
50
212
 
51
- this.props.view.whenLayerView(this.layer).then((lv) => {
52
- this.TimesliderWidget.fullTimeExtent = this.layer.timeInfo.fullTimeExtent;
53
- if (
54
- !this.layer.url.toLowerCase().includes('wms') &&
55
- !this.layer.url.toLowerCase().includes('wmts')
56
- ) {
57
- this.TimesliderWidget.stops = {
58
- interval: this.layer.timeInfo.interval,
59
- };
60
- }
61
- });
213
+ this.props.view
214
+ .whenLayerView(this.layer, this.TimesliderWidget)
215
+ .then((lv) => {
216
+ if (this.layer.type === 'feature') {
217
+ this.TimesliderWidget.fullTimeExtent = this.layer.timeInfo.fullTimeExtent;
218
+ this.TimesliderWidget.stops = {
219
+ interval: this.layer.timeInfo.interval,
220
+ };
221
+ this.TimesliderWidget.watch('timeExtent', (timeExtent) => {
222
+ if (!this.container.current ? true : false) {
223
+ this.TimesliderWidget.stop();
224
+ }
225
+ let start = new Date(timeExtent.start).getTime();
226
+ let end = new Date(timeExtent.end).getTime();
227
+ this.props.time.elem.setAttribute('time-start', start);
228
+ this.props.time.elem.setAttribute('time-end', end);
229
+ if (this.props.download) {
230
+ this.props.time.dataset.setAttribute('time-start', start);
231
+ this.props.time.dataset.setAttribute('time-end', end);
232
+ }
233
+ });
234
+ } else {
235
+ this.getTime(this.layer, this.layerName).then((v) => {
236
+ // Capabilities have time enabled
237
+ if (v !== false) {
238
+ // Start-End-Period
239
+ if (v.hasOwnProperty('period')) {
240
+ this.TimesliderWidget.fullTimeExtent = new TimeExtent({
241
+ start: new Date(v.start),
242
+ end: new Date(v.end),
243
+ });
62
244
 
63
- this.TimesliderWidget.watch('timeExtent', (timeExtent) => {
64
- if (!this.container.current ? true : false) {
65
- this.TimesliderWidget.stop();
66
- }
67
- let start = new Date(timeExtent.start).getTime();
68
- let end = new Date(timeExtent.end).getTime();
69
- this.props.time.elem.setAttribute('time-start', start);
70
- this.props.time.elem.setAttribute('time-end', end);
71
- if (this.props.download) {
72
- this.props.time.dataset.setAttribute('time-start', start);
73
- this.props.time.dataset.setAttribute('time-end', end);
74
- }
75
- });
76
- }
245
+ const period = this.parserPeriod(v.period);
246
+
247
+ this.TimesliderWidget.stops = {
248
+ interval: {
249
+ value:
250
+ period.years * 365 * 24 * 60 +
251
+ period.months * 31 * 24 * 60 +
252
+ period.weeks * 7 * 24 * 60 +
253
+ period.days * 24 * 60 +
254
+ period.hours * 60 +
255
+ period.minutes +
256
+ period.seconds / 60,
257
+ unit: 'minutes',
258
+ },
259
+ };
260
+ } else if (v.hasOwnProperty('array')) {
261
+ // Dates array
262
+ this.TimesliderWidget.fullTimeExtent = new TimeExtent({
263
+ start: new Date(v.array[0]),
264
+ end: new Date(v.array[v.array.length - 1]),
265
+ });
266
+ this.TimesliderWidget.stops = {
267
+ dates: v.array.map((e) => new Date(e)),
268
+ };
269
+
270
+ if (this.layer.type === 'wmts') {
271
+ this.layer.customParameters = {};
272
+ const time = v.array.map((d) => new Date(d));
273
+
274
+ for (let i in time) {
275
+ timeDict[time[i]] = v.array[i];
276
+ }
277
+ }
278
+ }
279
+ this.TimesliderWidget.watch('timeExtent', (timeExtent) => {
280
+ if (!this.container.current ? true : false) {
281
+ this.TimesliderWidget.stop();
282
+ }
283
+ let start = new Date(timeExtent.start).getTime();
284
+ let end = new Date(timeExtent.end).getTime();
285
+ this.props.time.elem.setAttribute('time-start', start);
286
+ this.props.time.elem.setAttribute('time-end', end);
287
+ if (this.props.download) {
288
+ this.props.time.dataset.setAttribute('time-start', start);
289
+ this.props.time.dataset.setAttribute('time-end', end);
290
+ }
291
+ if (this.layer.type === 'wmts') {
292
+ this.layer.customParameters = {};
293
+ this.layer.customParameters['TIME'] =
294
+ timeDict[this.TimesliderWidget.timeExtent.end];
295
+ this.layer.refresh();
296
+ }
297
+ });
298
+ } // if there is dimension time
299
+ else {
300
+ this.TimesliderWidget.disabled = true;
301
+ }
302
+ }); // GetTime
303
+ } // is feature or WMS/WMTS
304
+ });
305
+ } //componentDidMount
77
306
 
78
307
  /**
79
308
  * Needed to get the desired drag-and-drop behavior