2021-05-16 08:54:03 +00:00
|
|
|
import React, { useEffect, useState, useCallback } from 'react';
|
2021-05-16 05:26:31 +00:00
|
|
|
import config from 'config';
|
2021-05-16 06:03:26 +00:00
|
|
|
import { GoogleMap, LoadScript } from '@react-google-maps/api';
|
|
|
|
|
import { Marker } from '@react-google-maps/api';
|
2021-05-16 18:13:57 +00:00
|
|
|
import { resolveReferences } from '@/_helpers/utils';
|
2021-05-17 15:33:07 +00:00
|
|
|
import { Autocomplete } from '@react-google-maps/api';
|
2021-05-16 05:26:31 +00:00
|
|
|
|
|
|
|
|
export const Map = function Map({
|
|
|
|
|
id,
|
|
|
|
|
width,
|
|
|
|
|
height,
|
|
|
|
|
component,
|
|
|
|
|
onComponentClick,
|
|
|
|
|
currentState,
|
|
|
|
|
onComponentOptionChanged,
|
2021-05-16 08:54:03 +00:00
|
|
|
onComponentOptionsChanged,
|
2021-05-16 05:26:31 +00:00
|
|
|
onEvent
|
|
|
|
|
}) {
|
2021-05-16 06:03:26 +00:00
|
|
|
const center = component.definition.properties.initialLocation.value;
|
2021-05-16 06:25:48 +00:00
|
|
|
const defaultMarkerValue = component.definition.properties.defaultMarkers.value;
|
2021-05-16 09:00:58 +00:00
|
|
|
|
|
|
|
|
let defaultMarkers = []
|
|
|
|
|
try {
|
2021-05-16 18:13:57 +00:00
|
|
|
defaultMarkers = defaultMarkerValue
|
2021-05-16 09:00:58 +00:00
|
|
|
} catch (err) { console.log(err); }
|
|
|
|
|
|
2021-05-16 08:56:18 +00:00
|
|
|
const addNewMarkersProp = component.definition.properties.addNewMarkers;
|
|
|
|
|
const canAddNewMarkers = addNewMarkersProp ? addNewMarkersProp.value : false;
|
2021-05-16 05:26:31 +00:00
|
|
|
|
2021-05-16 08:54:03 +00:00
|
|
|
const [gmap, setGmap] = useState(null);
|
2021-05-17 15:33:07 +00:00
|
|
|
const [autoComplete, setAutoComplete] = useState(null);
|
2021-05-16 18:13:57 +00:00
|
|
|
const [mapCenter, setMapCenter] = useState(resolveReferences(JSON.parse(center), currentState, false));
|
|
|
|
|
const [markers, setMarkers] = useState(resolveReferences(defaultMarkers, currentState, []));
|
2021-05-16 07:29:18 +00:00
|
|
|
|
|
|
|
|
useEffect(() => {
|
2021-05-16 18:13:57 +00:00
|
|
|
setMarkers(resolveReferences(defaultMarkers, currentState, false));
|
|
|
|
|
}, [currentState]);
|
2021-05-16 07:29:18 +00:00
|
|
|
|
2021-05-16 05:26:31 +00:00
|
|
|
const containerStyle = {
|
|
|
|
|
width,
|
|
|
|
|
height
|
|
|
|
|
};
|
|
|
|
|
|
2021-05-16 07:29:18 +00:00
|
|
|
function handleMapClick(e) {
|
2021-05-16 08:56:18 +00:00
|
|
|
if(!canAddNewMarkers) { return }
|
|
|
|
|
|
2021-05-16 07:29:18 +00:00
|
|
|
const lat = e.latLng.lat();
|
|
|
|
|
const lng = e.latLng.lng();
|
|
|
|
|
|
|
|
|
|
const newMarkers = markers;
|
|
|
|
|
newMarkers.push({ lat, lng });
|
|
|
|
|
setMarkers(newMarkers);
|
2021-05-16 10:11:55 +00:00
|
|
|
|
|
|
|
|
onComponentOptionChanged(component, 'markers', newMarkers).then(() => onEvent('onCreateMarker', { component }));
|
2021-05-16 07:29:18 +00:00
|
|
|
}
|
2021-05-16 05:26:31 +00:00
|
|
|
|
2021-05-16 08:54:03 +00:00
|
|
|
function handleBoundsChange() {
|
|
|
|
|
const mapBounds = gmap.getBounds();
|
|
|
|
|
|
|
|
|
|
const bounds = {
|
|
|
|
|
northEast: mapBounds.getNorthEast().toJSON(),
|
|
|
|
|
southWest: mapBounds.getSouthWest().toJSON(),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const newCenter = gmap.center.toJSON();
|
|
|
|
|
setMapCenter(newCenter);
|
|
|
|
|
|
|
|
|
|
onComponentOptionsChanged(component, [
|
|
|
|
|
['bounds', bounds],
|
|
|
|
|
['center', newCenter]
|
2021-05-16 09:09:24 +00:00
|
|
|
]).then(() => onEvent('onBoundsChange', { component }));
|
2021-05-16 08:54:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const onLoad = useCallback(
|
2021-05-16 18:13:57 +00:00
|
|
|
function onLoad(mapInstance) {
|
2021-05-16 08:54:03 +00:00
|
|
|
setGmap(mapInstance);
|
2021-05-16 18:13:57 +00:00
|
|
|
onComponentOptionsChanged(component, [
|
|
|
|
|
['center', mapInstance.center.toJSON()]
|
|
|
|
|
])
|
2021-05-16 08:54:03 +00:00
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
2021-05-16 10:11:55 +00:00
|
|
|
function handleMarkerClick(index) {
|
|
|
|
|
onComponentOptionChanged(component,
|
|
|
|
|
'selectedMarker', markers[index]
|
|
|
|
|
).then(() => onEvent('onMarkerClick', { component }));
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-17 15:33:07 +00:00
|
|
|
function onPlaceChanged() {
|
|
|
|
|
const location = autoComplete.getPlace().geometry.location.toJSON();
|
|
|
|
|
setMapCenter(location);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function onAutocompleteLoad(autocompleteInstance) {
|
|
|
|
|
setAutoComplete(autocompleteInstance);
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-16 05:26:31 +00:00
|
|
|
return (
|
2021-05-17 15:33:07 +00:00
|
|
|
<div style={{ width, height }} onClick={() => onComponentClick(id, component)} className="map-widget">
|
2021-05-16 05:26:31 +00:00
|
|
|
<LoadScript
|
|
|
|
|
googleMapsApiKey={config.GOOGLE_MAPS_API_KEY}
|
2021-05-17 15:33:07 +00:00
|
|
|
libraries={["places"]}
|
2021-05-16 05:26:31 +00:00
|
|
|
>
|
|
|
|
|
<GoogleMap
|
2021-05-16 08:54:03 +00:00
|
|
|
center={mapCenter}
|
2021-05-16 05:26:31 +00:00
|
|
|
mapContainerStyle={containerStyle}
|
|
|
|
|
zoom={12}
|
|
|
|
|
options={{
|
|
|
|
|
streetViewControl: false,
|
2021-05-16 08:54:03 +00:00
|
|
|
mapTypeControl: false,
|
|
|
|
|
draggable: true
|
2021-05-16 05:26:31 +00:00
|
|
|
}}
|
2021-05-16 08:54:03 +00:00
|
|
|
onLoad={onLoad}
|
2021-05-16 07:29:18 +00:00
|
|
|
onClick={handleMapClick}
|
2021-05-16 08:54:03 +00:00
|
|
|
onDragEnd={handleBoundsChange}
|
2021-05-16 05:26:31 +00:00
|
|
|
>
|
2021-05-17 15:33:07 +00:00
|
|
|
<Autocomplete
|
|
|
|
|
onPlaceChanged={onPlaceChanged}
|
|
|
|
|
onLoad={onAutocompleteLoad}
|
|
|
|
|
>
|
|
|
|
|
<input
|
|
|
|
|
type="text"
|
|
|
|
|
placeholder="Search"
|
|
|
|
|
className="place-search-input"
|
|
|
|
|
/>
|
|
|
|
|
</Autocomplete>
|
2021-05-16 18:13:57 +00:00
|
|
|
{Array.isArray(markers) &&
|
|
|
|
|
<>
|
|
|
|
|
{markers.map((marker, index) =>
|
|
|
|
|
<Marker
|
|
|
|
|
position={marker}
|
|
|
|
|
label={marker.label}
|
|
|
|
|
onClick={(e) => handleMarkerClick(index)}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
|
|
|
|
</>
|
|
|
|
|
}
|
2021-05-16 05:26:31 +00:00
|
|
|
</GoogleMap>
|
|
|
|
|
</LoadScript>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|