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

Added ability to use custom map styles #19

Merged
merged 4 commits into from
Jun 1, 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
2 changes: 1 addition & 1 deletion client/dist/js/main.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion client/dist/js/main.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion client/dist/js/map.js
Original file line number Diff line number Diff line change
@@ -1 +1 @@
webpackJsonp([1],{706:function(n,c){}},[706]);
webpackJsonp([1],{704:function(n,c){}},[704]);
2 changes: 1 addition & 1 deletion client/dist/js/map.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 11 additions & 11 deletions client/dist/js/vendor.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion client/dist/js/vendor.js.map

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions client/src/js/actions/ActionTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const ActionTypes = {
// settings fetching
FETCH_INFO_WINDOW: 'FETCH_INFO_WINDOW',
FETCH_LIST: 'FETCH_LIST',
FETCH_MAP_STYLE: 'FETCH_MAP_STYLE',

// Search action
SEARCH: 'SEARCH',
Expand All @@ -35,4 +36,9 @@ ActionTypes.FETCH_LIST_LOADING = `${ActionTypes.FETCH_LIST}_LOADING`;
ActionTypes.FETCH_LIST_SUCCESS = `${ActionTypes.FETCH_LIST}_SUCCESS`;
ActionTypes.FETCH_LIST_ERROR = `${ActionTypes.FETCH_LIST}_ERROR`;

// uses the base FETCH_MAP_STYLE to construct resulting actions (can't do this in the actual const)
ActionTypes.FETCH_MAP_STYLE_LOADING = `${ActionTypes.FETCH_MAP_STYLE}_LOADING`;
ActionTypes.FETCH_MAP_STYLE_SUCCESS = `${ActionTypes.FETCH_MAP_STYLE}_SUCCESS`;
ActionTypes.FETCH_MAP_STYLE_ERROR = `${ActionTypes.FETCH_MAP_STYLE}_ERROR`;

export default ActionTypes;
18 changes: 18 additions & 0 deletions client/src/js/actions/settingsActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,21 @@ export function fetchList() {
payload: axios.get(`${loc.protocol}//${loc.host}${path}`),
};
}

export function fetchMapStyle() {
const loc = window.location;
const path = dynamic_locator.mapStylePath;

// so we don't try to fetch the home page of the site
if (path === '') {
return {
type: ActionType.FETCH_MAP_STYLE_ERROR,
payload: ActionType.FETCH_MAP_STYLE_ERROR,
};
}

return {
type: ActionType.FETCH_MAP_STYLE,
payload: axios.get(`${loc.protocol}//${loc.host}/${path}`),
};
}
3 changes: 2 additions & 1 deletion client/src/js/components/Locator.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { connect } from 'react-redux';

import { fetchLocations } from 'actions/locationActions';
import { fetchInfoWindow, fetchList } from 'actions/settingsActions';
import { fetchInfoWindow, fetchList, fetchMapStyle } from 'actions/settingsActions';

import Search from 'components/search/SearchBar';
import MapContainer from 'components/map/MapContainer';
Expand All @@ -21,6 +21,7 @@ export class Locator extends Component {
const { dispatch } = this.props;
dispatch(fetchInfoWindow());
dispatch(fetchList());
dispatch(fetchMapStyle());
}

/**
Expand Down
24 changes: 24 additions & 0 deletions client/src/js/components/map/Map.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export function markers(props) {
key={marker.key}
position={marker.position}
defaultAnimation={marker.defaultAnimation}
defaultIcon={marker.defaultIcon}
onClick={() => props.onMarkerClick(marker)}
>
{props.current === marker.key && props.showCurrent && (
Expand Down Expand Up @@ -42,10 +43,17 @@ export function Map(props) {
lng: props.center.Lng,
}
}

const defaultOptions = {};
if (props.mapStyle !== null) {
defaultOptions.styles = props.mapStyle;
}

return (
<GoogleMap
defaultZoom={9}
defaultCenter={{ lat: props.defaultCenter.lat, lng: props.defaultCenter.lng }}
defaultOptions={defaultOptions}
{...opts}
>
{props.clusters === true ? <MarkerClusterer
Expand All @@ -60,8 +68,16 @@ export function Map(props) {
);
}

/**
*
* @type {{clusters: *, mapStyle: shim, center: (shim|*), defaultCenter: (shim|*)}}
*/
Map.propTypes = {
clusters: PropTypes.bool.isRequired,
mapStyle: PropTypes.oneOfType([
() => {return null;},
PropTypes.object
]),
center: PropTypes.shape({
Lat: PropTypes.number.isRequired,
Lng: PropTypes.number.isRequired,
Expand All @@ -72,4 +88,12 @@ Map.propTypes = {
}).isRequired,
};

/**
* Defines the default values of the props
* @type {{mapStyle: null}}
*/
Map.defaultProps = {
mapStyle: null,
};

export default withGoogleMap(Map);
21 changes: 17 additions & 4 deletions client/src/js/components/map/MapContainer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export class MapContainer extends Component {
* Generates an array of marker objects to use on the map
*/
getMarkers() {
const { locations, template, emailText, websiteText } = this.props;
const { locations, template, emailText, websiteText, markerImagePath } = this.props;
const markers = [];

const htmlToReactParser = new HtmlToReactParser();
Expand All @@ -50,6 +50,7 @@ export class MapContainer extends Component {
},
key: location.ID,
defaultAnimation: 2,
defaultIcon: markerImagePath,
infoContent: (
<div>
{htmlToReactParser.parse(template(loc))}
Expand Down Expand Up @@ -98,7 +99,7 @@ export class MapContainer extends Component {
}

render() {
const { current, showCurrent, clusters, center, defaultCenter } = this.props;
const { current, showCurrent, clusters, center, defaultCenter, mapStyle } = this.props;
return (
<div className="map-container">
<Map
Expand All @@ -108,6 +109,7 @@ export class MapContainer extends Component {
mapElement={
<div style={{ height: '100%' }} />
}
mapStyle={mapStyle}
markers={this.getMarkers()}
onMarkerClick={this.handleMarkerClick}
onMarkerClose={this.handleMarkerClose}
Expand All @@ -124,7 +126,7 @@ export class MapContainer extends Component {

/**
* Defines the prop types
* @type {{locations: *}}
* @type {{locations: shim, dispatch: *, current: *, showCurrent: *, clusters: *, template: *, mapStyle: shim, center: (shim|*), defaultCenter: (shim|*)}}
*/
MapContainer.propTypes = {
// eslint-disable-next-line react/forbid-prop-types
Expand All @@ -134,6 +136,14 @@ MapContainer.propTypes = {
showCurrent: PropTypes.bool.isRequired,
clusters: PropTypes.bool.isRequired,
template: PropTypes.func.isRequired,
mapStyle: PropTypes.oneOfType([
() => {return null;},
PropTypes.object,
]),
markerImagePath: PropTypes.oneOfType([
PropTypes.bool,
PropTypes.string,
]).isRequired,
center: PropTypes.shape({
Lat: PropTypes.number.isRequired,
Lng: PropTypes.number.isRequired,
Expand All @@ -146,10 +156,11 @@ MapContainer.propTypes = {

/**
* Defines the default values of the props
* @type {{locations: {edges: Array}}}
* @type {{locations: Array, mapStyle: null}}
*/
MapContainer.defaultProps = {
locations: [],
mapStyle: null,
};

/**
Expand All @@ -163,6 +174,8 @@ export function mapStateToProps(state) {
showCurrent: state.map.showCurrent,
clusters: state.settings.clusters,
template: state.settings.infoWindowTemplate,
mapStyle: state.settings.mapStyle,
markerImagePath: state.settings.markerImagePath,
locations: state.locations.locations,
center: state.map.center,
defaultCenter: state.settings.defaultCenter,
Expand Down
60 changes: 52 additions & 8 deletions client/src/js/reducers/settingsReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ const defaultState = {
loadedSettings: false,
loadedWindowTemplate: false,
loadedListTemplate: false,
loadedMapStyle: false,

infoWindowTemplate: null,
listTemplate: null,
mapStyle: null,
markerImagePath: false,

unit: 'm',

Expand Down Expand Up @@ -46,21 +49,29 @@ function settings() {
lng: dynamic_locator.defaultCenter.lng,
},
autocomplete: dynamic_locator.autocomplete,
markerImagePath: dynamic_locator.markerImagePath,
// defaultLimit: dynamic_locator.defaultLimit,
};
}

function didSettingsLoad(state = defaultState) {
const { loadedListTemplate, loadedWindowTemplate, loadedMapStyle } = state;
return loadedListTemplate === true &&
loadedWindowTemplate === true &&
loadedMapStyle === true;
}

/**
* The reducer for creating a part in the store for things like radius and categories
*/
export default function reducer(state = defaultState, action) {
switch (action.type) {
case ActionType.FETCH_INFO_WINDOW_SUCCESS: {
const { data } = action.payload;
let loaded = state.loadedSettings;
if (state.loadedListTemplate === true) {
loaded = true;
}
const loaded = didSettingsLoad({
...state,
loadedWindowTemplate: true,
});

return {
...state,
Expand All @@ -73,10 +84,10 @@ export default function reducer(state = defaultState, action) {

case ActionType.FETCH_LIST_SUCCESS: {
const { data } = action.payload;
let loaded = state.loadedSettings;
if (state.loadedWindowTemplate === true) {
loaded = true;
}
const loaded = didSettingsLoad({
...state,
loadedListTemplate: true,
});

return {
...state,
Expand All @@ -87,6 +98,39 @@ export default function reducer(state = defaultState, action) {
};
}

case ActionType.FETCH_MAP_STYLE_SUCCESS: {
const { data } = action.payload;
const loaded = didSettingsLoad({
...state,
loadedMapStyle: true,
});

return {
...state,
...settings(),
loadedSettings: loaded,
loadedMapStyle: true,
mapStyle: data,
};
}

case ActionType.FETCH_MAP_STYLE_ERROR: {
if (action.payload === ActionType.FETCH_MAP_STYLE_ERROR) {
const loaded = didSettingsLoad({
...state,
loadedMapStyle: true,
});

return {
...state,
...settings(),
loadedSettings: loaded,
loadedMapStyle: true,
};
}
return state;
}

default:
return state;
}
Expand Down
27 changes: 27 additions & 0 deletions client/src/tests/actions/settingsActions.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,30 @@ test('fetch window action is valid', () => {
payload: new Promise(() => {}),
});
});

/**
* Tests to see if what the fetch map style action returns is valid when no path is set
*/
test('fetch map style action is valid without path', () => {
window.dynamic_locator = {
mapStylePath: '',
};
expect(actions.fetchMapStyle()).toEqual({
type: ActionType.FETCH_MAP_STYLE_ERROR,
payload: ActionType.FETCH_MAP_STYLE_ERROR,
});
});

/**
* Tests to see if what the fetch map style action returns is valid when a path is set
*/
test('fetch map style action is valid with path', () => {
window.dynamic_locator = {
mapStylePath: 'test/style/path/mapStyle.json',
};
expect(actions.fetchMapStyle()).toEqual({
type: ActionType.FETCH_MAP_STYLE,
payload: new Promise(() => {}),
});
});

1 change: 1 addition & 0 deletions client/src/tests/components/Locator.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jest.setMock('../../js/actions/locationActions', locationActions);
// mock the actions (because of axios)
settingsActions.fetchInfoWindow = jest.fn();
settingsActions.fetchList = jest.fn();
settingsActions.fetchMapStyle = jest.fn();
jest.setMock('../../js/actions/settingsActions', settingsActions);

const dispatch = jest.fn();
Expand Down
4 changes: 4 additions & 0 deletions client/src/tests/components/map/MapContainer.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ test('Map container component should render', () => {
showCurrent={false}
clusters={false}
template={() => 'template'}
markerImagePath=""
center={{
Lat: 91,
Lng: 181,
Expand All @@ -49,6 +50,7 @@ test('Map container component should have markers', () => {
showCurrent={false}
clusters={false}
template={() => 'template'}
markerImagePath=""
locations={[
{
ID: 1,
Expand Down Expand Up @@ -92,6 +94,7 @@ test('Map container component should handle marker clicks', () => {
showCurrent={false}
clusters={false}
template={() => 'template'}
markerImagePath=""
center={{
Lat: 91,
Lng: 181,
Expand Down Expand Up @@ -122,6 +125,7 @@ test('Map container component should handle marker closings', () => {
showCurrent={false}
clusters={false}
template={() => 'template'}
markerImagePath=""
center={{
Lat: 91,
Lng: 181,
Expand Down
Loading