ag visual farm added to the dev branch field related stuff not imported yet, and the geocoder has some bugs with the new version
This commit is contained in:
parent
b4da0d6859
commit
022925d7d7
41 changed files with 8895 additions and 79 deletions
704
src/maps/MapBase.tsx
Normal file
704
src/maps/MapBase.tsx
Normal file
|
|
@ -0,0 +1,704 @@
|
|||
import { useEffect, useRef, useState } from "react";
|
||||
import "mapbox-gl/dist/mapbox-gl.css";
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
Grid,
|
||||
Icon,
|
||||
IconButton,
|
||||
LinearProgress,
|
||||
MenuItem,
|
||||
Select,
|
||||
Theme
|
||||
} from "@mui/material";
|
||||
import { HomeMarker } from "models/HomeMarker";
|
||||
import { useGlobalState, useHomeMarkerAPI } from "providers";
|
||||
import { useMobile, useSnackbar } from "hooks";
|
||||
import { useCallback } from "react";
|
||||
import HomeIcon from "products/AgIcons/HomeIcon";
|
||||
//import { Theme } from "@material-ui/core/styles/createMuiTheme";
|
||||
import { GpsFixed, Layers } from "@mui/icons-material";
|
||||
//import Geocoder from "react-map-gl-geocoder";
|
||||
import "maps/mapboxStyleOverrides.css";
|
||||
import { pond } from "protobuf-ts/pond";
|
||||
import MarkerMove from "products/AgIcons/MarkerMove";
|
||||
import ResponsiveDialog from "common/ResponsiveDialog";
|
||||
import Markers, { MarkerData } from "./mapMarkers/Markers";
|
||||
import GeoMapLayer from "./mapLayers/geoMapLayer";
|
||||
import Geocoder from "./mapControllers/Geocoder";
|
||||
import { GeometryMapping, shapeFromCoords } from "models/GeometryMapping";
|
||||
import { FeatureCollection, Feature } from "geojson";
|
||||
import DrawController from "./mapControllers/drawController";
|
||||
//import { Geometry } from "geojson";
|
||||
import Map, { MapRef, Marker, MarkerDragEvent } from "react-map-gl/mapbox-legacy";
|
||||
import { getDistanceUnit } from "utils";
|
||||
import { MapMouseEvent } from "mapbox-gl";
|
||||
import { makeStyles } from "@mui/styles";
|
||||
import { Result } from "@mapbox/mapbox-gl-geocoder";
|
||||
|
||||
//const MAPBOX_TOKEN = process.env.REACT_APP_MAPBOX_ACCESS_TOKEN;
|
||||
const MAPBOX_TOKEN = import.meta.env.VITE_MAPBOX_ACCESS_TOKEN;
|
||||
|
||||
const mapStyleOptions = [
|
||||
{
|
||||
label: "Dark",
|
||||
value: "mapbox://styles/mapbox/dark-v10"
|
||||
},
|
||||
{
|
||||
label: "Satellite with streets",
|
||||
value: "mapbox://styles/mapbox/satellite-streets-v11"
|
||||
}
|
||||
];
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
iconButtons: {
|
||||
background: theme.palette.background.default,
|
||||
margin: 5,
|
||||
boxShadow: "4px 4px 10px black"
|
||||
},
|
||||
pin: {
|
||||
borderRadius: "50rem",
|
||||
display: "inline-block",
|
||||
borderBottomRightRadius: "0",
|
||||
transform: "rotate(45deg)",
|
||||
cursor: "pointer",
|
||||
boxShadow: "4px 4px 10px black"
|
||||
},
|
||||
geoDot: {
|
||||
height: "25px",
|
||||
width: "25px",
|
||||
backgroundColor: "yellow",
|
||||
borderRadius: "50%",
|
||||
border: "5px solid black"
|
||||
},
|
||||
geoIconColor: {
|
||||
color: "black"
|
||||
},
|
||||
geoIconSearch: {
|
||||
animation: "$rotation 3s infinite"
|
||||
},
|
||||
"@keyframes rotation": {
|
||||
from: {
|
||||
transform: "rotate(0deg)"
|
||||
},
|
||||
to: {
|
||||
transform: "rotate(360deg)"
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
export interface ViewData {
|
||||
longitude: number;
|
||||
latitude: number;
|
||||
zoom: number;
|
||||
transitionDuration?: number;
|
||||
xOffset?: number;
|
||||
yOffset?: number;
|
||||
}
|
||||
|
||||
export interface MeasurementData {
|
||||
key: string;
|
||||
geoShape: string;
|
||||
coordinates: number[][];
|
||||
segmentDistanceKm: number[];
|
||||
totalDistanceKm: number;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
mapTools: JSX.Element;
|
||||
mapClick(mapClickEvent: MapMouseEvent): void;
|
||||
currentView: ViewData;
|
||||
ignoreHomeLoad?: boolean;
|
||||
defaultMapStyle?: string;
|
||||
layerOptions?: JSX.Element;
|
||||
markerData?: MarkerData[];
|
||||
displayMarkerTitles?: boolean;
|
||||
displayMarkerDetails?: boolean;
|
||||
customCursor?: JSX.Element;
|
||||
objectGeoData?: Map<string, pond.GeoData>;
|
||||
measurementData?: Map<string, MeasurementData>;
|
||||
objectTitles?: boolean;
|
||||
editorMode?: "drawPolygon" | "drawLine" | "drawPoint" | "edit" | "none" | "delete";
|
||||
placingMarker?: boolean;
|
||||
linePointLimit?: number;
|
||||
customSearchEntries?: Result[];
|
||||
drawMeasurement?: boolean;
|
||||
geocoderResultFunction?: (result: Result) => void;
|
||||
geocoderTransitionFunction?: (result: Result) => void;
|
||||
cutHoleInPolygon?: (object: string, coordinates: any[], geoType: string) => void;
|
||||
editGeoCallback?: (object: string, borders: pond.Shape[], holes?: pond.Shape[]) => void;
|
||||
addNewShape?: (coordinates: any[], geoType: string) => void;
|
||||
addNewMeasurement?: (coordinates: number[][], geoType: string) => void;
|
||||
}
|
||||
|
||||
export default function MapBase(props: Props) {
|
||||
const [startingView, setStartingView] = useState<ViewData | undefined>();
|
||||
//const [viewport, setViewport] = useState<ViewData>(props.currentView);
|
||||
const transDuration = 3000; //in milliseconds
|
||||
const homeMarkerAPI = useHomeMarkerAPI();
|
||||
const classes = useStyles();
|
||||
const isMobile = useMobile();
|
||||
const [mapCursor, setMapCursor] = useState("auto");
|
||||
const [hcHovered, setHCHovered] = useState(false);
|
||||
const [gcHovered, setGCHovered] = useState(false);
|
||||
const [dcHovered, setDCHovered] = useState(false);
|
||||
const mapRef = useRef<MapRef>(null);
|
||||
const [haveHome, setHaveHome] = useState(false);
|
||||
const [homeKey, setHomeKey] = useState("");
|
||||
const [homePin, setHomePin] = useState<{ longitude: number; latitude: number }>();
|
||||
const [{ user, as }] = useGlobalState();
|
||||
const { openSnack } = useSnackbar();
|
||||
const [stateWatch, setStateWatch] = useState(0);
|
||||
const [watching, setWatching] = useState(false);
|
||||
const [locationFound, setLocationFound] = useState(true);
|
||||
const [geoPosition, setGeoPosition] = useState({ longitude: 0, latitude: 0 });
|
||||
const [dragAllowed, setDragAllowed] = useState(false);
|
||||
const [mapStyle, setMapStyle] = useState(
|
||||
props.defaultMapStyle ?? "mapbox://styles/mapbox/satellite-streets-v11"
|
||||
);
|
||||
const [styles, setStyles] = useState(false);
|
||||
const [msHovered, setMSHovered] = useState(false);
|
||||
const [layerIDs, setLayerIDs] = useState<string[]>([]);
|
||||
const [geoCollection, setGeoCollection] = useState<FeatureCollection>();
|
||||
const [measurementCollection, setMeasurementCollection] = useState<FeatureCollection>();
|
||||
const [groupSelect, setGroupSelect] = useState(false);
|
||||
const [currentZoom, setCurrentZoom] = useState(props.currentView.zoom);
|
||||
|
||||
const movePos = () => {
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
pos => {
|
||||
setGeoPosition({ longitude: pos.coords.longitude, latitude: pos.coords.latitude });
|
||||
setLocationFound(true);
|
||||
if (mapRef.current) {
|
||||
if (!mapRef.current.isMoving()) {
|
||||
mapRef.current.flyTo({
|
||||
center: [pos.coords.longitude, pos.coords.latitude],
|
||||
duration: transDuration,
|
||||
zoom: 18
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
() => {
|
||||
//error callback function
|
||||
},
|
||||
{ enableHighAccuracy: true }
|
||||
);
|
||||
};
|
||||
|
||||
const geolocateToggle = () => {
|
||||
if (!watching) {
|
||||
setWatching(true);
|
||||
setStateWatch(navigator.geolocation.watchPosition(e => movePos()));
|
||||
setLocationFound(false);
|
||||
} else {
|
||||
navigator.geolocation.clearWatch(stateWatch);
|
||||
setWatching(false);
|
||||
}
|
||||
};
|
||||
|
||||
//used to change the viewport from the parent
|
||||
useEffect(() => {
|
||||
//setViewport(props.currentView);
|
||||
if (mapRef.current) {
|
||||
let xOffset = props.currentView.xOffset ?? 0;
|
||||
let yOffset = props.currentView.yOffset ?? 0;
|
||||
mapRef.current.flyTo({
|
||||
offset: [xOffset, yOffset], //this is in pixels
|
||||
center: [props.currentView.longitude, props.currentView.latitude], //this is in degrees
|
||||
duration: props.currentView.transitionDuration,
|
||||
zoom: props.currentView.zoom
|
||||
});
|
||||
}
|
||||
}, [props.currentView]);
|
||||
|
||||
const homeControl = () => {
|
||||
if (!haveHome) {
|
||||
setHaveHome(true);
|
||||
if (mapRef.current) {
|
||||
setHomePin({
|
||||
longitude: mapRef.current.getCenter().lng,
|
||||
latitude: mapRef.current.getCenter().lat
|
||||
});
|
||||
}
|
||||
|
||||
// save the pin to the database
|
||||
saveHomeMarker();
|
||||
} else {
|
||||
if (mapRef.current && homePin) {
|
||||
mapRef.current.flyTo({
|
||||
center: [homePin.longitude, homePin.latitude],
|
||||
duration: transDuration
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const loadHomeMarkers = useCallback(() => {
|
||||
homeMarkerAPI
|
||||
.listHomeMarkers(1, 0, undefined, undefined, undefined, undefined, as)
|
||||
.then(resp => {
|
||||
if (resp.data.homeMarker.length < 1) {
|
||||
setHomePin(undefined);
|
||||
setHaveHome(false);
|
||||
setStartingView(props.currentView);
|
||||
return;
|
||||
}
|
||||
let hm = HomeMarker.any(resp.data.homeMarker[0]);
|
||||
setHomeKey(hm.key());
|
||||
setHomePin({
|
||||
longitude: hm.long(),
|
||||
latitude: hm.lat()
|
||||
});
|
||||
setHaveHome(true);
|
||||
if (props.ignoreHomeLoad) {
|
||||
setStartingView(props.currentView);
|
||||
} else if (!startingView) {
|
||||
setStartingView({
|
||||
longitude: hm.long(),
|
||||
latitude: hm.lat(),
|
||||
zoom: user.settings.mapZoom
|
||||
});
|
||||
} else if (mapRef.current) {
|
||||
mapRef.current.flyTo({
|
||||
center: [hm.long(), hm.lat()],
|
||||
zoom: user.settings.mapZoom,
|
||||
duration: 0
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
openSnack("Could not load Home Pin");
|
||||
});
|
||||
}, [as, homeMarkerAPI, openSnack, props.ignoreHomeLoad, user]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
const saveHomeMarker = () => {
|
||||
if (mapRef.current) {
|
||||
let hm = HomeMarker.create();
|
||||
hm.settings.userId = as ? as : user.id();
|
||||
hm.settings.longitude = mapRef.current.getCenter().lng;
|
||||
hm.settings.latitude = mapRef.current.getCenter().lat;
|
||||
homeMarkerAPI
|
||||
.addHomeMarker(hm.settings)
|
||||
.then(resp => {
|
||||
setHomeKey(resp.data.homeMarker);
|
||||
openSnack("New Home Marker Created");
|
||||
})
|
||||
.catch(err => openSnack("Failed to save new Home Marker"));
|
||||
}
|
||||
};
|
||||
|
||||
const updateHomeMarker = (longitude: number, latitude: number) => {
|
||||
let hm = HomeMarker.create();
|
||||
if (homePin) {
|
||||
hm.settings.latitude = latitude;
|
||||
hm.settings.longitude = longitude;
|
||||
hm.settings.userId = as ? as : user.id();
|
||||
homeMarkerAPI
|
||||
.updateHomeMarker(homeKey, hm.settings)
|
||||
.then(resp => {
|
||||
openSnack("Home Marker Moved");
|
||||
})
|
||||
.catch(err => openSnack("Failed to Update Home Marker"));
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
loadHomeMarkers();
|
||||
}, [loadHomeMarkers, as]);
|
||||
|
||||
const homeDragEnd = (event: MarkerDragEvent) => {
|
||||
let longitude = event.lngLat.lng;
|
||||
let latitude = event.lngLat.lat;
|
||||
setHomePin({ longitude, latitude });
|
||||
// update the pin in the database
|
||||
updateHomeMarker(longitude, latitude);
|
||||
};
|
||||
|
||||
const tools = () => {
|
||||
return (
|
||||
<Box>
|
||||
<Box
|
||||
style={{
|
||||
marginLeft: 10,
|
||||
position: "absolute",
|
||||
top: isMobile ? "120px" : "7%",
|
||||
left: isMobile ? 0 : 75
|
||||
}}
|
||||
className="mapboxgl-ctrl-top-left mapboxgl-ctrl">
|
||||
{props.mapTools}
|
||||
</Box>
|
||||
<Box
|
||||
style={{
|
||||
marginRight: 10,
|
||||
position: "absolute",
|
||||
bottom: isMobile ? "7%" : "3%",
|
||||
right: 10
|
||||
}}
|
||||
className="mapboxgl-ctrl-bottom-right mapboxgl-ctrl">
|
||||
<Box>
|
||||
{dragAllowed && (
|
||||
<IconButton
|
||||
className={classes.iconButtons}
|
||||
style={
|
||||
groupSelect ? { background: "yellow" } : dcHovered ? { background: "grey" } : {}
|
||||
}
|
||||
title="Group Select"
|
||||
onClick={() => setGroupSelect(!groupSelect)}
|
||||
onMouseOver={() => setDCHovered(true)}
|
||||
onMouseOut={() => setDCHovered(false)}>
|
||||
<MarkerMove />
|
||||
</IconButton>
|
||||
)}
|
||||
</Box>
|
||||
<Grid container direction={isMobile ? "column" : "row"}>
|
||||
<Grid item>
|
||||
<IconButton
|
||||
className={classes.iconButtons}
|
||||
style={
|
||||
dragAllowed ? { background: "yellow" } : dcHovered ? { background: "grey" } : {}
|
||||
}
|
||||
title="Toggle Drag"
|
||||
onClick={() => {
|
||||
setGroupSelect(false);
|
||||
setDragAllowed(!dragAllowed);
|
||||
}}
|
||||
onMouseOver={() => setDCHovered(true)}
|
||||
onMouseOut={() => setDCHovered(false)}>
|
||||
<MarkerMove />
|
||||
</IconButton>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<IconButton
|
||||
className={classes.iconButtons}
|
||||
style={msHovered ? { background: "grey" } : {}}
|
||||
title="Map Style"
|
||||
onClick={() => setStyles(true)}
|
||||
onMouseOver={() => setMSHovered(true)}
|
||||
onMouseOut={() => setMSHovered(false)}>
|
||||
<Layers />
|
||||
</IconButton>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<IconButton
|
||||
className={classes.iconButtons}
|
||||
style={hcHovered ? { background: "grey" } : {}}
|
||||
title="Home Pin"
|
||||
onClick={homeControl}
|
||||
onMouseOver={() => setHCHovered(true)}
|
||||
onMouseOut={() => setHCHovered(false)}>
|
||||
<HomeIcon />
|
||||
</IconButton>
|
||||
</Grid>
|
||||
<Grid item>
|
||||
<IconButton
|
||||
className={classes.iconButtons}
|
||||
style={
|
||||
watching ? { background: "yellow" } : gcHovered ? { background: "grey" } : {}
|
||||
}
|
||||
title="Find Me"
|
||||
onClick={geolocateToggle}
|
||||
onMouseOver={() => setGCHovered(true)}
|
||||
onMouseOut={() => setGCHovered(false)}>
|
||||
<Icon className={locationFound ? "" : classes.geoIconSearch}>
|
||||
<GpsFixed
|
||||
classes={{
|
||||
colorSecondary: classes.geoIconColor
|
||||
}}
|
||||
color={watching ? "secondary" : "inherit"}
|
||||
/>
|
||||
</Icon>
|
||||
</IconButton>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
const mapClick = (event: MapMouseEvent) => {
|
||||
if (!watching) {
|
||||
props.mapClick(event);
|
||||
}
|
||||
};
|
||||
|
||||
const mapStyleDialog = () => {
|
||||
return (
|
||||
<ResponsiveDialog open={styles} onClose={() => setStyles(false)}>
|
||||
<DialogTitle>Select Map Style</DialogTitle>
|
||||
<DialogContent>
|
||||
<Select
|
||||
fullWidth
|
||||
label="Style"
|
||||
value={mapStyle}
|
||||
onChange={e => setMapStyle(e.target.value as string)}>
|
||||
{mapStyleOptions.map(op => (
|
||||
<MenuItem key={op.value} value={op.value}>
|
||||
{op.label}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
{/* layer options from the object controller */}
|
||||
{props.layerOptions}
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => setStyles(false)}>Close</Button>
|
||||
</DialogActions>
|
||||
</ResponsiveDialog>
|
||||
);
|
||||
};
|
||||
|
||||
const onMouseEnter = useCallback(() => setMapCursor("pointer"), []);
|
||||
const onMouseLeave = useCallback(() => setMapCursor("auto"), []);
|
||||
|
||||
useEffect(() => {
|
||||
if (props.editorMode === "drawPolygon" || props.placingMarker) {
|
||||
setMapCursor("crosshair");
|
||||
} else {
|
||||
setMapCursor("auto");
|
||||
}
|
||||
}, [props.editorMode, props.placingMarker]);
|
||||
|
||||
useEffect(() => {
|
||||
if (props.objectGeoData) {
|
||||
let feats: Feature[] = [];
|
||||
props.objectGeoData.forEach(data => {
|
||||
let newFeature = GeometryMapping.geoJSON(data.geoShape, data.shapes, data.holes) as Feature;
|
||||
newFeature.id = data.objectKey;
|
||||
newFeature.properties = {
|
||||
title: data.title,
|
||||
objectKey: data.objectKey,
|
||||
fill: data.colour,
|
||||
lineWidth: data.geoShape === "LineString" ? 5 : 2,
|
||||
origin: data.origin
|
||||
};
|
||||
feats.push(newFeature);
|
||||
});
|
||||
let collection: FeatureCollection = {
|
||||
type: "FeatureCollection",
|
||||
features: feats
|
||||
};
|
||||
setGeoCollection(collection);
|
||||
}
|
||||
}, [props.objectGeoData]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
useEffect(() => {
|
||||
//add the measurementdata into the feature collection to be passed to our geo map layer
|
||||
if (props.measurementData) {
|
||||
let feats: Feature[] = [];
|
||||
props.measurementData.forEach(data => {
|
||||
let newFeature = GeometryMapping.geoJSON(data.geoShape, [
|
||||
shapeFromCoords(data.coordinates)
|
||||
]) as Feature;
|
||||
newFeature.id = data.key;
|
||||
newFeature.properties = {
|
||||
lineWidth: 5,
|
||||
origin: pond.DataOrigin.DATA_ORIGIN_ADAPTIVE,
|
||||
totalDist:
|
||||
getDistanceUnit() === pond.DistanceUnit.DISTANCE_UNIT_METERS
|
||||
? (data.totalDistanceKm / 1000).toFixed(2)
|
||||
: (data.totalDistanceKm * 3280.8398950131).toFixed(2)
|
||||
};
|
||||
feats.push(newFeature);
|
||||
});
|
||||
let collection: FeatureCollection = {
|
||||
type: "FeatureCollection",
|
||||
features: feats
|
||||
};
|
||||
setMeasurementCollection(collection);
|
||||
}
|
||||
}, [props.measurementData]);
|
||||
|
||||
const onUpdate = (event: any) => {
|
||||
let borders: pond.Shape[] = [];
|
||||
let holes: pond.Shape[] = [];
|
||||
let objectKey: string = "";
|
||||
if (event.action === "change_coordinates" && event.features) {
|
||||
let feature = event.features[0];
|
||||
if (feature) {
|
||||
let coords: any[] = feature.geometry.coordinates;
|
||||
objectKey = feature.id;
|
||||
if (feature.geometry.type === "Polygon") {
|
||||
coords.forEach((poly: any[], i) => {
|
||||
//the first shape is the border
|
||||
if (i === 0) {
|
||||
borders.push(shapeFromCoords(poly));
|
||||
} else {
|
||||
holes.push(shapeFromCoords(poly));
|
||||
}
|
||||
});
|
||||
} else if (feature.geometry.type === "LineString") {
|
||||
borders.push(shapeFromCoords(coords));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (props.editGeoCallback) {
|
||||
props.editGeoCallback(objectKey, borders, holes.length > 0 ? holes : undefined);
|
||||
}
|
||||
};
|
||||
|
||||
const onCreate = (event: any, objectToCut?: string, measurement?: boolean) => {
|
||||
let feature = event.features[0];
|
||||
console.log(feature)
|
||||
//if the string exist we are adding a hole to an existing object
|
||||
if (objectToCut) {
|
||||
if (props.cutHoleInPolygon) {
|
||||
props.cutHoleInPolygon(objectToCut, feature.geometry.coordinates, feature.geometry.type);
|
||||
}
|
||||
} else if (measurement) {
|
||||
if (props.addNewMeasurement) {
|
||||
props.addNewMeasurement(feature.geometry.coordinates, feature.geometry.type);
|
||||
}
|
||||
} else {
|
||||
if (props.addNewShape) {
|
||||
console.log("add new shape")
|
||||
props.addNewShape(feature.geometry.coordinates, feature.geometry.type);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const getEditableFeatures = () => {
|
||||
let editableFeatures: FeatureCollection = {
|
||||
type: "FeatureCollection",
|
||||
features: []
|
||||
};
|
||||
if (geoCollection) {
|
||||
geoCollection.features.forEach(feature => {
|
||||
//if the origin of the data comes from us (ie. a field/construction site with the adaptive origin)
|
||||
if (
|
||||
feature.properties &&
|
||||
feature.properties.origin === pond.DataOrigin.DATA_ORIGIN_ADAPTIVE
|
||||
) {
|
||||
editableFeatures.features.push(feature);
|
||||
}
|
||||
});
|
||||
}
|
||||
return editableFeatures;
|
||||
};
|
||||
|
||||
return startingView ? (
|
||||
<Box height="100%">
|
||||
{tools()}
|
||||
{mapStyleDialog()}
|
||||
<Map
|
||||
ref={mapRef}
|
||||
maxZoom={18}
|
||||
initialViewState={startingView}
|
||||
// {...viewport}
|
||||
mapStyle={mapStyle}
|
||||
onZoomEnd={e => {
|
||||
setCurrentZoom(e.viewState.zoom);
|
||||
}}
|
||||
onMouseEnter={() => {
|
||||
if (
|
||||
!props.editorMode ||
|
||||
!props.placingMarker ||
|
||||
props.editorMode === "none" ||
|
||||
!props.placingMarker
|
||||
)
|
||||
onMouseEnter();
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
if (
|
||||
!props.editorMode ||
|
||||
!props.placingMarker ||
|
||||
props.editorMode === "none" ||
|
||||
!props.placingMarker
|
||||
)
|
||||
onMouseLeave();
|
||||
}}
|
||||
interactiveLayerIds={layerIDs}
|
||||
// onMove={e => {
|
||||
// setViewport({
|
||||
// longitude: e.viewState.longitude,
|
||||
// latitude: e.viewState.latitude,
|
||||
// zoom: e.viewState.zoom
|
||||
// });
|
||||
// }}
|
||||
mapboxAccessToken={MAPBOX_TOKEN}
|
||||
cursor={mapCursor}
|
||||
onClick={e => {
|
||||
mapClick(e);
|
||||
}}
|
||||
doubleClickZoom={false}>
|
||||
{/* map controllers */}
|
||||
{MAPBOX_TOKEN && (
|
||||
<Geocoder
|
||||
mapboxAccessToken={MAPBOX_TOKEN}
|
||||
position="top-right"
|
||||
customEntries={props.customSearchEntries}
|
||||
resultFunction={props.geocoderResultFunction}
|
||||
customTransition={props.geocoderTransitionFunction}
|
||||
/>
|
||||
)}
|
||||
<DrawController
|
||||
featureCollection={getEditableFeatures()}
|
||||
editMode={props.editorMode}
|
||||
onCreate={onCreate}
|
||||
onUpdate={onUpdate}
|
||||
measurement={props.drawMeasurement}
|
||||
linePointLimit={props.linePointLimit}
|
||||
/>
|
||||
{/* markers */}
|
||||
{props.markerData && (
|
||||
<Markers
|
||||
markerData={props.markerData}
|
||||
dragOn={dragAllowed}
|
||||
groupSelect={groupSelect}
|
||||
mapZoomLevel={currentZoom}
|
||||
displayDetails={props.displayMarkerDetails}
|
||||
showMarkerTitle={props.displayMarkerTitles}
|
||||
/>
|
||||
)}
|
||||
|
||||
{watching && locationFound && (
|
||||
<Marker longitude={geoPosition.longitude} latitude={geoPosition.latitude}>
|
||||
<Box className={classes.geoDot} />
|
||||
</Marker>
|
||||
)}
|
||||
{haveHome && homePin && (
|
||||
<Marker
|
||||
longitude={homePin.longitude}
|
||||
latitude={homePin.latitude}
|
||||
draggable
|
||||
onDragEnd={homeDragEnd}
|
||||
offset={[0, -25]}>
|
||||
<Box
|
||||
className={classes.pin}
|
||||
style={{ pointerEvents: "none", width: 50, height: 50, background: "red" }}>
|
||||
<Box
|
||||
style={{
|
||||
transform: "rotate(-45deg)",
|
||||
width: 30,
|
||||
height: 30,
|
||||
marginTop: -10,
|
||||
marginLeft: -10,
|
||||
pointerEvents: "none"
|
||||
}}>
|
||||
<HomeIcon type="light" />
|
||||
</Box>
|
||||
</Box>
|
||||
</Marker>
|
||||
)}
|
||||
{/* map layers */}
|
||||
{geoCollection && (
|
||||
<GeoMapLayer
|
||||
objectCollection={geoCollection}
|
||||
measurementCollection={measurementCollection}
|
||||
showTitle={props.objectTitles}
|
||||
setInteractiveLayers={e => {
|
||||
setLayerIDs(e);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Map>
|
||||
</Box>
|
||||
) : (
|
||||
<Box>
|
||||
<LinearProgress />
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue