Skip to content

Commit

Permalink
geosolutions-it#9894 Add possibility to configure srs (geosolutions-i…
Browse files Browse the repository at this point in the history
  • Loading branch information
offtherailz authored Jan 18, 2024
1 parent 7eb4d3d commit 475605e
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 22 deletions.
3 changes: 2 additions & 1 deletion web/client/plugins/StreetView/StreetView.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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.
* <br>**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}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
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';
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");
};
Expand All @@ -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 <Message msgId="streetView.cyclomedia.errors.invalidCredentials" />;
return <Message msgId="streetView.cyclomedia.errors.invalidCredentials" msgParams={msgParams} />;
}
if (error?.message?.indexOf?.(PROJECTION_NOT_AVAILABLE) >= 0) {
return <Message msgId="streetView.cyclomedia.errors.projectionNotAvailable" msgParams={msgParams} />;
}

return error?.message ?? "Unknown error";
};

Expand Down Expand Up @@ -88,6 +93,7 @@ const CyclomediaView = ({ apiKey, style, location = {}, setPov = () => {}, setLo
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
`;
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;
Expand All @@ -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)
Expand All @@ -142,14 +152,19 @@ 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);
};

// initialize API
useEffect(() => {
if (!StreetSmartApi || !username || !password || !apiKey) return () => {};
if (!StreetSmartApi || !username || !password || !apiKey || !isProjectionAvailable(srs)) return () => {};
setInitializing(true);
StreetSmartApi.init({
targetElement,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -286,7 +302,7 @@ const CyclomediaView = ({ apiKey, style, location = {}, setPov = () => {}, setLo
</iframe>
<Alert bsStyle="danger" style={{...style, textAlign: 'center', alignContent: 'center', display: showError ? 'block' : 'none'}} key="error">
<Message msgId="streetView.cyclomedia.errorOccurred" />
{getErrorMessage(error)}
{getErrorMessage(error, {srs})}
{initialized ? <div><Button
onClick={() => {
setError(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ describe('Cyclomedia CyclomediaView', () => {
setCredentials(CYCLOMEDIA_CREDENTIALS_REFERENCE, {username: 'test', password: 'password'});
// set a default mock
window.__cyclomedia__mock__ = {
init: () => {},
open: () => {}
init: () => new Promise((resolve) => { resolve(); }),
open: () => new Promise((resolve) => { resolve(); })
};
setTimeout(done);
});
Expand Down Expand Up @@ -102,5 +102,24 @@ describe('Cyclomedia CyclomediaView', () => {
expect(div).toExist();

});

it('srs check for existing projection', () => {
const props = {
apiKey: testAPIKey
};
ReactDOM.render(<CyclomediaView {...props} providerSettings={{...mockProviderSettings, srs: "EPSG:4326"}}/>, document.getElementById("container"));
// no error shown.
const div = emptyStreetView();
expect(div).toExist();
});
it('srs not defined error handling', () => {
const props = {
apiKey: testAPIKey
};
ReactDOM.render(<CyclomediaView {...props} providerSettings={{...mockProviderSettings, srs: "UNKNOWN"}}/>, document.getElementById("container"));
// no error shown.
const div = emptyStreetView();
expect(div).toNotExist();
// check alert to exist
expect(document.querySelector('.alert-danger')).toExist();
});
});
3 changes: 2 additions & 1 deletion web/client/translations/data.de-DE.json
Original file line number Diff line number Diff line change
Expand Up @@ -3941,7 +3941,8 @@
"zoomIn": "Bitte zoomen Sie in die Karte, um die Street-View-Abdeckung zu sehen",
"errorOccurred": "Fehler aufgetreten: ",
"errors": {
"invalidCredentials": "Ungültige Anmeldeinformationen"
"invalidCredentials": "Ungültige Anmeldeinformationen",
"projectionNotAvailable": "Die konfigurierte Projektion {srs} ist nicht verfügbar. Bitte kontaktieren Sie den Administrator."
},
"reloadAPI": "API neu laden"
}
Expand Down
3 changes: 2 additions & 1 deletion web/client/translations/data.en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -3914,7 +3914,8 @@
"zoomIn": "Please zoom in the map to see the street view coverage",
"errorOccurred": "Error occurred: ",
"errors": {
"invalidCredentials": "Invalid credentials"
"invalidCredentials": "Invalid credentials",
"projectionNotAvailable": "The projection {srs} configured is not available. Please contact the administrator."
},
"reloadAPI": "Reload API"
}
Expand Down
3 changes: 2 additions & 1 deletion web/client/translations/data.es-ES.json
Original file line number Diff line number Diff line change
Expand Up @@ -3903,7 +3903,8 @@
"zoomIn": "Por favor, acerque el mapa para ver la cobertura de vista de calle",
"errorOccurred": "Se produjo un error: ",
"errors": {
"invalidCredentials": "Credenciales inválidas"
"invalidCredentials": "Credenciales inválidas",
"projectionNotAvailable": "La proyección {srs} configurada no está disponible. Por favor, contacte al administrador."
},
"reloadAPI": "Recargar API"
}
Expand Down
3 changes: 2 additions & 1 deletion web/client/translations/data.fr-FR.json
Original file line number Diff line number Diff line change
Expand Up @@ -3903,7 +3903,8 @@
"zoomIn": "Veuillez zoomer sur la carte pour voir la couverture Street View",
"errorOccurred": "Une erreur s'est produite : ",
"errors": {
"invalidCredentials": "Identifiants invalides"
"invalidCredentials": "Identifiants invalides",
"projectionNotAvailable": "La projection {srs} configurée n'est pas disponible. Veuillez contacter l'administrateur."
},
"reloadAPI": "Recharger l'API"
}
Expand Down
3 changes: 2 additions & 1 deletion web/client/translations/data.it-IT.json
Original file line number Diff line number Diff line change
Expand Up @@ -3903,7 +3903,8 @@
"zoomIn": "Effettua un ulteriore zoom sulla mappa per visualizzare dove sono disponibili le immagini",
"errorOccurred": "Si è verificato un errore: ",
"errors": {
"invalidCredentials": "Credenziali non valide"
"invalidCredentials": "Credenziali non valide",
"projectionNotAvailable": "La proiezione {srs} configurata non è disponibile. Contattare l'amministratore."
},
"reloadAPI": "Ricarica API"
}
Expand Down

0 comments on commit 475605e

Please sign in to comment.