From e19c6d9180d7638407c5e03f77fddf241e1c404a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20V=C3=A1clav=C3=ADk?= Date: Sun, 26 Jan 2025 16:09:10 +0100 Subject: [PATCH] EditDialog: Add text field for setting GPS coordinates --- .../EditFeatureMap/EditFeatureMap.tsx | 35 ++++++++++++++++++- .../EditFeatureMap/isGpsValid.tsx | 8 +++++ .../EditFeatureMap/useDraggableMarker.ts | 5 ++- .../EditFeatureMap/useInitEditFeatureMap.ts | 18 ++++++---- .../EditFeatureMap/useStaticMarkers.tsx | 2 +- src/locales/cs.js | 2 ++ src/locales/vocabulary.js | 2 ++ 7 files changed, 62 insertions(+), 10 deletions(-) create mode 100644 src/components/FeaturePanel/EditDialog/EditContent/FeatureEditSection/EditFeatureMap/isGpsValid.tsx diff --git a/src/components/FeaturePanel/EditDialog/EditContent/FeatureEditSection/EditFeatureMap/EditFeatureMap.tsx b/src/components/FeaturePanel/EditDialog/EditContent/FeatureEditSection/EditFeatureMap/EditFeatureMap.tsx index b8a8d459..0fe567d2 100644 --- a/src/components/FeaturePanel/EditDialog/EditContent/FeatureEditSection/EditFeatureMap/EditFeatureMap.tsx +++ b/src/components/FeaturePanel/EditDialog/EditContent/FeatureEditSection/EditFeatureMap/EditFeatureMap.tsx @@ -4,6 +4,8 @@ import { AccordionDetails, AccordionSummary, CircularProgress, + Stack, + TextField, Typography, } from '@mui/material'; import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; @@ -12,6 +14,7 @@ import styled from '@emotion/styled'; import { t } from '../../../../../../services/intl'; import { useFeatureEditData } from '../SingleFeatureEditContext'; import { useInitEditFeatureMap } from './useInitEditFeatureMap'; +import { LngLat } from 'maplibre-gl'; const Container = styled.div` width: 100%; @@ -35,7 +38,9 @@ const Map = styled.div<{ $isVisible: boolean }>` `; export default function EditFeatureMap() { - const { containerRef, isMapLoaded } = useInitEditFeatureMap(); + const [isFirstMapLoad, setIsFirstMapLoad] = useState(true); + const { containerRef, isMapLoaded, currentItem, onMarkerChange } = + useInitEditFeatureMap(isFirstMapLoad, setIsFirstMapLoad); const [expanded, setExpanded] = useState(false); const { shortId } = useFeatureEditData(); @@ -62,6 +67,34 @@ export default function EditFeatureMap() { )} + + { + onMarkerChange({ + lng: currentItem?.nodeLonLat[0], + lat: parseFloat(e.target.value), + } as LngLat); + setIsFirstMapLoad(true); + }} + size="small" + /> + { + onMarkerChange({ + lng: parseFloat(e.target.value), + lat: currentItem?.nodeLonLat[1], + } as LngLat); + setIsFirstMapLoad(true); + }} + size="small" + /> + ); diff --git a/src/components/FeaturePanel/EditDialog/EditContent/FeatureEditSection/EditFeatureMap/isGpsValid.tsx b/src/components/FeaturePanel/EditDialog/EditContent/FeatureEditSection/EditFeatureMap/isGpsValid.tsx new file mode 100644 index 00000000..bf3c330e --- /dev/null +++ b/src/components/FeaturePanel/EditDialog/EditContent/FeatureEditSection/EditFeatureMap/isGpsValid.tsx @@ -0,0 +1,8 @@ +import { LonLat } from '../../../../../../services/types'; + +export const isGpsValid = (nodeLonLat: LonLat) => { + if (!nodeLonLat) return false; + + const [lng, lat] = nodeLonLat; + return lng >= -90 && lng <= 90 && lat >= -180 && lat <= 180; +}; diff --git a/src/components/FeaturePanel/EditDialog/EditContent/FeatureEditSection/EditFeatureMap/useDraggableMarker.ts b/src/components/FeaturePanel/EditDialog/EditContent/FeatureEditSection/EditFeatureMap/useDraggableMarker.ts index 90ef42d2..fe0ef06c 100644 --- a/src/components/FeaturePanel/EditDialog/EditContent/FeatureEditSection/EditFeatureMap/useDraggableMarker.ts +++ b/src/components/FeaturePanel/EditDialog/EditContent/FeatureEditSection/EditFeatureMap/useDraggableMarker.ts @@ -2,6 +2,7 @@ import React, { useRef } from 'react'; import maplibregl, { LngLat } from 'maplibre-gl'; import { createMapEffectHook } from '../../../../../helpers'; import { LonLat } from '../../../../../../services/types'; +import { isGpsValid } from './isGpsValid'; const useUpdateDraggableFeatureMarker = createMapEffectHook< [ @@ -24,8 +25,9 @@ const useUpdateDraggableFeatureMarker = createMapEffectHook< markerRef.current?.remove(); markerRef.current = undefined; - if (nodeLonLat) { + if (nodeLonLat && isGpsValid(nodeLonLat)) { const [lng, lat] = nodeLonLat; + markerRef.current = new maplibregl.Marker({ color: 'salmon', draggable: true, @@ -56,4 +58,5 @@ export function useDraggableFeatureMarker( nodeLonLat: currentItem?.nodeLonLat, markerRef, }); + return { onMarkerChange }; } diff --git a/src/components/FeaturePanel/EditDialog/EditContent/FeatureEditSection/EditFeatureMap/useInitEditFeatureMap.ts b/src/components/FeaturePanel/EditDialog/EditContent/FeatureEditSection/EditFeatureMap/useInitEditFeatureMap.ts index 5c00e15a..ccbb9f0a 100644 --- a/src/components/FeaturePanel/EditDialog/EditContent/FeatureEditSection/EditFeatureMap/useInitEditFeatureMap.ts +++ b/src/components/FeaturePanel/EditDialog/EditContent/FeatureEditSection/EditFeatureMap/useInitEditFeatureMap.ts @@ -6,20 +6,20 @@ import { COMPASS_TOOLTIP } from '../../../../../Map/useAddTopRightControls'; import { useEditContext } from '../../../EditContext'; import { useFeatureMarkers } from './useStaticMarkers'; import { useDraggableFeatureMarker } from './useDraggableMarker'; +import { isGpsValid } from './isGpsValid'; -export function useInitEditFeatureMap() { +export function useInitEditFeatureMap(isFirstMapLoad, setIsFirstMapLoad) { const containerRef = React.useRef(null); const mapRef = React.useRef(null); const [isMapLoaded, setIsMapLoaded] = useState(false); - const [isFirstMapLoad, setIsFirstMapLoad] = useState(true); const { current, items, setCurrent } = useEditContext(); const currentItem = items.find((item) => item.shortId === current); useFeatureMarkers(mapRef, items, setCurrent, current); - useDraggableFeatureMarker(mapRef, currentItem); + const { onMarkerChange } = useDraggableFeatureMarker(mapRef, currentItem); useEffect(() => { setIsMapLoaded(false); @@ -58,14 +58,18 @@ export function useInitEditFeatureMap() { }, [containerRef, current]); const updateCenter = useCallback(() => { - if (isFirstMapLoad && currentItem?.nodeLonLat) { + if ( + isFirstMapLoad && + currentItem?.nodeLonLat && + isGpsValid(currentItem?.nodeLonLat) + ) { mapRef.current?.jumpTo({ center: currentItem.nodeLonLat as [number, number], zoom: 18.5, }); setIsFirstMapLoad(false); } - }, [currentItem?.nodeLonLat, isFirstMapLoad]); + }, [currentItem.nodeLonLat, isFirstMapLoad, setIsFirstMapLoad]); useEffect(() => { mapRef.current?.on('load', () => { @@ -79,7 +83,7 @@ export function useInitEditFeatureMap() { useEffect(() => { setIsFirstMapLoad(true); - }, [current]); + }, [current, setIsFirstMapLoad]); - return { containerRef, isMapLoaded }; + return { containerRef, isMapLoaded, currentItem, onMarkerChange }; } diff --git a/src/components/FeaturePanel/EditDialog/EditContent/FeatureEditSection/EditFeatureMap/useStaticMarkers.tsx b/src/components/FeaturePanel/EditDialog/EditContent/FeatureEditSection/EditFeatureMap/useStaticMarkers.tsx index 0254223c..795920ab 100644 --- a/src/components/FeaturePanel/EditDialog/EditContent/FeatureEditSection/EditFeatureMap/useStaticMarkers.tsx +++ b/src/components/FeaturePanel/EditDialog/EditContent/FeatureEditSection/EditFeatureMap/useStaticMarkers.tsx @@ -19,7 +19,7 @@ const useUpdateFeatureMarkers = createMapEffectHook< markerRefs.current = []; items.forEach((item) => { - if (!item.nodeLonLat || item.shortId === current) return; + if (!item.nodeLonLat || item.shortId === current || !lng || !lat) return; const [lng, lat] = item.nodeLonLat; const marker = new maplibregl.Marker({ diff --git a/src/locales/cs.js b/src/locales/cs.js index a4407504..2f9ffe8f 100644 --- a/src/locales/cs.js +++ b/src/locales/cs.js @@ -193,6 +193,8 @@ export default { 'editdialog.tags_editor': 'Všechny vlastnosti – tagy', 'editdialog.add_tag': 'Přidat tag', 'editdialog.location': 'Poloha', + 'editdialog.location_latitude': 'Zeměpisná šířka', + 'editdialog.location_longitude': 'Zeměpisná délka', 'editdialog.tags_editor_info': `Tagy popisují vlastnosti mapového prvku v dohodnutém formátu. Zde naleznete úplný přehled všech tagů v OpenStreetMap.`, 'editdialog.save_refused': 'Změny se nepodařilo uložit.', diff --git a/src/locales/vocabulary.js b/src/locales/vocabulary.js index cba46c99..8ac46260 100644 --- a/src/locales/vocabulary.js +++ b/src/locales/vocabulary.js @@ -232,6 +232,8 @@ export default { 'editdialog.tags_editor': 'All properties – Tags', 'editdialog.add_tag': 'Add tag', 'editdialog.location': 'Location', + 'editdialog.location_latitude': 'Latitude', + 'editdialog.location_longitude': 'Longitude', 'editdialog.tags_editor_info': `Tags contain the data used to display objects on the map.
You can find a reference for all tags on the OpenStreetMap Wiki.`, 'editdialog.login_in_progress': `Logging in...`, 'editdialog.save_refused': 'Unable to save your changes.',