Activities: display gpx on map
This commit is contained in:
@ -2,6 +2,10 @@ import mpwoApi from '../mwpoApi/activities'
|
||||
import { history } from '../index'
|
||||
import { setError } from './index'
|
||||
|
||||
export const setGpx = gpxContent => ({
|
||||
type: 'SET_GPX',
|
||||
gpxContent,
|
||||
})
|
||||
|
||||
export function addActivity(form) {
|
||||
return function(dispatch) {
|
||||
@ -17,3 +21,18 @@ export function addActivity(form) {
|
||||
.catch(error => dispatch(setError(`activities: ${error}`)))
|
||||
}
|
||||
}
|
||||
|
||||
export function getActivityGpx(activityId) {
|
||||
return function(dispatch) {
|
||||
return mpwoApi
|
||||
.getActivityGpx(activityId)
|
||||
.then(ret => {
|
||||
if (ret.status === 'success') {
|
||||
dispatch(setGpx(ret.data.gpx))
|
||||
} else {
|
||||
dispatch(setError(`activities: ${ret.message}`))
|
||||
}
|
||||
})
|
||||
.catch(error => dispatch(setError(`activities: ${error}`)))
|
||||
}
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ class ActivityDisplay extends React.Component {
|
||||
Map
|
||||
</div>
|
||||
<div className="card-body">
|
||||
<ActivityMap />
|
||||
<ActivityMap activity={activity} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,30 +1,57 @@
|
||||
import React from 'react'
|
||||
import { Map, TileLayer } from 'react-leaflet'
|
||||
import { GeoJSON, Map, TileLayer } from 'react-leaflet'
|
||||
import { connect } from 'react-redux'
|
||||
|
||||
import { thunderforestApiKey } from '../../utils'
|
||||
import { getActivityGpx } from '../../actions/activities'
|
||||
import { getGeoJson, thunderforestApiKey } from '../../utils'
|
||||
|
||||
export default class ActivityMap extends React.Component {
|
||||
class ActivityMap extends React.Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context)
|
||||
this.state = {
|
||||
lat: 51.505,
|
||||
lng: -0.09,
|
||||
zoom: 13,
|
||||
zoom: 13,
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.props.loadActivityGpx(this.props.activity.id)
|
||||
}
|
||||
|
||||
render() {
|
||||
const position = [this.state.lat, this.state.lng]
|
||||
const { gpxContent } = this.props
|
||||
const { jsonData, bounds } = getGeoJson(gpxContent)
|
||||
|
||||
return (
|
||||
<Map center={position} zoom={this.state.zoom}>
|
||||
<TileLayer
|
||||
// eslint-disable-next-line max-len
|
||||
attribution='© <a href="http://www.thunderforest.com/">Thunderforest</a>, © <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
||||
url="https://{s}.tile.thunderforest.com/outdoors/{z}/{x}/{y}.png"
|
||||
apikey={thunderforestApiKey}
|
||||
/>
|
||||
</Map>
|
||||
<div>
|
||||
{jsonData && (
|
||||
<Map
|
||||
zoom={this.state.zoom}
|
||||
bounds={bounds}
|
||||
boundsOptions={{ padding: [50, 50] }}
|
||||
>
|
||||
<TileLayer
|
||||
// eslint-disable-next-line max-len
|
||||
attribution='© <a href="http://www.thunderforest.com/">Thunderforest</a>, © <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
||||
// eslint-disable-next-line max-len
|
||||
url={`https://{s}.tile.thunderforest.com/outdoors/{z}/{x}/{y}.png?apikey=${thunderforestApiKey}`}
|
||||
/>
|
||||
<GeoJSON data={jsonData} />
|
||||
</Map>
|
||||
)}
|
||||
</div>
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(
|
||||
state => ({
|
||||
gpxContent: state.gpx
|
||||
}),
|
||||
dispatch => ({
|
||||
loadActivityGpx: activityId => {
|
||||
dispatch(getActivityGpx(activityId))
|
||||
},
|
||||
})
|
||||
)(ActivityMap)
|
||||
|
@ -15,4 +15,16 @@ export default class MpwoApi {
|
||||
.catch(error => error)
|
||||
}
|
||||
|
||||
static getActivityGpx(activityId) {
|
||||
const request = new Request(`${apiUrl}activities/${activityId}/gpx`, {
|
||||
method: 'GET',
|
||||
headers: new Headers({
|
||||
Authorization: `Bearer ${window.localStorage.getItem('authToken')}`,
|
||||
}),
|
||||
})
|
||||
return fetch(request)
|
||||
.then(response => response.json())
|
||||
.catch(error => error)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -66,6 +66,15 @@ const formProfile = (state = initial.formProfile, action) => {
|
||||
}
|
||||
}
|
||||
|
||||
const gpx = (state = initial.gpx, action) => {
|
||||
switch (action.type) {
|
||||
case 'SET_GPX':
|
||||
return action.gpxContent
|
||||
default:
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
const message = (state = initial.message, action) => {
|
||||
switch (action.type) {
|
||||
case 'AUTH_ERROR':
|
||||
@ -144,6 +153,7 @@ const reducers = combineReducers({
|
||||
activities,
|
||||
formData,
|
||||
formProfile,
|
||||
gpx,
|
||||
message,
|
||||
messages,
|
||||
router: routerReducer,
|
||||
|
@ -41,6 +41,8 @@ export default {
|
||||
activities: {
|
||||
...emptyData,
|
||||
},
|
||||
// check if storing gpx content is OK
|
||||
gpx: null,
|
||||
sports: {
|
||||
...emptyData,
|
||||
}
|
||||
|
@ -1,3 +1,6 @@
|
||||
import togeojson from '@mapbox/togeojson'
|
||||
import bbox from 'geojson-bbox'
|
||||
|
||||
export const apiUrl = `${process.env.REACT_APP_API_URL}/api/`
|
||||
export const thunderforestApiKey = `${
|
||||
process.env.REACT_APP_THUNDERFOREST_API_KEY
|
||||
@ -13,3 +16,18 @@ export function generateIds(arr) {
|
||||
return obj
|
||||
})
|
||||
}
|
||||
|
||||
export function getGeoJson(gpxContent) {
|
||||
let jsonData, bboxCorners
|
||||
let bounds = [[0, 0], [0, 0]]
|
||||
if (gpxContent) {
|
||||
const gpx = new DOMParser().parseFromString(gpxContent, 'text/xml')
|
||||
jsonData = togeojson.gpx(gpx)
|
||||
bboxCorners = bbox(jsonData)
|
||||
bounds = [
|
||||
[bboxCorners[1], bboxCorners[0]],
|
||||
[bboxCorners[3], bboxCorners[2]]
|
||||
]
|
||||
}
|
||||
return { jsonData, bounds }
|
||||
}
|
||||
|
Reference in New Issue
Block a user