@eeacms/volto-arcgis-block 0.1.23 → 0.1.24
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 +16 -0
- package/Jenkinsfile +1 -1
- package/package.json +4 -2
- package/src/components/MapViewer/AreaWidget.jsx +8 -4
- package/src/components/MapViewer/InfoWidget.jsx +389 -0
- package/src/components/MapViewer/MenuWidget.jsx +28 -1
- package/src/components/MapViewer/TimesliderWidget.jsx +1 -4
- package/src/components/MapViewer/css/ArcgisMap.css +29 -0
- package/src/components/UseCasesMapViewer/LegendWidget.jsx +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -4,8 +4,24 @@ 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.24](https://github.com/eea/volto-arcgis-block/compare/0.1.23...0.1.24)
|
|
8
|
+
|
|
9
|
+
- Bugs n improvements [`#80`](https://github.com/eea/volto-arcgis-block/pull/80)
|
|
10
|
+
- The area array to a json object and added a unique_id to the cart [`#79`](https://github.com/eea/volto-arcgis-block/pull/79)
|
|
11
|
+
- Remove Global from legend [`#76`](https://github.com/eea/volto-arcgis-block/pull/76)
|
|
12
|
+
- ESLint fix [`974d62b`](https://github.com/eea/volto-arcgis-block/commit/974d62bd5b66025e12fa85dffcd0d1a5ae04cba4)
|
|
13
|
+
- ESLint fix [`5c4b0d7`](https://github.com/eea/volto-arcgis-block/commit/5c4b0d76de50edd85809c35449f2fb364a9e9312)
|
|
14
|
+
- ESLint fix [`d57d144`](https://github.com/eea/volto-arcgis-block/commit/d57d144fd0e3dbbbbc95195f289d50e6c4b03375)
|
|
15
|
+
- ESLint fix [`9eb0a0c`](https://github.com/eea/volto-arcgis-block/commit/9eb0a0c17d018ac1b25bde422ac149b46b146ff4)
|
|
16
|
+
- ESLint fix [`5fd3772`](https://github.com/eea/volto-arcgis-block/commit/5fd3772f197a3a380067962a5638dbf901a4624e)
|
|
17
|
+
- Pixel info [`1ccef39`](https://github.com/eea/volto-arcgis-block/commit/1ccef39a9adcc3ee94655c77a5a166b613600a08)
|
|
18
|
+
- NUTS bug fix [`37fe7f3`](https://github.com/eea/volto-arcgis-block/commit/37fe7f3fad2c005e3b7c234b3b0564d5df92fa8c)
|
|
19
|
+
|
|
7
20
|
#### [0.1.23](https://github.com/eea/volto-arcgis-block/compare/0.1.22...0.1.23)
|
|
8
21
|
|
|
22
|
+
> 17 December 2021
|
|
23
|
+
|
|
24
|
+
- Develop [`#75`](https://github.com/eea/volto-arcgis-block/pull/75)
|
|
9
25
|
- Use cases region highlight [`#71`](https://github.com/eea/volto-arcgis-block/pull/71)
|
|
10
26
|
- Bugs n improvements [`#74`](https://github.com/eea/volto-arcgis-block/pull/74)
|
|
11
27
|
- Add NUTS 2 in the Map viewer [`#72`](https://github.com/eea/volto-arcgis-block/pull/72)
|
package/Jenkinsfile
CHANGED
|
@@ -4,7 +4,7 @@ pipeline {
|
|
|
4
4
|
environment {
|
|
5
5
|
GIT_NAME = "volto-arcgis-block"
|
|
6
6
|
NAMESPACE = "@eeacms"
|
|
7
|
-
SONARQUBE_TAGS = "volto.eea.europa.eu,clms.land.copernicus.eu"
|
|
7
|
+
SONARQUBE_TAGS = "volto.eea.europa.eu,clms.land.copernicus.eu,water.europa.eu-freshwater"
|
|
8
8
|
DEPENDENCIES = ""
|
|
9
9
|
}
|
|
10
10
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eeacms/volto-arcgis-block",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.24",
|
|
4
4
|
"description": "volto-arcgis-block: Volto add-on",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"author": "European Environment Agency: CodeSyntax",
|
|
@@ -40,7 +40,9 @@
|
|
|
40
40
|
"@fortawesome/fontawesome-svg-core": "1.2.35",
|
|
41
41
|
"@fortawesome/free-solid-svg-icons": "5.15.3",
|
|
42
42
|
"@fortawesome/react-fontawesome": "0.1.14",
|
|
43
|
-
"@eeacms/volto-clms-utils": "0.1.1"
|
|
43
|
+
"@eeacms/volto-clms-utils": "0.1.1",
|
|
44
|
+
"highcharts": "^9.3.2",
|
|
45
|
+
"highcharts-react-official": "^3.1.0"
|
|
44
46
|
},
|
|
45
47
|
"devDependencies": {
|
|
46
48
|
"@cypress/code-coverage": "^3.9.5",
|
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
import React, { createRef } from 'react';
|
|
2
|
-
//import "@arcgis/core/assets/esri/css/main.css";
|
|
3
|
-
//import "./css/ArcgisMap.css";
|
|
4
|
-
//import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
5
2
|
import { loadModules } from 'esri-loader';
|
|
6
3
|
|
|
7
4
|
var Graphic,
|
|
@@ -202,7 +199,14 @@ class AreaWidget extends React.Component {
|
|
|
202
199
|
});
|
|
203
200
|
this.props.map.add(this.nutsGroupLayer);
|
|
204
201
|
this.props.view.on('click', (event) => {
|
|
205
|
-
if (
|
|
202
|
+
if (
|
|
203
|
+
(this.props.mapViewer.activeWidget === this || this.props.download) &&
|
|
204
|
+
(this.props.mapViewer.activeWidget
|
|
205
|
+
? !this.props.mapViewer.activeWidget.container.current.classList.contains(
|
|
206
|
+
'info-container',
|
|
207
|
+
)
|
|
208
|
+
: true)
|
|
209
|
+
) {
|
|
206
210
|
this.props.view.hitTest(event).then((response) => {
|
|
207
211
|
if (response.results.length > 0) {
|
|
208
212
|
let graphic = response.results.filter((result) => {
|
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
import React, { createRef } from 'react';
|
|
2
|
+
import { loadModules } from 'esri-loader';
|
|
3
|
+
import Highcharts from 'highcharts';
|
|
4
|
+
import HighchartsReact from 'highcharts-react-official';
|
|
5
|
+
var GeometryEngine, Graphic;
|
|
6
|
+
|
|
7
|
+
class InfoWidget extends React.Component {
|
|
8
|
+
/**
|
|
9
|
+
* Creator of the InfoWidget 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.map = this.props.map;
|
|
20
|
+
this.menuClass =
|
|
21
|
+
'esri-icon-description esri-widget--button esri-widget esri-interactive';
|
|
22
|
+
//this.chartOptions;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
loader() {
|
|
26
|
+
return loadModules(['esri/geometry/geometryEngine', 'esri/Graphic']).then(
|
|
27
|
+
([_GeometryEngine, _Graphic]) => {
|
|
28
|
+
[GeometryEngine, Graphic] = [_GeometryEngine, _Graphic];
|
|
29
|
+
},
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Method that will be invoked when the
|
|
35
|
+
* button is clicked. It controls the open
|
|
36
|
+
* and close actions of the component
|
|
37
|
+
*/
|
|
38
|
+
openMenu() {
|
|
39
|
+
if (this.state.showMapMenu) {
|
|
40
|
+
this.props.mapViewer.setActiveWidget();
|
|
41
|
+
this.container.current.querySelector('.info-panel').style.display =
|
|
42
|
+
'none';
|
|
43
|
+
this.container.current
|
|
44
|
+
.querySelector('.esri-widget--button')
|
|
45
|
+
.classList.replace('esri-icon-right-arrow', 'esri-icon-description');
|
|
46
|
+
// By invoking the setState, we notify the state we want to reach
|
|
47
|
+
// and ensure that the component is rendered again
|
|
48
|
+
this.setState({ showMapMenu: false, pixelInfo: false });
|
|
49
|
+
this.props.view.popup.autoOpenEnabled = true;
|
|
50
|
+
this.removeMarker();
|
|
51
|
+
} else {
|
|
52
|
+
this.props.mapViewer.setActiveWidget(this);
|
|
53
|
+
this.container.current
|
|
54
|
+
.querySelector('.esri-widget--button')
|
|
55
|
+
.classList.replace('esri-icon-description', 'esri-icon-right-arrow');
|
|
56
|
+
this.container.current.querySelector('.info-panel').style.display =
|
|
57
|
+
'block';
|
|
58
|
+
// By invoking the setState, we notify the state we want to reach
|
|
59
|
+
// and ensure that the component is rendered again
|
|
60
|
+
this.setState({ showMapMenu: true });
|
|
61
|
+
this.props.mapViewer.view.popup.close();
|
|
62
|
+
this.props.view.popup.autoOpenEnabled = false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* This method is executed after the rener method is executed
|
|
67
|
+
*/
|
|
68
|
+
async componentDidMount() {
|
|
69
|
+
await this.loader();
|
|
70
|
+
this.props.view.ui.add(this.container.current, 'top-right');
|
|
71
|
+
this.props.view.on('click', (e) => {
|
|
72
|
+
if (this.props.mapViewer.activeWidget === this) {
|
|
73
|
+
let timeLayers = this.map.layers.items.filter(
|
|
74
|
+
(a) => a.timeInfo && a.visible,
|
|
75
|
+
);
|
|
76
|
+
let layer = timeLayers[timeLayers.length - 1];
|
|
77
|
+
let title;
|
|
78
|
+
if (layer.sublayers) {
|
|
79
|
+
title = layer.sublayers.items[0].title;
|
|
80
|
+
} else if (layer.activeLayer) {
|
|
81
|
+
title = layer.activeLayer.title;
|
|
82
|
+
} else {
|
|
83
|
+
title = layer.title;
|
|
84
|
+
}
|
|
85
|
+
this.identify(layer, e).then((response) => {
|
|
86
|
+
let variables = response.variables.options;
|
|
87
|
+
let variable = response.variables.selected;
|
|
88
|
+
if (
|
|
89
|
+
this.state.variables
|
|
90
|
+
? variables.includes(this.state.variables.selected)
|
|
91
|
+
: false
|
|
92
|
+
) {
|
|
93
|
+
variable = this.state.variables.selected;
|
|
94
|
+
}
|
|
95
|
+
let data = {
|
|
96
|
+
x: response.timeFields.values
|
|
97
|
+
.map((a) => {
|
|
98
|
+
return a[response.timeFields.start];
|
|
99
|
+
})
|
|
100
|
+
.sort((a, b) => {
|
|
101
|
+
return new Date(a).getTime() - new Date(b).getTime();
|
|
102
|
+
}),
|
|
103
|
+
y: response.data.values.map((a) => {
|
|
104
|
+
return Math.round(a[variable] * 100) / 100;
|
|
105
|
+
}),
|
|
106
|
+
};
|
|
107
|
+
let chartData = this.createChart(title, variable, data);
|
|
108
|
+
this.addMarker(e);
|
|
109
|
+
this.setState({
|
|
110
|
+
pixelInfo: true,
|
|
111
|
+
data: response,
|
|
112
|
+
options: chartData,
|
|
113
|
+
variables: { options: variables, selected: variable, title: title },
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
addMarker(evt) {
|
|
121
|
+
this.removeMarker();
|
|
122
|
+
let lat = evt.mapPoint.latitude;
|
|
123
|
+
let long = evt.mapPoint.longitude;
|
|
124
|
+
var point = {
|
|
125
|
+
type: 'point',
|
|
126
|
+
longitude: long,
|
|
127
|
+
latitude: lat,
|
|
128
|
+
};
|
|
129
|
+
var markerSymbol = {
|
|
130
|
+
type: 'simple-marker',
|
|
131
|
+
color: [255, 255, 255, 0.75],
|
|
132
|
+
outline: {
|
|
133
|
+
color: 'black',
|
|
134
|
+
width: '2px',
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
var pointGraphic = new Graphic({
|
|
138
|
+
geometry: point,
|
|
139
|
+
symbol: markerSymbol,
|
|
140
|
+
attributes: { long, lat, id: 'pixel-info' },
|
|
141
|
+
});
|
|
142
|
+
this.props.view.graphics.add(pointGraphic);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
removeMarker() {
|
|
146
|
+
if (
|
|
147
|
+
this.props.view.graphics.items.find((a) => {
|
|
148
|
+
return a.attributes ? a.attributes.id === 'pixel-info' : false;
|
|
149
|
+
})
|
|
150
|
+
) {
|
|
151
|
+
let marker = this.props.view.graphics.items.find((a) => {
|
|
152
|
+
return a.attributes && a.attributes.id === 'pixel-info';
|
|
153
|
+
});
|
|
154
|
+
this.props.view.graphics.remove(marker);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
let marker = this.props.view.graphics.items.find((a) => {
|
|
158
|
+
return a.attributes ? a.attributes.id === 'pixel-info' : false;
|
|
159
|
+
});
|
|
160
|
+
this.props.view.graphics.remove(marker);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
identify(layer, evt) {
|
|
164
|
+
let values = { timeFields: {}, data: {}, variables: {} };
|
|
165
|
+
//Complete time data
|
|
166
|
+
values.timeFields['start'] = layer.timeInfo.startField;
|
|
167
|
+
values.timeFields['end'] = layer.timeInfo.endField;
|
|
168
|
+
let timeQuery = layer.createQuery();
|
|
169
|
+
timeQuery.outFields = [layer.timeInfo.startField];
|
|
170
|
+
let fields = layer.fields
|
|
171
|
+
.filter((a) => {
|
|
172
|
+
return (
|
|
173
|
+
a.type !== 'date' &&
|
|
174
|
+
a.type !== 'geometry' &&
|
|
175
|
+
a.type !== 'string' &&
|
|
176
|
+
a.type !== 'oid'
|
|
177
|
+
);
|
|
178
|
+
})
|
|
179
|
+
.map((b) => {
|
|
180
|
+
return b.name;
|
|
181
|
+
});
|
|
182
|
+
let field = layer.displayField in fields ? layer.displayField : fields[0];
|
|
183
|
+
values.variables = { options: fields, selected: field };
|
|
184
|
+
if (layer.timeInfo.fullTimeExtent.endField) {
|
|
185
|
+
timeQuery.outFields.push(layer.timeInfo.endField);
|
|
186
|
+
}
|
|
187
|
+
timeQuery.returnDistinctValues = true;
|
|
188
|
+
timeQuery.returnGeometry = false;
|
|
189
|
+
let p1 = layer.queryFeatures(timeQuery).then((r) => {
|
|
190
|
+
let timevals = [];
|
|
191
|
+
r.features.forEach((e) => timevals.push(e.attributes));
|
|
192
|
+
values.timeFields['values'] = timevals;
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
//Query for data
|
|
196
|
+
let query = layer.createQuery();
|
|
197
|
+
query.geometry = this.props.view.toMap(evt); // the point location of the pointer
|
|
198
|
+
query.distance = 1000;
|
|
199
|
+
query.units = 'meters';
|
|
200
|
+
query.spatialRelationship = 'intersects'; // this is the default
|
|
201
|
+
query.returnGeometry = true;
|
|
202
|
+
query.outFields = [fields.toString()]; // Information to be returned
|
|
203
|
+
values.data['outFields'] = [fields.toString()];
|
|
204
|
+
|
|
205
|
+
let p2 = layer.queryFeatures(query).then((response) => {
|
|
206
|
+
//First of all, we get all the points with its distance to click point
|
|
207
|
+
let points = response.features.map((e) => {
|
|
208
|
+
return {
|
|
209
|
+
latitude: e.geometry.latitude,
|
|
210
|
+
longitude: e.geometry.longitude,
|
|
211
|
+
distance: GeometryEngine.distance(
|
|
212
|
+
this.props.view.toMap(evt),
|
|
213
|
+
e.geometry,
|
|
214
|
+
'meters',
|
|
215
|
+
),
|
|
216
|
+
};
|
|
217
|
+
});
|
|
218
|
+
let min_distance = Math.min.apply(
|
|
219
|
+
null,
|
|
220
|
+
points.map((e) => e.distance),
|
|
221
|
+
); //minimum distance
|
|
222
|
+
let point = points.find((e) => e.distance <= min_distance); //minimum distance point
|
|
223
|
+
//get de info of the minimum distance point at all the times possible
|
|
224
|
+
let info = response.features.filter(
|
|
225
|
+
(e) =>
|
|
226
|
+
e.geometry.latitude === point.latitude &&
|
|
227
|
+
e.geometry.longitude === point.longitude,
|
|
228
|
+
);
|
|
229
|
+
values.data['values'] = info.map((e) => {
|
|
230
|
+
return e.attributes;
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
return Promise.all([p1, p2]).then(() => {
|
|
235
|
+
return values;
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
createChart(title, variable, chartData) {
|
|
240
|
+
let chartOptions = {
|
|
241
|
+
chart: {
|
|
242
|
+
height: 208,
|
|
243
|
+
},
|
|
244
|
+
title: {
|
|
245
|
+
text: title,
|
|
246
|
+
style: {},
|
|
247
|
+
},
|
|
248
|
+
subtitle: {
|
|
249
|
+
text: '',
|
|
250
|
+
style: {
|
|
251
|
+
display: 'none',
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
plotOptions: {
|
|
255
|
+
line: {
|
|
256
|
+
pointPlacement: 'between',
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
xAxis: {
|
|
260
|
+
title: {
|
|
261
|
+
text: null,
|
|
262
|
+
},
|
|
263
|
+
labels: {
|
|
264
|
+
format: '{value:%d/%m/%Y}',
|
|
265
|
+
},
|
|
266
|
+
type: 'datetime',
|
|
267
|
+
categories: chartData.x,
|
|
268
|
+
tickmarkPlacement: 'between',
|
|
269
|
+
startOnTick: true,
|
|
270
|
+
endOnTick: true,
|
|
271
|
+
},
|
|
272
|
+
legend: {
|
|
273
|
+
enabled: false,
|
|
274
|
+
},
|
|
275
|
+
tooltip: {
|
|
276
|
+
shared: true,
|
|
277
|
+
useHTML: true,
|
|
278
|
+
headerFormat: '{point.x:%d/%m/%Y}<br><b>{point.point.symbolName}</b>',
|
|
279
|
+
},
|
|
280
|
+
series: [
|
|
281
|
+
{
|
|
282
|
+
marker: {
|
|
283
|
+
enabled: false,
|
|
284
|
+
},
|
|
285
|
+
name: variable,
|
|
286
|
+
data: chartData.y,
|
|
287
|
+
shadow: false,
|
|
288
|
+
zIndex: 1,
|
|
289
|
+
color: '#a0b128',
|
|
290
|
+
},
|
|
291
|
+
],
|
|
292
|
+
exporting: {
|
|
293
|
+
buttons: {
|
|
294
|
+
contextButton: {
|
|
295
|
+
enabled: false,
|
|
296
|
+
},
|
|
297
|
+
},
|
|
298
|
+
},
|
|
299
|
+
credits: {
|
|
300
|
+
enabled: false,
|
|
301
|
+
},
|
|
302
|
+
};
|
|
303
|
+
return chartOptions;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
selectVariable(option) {
|
|
307
|
+
let variables = this.state.variables.options;
|
|
308
|
+
let variable = option;
|
|
309
|
+
let title = this.state.variables.title;
|
|
310
|
+
let data = {
|
|
311
|
+
x: this.state.data.timeFields.values
|
|
312
|
+
.map((a) => {
|
|
313
|
+
return a[this.state.data.timeFields.start];
|
|
314
|
+
})
|
|
315
|
+
.sort((a, b) => {
|
|
316
|
+
return new Date(a).getTime() - new Date(b).getTime();
|
|
317
|
+
}),
|
|
318
|
+
y: this.state.data.data.values.map((a) => {
|
|
319
|
+
return Math.round(a[variable] * 100) / 100;
|
|
320
|
+
}),
|
|
321
|
+
};
|
|
322
|
+
let chartData = this.createChart(title, variable, data);
|
|
323
|
+
this.setState({
|
|
324
|
+
options: chartData,
|
|
325
|
+
variables: { options: variables, selected: variable, title: title },
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* This method renders the component
|
|
331
|
+
* @returns jsx
|
|
332
|
+
*/
|
|
333
|
+
render() {
|
|
334
|
+
let isEmpty;
|
|
335
|
+
if (this.state.data) {
|
|
336
|
+
isEmpty =
|
|
337
|
+
this.state.data.data.values.map((a) => {
|
|
338
|
+
return a[this.state.variables.selected];
|
|
339
|
+
}).length === 0;
|
|
340
|
+
}
|
|
341
|
+
return (
|
|
342
|
+
<>
|
|
343
|
+
<div ref={this.container} className="info-container">
|
|
344
|
+
<div
|
|
345
|
+
className={this.menuClass}
|
|
346
|
+
id="info_button"
|
|
347
|
+
title="Info"
|
|
348
|
+
onClick={this.openMenu.bind(this)}
|
|
349
|
+
onKeyDown={this.openMenu.bind(this)}
|
|
350
|
+
tabIndex="0"
|
|
351
|
+
role="button"
|
|
352
|
+
></div>
|
|
353
|
+
<div className="info-panel">
|
|
354
|
+
{this.state.pixelInfo ? (
|
|
355
|
+
<>
|
|
356
|
+
<select
|
|
357
|
+
className="esri-select"
|
|
358
|
+
value={this.state.variables.selected}
|
|
359
|
+
onBlur={(e) => this.selectVariable(e.target.value)}
|
|
360
|
+
onChange={(e) => this.selectVariable(e.target.value)}
|
|
361
|
+
>
|
|
362
|
+
{this.state.variables.options.map((option) => (
|
|
363
|
+
<option key={option} value={option}>
|
|
364
|
+
{option}
|
|
365
|
+
</option>
|
|
366
|
+
))}
|
|
367
|
+
</select>
|
|
368
|
+
{isEmpty ? (
|
|
369
|
+
<span className="info-panel-empty">No data</span>
|
|
370
|
+
) : (
|
|
371
|
+
<HighchartsReact
|
|
372
|
+
highcharts={Highcharts}
|
|
373
|
+
options={this.state.options}
|
|
374
|
+
/>
|
|
375
|
+
)}
|
|
376
|
+
</>
|
|
377
|
+
) : (
|
|
378
|
+
<span className="info-panel-empty">
|
|
379
|
+
Click on the map to get pixel info
|
|
380
|
+
</span>
|
|
381
|
+
)}
|
|
382
|
+
</div>
|
|
383
|
+
</div>
|
|
384
|
+
</>
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
export default InfoWidget;
|
|
@@ -8,6 +8,7 @@ import { useIntl } from 'react-intl';
|
|
|
8
8
|
import { Message, Modal } from 'semantic-ui-react';
|
|
9
9
|
import AreaWidget from './AreaWidget';
|
|
10
10
|
import TimesliderWidget from './TimesliderWidget';
|
|
11
|
+
import InfoWidget from './InfoWidget';
|
|
11
12
|
var WMSLayer, WMTSLayer, FeatureLayer;
|
|
12
13
|
|
|
13
14
|
export const AddCartItem = ({
|
|
@@ -27,7 +28,7 @@ export const AddCartItem = ({
|
|
|
27
28
|
|
|
28
29
|
const checkArea = () => {
|
|
29
30
|
let check = document.querySelector('.area-panel input:checked').value;
|
|
30
|
-
let area =
|
|
31
|
+
let area = {};
|
|
31
32
|
if (check === 'area') {
|
|
32
33
|
let graphics = mapViewer.view.graphics;
|
|
33
34
|
if (graphics.length === 0) {
|
|
@@ -76,6 +77,8 @@ export const AddCartItem = ({
|
|
|
76
77
|
let datasetElem = document.querySelector('div[datasetid="' + id + '"]');
|
|
77
78
|
let datasetData = {
|
|
78
79
|
id: id,
|
|
80
|
+
UID: id,
|
|
81
|
+
unique_id: `${id}-${new Date().getTime()}`,
|
|
79
82
|
area: area,
|
|
80
83
|
};
|
|
81
84
|
if (
|
|
@@ -711,6 +714,23 @@ class MenuWidget extends React.Component {
|
|
|
711
714
|
if (nuts) {
|
|
712
715
|
this.map.reorder(nuts, this.map.layers.items.length + 1);
|
|
713
716
|
}
|
|
717
|
+
if (Object.keys(this.timeLayers).length > 0) {
|
|
718
|
+
if (!document.querySelector('.info-container')) {
|
|
719
|
+
let div = document.createElement('div');
|
|
720
|
+
document.querySelector('.esri-ui-top-right').appendChild(div);
|
|
721
|
+
ReactDOM.render(
|
|
722
|
+
<InfoWidget
|
|
723
|
+
view={this.props.view}
|
|
724
|
+
map={this.map}
|
|
725
|
+
mapViewer={this.props.mapViewer}
|
|
726
|
+
/>,
|
|
727
|
+
div,
|
|
728
|
+
);
|
|
729
|
+
div.remove();
|
|
730
|
+
} else {
|
|
731
|
+
document.querySelector('.info-container').style.display = '';
|
|
732
|
+
}
|
|
733
|
+
}
|
|
714
734
|
} else {
|
|
715
735
|
let checkboxes = document.getElementsByName('layerCheckbox');
|
|
716
736
|
let repeatedLayers = [];
|
|
@@ -727,6 +747,13 @@ class MenuWidget extends React.Component {
|
|
|
727
747
|
}
|
|
728
748
|
}
|
|
729
749
|
this.updateCheckDataset(parentId);
|
|
750
|
+
if (
|
|
751
|
+
Object.keys(this.timeLayers).length === 0 &&
|
|
752
|
+
document.querySelector('.info-container')
|
|
753
|
+
) {
|
|
754
|
+
this.props.mapViewer.closeActiveWidget();
|
|
755
|
+
document.querySelector('.info-container').style.display = 'none';
|
|
756
|
+
}
|
|
730
757
|
this.setState({});
|
|
731
758
|
}
|
|
732
759
|
|
|
@@ -19,10 +19,7 @@ class TimesliderWidget extends React.Component {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
loader() {
|
|
22
|
-
return loadModules([
|
|
23
|
-
'esri/widgets/TimeSlider',
|
|
24
|
-
'esri/layers/WMSLayer',
|
|
25
|
-
]).then(([_TimeSlider]) => {
|
|
22
|
+
return loadModules(['esri/widgets/TimeSlider']).then(([_TimeSlider]) => {
|
|
26
23
|
[TimeSlider] = [_TimeSlider];
|
|
27
24
|
});
|
|
28
25
|
}
|
|
@@ -37,6 +37,11 @@
|
|
|
37
37
|
max-height: 250px !important;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
.esri-ui-top-right,
|
|
41
|
+
.esri-ui-top-left {
|
|
42
|
+
z-index: 1;
|
|
43
|
+
}
|
|
44
|
+
|
|
40
45
|
.esri-component.esri-zoom.esri-widget {
|
|
41
46
|
background: none;
|
|
42
47
|
box-shadow: none;
|
|
@@ -76,6 +81,10 @@
|
|
|
76
81
|
order: 5;
|
|
77
82
|
}
|
|
78
83
|
|
|
84
|
+
.info-container {
|
|
85
|
+
order: 6;
|
|
86
|
+
}
|
|
87
|
+
|
|
79
88
|
/* Basemap */
|
|
80
89
|
.basemap-container {
|
|
81
90
|
display: flex;
|
|
@@ -586,6 +595,26 @@
|
|
|
586
595
|
overflow: auto;
|
|
587
596
|
}
|
|
588
597
|
|
|
598
|
+
/* Pixel info */
|
|
599
|
+
.info-container {
|
|
600
|
+
display: flex;
|
|
601
|
+
box-shadow: none !important;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
.info-panel {
|
|
605
|
+
display: none;
|
|
606
|
+
overflow: auto;
|
|
607
|
+
width: 300px;
|
|
608
|
+
max-height: 240px;
|
|
609
|
+
padding: 1rem;
|
|
610
|
+
background-color: white;
|
|
611
|
+
font-size: 1rem;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
.info-panel select {
|
|
615
|
+
margin-bottom: 1rem;
|
|
616
|
+
}
|
|
617
|
+
|
|
589
618
|
/* Modal */
|
|
590
619
|
.map-download-modal.ui.modal {
|
|
591
620
|
margin: 0 !important;
|
|
@@ -75,6 +75,12 @@ class LegendWidget extends React.Component {
|
|
|
75
75
|
break;
|
|
76
76
|
}
|
|
77
77
|
}
|
|
78
|
+
|
|
79
|
+
let legendRow = document.querySelectorAll('.esri-legend__layer-row');
|
|
80
|
+
for (let i = 0; i < legendRow.length; i++) {
|
|
81
|
+
legendRow[i].textContent.toLowerCase() === 'global' &&
|
|
82
|
+
legendRow[i].remove();
|
|
83
|
+
}
|
|
78
84
|
// By invoking the setState, we notify the state we want to reach
|
|
79
85
|
// and ensure that the component is rendered again
|
|
80
86
|
this.mapViewer.setState({ showMapMenu: true });
|