diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ab259aaf..622fbf4b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,15 @@ The format is based on This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## [v3.15.7] - 2024-7-02 +## [v3.15.8] - 2024-7-10 +Released with [maproulette-backend_v4.5.4](https://github.com/maproulette/maproulette-backend/releases/tag/v4.5.4) + +## What's Changed +* Fix zoom and panning issues in maps by @CollinBeczak in https://github.com/maproulette/maproulette3/pull/2378 + +**Full Changelog**: https://github.com/maproulette/maproulette3/compare/v3.15.7...v3.15.8 + +## [v3.15.7] - 2024-7-09 Released with [maproulette-backend_v4.5.4](https://github.com/maproulette/maproulette-backend/releases/tag/v4.5.4) ## What's Changed diff --git a/package.json b/package.json index ece748926..5a74616af 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "maproulette3", - "version": "3.15.7", + "version": "3.15.8", "private": true, "dependencies": { "@apollo/client": "^3.5.4", diff --git a/src/components/EnhancedMap/SourcedTileLayer/SourcedTileLayer.js b/src/components/EnhancedMap/SourcedTileLayer/SourcedTileLayer.js index e950b2c1b..9d6d9148d 100644 --- a/src/components/EnhancedMap/SourcedTileLayer/SourcedTileLayer.js +++ b/src/components/EnhancedMap/SourcedTileLayer/SourcedTileLayer.js @@ -70,7 +70,6 @@ const SourcedTileLayer = (props) => { return ( { const [layer, setLayer] = useState(null) - const [numberOfFeatures, setNumberOfFeatures] = useState(0) const map = useMap() const propertyList = (featureProperties, onBack) => { @@ -104,23 +103,6 @@ const TaskFeatureLayer = props => { ) }, [features.length]) - useEffect(() => { - if(numberOfFeatures !== features.length) { - const geoJSONFeatures = new FeatureGroup() - - map.eachLayer(layer => { - if (layer.feature && layer.feature.type === "Feature") { - geoJSONFeatures.addLayer(layer) - } - }) - - if (geoJSONFeatures.getLayers().length !== 0) { - map.fitBounds(geoJSONFeatures.getBounds().pad(0.2)) - } - setNumberOfFeatures(features.length) - } - }, [layer]) - return layer } diff --git a/src/components/TaskClusterMap/MapMarkers.js b/src/components/TaskClusterMap/MapMarkers.js index 0ab83bb52..1653b7234 100644 --- a/src/components/TaskClusterMap/MapMarkers.js +++ b/src/components/TaskClusterMap/MapMarkers.js @@ -102,7 +102,7 @@ const Markers = (props) => { }, [props.currentZoom]); useEffect(() => { - // Fit bounds to initial tasks when they are loaded + // Fit bounds to initial tasks when they are loaded if (!initialLoadComplete && mapMarkers && mapMarkers.length > 0) { const bounds = props.centerBounds || toLatLngBounds( bbox({ @@ -121,9 +121,11 @@ const Markers = (props) => { map.fitBounds(bounds.pad(0.2)); props.setCurrentBounds(bounds.pad(0.2)); - setInitialLoadComplete(true); + } + else if (props.taskCenter && !props.taskCenter.equals(prevProps.current.taskCenter)) { + map.panTo(props.taskCenter) } - }, [mapMarkers, initialLoadComplete]); + }, [props, mapMarkers, initialLoadComplete]); const refreshSpidered = () => { if (spidered.size === 0) { diff --git a/src/components/TaskPane/TaskMap/TaskMap.js b/src/components/TaskPane/TaskMap/TaskMap.js index f230264b9..f0680e67b 100644 --- a/src/components/TaskPane/TaskMap/TaskMap.js +++ b/src/components/TaskPane/TaskMap/TaskMap.js @@ -6,6 +6,8 @@ import { featureCollection } from '@turf/helpers' import { coordAll } from '@turf/meta' import { point } from '@turf/helpers' import _isObject from 'lodash/isObject' +import _uniqueId from 'lodash/uniqueId' +import L from 'leaflet' import _get from 'lodash/get' import _isFinite from 'lodash/isFinite' import _map from 'lodash/map' @@ -69,8 +71,31 @@ export const TaskMapContainer = (props) => { const [osmDataLoading, setOsmDataLoading] = useState(null) const [mapillaryViewerImage, setMapillaryViewerImage] = useState(null) const [openStreetCamViewerImage, setOpenStreetCamViewerImage] = useState(null) - const [directionalityIndicators, setDirectionalityIndicators] = useState(null) + const [directionalityIndicators, setDirectionalityIndicators] = useState({}) const [showOSMElements, setShowOSMElements] = useState({ nodes: true, ways: true, areas: true }) + const taskFeatures = () => { + if (_get(props, 'taskBundle.tasks.length', 0) > 0) { + return featureCollection( + _flatten(_compact(_map(props.taskBundle.tasks, + task => _get(task, 'geometries.features')))) + ).features + } + + // If current OSM data is available, show the feature's current OSM tags + // instead of those bundled with the GeoJSON. We preserve any simplestyle + // properties, allowing display colors and what not to be customized + if (_get(props, 'osmElements.size', 0) > 0) { + return AsMappableTask(props.task).featuresWithTags( + _get(props.task, 'geometries.features'), + props.osmElements, + true, + supportedSimplestyles, + ) + } + + return _get(props.task, 'geometries.features') + } + const features = taskFeatures() const animator = new MapAnimator() useMapEvents({ @@ -273,10 +298,13 @@ export const TaskMapContainer = (props) => { }, [props.task.id]); useEffect(() => { - return () => { - props.deactivateKeyboardShortcutGroup(shortcutGroup, handleKeyboardShortcuts); - }; - }, []); + if (features.length !== 0) { + const layerGroup = L.featureGroup( + features.map(feature => L.geoJSON(feature)) + ); + map.fitBounds(layerGroup.getBounds().pad(0.2)); + } + }, [props.taskBundle, props.taskId]); const mapillaryImageMarkers = () => { return { @@ -312,7 +340,7 @@ export const TaskMapContainer = (props) => { const generateDirectionalityMarkers = () => { const markers = [] - const allFeatures = taskFeatures() + const allFeatures = features _each(allFeatures, (feature, featureIndex) => { if (!feature.properties || !feature.properties.oneway) { return @@ -353,29 +381,6 @@ export const TaskMapContainer = (props) => { }) } - const taskFeatures = () => { - if (_get(props, 'taskBundle.tasks.length', 0) > 0) { - return featureCollection( - _flatten(_compact(_map(props.taskBundle.tasks, - task => _get(task, 'geometries.features')))) - ).features - } - - // If current OSM data is available, show the feature's current OSM tags - // instead of those bundled with the GeoJSON. We preserve any simplestyle - // properties, allowing display colors and what not to be customized - if (_get(props, 'osmElements.size', 0) > 0) { - return AsMappableTask(props.task).featuresWithTags( - _get(props.task, 'geometries.features'), - props.osmElements, - true, - supportedSimplestyles, - ) - } - - return _get(props.task, 'geometries.features') - } - const applyStyling = taskFeatures => { // If the challenge has conditional styles, apply those const conditionalStyles = _get(props, 'challenge.taskStyles') @@ -400,6 +405,7 @@ export const TaskMapContainer = (props) => { ) } const maxZoom = _get(props.task, "parent.maxZoom", MAX_ZOOM) + const renderId = _uniqueId() let overlayOrder = props.getUserAppSetting(props.user, 'mapOverlayOrder') if (_isEmpty(overlayOrder)) { overlayOrder = DEFAULT_OVERLAY_ORDER @@ -426,7 +432,7 @@ export const TaskMapContainer = (props) => { @@ -495,18 +501,19 @@ export const TaskMapContainer = (props) => { openStreetCamCount={_get(props, 'openStreetCamImages.length', 0)} overlayOrder={overlayOrder} /> - - - - {_map(overlayLayers, (layer, index) => ( - - {layer.component} - - ))} + + + + {_map(overlayLayers, (layer, index) => ( + + {layer.component} + + ))} {mapillaryViewerImage && renderMapillaryViewer()} @@ -532,7 +539,7 @@ const TaskMap = (props) => { zoom={DEFAULT_ZOOM} zoomControl={false} minZoom={2} - maxZoom={18} + maxZoom={MAX_ZOOM} attributionControl={false} maxBounds={[[-90, -180], [90, 180]]} > diff --git a/src/lang/nl.json b/src/lang/nl.json index 0ba415fc1..420a6ce3e 100644 --- a/src/lang/nl.json +++ b/src/lang/nl.json @@ -497,7 +497,7 @@ "Challenge.difficulty.expert": "Expert", "Challenge.difficulty.normal": "Normaal", "Challenge.fields.ChallengeResultList.label": "{count,plural,=0{Geen uitdaging} one{# uitdaging} other{# uitdagingen}} voltooid in project", - "Challenge.fields.completed.label": "Completed", + "Challenge.fields.completed.label": "Voltooid", "Challenge.fields.difficulty.label": "Moeilijkheidsgraad", "Challenge.fields.lastTaskRefresh.label": "Taakgegevens opgehaald op", "Challenge.fields.viewLeaderboard.label": "Scorebord bekijken", @@ -1101,7 +1101,7 @@ "Locale.nl.label": "nl (Nederlands)", "Locale.pl.label": "pl (Pools)", "Locale.pt-BR.label": "pt-BR (Portugees Braziliaans)", - "Locale.pt-PT.label": "pt-PT (Português Portugal)", + "Locale.pt-PT.label": "pt-PT (Portugees Portugal)", "Locale.ru-RU.label": "ru-RU (Russisch - Rusland)", "Locale.sr.label": "sr (Servisch)", "Locale.tr.label": "tr (Turks)", @@ -1269,7 +1269,7 @@ "ProjectDetails.fields.viewLeaderboard.label": "Scorebord bekijken", "ProjectDetails.fields.viewReviews.label": "Beoordelen", "ProjectDetails.management.controls.manage.label": "Beheren", - "ProjectDetails.management.controls.showAll.label": "Display All Challenges", + "ProjectDetails.management.controls.showAll.label": "Alle uitdagingen weergeven", "ProjectDetails.management.controls.start.label": "Beginnen", "ProjectPickerModal.chooseProject": "Kies een project", "ProjectPickerModal.noProjects": "Geen projecten gevonden",