diff --git a/web/client/components/mapcontrols/search/SearchBar.jsx b/web/client/components/mapcontrols/search/SearchBar.jsx index d9a3b757f8..d4836844ca 100644 --- a/web/client/components/mapcontrols/search/SearchBar.jsx +++ b/web/client/components/mapcontrols/search/SearchBar.jsx @@ -20,6 +20,7 @@ import SearchBarToolbar from '../../search/SearchBarToolbar'; import { defaultSearchWrapper } from '../../search/SearchBarUtils'; import BookmarkSelect, {BookmarkOptions} from "../searchbookmarkconfig/BookmarkSelect"; import CoordinatesSearch, {CoordinateOptions} from "../searchcoordinates/CoordinatesSearch"; +import CurrentMapCRSCoordSearch from '../searchcoordinates/CurrentMapCRSCoordSearch'; import tooltip from '../../misc/enhancers/tooltip'; const TMenuItem = tooltip(MenuItem); @@ -101,6 +102,7 @@ export default ({ onZoomToPoint = () => {}, onClearBookmarkSearch = () => {}, onPurgeResults, + currentMapCRS = 'EPSG:4326', items = [], ...props }) => { @@ -112,6 +114,13 @@ export default ({ } }, [searchOptions?.services]); + useEffect(() => { + // Switch back to coordinate search when map CRS is EPSG:4326 and active tool is Map CRS coordinate search + if (currentMapCRS === 'EPSG:4326' && activeTool === 'mapCRSCoordinatesSearch') { + onChangeActiveSearchTool('coordinatesSearch'); + } + }, [currentMapCRS]); + const selectedServices = searchOptions?.services?.filter((_, index) => selectedSearchService >= 0 ? selectedSearchService === index : true) ?? []; const search = defaultSearchWrapper({ searchText, @@ -160,6 +169,8 @@ export default ({ clearSearch={clearSearch} onChangeActiveSearchTool={onChangeActiveSearchTool} onClearBookmarkSearch={onClearBookmarkSearch} + currentMapCRS={currentMapCRS} + onChangeFormat={onChangeFormat} />); } @@ -224,7 +235,10 @@ export default ({ onCancelSelectedItem={onCancelSelectedItem} onPurgeResults={onPurgeResults}/> {activeTool === "coordinatesSearch" && showCoordinatesSearchOption && - + + } + {activeTool === "mapCRSCoordinatesSearch" && showCoordinatesSearchOption && currentMapCRS && + } { activeTool === "bookmarkSearch" && showBookMarkSearchOption && @@ -253,7 +267,7 @@ export default ({ clearSearch(); } }, - ...(activeTool === "coordinatesSearch" && + ...(["coordinatesSearch", "mapCRSCoordinatesSearch"].includes(activeTool) && CoordinateOptions.removeIcon(activeTool, coordinate, onClearCoordinatesSearch, onChangeCoord)) }, { glyph: searchIcon, @@ -265,8 +279,8 @@ export default ({ visible: activeTool === "addressSearch" && (!(searchText !== "" || selectedItems && selectedItems.length > 0) || !splitTools), onClick: () => isSearchClickable && search(), - ...(activeTool === "coordinatesSearch" && - CoordinateOptions.searchIcon(activeTool, coordinate, onZoomToPoint, defaultZoomLevel)), + ...(["coordinatesSearch", "mapCRSCoordinatesSearch"].includes(activeTool) && + CoordinateOptions.searchIcon(activeTool, coordinate, onZoomToPoint, defaultZoomLevel, currentMapCRS)), ...(activeTool === "bookmarkSearch" && BookmarkOptions.searchIcon(activeTool, props)) }, { diff --git a/web/client/components/mapcontrols/search/__tests__/SearchBar-test.jsx b/web/client/components/mapcontrols/search/__tests__/SearchBar-test.jsx index e1a3eabc90..4eff38ec0a 100644 --- a/web/client/components/mapcontrols/search/__tests__/SearchBar-test.jsx +++ b/web/client/components/mapcontrols/search/__tests__/SearchBar-test.jsx @@ -296,6 +296,17 @@ describe("test the SearchBar", () => { expect(cog.length).toBe(1); }); + it('test zoomToPoint, with search, with decimal, with reset if mapCRS different than default 4326', () => { + const store = {dispatch: () => {}, subscribe: () => {}, getState: () => ({search: {coordinate: {lat: 0.05, lon: 0.05, yCoord: 2, xCoord: 2}}})}; + ReactDOM.render(, document.getElementById("container")); + let reset = document.getElementsByClassName("glyphicon-1-close"); + let search = document.getElementsByClassName("glyphicon-search"); + let cog = document.getElementsByClassName("glyphicon-cog"); + expect(reset.length).toBe(1); + expect(search.length).toBe(1); + expect(cog.length).toBe(0); + }); + it('test zoomToPoint, with search, with aeronautical, with reset', () => { const store = {dispatch: () => {}, subscribe: () => {}, getState: () => ({search: {coordinate: {lat: 2, lon: 2}}})}; ReactDOM.render(, document.getElementById("container")); @@ -342,6 +353,41 @@ describe("test the SearchBar", () => { } }); }); + it('test calling zoomToPoint with onKeyDown event if mapCRS different than default 4326', (done) => { + const store = { + dispatch: () => {}, + subscribe: () => {}, + getState: () => ({search: {coordinate: {yCoord: 15, xCoord: 15}}}) + }; + ReactDOM.render( + + { + expect(point).toEqual({x: 15, y: 15}); + expect(zoom).toEqual(12); + expect(crs).toEqual("EPSG:4326"); + done(); + }} + coordinate={{yCoord: 15, xCoord: 15}} + currentMapCRS={"EPSG:900913"} + typeAhead={false} /> + + , document.getElementById("container") + ); + const container = document.getElementById('container'); + const elements = container.querySelectorAll('input'); + TestUtils.Simulate.keyDown(elements[0], { + keyCode: 13, + preventDefault: () => { + expect(true).toBe(true); + done(); + } + }); + }); + it('Test SearchBar with not allowed e char for keyDown event', (done) => { const store = { dispatch: () => {}, @@ -374,6 +420,40 @@ describe("test the SearchBar", () => { } }); }); + it('Test SearchBar with not allowed e char for keyDown event if mapCRS different than default 4326', (done) => { + const store = { + dispatch: () => {}, + subscribe: () => {}, + getState: () => ({search: {coordinate: {yCoord: 150, xCoord: 150}}}) + }; + ReactDOM.render( + + { + expect(true).toBe(false); + }} + coordinate={{yCoord: 150, xCoord: 150}} + currentMapCRS={"EPSG:900913"} + typeAhead={false} /> + , document.getElementById("container") + ); + const container = document.getElementById('container'); + const elements = container.querySelectorAll('input'); + expect(elements.length).toBe(2); + expect(elements[0].value).toBe('150'); + + TestUtils.Simulate.keyDown(elements[0], { + keyCode: 69, // char e + preventDefault: () => { + expect(true).toBe(true); + done(); + } + }); + }); + it('Test SearchBar with valid onKeyDown event by pressing number 8', () => { const store = { dispatch: () => {}, @@ -405,6 +485,38 @@ describe("test the SearchBar", () => { } }); }); + it('Test SearchBar with valid onKeyDown event by pressing number 8 if mapCRS different than default 4326', () => { + const store = { + dispatch: () => {}, + subscribe: () => {}, + getState: () => ({search: {coordinate: {yCoord: 1, xCoord: 1}}}) + }; + ReactDOM.render( + + { + expect(true).toBe(false); + }} + coordinate={{yCoord: 1, xCoord: 1}} + currentMapCRS={"EPSG:900913"} + typeAhead={false} /> + , document.getElementById("container") + ); + const container = document.getElementById('container'); + const elements = container.querySelectorAll('input'); + expect(elements.length).toBe(2); + expect(elements[0].value).toBe('1'); + + TestUtils.Simulate.keyDown(elements[0], { + keyCode: 56, + preventDefault: () => { + expect(true).toBe(false); + } + }); + }); it('test showOptions false, only address tool visible', () => { ReactDOM.render(, document.getElementById("container")); diff --git a/web/client/components/mapcontrols/searchcoordinates/CoordinatesSearch.js b/web/client/components/mapcontrols/searchcoordinates/CoordinatesSearch.js index 92bbe14222..a31ceb90cb 100644 --- a/web/client/components/mapcontrols/searchcoordinates/CoordinatesSearch.js +++ b/web/client/components/mapcontrols/searchcoordinates/CoordinatesSearch.js @@ -26,10 +26,14 @@ import { zoomAndAddPoint, changeCoord } from '../../../actions/search'; export const CoordinateOptions = ({ clearCoordinates: (onClearCoordinatesSearch, onChangeCoord) =>{ onClearCoordinatesSearch({owner: "search"}); - onChangeCoord("lat", ""); - onChangeCoord("lon", ""); + const clearedFields = ["lat", "lon", "xCoord", "yCoord"]; + const resetVal = ''; + clearedFields.forEach(field => onChangeCoord(field, resetVal)); + }, + areValidCoordinates: (coordinate) => { + if (!coordinate) return false; + return isNumber(coordinate?.lon) && isNumber(coordinate?.lat); }, - areValidCoordinates: (coordinate) => isNumber(coordinate?.lon) && isNumber(coordinate?.lat), zoomToPoint: (onZoomToPoint, coordinate, defaultZoomLevel = 12) => { onZoomToPoint({ x: parseFloat(coordinate.lon), @@ -63,19 +67,31 @@ export const CoordinateOptions = ({ coordinate, onClearCoordinatesSearch, onChangeCoord) =>({ - visible: activeTool === "coordinatesSearch" && (isNumber(coordinate.lon) || isNumber(coordinate.lat)), + visible: (['coordinatesSearch', 'mapCRSCoordinatesSearch'].includes(activeTool)) && (isNumber(coordinate.lon) || isNumber(coordinate.lat) || isNumber(coordinate.xCoord) || isNumber(coordinate.yCoord)), onClick: () => CoordinateOptions.clearCoordinates(onClearCoordinatesSearch, onChangeCoord) }), searchIcon: (activeTool, coordinate, onZoomToPoint, defaultZoomLevel) => ({ - visible: activeTool === "coordinatesSearch", + visible: ["coordinatesSearch", "mapCRSCoordinatesSearch"].includes(activeTool), onClick: () => { - if (activeTool === "coordinatesSearch" && CoordinateOptions.areValidCoordinates(coordinate)) { + if ((['coordinatesSearch', 'mapCRSCoordinatesSearch'].includes(activeTool)) && CoordinateOptions.areValidCoordinates(coordinate)) { CoordinateOptions.zoomToPoint(onZoomToPoint, coordinate, defaultZoomLevel); } } }), - coordinatesMenuItem: ({activeTool, searchText, clearSearch, onChangeActiveSearchTool, onClearBookmarkSearch}) =>( - { + coordinatesMenuItem: ({activeTool, searchText, clearSearch, onChangeActiveSearchTool, onClearBookmarkSearch, currentMapCRS, onChangeFormat}) =>{ + if (currentMapCRS === 'EPSG:4326') { + return ( { + if (searchText !== undefined && searchText !== "") { + clearSearch(); + } + onClearBookmarkSearch("selected"); + onChangeActiveSearchTool("coordinatesSearch"); + document.dispatchEvent(new MouseEvent('click')); + }}> + + ); + } + return (<> { if (searchText !== undefined && searchText !== "") { clearSearch(); } @@ -85,7 +101,21 @@ export const CoordinateOptions = ({ }}> - ) + { + if (searchText !== undefined && searchText !== "") { + clearSearch(); + } + onClearBookmarkSearch("selected"); + onChangeActiveSearchTool("mapCRSCoordinatesSearch"); + onChangeFormat("decimal"); + document.dispatchEvent(new MouseEvent('click')); + }}> + + + + + ); + } }); @@ -147,6 +177,7 @@ const CoordinatesSearch = ({ { + const {zoomToPoint, areValidCoordinates} = CoordinateOptions; + const getConstraintsCoordEditor = (projection) =>{ + const extent = getProjection(projection).extent; + const [minx, miny, maxx, maxy] = extent; + return { + decimal: { + yCoord: { + min: miny, + max: maxy + }, + xCoord: { + min: minx, + max: maxx + } + } + }; + }; + // helper function to validate if the coordinate is within the crs extent or not + const isCoordWithinCrs = (value, coordType) => { + const min = getConstraintsCoordEditor(currentMapCRS).decimal[coordType]?.min || 0; + const max = getConstraintsCoordEditor(currentMapCRS).decimal[coordType]?.max || 0; + const coordValue = parseFloat(value); + if (isNaN(coordValue) || coordValue < min || coordValue > max ) { + return false; + } + return true; + }; + React.useEffect(() => { + if (!currentMapCRS || currentMapCRS === 'EPSG:4326') return; + // if there are lat, lon values --> reproject the point and get xCoord and yCoord for map CRS + const isLatNumberVal = isNumber(coordinate.lat) && !isNaN(coordinate.lat); + const isLonNumberVal = isNumber(coordinate.lon) && !isNaN(coordinate.lon); + if (isLatNumberVal && isLonNumberVal) { + const reprojectedValue = reproject([coordinate.lon, coordinate.lat], 'EPSG:4326', currentMapCRS, true); + const parsedXCoord = parseFloat((reprojectedValue?.x)); + const parsedYCoord = parseFloat((reprojectedValue?.y)); + onChangeCoord('xCoord', parsedXCoord); + onChangeCoord('yCoord', parsedYCoord); + // if coords are out of crs extent --> clear the marker + if (!isCoordWithinCrs(parsedXCoord, 'xCoord') || !isCoordWithinCrs(parsedYCoord, 'yCoord')) onClearCoordinatesSearch({owner: "search"}); + return; + } + coordinate.xCoord && onChangeCoord('xCoord', ''); + coordinate.yCoord && onChangeCoord('yCoord', ''); + }, [currentMapCRS]); + + const changeCoordinates = (coord, value) => { + // clear coordinate marker + if (!areValidCoordinates()) { + onClearCoordinatesSearch({owner: "search"}); + } + // set change value + const numValue = parseFloat(value); + onChangeCoord(coord, numValue); + // reproject the new point and set lat/lon + if (coord === 'yCoord') { + const yCoordValidNum = isNumber(numValue) && !isNaN(numValue) && isCoordWithinCrs(numValue, 'yCoord'); + const xCoordValidNum = isNumber(coordinate.xCoord) && !isNaN(coordinate.xCoord) && isCoordWithinCrs(coordinate.xCoord, 'xCoord'); + if (yCoordValidNum && xCoordValidNum) { + const projectedPt = reproject([coordinate.xCoord, numValue], currentMapCRS, 'EPSG:4326', true); + onChangeCoord('lat', (projectedPt.y)); + onChangeCoord('lon', (projectedPt.x)); + return; + } + } else { + const xCoordValidNum = isNumber(numValue) && !isNaN(numValue) && isCoordWithinCrs(numValue, 'xCoord'); + const yCoordValidNum = isNumber(coordinate.yCoord) && !isNaN(coordinate.yCoord) && isCoordWithinCrs(coordinate.yCoord, 'yCoord'); + if (yCoordValidNum && xCoordValidNum) { + const projectedPt = reproject([numValue, coordinate.yCoord], currentMapCRS, 'EPSG:4326', true); + onChangeCoord('lat', (projectedPt.y)); + onChangeCoord('lon', (projectedPt.x)); + return; + } + } + const resetValue = ''; + onChangeCoord('lat', resetValue); + onChangeCoord('lon', resetValue); + + }; + + const onZoom = () => { + zoomToPoint(onZoomToPoint, coordinate, defaultZoomLevel); + }; + + return ( +
+ + + + + changeCoordinates("xCoord", dd)} + onKeyDown={() => { + if (areValidCoordinates(coordinate)) { + onZoom(); + } + }} + /> + + + + + + + + changeCoordinates("yCoord", dd)} + onKeyDown={() => { + if (areValidCoordinates(coordinate)) { + onZoom(); + } + }} + /> + + + +
+ ); +}; + +CurrentMapCRSCoordinatesSearch.propTypes = { + coordinate: PropTypes.object, + format: PropTypes.string, + onClearCoordinatesSearch: PropTypes.func, + onZoomToPoint: PropTypes.func, + onChangeCoord: PropTypes.func, + defaultZoomLevel: PropTypes.number +}; + +export default connect((state)=>{ + return { + coordinate: state.search.coordinate || {} + }; +}, { + onZoomToPoint: zoomAndAddPoint, + onChangeCoord: changeCoord +})(CurrentMapCRSCoordinatesSearch); diff --git a/web/client/components/misc/coordinateeditors/CoordinateEntry.jsx b/web/client/components/misc/coordinateeditors/CoordinateEntry.jsx index 746a126d61..02510e890c 100644 --- a/web/client/components/misc/coordinateeditors/CoordinateEntry.jsx +++ b/web/client/components/misc/coordinateeditors/CoordinateEntry.jsx @@ -10,6 +10,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import DecimalCoordinateEditor from './editors/DecimalCoordinateEditor'; +import CRSCoordinateEditor from './editors/CRSCoordinateEditor'; import AeronauticalCoordinateEditor from './editors/AeronauticalCoordinateEditor'; import { isNil } from 'lodash'; import no90Lat from './enhancers/no90Lat'; @@ -26,7 +27,8 @@ class CoordinateEntry extends React.Component { aeronauticalOptions: PropTypes.object, coordinate: PropTypes.string, onChange: PropTypes.func, - onKeyDown: PropTypes.func + onKeyDown: PropTypes.func, + owner: PropTypes.string }; static defaultProps = { @@ -42,13 +44,14 @@ class CoordinateEntry extends React.Component { max: 180 } } - } + }, + owner: '' } render() { - const {format} = this.props; + const {format, owner, currentMapCRS} = this.props; return format === "decimal" || isNil(format) ? - : + owner === 'search' && currentMapCRS ? : : ; } } diff --git a/web/client/components/misc/coordinateeditors/editors/CRSCoordinateEditor.jsx b/web/client/components/misc/coordinateeditors/editors/CRSCoordinateEditor.jsx new file mode 100644 index 0000000000..9206ed753a --- /dev/null +++ b/web/client/components/misc/coordinateeditors/editors/CRSCoordinateEditor.jsx @@ -0,0 +1,117 @@ +/* + * Copyright 2024, GeoSolutions Sas. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. +*/ + +import {capitalize} from 'lodash'; +import PropTypes from 'prop-types'; +import React from 'react'; +import {FormGroup} from 'react-bootstrap'; +import IntlNumberFormControl from '../../../I18N/IntlNumberFormControl'; + +/** + This component renders a custom coordiante inpout for decimal degrees for default coordinate CRS and current map CRS as well +*/ +class CRSCoordinateEditor extends React.Component { + + static propTypes = { + idx: PropTypes.number, + value: PropTypes.number, + constraints: PropTypes.object, + format: PropTypes.string, + coordinate: PropTypes.string, + onChange: PropTypes.func, + onKeyDown: PropTypes.func, + onSubmit: PropTypes.func, + disabled: PropTypes.bool, + currentMapCRS: PropTypes.string + }; + static contextTypes = { + intl: PropTypes.object + }; + static defaultProps = { + format: "decimal", + coordinate: "lat", + constraints: { + decimal: { + lat: { + min: -90, + max: 90 + }, + lon: { + min: -180, + max: 180 + } + } + }, + onKeyDown: () => {}, + disabled: false, + currentMapCRS: 'EPSG:4326' + } + render() { + const {coordinate, onChange, disabled, value} = this.props; + const validateNameFunc = "validateDecimal" + capitalize(coordinate); + return ( + + { + if (val === "") { + onChange(""); + } else { + onChange(val); + } + }} + onKeyDown={this.verifyOnKeyDownEvent} + step={1} + validateNameFunc={this[validateNameFunc]} + type="number" + /> + + ); + } + /** + * checking and blocking the keydown event to avoid + * the only letters matched by input type number 'e' or 'E' + * see https://github.com/geosolutions-it/MapStore2/issues/3523#issuecomment-502660391 + * @param event keydown event + */ + verifyOnKeyDownEvent = (event) => { + if (event.keyCode === 69) { + event.preventDefault(); + } + if (event.keyCode === 13) { + event.preventDefault(); + event.stopPropagation(); + this.props.onKeyDown(event); + } + }; + validateDecimalX = (xCoordinate) => { + const min = this.props.constraints[this.props.format].xCoord.min; + const max = this.props.constraints[this.props.format].xCoord.max; + const xCoord = parseFloat(xCoordinate); + if (isNaN(xCoord) || xCoord < min || xCoord > max ) { + return "error"; + } + return null; // "success" + }; + validateDecimalY = (yCoordinate) => { + const min = this.props.constraints[this.props.format].yCoord.min; + const max = this.props.constraints[this.props.format].yCoord.max; + const yCoord = parseFloat(yCoordinate); + if (isNaN(yCoord) || yCoord < min || yCoord > max ) { + return "error"; + } + return null; // "success" + } + +} + +export default CRSCoordinateEditor; diff --git a/web/client/plugins/Search.jsx b/web/client/plugins/Search.jsx index 834cc8b0e1..1f6dfc0622 100644 --- a/web/client/plugins/Search.jsx +++ b/web/client/plugins/Search.jsx @@ -48,7 +48,7 @@ import { import mapInfoReducers from '../reducers/mapInfo'; import searchReducers from '../reducers/search'; import { layersSelector } from '../selectors/layers'; -import {mapSelector, mapSizeValuesSelector} from '../selectors/map'; +import {mapSelector, mapSizeValuesSelector, projectionSelector} from '../selectors/map'; import ConfigUtils from '../utils/ConfigUtils'; import { defaultIconStyle } from '../utils/SearchUtils'; import ToggleButton from './searchbar/ToggleButton'; @@ -60,8 +60,9 @@ const searchSelector = createSelector([ state => state.search || null, state => state.controls && state.controls.searchBookmarkConfig || null, state => state.mapConfigRawData || {}, - state => state?.searchbookmarkconfig || '' -], (searchState, searchBookmarkConfigControl, mapInitial, bookmarkConfig) => ({ + state => state?.searchbookmarkconfig || '', + projectionSelector +], (searchState, searchBookmarkConfigControl, mapInitial, bookmarkConfig, currentMapCRS) => ({ enabledSearchBookmarkConfig: searchBookmarkConfigControl && searchBookmarkConfigControl.enabled || false, error: searchState && searchState.error, coordinate: searchState && searchState.coordinate || {}, @@ -71,7 +72,8 @@ const searchSelector = createSelector([ format: get(searchState, "format") || ConfigUtils.getConfigProp("defaultCoordinateFormat"), selectedItems: searchState && searchState.selectedItems, mapInitial, - bookmarkConfig: bookmarkConfig || {} + bookmarkConfig: bookmarkConfig || {}, + currentMapCRS })); const SearchBar = connect(searchSelector, { diff --git a/web/client/translations/data.de-DE.json b/web/client/translations/data.de-DE.json index ab5a49c758..0e72bfdf38 100644 --- a/web/client/translations/data.de-DE.json +++ b/web/client/translations/data.de-DE.json @@ -903,6 +903,7 @@ "addressSearch": "Suche nach Standortname", "searchOnAllServices": "Suchen Sie unten nach allen Diensten", "coordinatesSearch": "Suche nach Koordinaten", + "currentMapCRS": "Aktuelles Kartenkoordinatensystem", "searchservicesbutton": "Suchdienste konfigurieren", "configpaneltitle": "Einen Suchdienst anlegen / bearbeiten", "serviceslistlabel": "Verfügbare Suchdienste", @@ -924,6 +925,8 @@ "b_newpaneltitle": "Neues Lesezeichen hinzufügen", "latitude": "Lat", "longitude": "Lon", + "yCoord": "Y", + "xCoord": "X", "b_title": "Titel", "b_layer_tooltip": "Deaktivieren Sie das Neuladen der Ebenensichtbarkeit", "b_bbox": "Begrenzungsrahmen", diff --git a/web/client/translations/data.en-US.json b/web/client/translations/data.en-US.json index 8bb7a0907c..58c7af2b42 100644 --- a/web/client/translations/data.en-US.json +++ b/web/client/translations/data.en-US.json @@ -864,6 +864,7 @@ "addressSearch": "Search by location name", "searchOnAllServices": "Search on all services below", "coordinatesSearch": "Search by coordinates", + "currentMapCRS": "Current Map CRS", "searchservicesbutton": "Configure search services", "configpaneltitle": "Create/edit a search service", "serviceslistlabel": "Available services", @@ -885,6 +886,8 @@ "b_newpaneltitle": "Add new bookmark", "latitude": "Lat", "longitude": "Lon", + "yCoord": "Y", + "xCoord": "X", "b_title": "Title", "b_layer_tooltip": "Toggle layer visibility reload", "b_bbox": "Bounding Box", diff --git a/web/client/translations/data.es-ES.json b/web/client/translations/data.es-ES.json index cf2df613ff..e67a269938 100644 --- a/web/client/translations/data.es-ES.json +++ b/web/client/translations/data.es-ES.json @@ -864,6 +864,7 @@ "addressSearch": "Buscar por nombre de ubicación", "searchOnAllServices": "Busque en todos los servicios a continuación", "coordinatesSearch": "buscar por coordenadas", + "currentMapCRS": "Sistema de coordenadas del mapa actual", "searchservicesbutton": "Configurar los servicios de búsqueda", "configpaneltitle": "Crear / modificar un servicio de búsqueda", "serviceslistlabel": "Servicios disponibles", @@ -885,6 +886,8 @@ "b_newpaneltitle": "Agregar nuevo marcador", "latitude": "Lat", "longitude": "Lon", + "yCoord": "Y", + "xCoord": "X", "b_title": "Título", "b_layer_tooltip": "Alternar recarga de visibilidad de capa", "b_bbox": "Cuadro delimitador", diff --git a/web/client/translations/data.fr-FR.json b/web/client/translations/data.fr-FR.json index 32e1607fc5..94ea4bf37b 100644 --- a/web/client/translations/data.fr-FR.json +++ b/web/client/translations/data.fr-FR.json @@ -864,6 +864,7 @@ "addressSearch": "Recherche par nom de lieu", "searchOnAllServices": "Recherchez tous les services ci-dessous", "coordinatesSearch": "Rechercher par coordonnées", + "currentMapCRS": "Système de coordonnées cartographiques actuel", "searchservicesbutton": "Configurer les services de recherche", "configpaneltitle": "Créer / modifier un service de recherche", "serviceslistlabel": "Services disponibles", @@ -885,6 +886,8 @@ "b_newpaneltitle": "Ajouter un nouveau signet", "latitude": "Lat", "longitude": "Lon", + "yCoord": "Y", + "xCoord": "X", "b_title": "Titre", "b_layer_tooltip": "Basculer le rechargement de la visibilité des calques", "b_bbox": "Boîte englobante", diff --git a/web/client/translations/data.it-IT.json b/web/client/translations/data.it-IT.json index e2c5069c69..9771c33d74 100644 --- a/web/client/translations/data.it-IT.json +++ b/web/client/translations/data.it-IT.json @@ -864,6 +864,7 @@ "addressSearch": "Cerca un indirizzo", "searchOnAllServices": "Cerca su tutti i servizi di seguito", "coordinatesSearch": "Cerca per coordinate", + "currentMapCRS": "Sistema di coordinate della mappa corrente", "searchservicesbutton": "Configura servizi di ricerca", "configpaneltitle": "Aggiungi/modifica un servizio di ricerca", "serviceslistlabel": "Servizi disponibili", @@ -885,6 +886,8 @@ "b_newpaneltitle": "Aggiungi nuovo segnalibro", "latitude": "Lat", "longitude": "Lon", + "yCoord": "Y", + "xCoord": "X", "b_title": "Titolo", "b_layer_tooltip": "Interruttore ricarica visibilità livello", "b_bbox": "Rettangolo di selezione",