@eeacms/volto-arcgis-block 0.1.483 → 0.1.484
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,11 @@ 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.484](https://github.com/eea/volto-arcgis-block/compare/0.1.483...0.1.484) - 15 September 2026
|
|
8
|
+
|
|
9
|
+
#### :hammer_and_wrench: Others
|
|
10
|
+
|
|
11
|
+
- (lint): lint and prettified [Unai Bolivar - [`13294af`](https://github.com/eea/volto-arcgis-block/commit/13294aff5e09463006cbc6421800c8f71bd4ac49)]
|
|
7
12
|
### [0.1.483](https://github.com/eea/volto-arcgis-block/compare/0.1.482...0.1.483) - 15 September 2026
|
|
8
13
|
|
|
9
14
|
### [0.1.482](https://github.com/eea/volto-arcgis-block/compare/0.1.481...0.1.482) - 15 September 2026
|
package/package.json
CHANGED
|
@@ -7,6 +7,7 @@ import useCartState from '@eeacms/volto-clms-utils/cart/useCartState';
|
|
|
7
7
|
import { Modal, Popup } from 'semantic-ui-react';
|
|
8
8
|
import AreaWidget from './AreaWidget';
|
|
9
9
|
import TimesliderWidget from './TimesliderWidget';
|
|
10
|
+
import { resolveServiceUrl } from './serviceUrlResolver';
|
|
10
11
|
|
|
11
12
|
export const USER_SERVICES_KEY = 'user_services_session';
|
|
12
13
|
|
|
@@ -2661,28 +2662,6 @@ class MenuWidget extends React.Component {
|
|
|
2661
2662
|
);
|
|
2662
2663
|
}
|
|
2663
2664
|
|
|
2664
|
-
stripProtocol(url) {
|
|
2665
|
-
return (url || '').replace(/^https?:\/\//i, '');
|
|
2666
|
-
}
|
|
2667
|
-
|
|
2668
|
-
getProxyBase = () => {
|
|
2669
|
-
const origin = window?.location?.origin || '';
|
|
2670
|
-
return origin ? `${origin}/ogcproxy/` : '/ogcproxy/';
|
|
2671
|
-
// return 'https://clmsdemo.devel6cph.eea.europa.eu/ogcproxy/';
|
|
2672
|
-
// return 'https://land.copernicus.eu/ogcproxy/';
|
|
2673
|
-
};
|
|
2674
|
-
|
|
2675
|
-
buildProxiedUrl(url) {
|
|
2676
|
-
if (!url) return url;
|
|
2677
|
-
const hasProxy = /\/ogcproxy\//i.test(url);
|
|
2678
|
-
if (hasProxy) {
|
|
2679
|
-
const strippedUrl = this.stripProtocol(url);
|
|
2680
|
-
const proxyPath = strippedUrl.split(/\/ogcproxy\//i)[1] || '';
|
|
2681
|
-
return this.getProxyBase() + proxyPath.replace(/^\/+/, '');
|
|
2682
|
-
}
|
|
2683
|
-
return this.getProxyBase() + this.stripProtocol(url);
|
|
2684
|
-
}
|
|
2685
|
-
|
|
2686
2665
|
buildCdseLegendUrl(serviceUrl, layerTitle) {
|
|
2687
2666
|
if (!serviceUrl || !layerTitle) return null;
|
|
2688
2667
|
const collectionMatch =
|
|
@@ -3657,9 +3636,11 @@ class MenuWidget extends React.Component {
|
|
|
3657
3636
|
|
|
3658
3637
|
async handleNewMapServiceLayer(viewService, serviceType, serviceSelection) {
|
|
3659
3638
|
let resourceLayers = [];
|
|
3660
|
-
const
|
|
3639
|
+
const resolvedServiceUrl = resolveServiceUrl(viewService, {
|
|
3640
|
+
fromUploadWidget: true,
|
|
3641
|
+
});
|
|
3661
3642
|
try {
|
|
3662
|
-
const rawUrl = (
|
|
3643
|
+
const rawUrl = (resolvedServiceUrl || '').trim();
|
|
3663
3644
|
const baseUrl = rawUrl.split('?')[0];
|
|
3664
3645
|
const resolveCapabilitiesText = (xmlData) => {
|
|
3665
3646
|
if (!xmlData) {
|
|
@@ -4034,7 +4015,7 @@ class MenuWidget extends React.Component {
|
|
|
4034
4015
|
}
|
|
4035
4016
|
}
|
|
4036
4017
|
if (serviceType === 'WMS' || serviceType === 'WMTS') {
|
|
4037
|
-
const forced = (
|
|
4018
|
+
const forced = (resolvedServiceUrl || '').trim();
|
|
4038
4019
|
if (forced) {
|
|
4039
4020
|
if (typeof resourceLayer.url === 'string') {
|
|
4040
4021
|
resourceLayer.url = forced;
|
|
@@ -6195,7 +6176,9 @@ class MenuWidget extends React.Component {
|
|
|
6195
6176
|
|
|
6196
6177
|
getCapabilities = async (url, serviceType, options = {}) => {
|
|
6197
6178
|
const useProxy = !!options?.useProxy;
|
|
6198
|
-
const targetUrl = useProxy
|
|
6179
|
+
const targetUrl = useProxy
|
|
6180
|
+
? resolveServiceUrl(url, { fromUploadWidget: true })
|
|
6181
|
+
: url;
|
|
6199
6182
|
const evaluateXmlResponse = (responseData) => {
|
|
6200
6183
|
const parser = new DOMParser();
|
|
6201
6184
|
const xmlDoc = parser.parseFromString(responseData, 'text/xml');
|
|
@@ -2,6 +2,7 @@ import React, { createRef } from 'react';
|
|
|
2
2
|
import { loadModules } from 'esri-loader';
|
|
3
3
|
// import { FontAwesomeIcon } from '@eeacms/volto-clms-utils/components';
|
|
4
4
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
|
5
|
+
import { resolveServiceUrl } from './serviceUrlResolver';
|
|
5
6
|
|
|
6
7
|
var WMSLayer, WMTSLayer, WFSLayer, esriRequest;
|
|
7
8
|
const SHAPEFILE_MAX_SIZE_BYTES = 2097152;
|
|
@@ -334,28 +335,6 @@ class UploadWidget extends React.Component {
|
|
|
334
335
|
this.clearUploadForm(true);
|
|
335
336
|
};
|
|
336
337
|
|
|
337
|
-
stripProtocol = (url) => {
|
|
338
|
-
return (url || '').replace(/^https?:\/\//i, '');
|
|
339
|
-
};
|
|
340
|
-
|
|
341
|
-
getProxyBase = () => {
|
|
342
|
-
const origin = window?.location?.origin || '';
|
|
343
|
-
return origin ? `${origin}/ogcproxy/` : '/ogcproxy/';
|
|
344
|
-
// return 'https://clmsdemo.devel6cph.eea.europa.eu/ogcproxy/';
|
|
345
|
-
// return 'https://land.copernicus.eu/ogcproxy/';
|
|
346
|
-
};
|
|
347
|
-
|
|
348
|
-
buildProxiedUrl = (url) => {
|
|
349
|
-
if (!url) return url;
|
|
350
|
-
const hasProxy = /\/ogcproxy\//i.test(url);
|
|
351
|
-
if (hasProxy) {
|
|
352
|
-
const strippedUrl = this.stripProtocol(url);
|
|
353
|
-
const proxyPath = strippedUrl.split(/\/ogcproxy\//i)[1] || '';
|
|
354
|
-
return this.getProxyBase() + proxyPath.replace(/^\/+/, '');
|
|
355
|
-
}
|
|
356
|
-
return this.getProxyBase() + this.stripProtocol(url);
|
|
357
|
-
};
|
|
358
|
-
|
|
359
338
|
resolveNodeValue = (nodeValue) => {
|
|
360
339
|
if (nodeValue === null || nodeValue === undefined) {
|
|
361
340
|
return null;
|
|
@@ -510,8 +489,10 @@ class UploadWidget extends React.Component {
|
|
|
510
489
|
|
|
511
490
|
getCapabilities = (url, serviceType) => {
|
|
512
491
|
// Get the coordinates of the click on the view
|
|
513
|
-
const
|
|
514
|
-
|
|
492
|
+
const resolvedServiceUrl = resolveServiceUrl(url, {
|
|
493
|
+
fromUploadWidget: true,
|
|
494
|
+
});
|
|
495
|
+
return esriRequest(resolvedServiceUrl, {
|
|
515
496
|
responseType: 'text',
|
|
516
497
|
query: {
|
|
517
498
|
request: 'GetCapabilities',
|
|
@@ -617,15 +598,21 @@ class UploadWidget extends React.Component {
|
|
|
617
598
|
trimmedServiceUrl,
|
|
618
599
|
selectedServiceType,
|
|
619
600
|
);
|
|
620
|
-
const
|
|
601
|
+
const resolvedServiceUrl = resolveServiceUrl(normalizedUrl, {
|
|
602
|
+
fromUploadWidget: true,
|
|
603
|
+
});
|
|
621
604
|
if (selectedServiceType === 'WMS') {
|
|
622
|
-
this.uploadUrlServiceHandler(
|
|
605
|
+
this.uploadUrlServiceHandler(resolvedServiceUrl, 'WMS');
|
|
623
606
|
this.setState({ serviceUrl: '' });
|
|
624
607
|
} else if (selectedServiceType === 'WMTS') {
|
|
625
|
-
this.uploadUrlServiceHandler(
|
|
608
|
+
this.uploadUrlServiceHandler(resolvedServiceUrl, 'WMTS');
|
|
626
609
|
this.setState({ serviceUrl: '' });
|
|
627
610
|
} else if (selectedServiceType === 'WFS') {
|
|
628
|
-
this.uploadUrlServiceHandler(
|
|
611
|
+
this.uploadUrlServiceHandler(
|
|
612
|
+
resolvedServiceUrl,
|
|
613
|
+
'WFS',
|
|
614
|
+
selectedFeatures,
|
|
615
|
+
);
|
|
629
616
|
this.setState({ wfsFeatures: {}, serviceUrl: '' });
|
|
630
617
|
this.setState({ selectedFeatures: {} });
|
|
631
618
|
} else {
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
const PROXY_PATH_PATTERN = /\/ogcproxy\//i;
|
|
2
|
+
const INTERNAL_HOST_PATTERNS = [
|
|
3
|
+
/^localhost$/i,
|
|
4
|
+
/^127\.0\.0\.1$/i,
|
|
5
|
+
/^0\.0\.0\.0$/i,
|
|
6
|
+
/(^|\.)land\.copernicus\.eu$/i,
|
|
7
|
+
/(^|\.)clms-staging\.eea\.europa\.eu$/i,
|
|
8
|
+
];
|
|
9
|
+
|
|
10
|
+
const stripProtocol = (url) => {
|
|
11
|
+
return (url || '').replace(/^https?:\/\//i, '');
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const getProxyBase = () => {
|
|
15
|
+
const origin = window?.location?.origin || '';
|
|
16
|
+
return origin ? `${origin}/ogcproxy/` : '/ogcproxy/';
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const resolveAbsoluteUrl = (url) => {
|
|
20
|
+
if (!url || typeof url !== 'string') {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
return new URL(url, window?.location?.origin || undefined);
|
|
25
|
+
} catch (e) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const isRelativeUrl = (url) => {
|
|
31
|
+
if (!url || typeof url !== 'string') {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
return !/^[a-zA-Z][a-zA-Z\d+.-]*:/.test(url);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const isInternalHost = (hostname, currentHostname) => {
|
|
38
|
+
const hostValue = String(hostname || '').toLowerCase();
|
|
39
|
+
const currentHostValue = String(currentHostname || '').toLowerCase();
|
|
40
|
+
if (!hostValue) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
if (
|
|
44
|
+
INTERNAL_HOST_PATTERNS.some((hostPattern) => hostPattern.test(hostValue))
|
|
45
|
+
) {
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
if (currentHostValue && hostValue === currentHostValue) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
if (currentHostValue && hostValue.endsWith(`.${currentHostValue}`)) {
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
if (currentHostValue && currentHostValue.endsWith(`.${hostValue}`)) {
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
return false;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const isInternalAbsoluteUrl = (absoluteUrl) => {
|
|
61
|
+
if (!absoluteUrl) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
const currentOrigin = window?.location?.origin || '';
|
|
65
|
+
const currentHostname = window?.location?.hostname || '';
|
|
66
|
+
if (currentOrigin && absoluteUrl.origin === currentOrigin) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
return isInternalHost(absoluteUrl.hostname, currentHostname);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const resolveUnproxiedUrl = (inputUrl) => {
|
|
73
|
+
if (!inputUrl || !PROXY_PATH_PATTERN.test(inputUrl)) {
|
|
74
|
+
return inputUrl;
|
|
75
|
+
}
|
|
76
|
+
const strippedUrl = stripProtocol(inputUrl);
|
|
77
|
+
const proxyPathData = strippedUrl.split(PROXY_PATH_PATTERN)[1] || '';
|
|
78
|
+
const normalizedPathData = proxyPathData.replace(/^\/+/, '');
|
|
79
|
+
if (!normalizedPathData) {
|
|
80
|
+
return inputUrl;
|
|
81
|
+
}
|
|
82
|
+
if (/^https?:\/\//i.test(normalizedPathData)) {
|
|
83
|
+
return normalizedPathData;
|
|
84
|
+
}
|
|
85
|
+
const secureProtocol =
|
|
86
|
+
window?.location?.protocol === 'http:' ? 'http://' : 'https://';
|
|
87
|
+
return secureProtocol + normalizedPathData;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export const resolveServiceUrl = (url, options = {}) => {
|
|
91
|
+
if (!url || typeof url !== 'string') {
|
|
92
|
+
return url;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (!options.fromUploadWidget) {
|
|
96
|
+
return url;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const trimmedUrl = url.trim();
|
|
100
|
+
if (!trimmedUrl) {
|
|
101
|
+
return trimmedUrl;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (/^(blob:|data:|about:)/i.test(trimmedUrl)) {
|
|
105
|
+
return trimmedUrl;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (isRelativeUrl(trimmedUrl) && !PROXY_PATH_PATTERN.test(trimmedUrl)) {
|
|
109
|
+
return trimmedUrl;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const alreadyProxied = PROXY_PATH_PATTERN.test(trimmedUrl);
|
|
113
|
+
const unproxiedUrl = resolveUnproxiedUrl(trimmedUrl);
|
|
114
|
+
const absoluteUrl = resolveAbsoluteUrl(unproxiedUrl);
|
|
115
|
+
|
|
116
|
+
if (!absoluteUrl) {
|
|
117
|
+
return trimmedUrl;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (isInternalAbsoluteUrl(absoluteUrl)) {
|
|
121
|
+
return absoluteUrl.toString();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const normalizedExternalUrl = stripProtocol(absoluteUrl.toString());
|
|
125
|
+
if (alreadyProxied) {
|
|
126
|
+
const proxyPathData = normalizedExternalUrl.replace(/^\/+/, '');
|
|
127
|
+
return getProxyBase() + proxyPathData;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return getProxyBase() + normalizedExternalUrl;
|
|
131
|
+
};
|