ToolJet/frontend/src/Editor/Components/Map/Map.jsx

176 lines
5.1 KiB
React
Raw Normal View History

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';
import { resolveReferences, resolveWidgetFieldValue } from '@/_helpers/utils';
import { Autocomplete } from '@react-google-maps/api';
import { darkModeStyles } from './styles';
2021-05-16 05:26:31 +00:00
export const Map = function Map({
id,
width,
height,
component,
darkMode,
2021-05-16 05:26:31 +00:00
onComponentClick,
currentState,
onComponentOptionChanged,
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;
let defaultMarkers = []
try {
2021-05-16 18:13:57 +00:00
defaultMarkers = defaultMarkerValue
} 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-17 15:49:18 +00:00
const canSearchProp = component.definition.properties.canSearch;
const canSearch = canSearchProp ? canSearchProp.value : false;
const widgetVisibility = component.definition.styles?.visibility?.value ?? true;
const disabledState = component.definition.styles?.disabledState?.value ?? false;
const parsedDisabledState = typeof disabledState !== 'boolean' ? resolveWidgetFieldValue(disabledState, currentState) : disabledState;
2021-08-30 11:43:05 +00:00
let parsedWidgetVisibility = widgetVisibility;
2021-08-31 16:36:31 +00:00
2021-08-30 11:43:05 +00:00
try {
parsedWidgetVisibility = resolveReferences(parsedWidgetVisibility, currentState, []);
} catch (err) { console.log(err); }
2021-05-17 15:49:18 +00:00
const [gmap, setGmap] = useState(null);
const [autoComplete, setAutoComplete] = useState(null);
2021-08-31 16:36:31 +00:00
const [mapCenter, setMapCenter] = useState(resolveReferences(center, currentState));
const [markers, setMarkers] = useState(resolveReferences(defaultMarkers, currentState));
2021-05-16 05:26:31 +00:00
const containerStyle = {
width,
height
};
function handleMapClick(e) {
2021-05-16 08:56:18 +00:00
if(!canAddNewMarkers) { return }
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 05:26:31 +00:00
function handleBoundsChange() {
const mapBounds = gmap.getBounds();
const bounds = {
2021-09-01 04:13:00 +00:00
northEast: mapBounds.getNorthEast()?.toJSON(),
southWest: mapBounds.getSouthWest()?.toJSON(),
}
2021-09-01 04:13:00 +00:00
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 }));
}
const onLoad = useCallback(
2021-05-16 18:13:57 +00:00
function onLoad(mapInstance) {
setGmap(mapInstance);
2021-05-16 18:13:57 +00:00
onComponentOptionsChanged(component, [
2021-09-01 04:13:00 +00:00
['center', mapInstance.center?.toJSON()]
2021-05-16 18:13:57 +00:00
])
}
)
2021-05-16 10:11:55 +00:00
function handleMarkerClick(index) {
onComponentOptionChanged(component,
'selectedMarker', markers[index]
).then(() => onEvent('onMarkerClick', { component }));
}
function onPlaceChanged() {
2021-09-01 04:13:00 +00:00
const location = autoComplete.getPlace().geometry.location?.toJSON();
setMapCenter(location);
handleBoundsChange();
}
function onAutocompleteLoad(autocompleteInstance) {
setAutoComplete(autocompleteInstance);
}
2021-08-31 16:36:31 +00:00
2021-05-16 05:26:31 +00:00
return (
<div data-disabled={parsedDisabledState} style={{ width, height, display:parsedWidgetVisibility ? '' : 'none' }} onClick={event => {event.stopPropagation(); onComponentClick(id, component)}} className="map-widget">
2021-09-02 15:20:42 +00:00
<div
className="map-center"
style={
{
right: width*0.5-18,
top: height*0.5-50
}
}>
<img
className="mx-2"
src="/assets/images/icons/marker.svg"
width="24"
height="64"
/>
</div>
2021-05-16 05:26:31 +00:00
<LoadScript
googleMapsApiKey={config.GOOGLE_MAPS_API_KEY}
libraries={["places"]}
2021-05-16 05:26:31 +00:00
>
<GoogleMap
center={mapCenter}
2021-05-16 05:26:31 +00:00
mapContainerStyle={containerStyle}
zoom={12}
options={{
styles: darkMode === true ? darkModeStyles : '',
2021-05-16 05:26:31 +00:00
streetViewControl: false,
mapTypeControl: false,
draggable: true
2021-05-16 05:26:31 +00:00
}}
onLoad={onLoad}
onClick={handleMapClick}
onDragEnd={handleBoundsChange}
2021-05-16 05:26:31 +00:00
>
2021-05-17 15:49:18 +00:00
{canSearch &&
<Autocomplete
onPlaceChanged={onPlaceChanged}
onLoad={onAutocompleteLoad}
>
<input
type="text"
placeholder="Search"
className="place-search-input"
/>
</Autocomplete>
2021-05-17 15:49:18 +00:00
}
{Array.isArray(markers) &&
2021-05-16 18:13:57 +00:00
<>
{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>
);
2021-08-31 16:36:31 +00:00
};