diff --git a/web/client/plugins/StreetView/StreetView.jsx b/web/client/plugins/StreetView/StreetView.jsx
index de56a078a9..82c42646a3 100644
--- a/web/client/plugins/StreetView/StreetView.jsx
+++ b/web/client/plugins/StreetView/StreetView.jsx
@@ -59,7 +59,8 @@ const StreetViewPluginContainer = connect(() => ({}), {
* - `cyclomedia` provider: The API key is mandatory and can be configured only in the plugin configuration. It is not possible to configure it globally in `localConfig.json`, in `apiKeys.cyclomediaAPIKey`.
* @property {string} providerSettings The settings specific for the provider. Depending on the `provider` property, the following settings are available:
* - `cyclomedia` provider:
- * - `StreetSmartApiURL` (optional). The URL of the StreetSmart API. Default: `https://streetsmart.cyclomedia.com/api/v23.7/StreetSmartApi.js`.
+ * - `providerSettings.StreetSmartApiURL` (optional). The URL of the StreetSmart API. Default: `https://streetsmart.cyclomedia.com/api/v23.7/StreetSmartApi.js`.
+ * - `providerSettings.srs` (optional). Coordinate reference system code to use for the API. Default: `EPSG:4326`. Note that the SRS used here must be supported by the StreetSmart API **and** defined in `localConfig.json` file, in `projectionDefs`.
*
* Generally speaking, you should prefer general settings in `localConfig.json` over the plugin configuration, in order to reuse the same configuration for default viewer and all the contexts, automatically. This way you will not need to configure the `apiKey` in every context.
* **Important**: You can use only **one** API-key for a MapStore instance. The api-key can be configured replicated in every plugin configuration or using one of the unique global settings (suggested) in `localConfig.json`). @see {@link https://github.com/googlemaps/js-api-loader/issues/5|here} and @see {@link https://github.com/googlemaps/js-api-loader/issues/100|here}
diff --git a/web/client/plugins/StreetView/components/CyclomediaView/CyclomediaView.js b/web/client/plugins/StreetView/components/CyclomediaView/CyclomediaView.js
index 038141dbfe..5c7e23d27a 100644
--- a/web/client/plugins/StreetView/components/CyclomediaView/CyclomediaView.js
+++ b/web/client/plugins/StreetView/components/CyclomediaView/CyclomediaView.js
@@ -1,5 +1,8 @@
import React, {useState, useEffect, useRef} from 'react';
import Message from '../../../../components/I18N/Message';
+import { isProjectionAvailable } from '../../../../utils/ProjectionUtils';
+import { reproject } from '../../../../utils/CoordinatesUtils';
+
import { getCredentials as getStoredCredentials, setCredentials as setStoredCredentials } from '../../../../utils/SecurityUtils';
import { CYCLOMEDIA_CREDENTIALS_REFERENCE } from '../../constants';
@@ -7,7 +10,7 @@ import { Alert, Button } from 'react-bootstrap';
import CyclomediaCredentials from './Credentials';
import EmptyStreetView from '../EmptyStreetView';
-
+const PROJECTION_NOT_AVAILABLE = "Projection not available";
const isInvalidCredentials = (error) => {
return error?.message?.indexOf?.("code 401");
};
@@ -17,11 +20,13 @@ const isInvalidCredentials = (error) => {
* @param {object|string} error the error to parse
* @returns {string|JSX.Element} the error message
*/
-const getErrorMessage = (error) => {
+const getErrorMessage = (error, msgParams = {}) => {
if (isInvalidCredentials(error) >= 0) {
- return ;
+ return ;
+ }
+ if (error?.message?.indexOf?.(PROJECTION_NOT_AVAILABLE) >= 0) {
+ return ;
}
-
return error?.message ?? "Unknown error";
};
@@ -88,6 +93,7 @@ const CyclomediaView = ({ apiKey, style, location = {}, setPov = () => {}, setLo
`;
const initOptions = providerSettings?.initOptions ?? {};
+ const srs = providerSettings?.srs ?? 'EPSG:4326'; // for measurement tool and oblique tool 'EPSG:7791' is one of the supported SRS
// location contains the latLng and the properties of the feature
// properties contains the `imageId` that can be used as query
const {properties} = location;
@@ -114,12 +120,16 @@ const CyclomediaView = ({ apiKey, style, location = {}, setPov = () => {}, setLo
setStoredCredentials(CYCLOMEDIA_CREDENTIALS_REFERENCE, undefined);
}
};
+ // setting a custom srs enables the measurement tool (where present) and other tools, but coordinates of the click
+ // will be managed in the SRS used, so we need to convert them to EPSG:4326.
+ // So we need to make sure that the SRS is available for coordinates conversion
+ useEffect(() => {
+ if (!isProjectionAvailable(srs)) {
+ console.error(`Cyclomedia API: init: error: projection ${srs} is not available`);
+ setError(new Error(PROJECTION_NOT_AVAILABLE));
+ }
+ }, [srs]);
- const srs = 'EPSG:4326';
- // this EPSG:7791 enables the measurement tool (where present), but coordinates of the click
- // are in the srs named, so we need to convert them to EPSG:4326. Actually definition is not in place
- // and have to be implemented
- // it enables also the oblique tool, but we have to implement the click on that point too.
/**
* Utility function to open an image in street smart viewer (it must be called after the API is initialized)
@@ -142,6 +152,11 @@ const CyclomediaView = ({ apiKey, style, location = {}, setPov = () => {}, setLo
measureTypeButtonVisible: true,
measureTypeButtonStart: true,
measureTypeButtonToggle: true
+ },
+ obliqueViewer: {
+ closable: true,
+ maximizable: true,
+ navbarVisible: false
}
};
return StreetSmartApi.open(query, options);
@@ -149,7 +164,7 @@ const CyclomediaView = ({ apiKey, style, location = {}, setPov = () => {}, setLo
// initialize API
useEffect(() => {
- if (!StreetSmartApi || !username || !password || !apiKey) return () => {};
+ if (!StreetSmartApi || !username || !password || !apiKey || !isProjectionAvailable(srs)) return () => {};
setInitializing(true);
StreetSmartApi.init({
targetElement,
@@ -198,10 +213,11 @@ const CyclomediaView = ({ apiKey, style, location = {}, setPov = () => {}, setLo
const {recording} = detail ?? {};
// extract coordinates lat long from `xyz` of `recording` and `imageId` from recording `id` property
if (recording?.xyz && recording?.id) {
+ const {x: lng, y: lat} = reproject([recording?.xyz?.[0], recording?.xyz?.[1]], srs, 'EPSG:4326');
setLocation({
latLng: {
- lat: recording?.xyz?.[1],
- lng: recording?.xyz?.[0]
+ lat,
+ lng
},
properties: {
...recording,
@@ -286,7 +302,7 @@ const CyclomediaView = ({ apiKey, style, location = {}, setPov = () => {}, setLo
- {getErrorMessage(error)}
+ {getErrorMessage(error, {srs})}
{initialized ?