@eeacms/volto-arcgis-block 0.1.429 → 0.1.430
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,10 +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.430](https://github.com/eea/volto-arcgis-block/compare/0.1.429...0.1.430) - 19 February 2026
|
|
8
|
+
|
|
9
|
+
#### :hammer_and_wrench: Others
|
|
10
|
+
|
|
11
|
+
- (bug): WFS fix [Unai Bolivar - [`dd08e60`](https://github.com/eea/volto-arcgis-block/commit/dd08e60240a885b9e611b6e096d413027a4d2b2c)]
|
|
12
|
+
- (bug): shapefileLimit error popup [Unai Bolivar - [`70d95a5`](https://github.com/eea/volto-arcgis-block/commit/70d95a5d58feed47bf027a0a213eb892a6d1a661)]
|
|
7
13
|
### [0.1.429](https://github.com/eea/volto-arcgis-block/compare/0.1.428...0.1.429) - 17 February 2026
|
|
8
14
|
|
|
9
15
|
#### :hammer_and_wrench: Others
|
|
10
16
|
|
|
17
|
+
- Merge pull request #1104 from eea/develop [Unai Bolivar - [`b5afb9b`](https://github.com/eea/volto-arcgis-block/commit/b5afb9bb2ca6486c1d0b72c87caebf4acc630e07)]
|
|
11
18
|
- (bug): styles for buttons in upload widget and error popup message for file size limit on hspae files [Unai Bolivar - [`d9ca59e`](https://github.com/eea/volto-arcgis-block/commit/d9ca59ec245fdc94a2d1bf678b6e3d610d5a792d)]
|
|
12
19
|
- (bug): reset upload widget to allow users to start from zero without finishing a process first [Unai Bolivar - [`1539a3a`](https://github.com/eea/volto-arcgis-block/commit/1539a3ada8fef0fbda5203b61ec2aed60ab014b5)]
|
|
13
20
|
- (bug): truncate title to 33 max char and add ellipsis for user created services and move trashcan icon to the right edge of the menu item div [Unai Bolivar - [`a31612d`](https://github.com/eea/volto-arcgis-block/commit/a31612df1ee629937e115b1fec1c50092b659626)]
|
package/package.json
CHANGED
|
@@ -2474,6 +2474,17 @@ class MenuWidget extends React.Component {
|
|
|
2474
2474
|
const versionList = Array.from(versionSet);
|
|
2475
2475
|
const formatList = Array.from(formatSet);
|
|
2476
2476
|
const srsList = Array.from(srsSet);
|
|
2477
|
+
const normalizedSrsList = srsList
|
|
2478
|
+
.map((srsValue) => {
|
|
2479
|
+
const textValue = (srsValue || '').trim();
|
|
2480
|
+
const epsgMatch = textValue.match(/EPSG(?::|::|\/)(\d+)/i);
|
|
2481
|
+
if (epsgMatch && epsgMatch[1]) {
|
|
2482
|
+
return `EPSG:${epsgMatch[1]}`;
|
|
2483
|
+
}
|
|
2484
|
+
const normalizedSrsValue = textValue.toUpperCase();
|
|
2485
|
+
return normalizedSrsValue || null;
|
|
2486
|
+
})
|
|
2487
|
+
.filter(Boolean);
|
|
2477
2488
|
const requestVersion = versionList.includes('2.0.0')
|
|
2478
2489
|
? '2.0.0'
|
|
2479
2490
|
: versionList.includes('1.1.0')
|
|
@@ -2487,9 +2498,9 @@ class MenuWidget extends React.Component {
|
|
|
2487
2498
|
const preferredXmlFormat = formatList.find((item) =>
|
|
2488
2499
|
/text\/xml|xml|gml/i.test(item),
|
|
2489
2500
|
);
|
|
2490
|
-
const requestSrsName =
|
|
2501
|
+
const requestSrsName = normalizedSrsList.includes('EPSG:4326')
|
|
2491
2502
|
? 'EPSG:4326'
|
|
2492
|
-
:
|
|
2503
|
+
: normalizedSrsList[0] || 'EPSG:4326';
|
|
2493
2504
|
return {
|
|
2494
2505
|
requestVersion,
|
|
2495
2506
|
requestFormat: preferredJsonFormat || preferredXmlFormat || null,
|
|
@@ -2581,6 +2592,69 @@ class MenuWidget extends React.Component {
|
|
|
2581
2592
|
);
|
|
2582
2593
|
}
|
|
2583
2594
|
|
|
2595
|
+
resolveResponseData(responseData) {
|
|
2596
|
+
const resolveJsonData = (dataValue) => {
|
|
2597
|
+
if (!dataValue || typeof dataValue !== 'object') {
|
|
2598
|
+
return null;
|
|
2599
|
+
}
|
|
2600
|
+
if (
|
|
2601
|
+
dataValue.type === 'FeatureCollection' &&
|
|
2602
|
+
Array.isArray(dataValue.features)
|
|
2603
|
+
) {
|
|
2604
|
+
return {
|
|
2605
|
+
...dataValue,
|
|
2606
|
+
type: 'FeatureCollection',
|
|
2607
|
+
features: dataValue.features,
|
|
2608
|
+
};
|
|
2609
|
+
}
|
|
2610
|
+
if (Array.isArray(dataValue.features)) {
|
|
2611
|
+
return {
|
|
2612
|
+
...dataValue,
|
|
2613
|
+
type: 'FeatureCollection',
|
|
2614
|
+
features: dataValue.features,
|
|
2615
|
+
};
|
|
2616
|
+
}
|
|
2617
|
+
if (dataValue.type === 'Feature' && dataValue.geometry) {
|
|
2618
|
+
return {
|
|
2619
|
+
type: 'FeatureCollection',
|
|
2620
|
+
features: [dataValue],
|
|
2621
|
+
};
|
|
2622
|
+
}
|
|
2623
|
+
return null;
|
|
2624
|
+
};
|
|
2625
|
+
|
|
2626
|
+
if (typeof responseData === 'string') {
|
|
2627
|
+
const textValue = responseData.trim();
|
|
2628
|
+
if (!textValue) {
|
|
2629
|
+
return null;
|
|
2630
|
+
}
|
|
2631
|
+
if (this.hasExceptionResponse(textValue)) {
|
|
2632
|
+
const exceptionMessage = this.resolveExceptionMessage(textValue);
|
|
2633
|
+
throw new Error(exceptionMessage || 'WFS request failed');
|
|
2634
|
+
}
|
|
2635
|
+
let parsedData = null;
|
|
2636
|
+
try {
|
|
2637
|
+
parsedData = JSON.parse(textValue);
|
|
2638
|
+
} catch (e) {}
|
|
2639
|
+
const jsonData = resolveJsonData(parsedData);
|
|
2640
|
+
if (jsonData) {
|
|
2641
|
+
return jsonData;
|
|
2642
|
+
}
|
|
2643
|
+
const xmlData = this.processXmlData(textValue);
|
|
2644
|
+
return this.resolveFeatureCollection(xmlData);
|
|
2645
|
+
}
|
|
2646
|
+
|
|
2647
|
+
return resolveJsonData(responseData);
|
|
2648
|
+
}
|
|
2649
|
+
|
|
2650
|
+
hasResultData(resultData) {
|
|
2651
|
+
return Boolean(
|
|
2652
|
+
resultData &&
|
|
2653
|
+
Array.isArray(resultData.features) &&
|
|
2654
|
+
resultData.features.length > 0,
|
|
2655
|
+
);
|
|
2656
|
+
}
|
|
2657
|
+
|
|
2584
2658
|
processXmlData(xmlInput) {
|
|
2585
2659
|
let doc = xmlInput;
|
|
2586
2660
|
if (typeof xmlInput === 'string') {
|
|
@@ -2993,34 +3067,16 @@ class MenuWidget extends React.Component {
|
|
|
2993
3067
|
const requestParams = this.buildRequestParams(name, requestConfig);
|
|
2994
3068
|
if (requestConfig.hasJsonFormat && requestConfig.requestFormat) {
|
|
2995
3069
|
requestParams.outputFormat = requestConfig.requestFormat;
|
|
3070
|
+
requestParams.outputformat = requestConfig.requestFormat;
|
|
2996
3071
|
}
|
|
2997
3072
|
const requestQuery = new URLSearchParams(requestParams).toString();
|
|
2998
3073
|
const requestUrl = baseUrl + '?' + requestQuery;
|
|
2999
3074
|
|
|
3000
3075
|
const id = (name || baseUrl).toUpperCase().replace(/[: ]/g, '_');
|
|
3001
|
-
|
|
3002
|
-
const layer = new GeoJSONLayer({
|
|
3003
|
-
url: requestUrl,
|
|
3004
|
-
id: id,
|
|
3005
|
-
title: title || name,
|
|
3006
|
-
});
|
|
3007
|
-
layer.LayerId = id;
|
|
3008
|
-
layer.ViewService = baseUrl;
|
|
3009
|
-
layer.name = name;
|
|
3010
|
-
return layer;
|
|
3011
|
-
}
|
|
3012
|
-
|
|
3013
|
-
const xmlResponse = await esriRequest(requestUrl, {
|
|
3076
|
+
const response = await esriRequest(requestUrl, {
|
|
3014
3077
|
responseType: 'text',
|
|
3015
3078
|
});
|
|
3016
|
-
|
|
3017
|
-
const exceptionMessage = this.resolveExceptionMessage(
|
|
3018
|
-
xmlResponse.data,
|
|
3019
|
-
);
|
|
3020
|
-
throw new Error(exceptionMessage || 'WFS request failed');
|
|
3021
|
-
}
|
|
3022
|
-
const xmlData = this.processXmlData(xmlResponse.data);
|
|
3023
|
-
const featureCollection = this.resolveFeatureCollection(xmlData);
|
|
3079
|
+
const featureCollection = this.resolveResponseData(response.data);
|
|
3024
3080
|
if (
|
|
3025
3081
|
featureCollection &&
|
|
3026
3082
|
featureCollection.memberCount > 0 &&
|
|
@@ -3031,7 +3087,7 @@ class MenuWidget extends React.Component {
|
|
|
3031
3087
|
'Selected WFS feature type has no geometry and cannot be displayed on map',
|
|
3032
3088
|
);
|
|
3033
3089
|
}
|
|
3034
|
-
if (!featureCollection
|
|
3090
|
+
if (!this.hasResultData(featureCollection)) {
|
|
3035
3091
|
throw new Error('No WFS features were returned for this layer');
|
|
3036
3092
|
}
|
|
3037
3093
|
const blobData = new Blob([JSON.stringify(featureCollection)], {
|
|
@@ -4,6 +4,7 @@ import { loadModules } from 'esri-loader';
|
|
|
4
4
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
5
5
|
|
|
6
6
|
var WMSLayer, WMTSLayer, WFSLayer, esriRequest;
|
|
7
|
+
const SHAPEFILE_MAX_SIZE_BYTES = 2097152;
|
|
7
8
|
|
|
8
9
|
class UploadWidget extends React.Component {
|
|
9
10
|
/**
|
|
@@ -193,18 +194,39 @@ class UploadWidget extends React.Component {
|
|
|
193
194
|
if (!file) {
|
|
194
195
|
return;
|
|
195
196
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
197
|
+
this.processInputPayload(file);
|
|
198
|
+
e.target.value = null;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
resolveInputError(filePayload) {
|
|
202
|
+
const inputName = ((filePayload && filePayload.name) || '').toLowerCase();
|
|
203
|
+
const inputExtension = inputName.split('.').pop();
|
|
204
|
+
if (inputExtension !== 'zip') {
|
|
205
|
+
return 'fileUploadError';
|
|
206
|
+
}
|
|
207
|
+
const inputSize = (filePayload && filePayload.size) || 0;
|
|
208
|
+
if (inputSize > SHAPEFILE_MAX_SIZE_BYTES) {
|
|
209
|
+
return 'shapefileLimit';
|
|
210
|
+
}
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
processInputPayload(filePayload) {
|
|
215
|
+
const inputError = this.resolveInputError(filePayload);
|
|
216
|
+
if (inputError) {
|
|
217
|
+
this.setState({
|
|
218
|
+
showInfoPopup: true,
|
|
219
|
+
infoPopupType: inputError,
|
|
220
|
+
selectedFile: null,
|
|
221
|
+
globalDragActive: false,
|
|
222
|
+
});
|
|
200
223
|
if (typeof this.uploadFileErrorHandler === 'function') {
|
|
201
|
-
this.uploadFileErrorHandler();
|
|
224
|
+
this.uploadFileErrorHandler(inputError);
|
|
202
225
|
}
|
|
203
|
-
|
|
204
|
-
return;
|
|
226
|
+
return false;
|
|
205
227
|
}
|
|
206
|
-
this.setState({ selectedFile:
|
|
207
|
-
|
|
228
|
+
this.setState({ selectedFile: filePayload, globalDragActive: false });
|
|
229
|
+
return true;
|
|
208
230
|
}
|
|
209
231
|
|
|
210
232
|
getNormalizedUrlForType = (serviceUrl, serviceType) => {
|
|
@@ -259,14 +281,13 @@ class UploadWidget extends React.Component {
|
|
|
259
281
|
) {
|
|
260
282
|
return queryService;
|
|
261
283
|
}
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
/(^|[^a-z])(wmts|wms|wfs)([^a-z]|$)/i,
|
|
284
|
+
const pathName = (parsedUrl.pathname || '').toLowerCase();
|
|
285
|
+
const pathSegments = pathName.split('/').filter(Boolean);
|
|
286
|
+
const serviceMatch = pathSegments.find((segment) =>
|
|
287
|
+
/^(wmts|wms|wfs)$/i.test(segment),
|
|
267
288
|
);
|
|
268
|
-
if (serviceMatch
|
|
269
|
-
return serviceMatch
|
|
289
|
+
if (serviceMatch) {
|
|
290
|
+
return serviceMatch.toUpperCase();
|
|
270
291
|
}
|
|
271
292
|
return null;
|
|
272
293
|
} catch (e) {
|
|
@@ -1095,25 +1116,28 @@ class UploadWidget extends React.Component {
|
|
|
1095
1116
|
const file =
|
|
1096
1117
|
e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files[0];
|
|
1097
1118
|
if (!file) return;
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1119
|
+
this.processInputPayload(file);
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
handleAddClick() {
|
|
1123
|
+
const file = this.state.selectedFile;
|
|
1124
|
+
if (!file) return;
|
|
1125
|
+
const inputError = this.resolveInputError(file);
|
|
1126
|
+
if (inputError) {
|
|
1101
1127
|
this.setState({
|
|
1102
1128
|
showInfoPopup: true,
|
|
1103
|
-
infoPopupType:
|
|
1129
|
+
infoPopupType: inputError,
|
|
1104
1130
|
selectedFile: null,
|
|
1131
|
+
globalDragActive: false,
|
|
1105
1132
|
});
|
|
1106
1133
|
if (typeof this.uploadFileErrorHandler === 'function') {
|
|
1107
|
-
this.uploadFileErrorHandler();
|
|
1134
|
+
this.uploadFileErrorHandler(inputError);
|
|
1135
|
+
}
|
|
1136
|
+
if (this.fileInput && this.fileInput.current) {
|
|
1137
|
+
this.fileInput.current.value = null;
|
|
1108
1138
|
}
|
|
1109
1139
|
return;
|
|
1110
1140
|
}
|
|
1111
|
-
this.setState({ selectedFile: file, globalDragActive: false });
|
|
1112
|
-
}
|
|
1113
|
-
|
|
1114
|
-
handleAddClick() {
|
|
1115
|
-
const file = this.state.selectedFile;
|
|
1116
|
-
if (!file) return;
|
|
1117
1141
|
try {
|
|
1118
1142
|
this.uploadUrlServiceHandler(file, 'FILE');
|
|
1119
1143
|
} catch (err) {
|