Skip to content

Commit

Permalink
Document integration to supported map providers
Browse files Browse the repository at this point in the history
  • Loading branch information
Gnito committed Sep 14, 2018
1 parent 51adfc4 commit 02a7ecd
Show file tree
Hide file tree
Showing 2 changed files with 213 additions and 13 deletions.
159 changes: 146 additions & 13 deletions docs/google-maps.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
# Google Maps

The Flex template for web uses the Google Maps API for showing a map and in searching locations in
the search autocompletion. This document describes how to setup the API key for the API requests to
work properly.
The Flex template for web can use the Google Maps API for showing a map and in searching locations
in the search autocompletion. This document describes how to set up the API key for the API requests
to work properly.

> Note: before making the change to Google Map, you should consider if you are OK with their current
> pricing. There's a pricing calculator available in their
> [pricing page](https://cloud.google.com/maps-platform/pricing/)
## Generate a Google Maps API key

Expand All @@ -28,15 +32,144 @@ REACT_APP_GOOGLE_MAPS_API_KEY=my-key-here

## Setup common locations to reduce typing

The location autocomplete input in the landing page and the topbar can
be configured to have specific locations shown by default when the
user focuses on the input and hasn't yet typed in any searches. This
reduces the typing required for common searches, and also reduces the
need to use the Google Places geolocation API that much.
The location autocomplete-input in the landing page and the topbar can be configured to have
specific locations shown by default when the user focuses on the input and hasn't yet typed in any
searches. This reduces the typing required for common searches and also reduces the need to use
Google Map Places API that much.

To use default searches, another environment variable needs to be set:

```
REACT_APP_DEFAULT_SEARCHES_ENABLED=true
```

The default locations have been described in file:
[src/default-location-searches.js](../src/default-location-searches.js).

The same environment variable also shows "current location" suggestion, which will make the browser
to ask user's current location. This is a fast way to search listings nearby. You can specify
whether to use the current location from [config.js](../src/config.js). Search for variables:
`suggestCurrentLocation` and `currentLocationBoundsDistance`.

## Change components: use Google Map versions instead of Mapbox

### 1. Include Google Map script instead of Mapbox scripts

Mapbox related scripts can be removed from index.html and instead use Google Map script described in
comments.

_public/index.html:_

```html
<script src="%PUBLIC_URL%/static/scripts/mapbox/mapbox-sdk.min.js"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v0.47.0/mapbox-gl.css" rel="stylesheet" />
<script src="https://api.mapbox.com/mapbox-gl-js/v0.47.0/mapbox-gl.js"></script>
<script>
window.mapboxgl.accessToken = '%REACT_APP_MAPBOX_ACCESS_TOKEN%';
</script>
<!--
If Google Maps is used instead of Mapbox, you need to include Google's script instead:
<script src="https://maps.googleapis.com/maps/api/js?key=%REACT_APP_GOOGLE_MAPS_API_KEY%&libraries=places"></script>
-->
```

### 2. Searching with Google's geocoding API

Location search aka LocationAutocompleteInput should use Google Map specific geocoder. The correct
import is written to the comments of LocationAutocompleteInput component.

_src/components/LocationAutocompleteInput/LocationAutocompleteInputImpl.js:_

```js
import Geocoder, { GeocoderAttribution, CURRENT_LOCATION_ID } from './GeocoderMapbox';
// import Geocoder, { GeocoderAttribution, CURRENT_LOCATION_ID } from './GeocoderGoogleMaps';
```

Furthermore, Google Map states in their terms of service that Google logo needs to be visible when
using their geocoding service. It is available as a background image below the autocomplete
predictions. However, there needs to be enough padding for that logo. You can change the padding
through `marketplace.css`.

The default locations can be configured in
[src/components/LocationAutocompleteInput/GeocoderGoogleMaps.js](../src/components/LocationAutocompleteInput/GeocoderGoogleMaps.js).
_src/marketplace.css:_

```js
/* Google Maps needs 72px bottom padding to accommodate logo, Mapbox doesn't have one */
--locationAutocompleteBottomPadding: 8px;
```

### 3. Show correct map on ListingPage (Map component)

Google Map version (containing both static and dynamic maps) can be taken into use by importing
correct map subcomponent.

_src/components/Map/Map.js:_

```js
import { StaticMap, DynamicMap, isMapsLibLoaded } from './MapboxMap';
// import { StaticMap, DynamicMap, isMapsLibLoaded } from './GoogleMap';
```

### 4. SearchMap.js

The most complex change is happening in SearchPage. First, you need to import `SearchMapWithMapbox`
instead of `SearchMapWithGoogleMap`.

_src/components/SearchMap/SearchMap.js:_

Remove this:

```js
import SearchMapWithMapbox, {
LABEL_HANDLE,
INFO_CARD_HANDLE,
getMapBounds,
getMapCenter,
fitMapToBounds,
isMapsLibLoaded,
} from './SearchMapWithMapbox';
```

And add this instead:

```js
import SearchMapWithGoogleMap, {
LABEL_HANDLE,
INFO_CARD_HANDLE,
getMapBounds,
getMapCenter,
fitMapToBounds,
isMapsLibLoaded,
} from './SearchMapWithGoogleMap';
```

Then, in `render` method, you need to put `SearchMapWithGoogleMap` component into use by replacing
`SearchMapWithMapbox` which is defined inside `ReusableMapContainer`. The component with correct
props is already there in the comments:

```js
// Using Google Maps as map provider should use following component
// instead of SearchMapWithMapbox:
//
// <SearchMapWithGoogleMap
// containerElement={
// <div id="search-map-container" className={classes} onClick={this.onMapClicked} />
// }
// mapElement={<div className={mapRootClassName || css.mapRoot} />}
// bounds={bounds}
// center={center}
// location={location}
// infoCardOpen={infoCardOpen}
// listings={listings}
// activeListingId={activeListingId}
// mapComponentRefreshToken={this.state.mapReattachmentCount}
// createURLToListing={this.createURLToListing}
// onListingClicked={this.onListingClicked}
// onListingInfoCardClicked={this.onListingInfoCardClicked}
// onMapLoad={this.onMapLoadHandler}
// onMapMoveEnd={onMapMoveEnd}
// zoom={zoom}
// />
```

You can also setup a default location that asks the user's current
location. This will enable e.g. searching listings near the user. The
current location is configured in the same file.
The only extra step is to make `mapRootClassName` property available from `this.props` at the
beginning of the `render` method.
67 changes: 67 additions & 0 deletions docs/map-providers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Integrating to map providers

> After Google made significant pricing changes to their Google Map APIs, we pushed hard to reduce
> the number of calls to the Google Maps API. After careful consideration, we also decided that
> there needs to be an alternative map provider available for users of Flex Template for Web. We
> ended up to choose Mapbox since they have been a major innovator in the field.
## Setting up the Mapbox integration (the default map provider)

### 1. Generate a Mapbox access key

Sign up for a Mapbox and go to [account page](https://www.mapbox.com/account/). Then click
`Create access token`.

> Read more about
> [access tokens and consider rotating them](https://www.mapbox.com/help/how-access-tokens-work/).
### 2. Setup the application to use the access key

The application uses the `REACT_APP_MAPBOX_ACCESS_TOKEN` environment variable for the key value. For
local development, you can add the variable in the Gitignored `.env` file in the project root:

```
REACT_APP_MAPBOX_ACCESS_TOKEN=my-access-token-here
```

### 3. Setup common locations to reduce typing

The location autocomplete input in the landing page and the topbar can be configured to have
specific locations shown by default when the user focuses on the input and hasn't yet typed in any
searches. This reduces the typing required for common searches and also reduces the need to use
Mapbox geolocation API that much.

To use default searches, another environment variable needs to be set:

```
REACT_APP_DEFAULT_SEARCHES_ENABLED=true
```

The default locations have been described in file:
[src/default-location-searches.js](../src/default-location-searches.js).

The same environment variable also shows "current location" suggestion, which will make the browser
to ask user's current location. This is a fast way to search listings nearby. You can specify
whether to use the current location from [config.js](../src/config.js). Search for variables:
`suggestCurrentLocation` and `currentLocationBoundsDistance`.

### 4. Check rare default configurations

Mapbox geocoding API doesn't always return bounding boxes for locations. Without bounding box
SearchMap component can't adjust zoom level right for that particular place. Therefore there are
default bounding boxes defined to different place types in
[Mapbox specific geocoder](../src/components/LocationAutocompleteInput/GeocoderMapbox.js).

## Changing to other map providers

### How to change from Mapbox to Google Map

It is possible to use Google Map instead of the default map provider. Read more from
[Google Map setup guide](./google-maps.md)

### How to use other map providers

Our default map setup uses library called `mapbox-gl-js`. It is supported by quite many other map
providers too. So, as a first step, check if the map provider you are considering is supporting it -
if so, the change might be quite easy. However, if you change the map tile provider you should also
change geocoding API too (i.e. the API endpoint for `LocationAutocompleteInput` component).

0 comments on commit 02a7ecd

Please sign in to comment.