Skip to content

Instantly share code, notes, and snippets.

@YarikST
Created October 10, 2019 16:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save YarikST/67b124c817b70e4e5f8e26b52b802455 to your computer and use it in GitHub Desktop.
Save YarikST/67b124c817b70e4e5f8e26b52b802455 to your computer and use it in GitHub Desktop.
#More detali safepal and mobstar
google api key - https://developers.google.com/maps/documentation/javascript/get-api-key
doc - https://github.com/tomchentw/react-google-maps
//--authorization
import React from "react"
import { compose, withProps } from "recompose"
import { withScriptjs, withGoogleMap } from "react-google-maps"
export default Map =>
compose(
withProps({
googleMapURL: `https://maps.googleapis.com/maps/api/js?key=${document.querySelector('meta[name="google_maps_key"]').content}&v=3.exp&libraries=geometry,drawing,places`,
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: `600px` }} />,
mapElement: <div style={{ height: `100%` }} />,
}),
withScriptjs,
withGoogleMap
)((props) =>
<Map
defaultZoom={16}
defaultCenter = {{
lat: -1.2884,
lng: 36.8233
}}
{...props}
/>
)
//--track you location
import React from "react"
import { compose, withState, lifecycle } from "recompose"
export default CurrentLocation =>
compose(
withState('currentLocation', 'setCurrentLocation'),
lifecycle({
componentDidMount() {
console.log('CurrentLocation componentDidMount');
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition((position) =>{
let location = {
lat: position.coords.latitude,
lng: position.coords.longitude
};
this.props.setCurrentLocation(location);
}, ()=>{
console.log('Error: The Geolocation service failed.')
});
} else {
console.log('Error: Your browser doesn\'t support geolocation.')
}
}
})
)((props)=>
<CurrentLocation
{...props}
/>
)
//-- first component MapMarker
import React from "react"
import { compose, withProps, withHandlers, withState, lifecycle } from "recompose"
import { GoogleMap, Marker } from "react-google-maps"
import SearchBox from "react-google-maps/lib/components/places/SearchBox";
import GoogleApiWrapper from './api'
import GoogleCurrentLocationWrapper from './current-location'
const styles={
deleteMarker:{
position: 'relative',
top: 0,
left: 0,
zIndex: 5
}
}
const MapMarker = compose(
withState('bounds', 'setBounds'),
withState('zoom', 'setZoom', 16),
withHandlers(()=> {
const refs = {
map: undefined,
}
return {
onMapMounted: ()=> ref=> {
refs.map = ref
},
onMarkerMounted: () => ref => {
refs.marker = ref
},
onSearchBoxMounted: ()=> ref => {
refs.searchBox = ref;
},
onBoundsChanged: (props)=> () => {
props.setBounds(refs.map.getBounds())
},
onPlacesChanged: ()=> ()=> {
const places = refs.searchBox.getPlaces();
const bounds = new google.maps.LatLngBounds();
places.forEach(place => {
if (place.geometry.viewport) {
bounds.union(place.geometry.viewport)
} else {
bounds.extend(place.geometry.location)
}
});
refs.map.fitBounds(bounds);
refs.map.panToBounds(bounds);
},
onMapClick: (props)=> (event)=>{
const markerPosition = {
lat: event.latLng.lat(),
lng: event.latLng.lng()
};
console.log('onMapClick', markerPosition);
props.onChange && props.onChange(markerPosition);
if(props.onChangeAddress){
new google.maps.Geocoder().geocode({'location': event.latLng}, (results, status) => {
let address = '';
if (status === 'OK') {
if (results[0]) {
address = results[0].formatted_address;
} else {
console.log('No results found');
}
} else {
console.log('Geocoder failed due to: ' + status);
}
props.onChangeAddress(address);
})
}
},
deleteMarker: (props)=> ()=>{
props.onChange && props.onChange(null);
props.onChangeAddress && props.onChangeAddress('');
},
onLoad: (props)=> ()=>{
if(props.markerPosition || props.currentLocation){
const bounds = new google.maps.LatLngBounds();
bounds.extend(props.markerPosition || props.currentLocation);
refs.map.fitBounds(bounds);
refs.map.panToBounds(bounds);
}
}
}
}),
lifecycle({
componentDidMount() {
this.props.onLoad()
},
componentDidUpdate(prevProps, prevState){
((this.props.markerPosition && !prevProps.markerPosition) ||
(this.props.markerPosition && this.props.markerPosition.lat != prevProps.markerPosition.lat && this.props.markerPosition.lng != prevProps.markerPosition.lng) ||
(this.props.currentLocation && !prevProps.currentLocation && !this.props.markerPosition)
)
&& this.props.onLoad()
}
})
)((props)=>
<GoogleMap
ref={props.onMapMounted}
defaultCenter = {props.defaultCenter}
defaultZoom = {props.defaultZoom}
onBoundsChanged={props.onBoundsChanged}
zoom={props.zoom}
onClick={props.onMapClick}
>
<SearchBox
ref={props.onSearchBoxMounted}
bounds={props.bounds}
controlPosition={google.maps.ControlPosition.TOP_LEFT}
onPlacesChanged={props.onPlacesChanged}
>
<input
type="text"
placeholder="Search"
style={{
boxSizing: `border-box`,
border: `1px solid transparent`,
width: `240px`,
height: `32px`,
marginTop: `16px`,
padding: `0 12px`,
borderRadius: `3px`,
boxShadow: `0 2px 6px rgba(0, 0, 0, 0.3)`,
fontSize: `14px`,
outline: `none`,
textOverflow: `ellipses`,
color: 'black'
}}
/>
</SearchBox>
{
props.markerPosition != null ?
<Marker
ref={props.onMarkerMounted}
position={props.markerPosition}
/>
:
null
}
{
(props.markerPosition != null && props.onChange != null) ?
<input
style={styles.deleteMarker}
onClick={props.deleteMarker}
type="button"
value="Delete Marker"
/>
:
null
}
</GoogleMap>
)
export default compose(
GoogleApiWrapper,
GoogleCurrentLocationWrapper
)(MapMarker)
module ApplicationHelper
def meta_tag(tag, text)
content_for :"meta_#{tag}", text
end
def yield_meta_tag(tag, default_text='')
content_for?(:"meta_#{tag}") ? content_for(:"meta_#{tag}") : default_text
end
end
module ValidationHelper
UNICODE_TEXT = /\A([\p{L}\p{P}\d\s])+\z/
end
<% meta_tag :google_maps_key, "key" %>
<meta name='google_maps_key'
content='<%= yield_meta_tag(:google_maps_key, 'invalid_key') %>' />
validates :latitude,
numericality: {
message: "Latitude must be numericality",
allow_blank: true,
greater_than_or_equal_to: -90,
less_than_or_equal_to: 90,
}
validates :longitude,
numericality: {
message: "Longitude must be numericality",
allow_blank: true,
greater_than_or_equal_to: -180,
less_than_or_equal_to: 180,
}
validates :address,
presence: {message: 'Address can\'t be blank.', if: -> {latitude.present? && longitude.present?}},
length: {maximum: 100, message: "Address must be in range", allow_blank: true},
format: {with: ValidationHelper::UNICODE_TEXT, message: "Incorrect format of the address", allow_blank: true}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment