Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reorganize maps configuration #900

Merged
merged 5 commits into from
Aug 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env-template
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,4 @@ REACT_APP_ENV=production
#

REACT_APP_AVAILABILITY_ENABLED=true
REACT_APP_DEFAULT_SEARCHES_ENABLED=true
16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,22 @@ way to update this template, but currently, we follow a pattern:
* [fix] Fix window resize redirecting to search page with reusable map component
[#905](https://github.com/sharetribe/flex-template-web/pull/905)

* [change] Maps configuration has been restructured. The new
configuration is agnostic of the maps provider in use and works with
both Google Maps as well as Mapbox.

The fuzzy location circle has less configuration, but otherwise all
the previous settings can be set also in the new configuration. See
`config.js` for details.

The default location searches are now enabled in the
`.env-template`. For old installations, the
`REACT_APP_DEFAULT_SEARCHES_ENABLED` env var should be set to
`true`. The default searches can then be configured in
`src/default-location-searches.js`.

[#900](https://github.com/sharetribe/flex-template-web/pull/900)

## v1.4.0 2018-08-17
* [change] Put availability calendar behind a feature flag
[#902](https://github.com/sharetribe/flex-template-web/pull/902)
Expand Down
1 change: 1 addition & 0 deletions docs/env.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ them have defaults that work for development environment. For production deploys
| BASIC_AUTH_PASSWORD | Set to enable HTTP Basic Auth |
| REACT_APP_GOOGLE_ANALYTICS_ID | See: [Google Analytics](./analytics.md) |
| REACT_APP_AVAILABILITY_ENABLED | Enables availability calendar for listings. |
| REACT_APP_DEFAULT_SEARCHES_ENABLED | Enables default search suggestions in location autocomplete search input. |

## Defining configuration

Expand Down
33 changes: 3 additions & 30 deletions src/components/LocationAutocompleteInput/GeocoderGoogleMaps.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,12 @@
import React from 'react';
// import { types as sdkTypes } from '../../util/sdkLoader';
import classNames from 'classnames';
import { getPlacePredictions, getPlaceDetails, locationBounds } from '../../util/googleMaps';
import { userLocation } from '../../util/maps';
import css from './LocationAutocompleteInput.css';
import config from '../../config';

// const { LatLng: SDKLatLng, LatLngBounds: SDKLatLngBounds } = sdkTypes;
import css from './LocationAutocompleteInput.css';

export const CURRENT_LOCATION_ID = 'current-location';
const CURRENT_LOCATION_BOUNDS_DISTANCE = 1000; // meters

// A list of default predictions that can be shown when the user
// focuses on the autocomplete input without typing a search. This can
// be used to reduce typing and Geocoding API calls for common
// searches.
export const defaultPredictions = [
// Examples:
// Current user location from the browser geolocation API
// {
// id: CURRENT_LOCATION_ID,
// predictionPlace: {},
// },
// Helsinki
// {
// id: 'default-helsinki',
// predictionPlace: {
// address: 'Helsinki, Finland',
// origin: new SDKLatLng(60.16985, 24.93837),
// bounds: new SDKLatLngBounds(
// new SDKLatLng(60.29783, 25.25448),
// new SDKLatLng(59.92248, 24.78287)
// ),
// },
// },
];

// When displaying data from the Google Maps Places API, and
// attribution is required next to the results.
Expand Down Expand Up @@ -117,7 +90,7 @@ class GeocoderGoogleMaps {
return {
address: '',
origin: latlng,
bounds: locationBounds(latlng, CURRENT_LOCATION_BOUNDS_DISTANCE),
bounds: locationBounds(latlng, config.maps.search.currentLocationBoundsDistance),
};
});
}
Expand Down
28 changes: 1 addition & 27 deletions src/components/LocationAutocompleteInput/GeocoderMapbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import config from '../../config';
const { LatLng: SDKLatLng, LatLngBounds: SDKLatLngBounds } = sdkTypes;

export const CURRENT_LOCATION_ID = 'current-location';
const CURRENT_LOCATION_BOUNDS_DISTANCE = 1000; // meters

const locationBounds = (latlng, distance) => {
const bounds = new window.mapboxgl.LngLat(latlng.lng, latlng.lat).toBounds(distance);
Expand Down Expand Up @@ -34,31 +33,6 @@ const placeBounds = prediction => {
return null;
};

// A list of default predictions that can be shown when the user
// focuses on the autocomplete input without typing a search. This can
// be used to reduce typing and Geocoding API calls for common
// searches.
export const defaultPredictions = [
// Examples:
// Current user location from the browser geolocation API
// {
// id: CURRENT_LOCATION_ID,
// predictionPlace: {},
// },
// Helsinki
// {
// id: 'default-helsinki',
// predictionPlace: {
// address: 'Helsinki, Finland',
// origin: new SDKLatLng(60.16985, 24.93837),
// bounds: new SDKLatLngBounds(
// new SDKLatLng(60.29783, 25.25448),
// new SDKLatLng(59.92248, 24.78287)
// ),
// },
// },
];

export const GeocoderAttribution = () => null;

/**
Expand Down Expand Up @@ -140,7 +114,7 @@ class GeocoderMapbox {
return {
address: '',
origin: latlng,
bounds: locationBounds(latlng, CURRENT_LOCATION_BOUNDS_DISTANCE),
bounds: locationBounds(latlng, config.maps.search.currentLocationBoundsDistance),
};
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,21 @@ import { IconSpinner } from '../../components';
import { propTypes } from '../../util/types';
import IconHourGlass from './IconHourGlass';
import IconCurrentLocation from './IconCurrentLocation';
import Geocoder, {
GeocoderAttribution,
defaultPredictions,
CURRENT_LOCATION_ID,
} from './GeocoderGoogleMaps';
// import Geocoder, { GeocoderAttribution, defaultPredictions, CURRENT_LOCATION_ID } from './GeocoderMapbox';
import Geocoder, { GeocoderAttribution, CURRENT_LOCATION_ID } from './GeocoderGoogleMaps';
// import Geocoder, { GeocoderAttribution, CURRENT_LOCATION_ID } from './GeocoderMapbox';
import config from '../../config';

import css from './LocationAutocompleteInput.css';

// A list of default predictions that can be shown when the user
// focuses on the autocomplete input without typing a search. This can
// be used to reduce typing and Geocoding API calls for common
// searches.
export const defaultPredictions = (config.maps.search.suggestCurrentLocation
? [{ id: CURRENT_LOCATION_ID, predictionPlace: {} }]
: []
).concat(config.maps.search.defaults);

const DEBOUNCE_WAIT_TIME = 200;
const KEY_CODE_ARROW_UP = 38;
const KEY_CODE_ARROW_DOWN = 40;
Expand Down
27 changes: 17 additions & 10 deletions src/components/Map/DynamicGoogleMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import config from '../../config';
* It handles some of the google map initialization states.
*/
const DynamicGoogleMap = withGoogleMap(props => {
const { center, zoom, address, coordinatesConfig } = props;
const { center, zoom, address, mapsConfig } = props;

const { markerURI, anchorX, anchorY, width, height } = coordinatesConfig.customMarker || {};
const markerIcon = coordinatesConfig.customMarker
const { enabled, url, anchorX, anchorY, width, height } = mapsConfig.customMarker;
const markerIcon = enabled
? {
icon: {
url: markerURI,
url,

// The origin for this image is (0, 0).
origin: new window.google.maps.Point(0, 0),
Expand All @@ -27,8 +27,15 @@ const DynamicGoogleMap = withGoogleMap(props => {
const marker = <Marker position={center} {...markerIcon} title={address} />;

const circleProps = {
options: coordinatesConfig.circleOptions,
radius: coordinatesConfig.coordinateOffset,
options: {
fillColor: mapsConfig.fuzzy.circleColor,
fillOpacity: 0.2,
strokeColor: mapsConfig.fuzzy.circleColor,
strokeOpacity: 0.5,
strokeWeight: 1,
clickable: false,
},
radius: mapsConfig.fuzzy.offset,
center,
};

Expand Down Expand Up @@ -59,16 +66,16 @@ const DynamicGoogleMap = withGoogleMap(props => {
},
}}
>
{coordinatesConfig.fuzzy ? circle : marker}
{mapsConfig.fuzzy.enabled ? circle : marker}
</GoogleMap>
);
});

DynamicGoogleMap.defaultProps = {
address: '',
center: null,
zoom: config.coordinates.fuzzy ? config.coordinates.fuzzyDefaultZoomLevel : 11,
coordinatesConfig: config.coordinates,
zoom: config.maps.fuzzy.enabled ? config.maps.fuzzy.defaultZoomLevel : 11,
mapsConfig: config.maps,
};

DynamicGoogleMap.propTypes = {
Expand All @@ -78,7 +85,7 @@ DynamicGoogleMap.propTypes = {
lng: number.isRequired,
}).isRequired,
zoom: number,
coordinatesConfig: object,
mapsConfig: object,
};

export default DynamicGoogleMap;
48 changes: 22 additions & 26 deletions src/components/Map/DynamicMapboxMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,21 @@ import uniqueId from 'lodash/uniqueId';
import { circlePolyline } from '../../util/maps';
import config from '../../config';

const mapMarker = coordinatesConfig => {
const { customMarker } = coordinatesConfig;
if (customMarker) {
const mapMarker = mapsConfig => {
const { enabled, url, width, height } = mapsConfig.customMarker;
if (enabled) {
const element = document.createElement('div');
element.style.backgroundImage = `url(${customMarker.markerURI})`;
element.style.width = `${customMarker.width}px`;
element.style.height = `${customMarker.height}px`;
element.style.backgroundImage = `url(${url})`;
element.style.width = `${width}px`;
element.style.height = `${height}px`;
return new window.mapboxgl.Marker({ element });
} else {
return new window.mapboxgl.Marker();
}
};

const circleLayer = (center, coordinatesConfig, layerId) => {
const { fillColor, fillOpacity } = coordinatesConfig.circleOptions;
const path = circlePolyline(center, coordinatesConfig.coordinateOffset).map(([lat, lng]) => [
lng,
lat,
]);
const circleLayer = (center, mapsConfig, layerId) => {
const path = circlePolyline(center, mapsConfig.fuzzy.offset).map(([lat, lng]) => [lng, lat]);
return {
id: layerId,
type: 'fill',
Expand All @@ -37,8 +33,8 @@ const circleLayer = (center, coordinatesConfig, layerId) => {
},
},
paint: {
'fill-color': fillColor,
'fill-opacity': fillOpacity,
'fill-color': mapsConfig.fuzzy.circleColor,
'fill-opacity': 0.2,
},
};
};
Expand All @@ -59,7 +55,7 @@ class DynamicMapboxMap extends Component {
this.updateFuzzyCirclelayer = this.updateFuzzyCirclelayer.bind(this);
}
componentDidMount() {
const { center, zoom, coordinatesConfig } = this.props;
const { center, zoom, mapsConfig } = this.props;
const position = [center.lng, center.lat];

this.map = new window.mapboxgl.Map({
Expand All @@ -71,12 +67,12 @@ class DynamicMapboxMap extends Component {
});
this.map.addControl(new window.mapboxgl.NavigationControl(), 'top-left');

if (coordinatesConfig.fuzzy) {
if (mapsConfig.fuzzy.enabled) {
this.map.on('load', () => {
this.map.addLayer(circleLayer(center, coordinatesConfig, this.fuzzyLayerId));
this.map.addLayer(circleLayer(center, mapsConfig, this.fuzzyLayerId));
});
} else {
this.centerMarker = mapMarker(coordinatesConfig);
this.centerMarker = mapMarker(mapsConfig);
this.centerMarker.setLngLat(position).addTo(this.map);
}
}
Expand All @@ -92,7 +88,7 @@ class DynamicMapboxMap extends Component {
return;
}

const { center, zoom, coordinatesConfig } = this.props;
const { center, zoom, mapsConfig } = this.props;
const { lat, lng } = center;
const position = [lng, lat];

Expand All @@ -110,30 +106,30 @@ class DynamicMapboxMap extends Component {
}

// fuzzy circle change
if (coordinatesConfig.fuzzy && centerChanged) {
if (mapsConfig.fuzzy.enabled && centerChanged) {
if (this.map.loaded()) {
this.updateFuzzyCirclelayer();
} else {
this.map.on('load', this.updateFuzzyCirclelayer);
}
}

// NOTE: coordinatesConfig changes are not handled
// NOTE: mapsConfig changes are not handled
}
updateFuzzyCirclelayer() {
if (!this.map) {
// map already removed
return;
}
const { center, coordinatesConfig } = this.props;
const { center, mapsConfig } = this.props;
const { lat, lng } = center;
const position = [lng, lat];

this.map.removeLayer(this.fuzzyLayerId);

// We have to use a different layer id to avoid Mapbox errors
this.fuzzyLayerId = generateFuzzyLayerId();
this.map.addLayer(circleLayer(center, coordinatesConfig, this.fuzzyLayerId));
this.map.addLayer(circleLayer(center, mapsConfig, this.fuzzyLayerId));

this.map.setCenter(position);
}
Expand All @@ -150,8 +146,8 @@ class DynamicMapboxMap extends Component {
DynamicMapboxMap.defaultProps = {
address: '',
center: null,
zoom: config.coordinates.fuzzy ? config.coordinates.fuzzyDefaultZoomLevel : 11,
coordinatesConfig: config.coordinates,
zoom: config.maps.fuzzy.enabled ? config.maps.fuzzy.defaultZoomLevel : 11,
mapsConfig: config.maps,
};

DynamicMapboxMap.propTypes = {
Expand All @@ -161,7 +157,7 @@ DynamicMapboxMap.propTypes = {
lng: number.isRequired,
}).isRequired,
zoom: number,
coordinatesConfig: object,
mapsConfig: object,
};

export default DynamicMapboxMap;
18 changes: 12 additions & 6 deletions src/components/Map/Map.example.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,12 @@ export const WithObfuscatedLocation = {
obfuscatedCenter: new LatLng(60.16502999999999, 24.940064399999983),
address: 'Sharetribe',
zoom: 14,
coordinatesConfig: {
...config.coordinates,
fuzzy: true,
mapsConfig: {
...config.maps,
fuzzy: {
...config.maps.fuzzy,
enabled: true,
},
},
},
};
Expand All @@ -48,9 +51,12 @@ export const WithCircleLocation = {
center: new LatLng(60.16502999999999, 24.940064399999983),
obfuscatedCenter: obfuscatedCoordinates(new LatLng(60.16502999999999, 24.940064399999983)),
address: 'Sharetribe',
coordinatesConfig: {
...config.coordinates,
fuzzy: true,
mapsConfig: {
...config.maps,
fuzzy: {
...config.maps.fuzzy,
enabled: true,
},
},
},
};
Loading