diff --git a/client/src/components/Leaflet.js b/client/src/components/Leaflet.js index 85bf25ec61..619494dfe4 100644 --- a/client/src/components/Leaflet.js +++ b/client/src/components/Leaflet.js @@ -1,3 +1,5 @@ +import API from "api" +import { gql } from "apollo-boost" import { Control, CRS, Icon, Map, Marker, TileLayer } from "leaflet" import "leaflet-defaulticon-compatibility" import "leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.webpack.css" @@ -14,13 +16,29 @@ import "leaflet.markercluster/dist/MarkerCluster.css" import "leaflet.markercluster/dist/MarkerCluster.Default.css" import "leaflet/dist/leaflet.css" import { Location } from "models" +import GeoLocation from "pages/locations/GeoLocation" import PropTypes from "prop-types" import React, { useCallback, useEffect, useRef, useState } from "react" +import ReactDOM from "react-dom" +import MARKER_FLAG_BLUE from "resources/leaflet/marker-flag-blue.png" import MARKER_ICON_2X from "resources/leaflet/marker-icon-2x.png" import MARKER_ICON from "resources/leaflet/marker-icon.png" import MARKER_SHADOW from "resources/leaflet/marker-shadow.png" import Settings from "settings" +const allLocationsQuery = gql` + query { + locationList(query: { pageSize: 0 }) { + list { + uuid + name + lat + lng + } + } + } +` + const css = { zIndex: 1 } @@ -68,6 +86,13 @@ const icon = new Icon({ shadowSize: [41, 41] }) +const icon2 = new Icon({ + iconUrl: MARKER_FLAG_BLUE, + iconSize: [64, 64], + iconAnchor: [32, 64], + popupAnchor: [4, -58] +}) + const addLayers = (map, layerControl) => { let defaultLayer = null Settings.imagery.baseLayers.forEach(layerConfig => { @@ -112,6 +137,8 @@ const Leaflet = ({ const [map, setMap] = useState(null) const [markerLayer, setMarkerLayer] = useState(null) + const [layerControl, setLayerControl] = useState(null) + const [allLocationsLayer, setAllLocationsLayer] = useState(null) const [doInitializeMarkerLayer, setDoInitializeMarkerLayer] = useState(false) const prevMarkersRef = useRef() @@ -125,7 +152,8 @@ const Leaflet = ({ icon: icon, draggable: m.draggable || false, autoPan: m.autoPan || false, - id: m.id + id: m.id, + zIndexOffset: 1000 }) if (m.name) { marker.bindPopup(m.name) @@ -170,6 +198,7 @@ const Leaflet = ({ const layerControl = new Control.Layers({}, {}, { collapsed: false }) layerControl.addTo(newMap) addLayers(newMap, layerControl) + setLayerControl(layerControl) setMap(newMap) @@ -242,6 +271,72 @@ const Leaflet = ({ widthPropUnchanged ]) + const { data } = API.useApiQuery(allLocationsQuery) + + if ( + data?.locationList?.list?.length && + map && + layerControl && + !allLocationsLayer + ) { + const allMarkers = data.locationList.list + .filter(loc => Location.hasCoordinates(loc)) + .map(location => { + const popupContent = document.createElement("div") + popupContent.setAttribute("style", "width: 300px;text-align: center") + + return new Marker([location.lat, location.lng], { + icon: icon2, + draggable: false, + autoPan: false, + id: location.uuid + }) + .bindPopup(popupContent) + .on("popupopen", e => { + // TODO LinkTo component will be utilized here to provide routing + ReactDOM.render( + <> + {location.name} @{" "} + + , + e.popup.getContent() + ) + }) + }) + + const locationsLayer = new MarkerClusterGroup() + .addLayers(allMarkers) + .on("add", () => { + if (markers?.length && markers.some(m => m.onMove)) { + return // While editing a location don't change zoom levels + } + + map.fitBounds(locationsLayer.getBounds()) + }) + .on("remove", () => { + if (markers?.length && markers.some(m => m.onMove)) { + return // While editing a location don't change zoom levels + } + + const curMarkersWithLatLng = (markers || []) + .filter(m => Location.hasCoordinates(m)) + .map(m => new Marker([m.lat, m.lng])) + + if (curMarkersWithLatLng.length) { + map.fitBounds( + new MarkerClusterGroup() + .addLayers(curMarkersWithLatLng) + .getBounds(), + { maxZoom: 15 } + ) + } + }) + + layerControl.addOverlay(locationsLayer, "All Locations") + + setAllLocationsLayer(locationsLayer) + } + return
} Leaflet.propTypes = { diff --git a/client/src/resources/leaflet/marker-flag-blue.png b/client/src/resources/leaflet/marker-flag-blue.png new file mode 100644 index 0000000000..00dca0e1df Binary files /dev/null and b/client/src/resources/leaflet/marker-flag-blue.png differ diff --git a/client/src/resources/leaflet/marker-flag-red.png b/client/src/resources/leaflet/marker-flag-red.png new file mode 100644 index 0000000000..4172f534dc Binary files /dev/null and b/client/src/resources/leaflet/marker-flag-red.png differ