Api & Client: add an activity
This commit is contained in:
parent
efd076aa41
commit
c553a5a8d3
@ -95,6 +95,7 @@ def post_activity(auth_user_id):
|
|||||||
new_activity.ascent = gpx_data['uphill']
|
new_activity.ascent = gpx_data['uphill']
|
||||||
new_activity.max_speed = gpx_data['max_speed']
|
new_activity.max_speed = gpx_data['max_speed']
|
||||||
new_activity.ave_speed = gpx_data['average_speed']
|
new_activity.ave_speed = gpx_data['average_speed']
|
||||||
|
db.session.add(new_activity)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
response_object = {
|
response_object = {
|
||||||
|
19
mpwo_client/src/actions/activities.js
Normal file
19
mpwo_client/src/actions/activities.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import mpwoApi from '../mwpoApi/activities'
|
||||||
|
import { history } from '../index'
|
||||||
|
import { setError } from './index'
|
||||||
|
|
||||||
|
|
||||||
|
export function addActivity(form) {
|
||||||
|
return function(dispatch) {
|
||||||
|
return mpwoApi
|
||||||
|
.addActivity(form)
|
||||||
|
.then(ret => {
|
||||||
|
if (ret.status === 'created') {
|
||||||
|
history.push('/')
|
||||||
|
} else {
|
||||||
|
dispatch(setError(`activities: ${ret.message}`))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => dispatch(setError(`activities: ${error}`)))
|
||||||
|
}
|
||||||
|
}
|
114
mpwo_client/src/components/Activities/AddActivity.jsx
Normal file
114
mpwo_client/src/components/Activities/AddActivity.jsx
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { Helmet } from 'react-helmet'
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
|
||||||
|
import { addActivity } from '../../actions/activities'
|
||||||
|
import { getData } from '../../actions/index'
|
||||||
|
import { history } from '../../index'
|
||||||
|
|
||||||
|
|
||||||
|
class AddActivity extends React.Component {
|
||||||
|
componentDidMount() {
|
||||||
|
this.props.loadSports()
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { message, onAddSport, sports } = this.props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Helmet>
|
||||||
|
<title>mpwo - Add an activity</title>
|
||||||
|
</Helmet>
|
||||||
|
<br /><br />
|
||||||
|
{message && (
|
||||||
|
<code>{message}</code>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="container">
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-2" />
|
||||||
|
<div className="col-md-8">
|
||||||
|
<div className="card add-activity">
|
||||||
|
<h2 className="card-header text-center">
|
||||||
|
Add a sport
|
||||||
|
</h2>
|
||||||
|
<div className="card-body">
|
||||||
|
<form
|
||||||
|
encType="multipart/form-data"
|
||||||
|
method="post"
|
||||||
|
onSubmit={event => event.preventDefault()}
|
||||||
|
>
|
||||||
|
<div className="form-group">
|
||||||
|
<label>
|
||||||
|
Sport:
|
||||||
|
<select
|
||||||
|
className="form-control input-lg"
|
||||||
|
name="sport"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<option value="" />
|
||||||
|
{sports.map(sport => (
|
||||||
|
<option key={sport.id} value={sport.id}>
|
||||||
|
{sport.label}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className="form-group">
|
||||||
|
<label>
|
||||||
|
GPX file:
|
||||||
|
<input
|
||||||
|
accept=".gpx"
|
||||||
|
className="form-control input-lg"
|
||||||
|
name="gpxFile"
|
||||||
|
required
|
||||||
|
type="file"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
type="submit"
|
||||||
|
className="btn btn-primary btn-lg btn-block"
|
||||||
|
onClick={event => onAddSport(event)}
|
||||||
|
value="Submit"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="submit"
|
||||||
|
className="btn btn-secondary btn-lg btn-block"
|
||||||
|
onClick={() => history.go(-1)}
|
||||||
|
value="Cancel"
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="col-md-2" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(
|
||||||
|
state => ({
|
||||||
|
message: state.message,
|
||||||
|
sports: state.sports.data,
|
||||||
|
user: state.user,
|
||||||
|
}),
|
||||||
|
dispatch => ({
|
||||||
|
loadSports: () => {
|
||||||
|
dispatch(getData('sports'))
|
||||||
|
},
|
||||||
|
onAddSport: event => {
|
||||||
|
const form = new FormData()
|
||||||
|
form.append('file', event.target.form.gpxFile.files[0])
|
||||||
|
form.append(
|
||||||
|
'data', `{"sport_id": ${event.target.form.sport.value}}`
|
||||||
|
)
|
||||||
|
dispatch(addActivity(form))
|
||||||
|
},
|
||||||
|
})
|
||||||
|
)(AddActivity)
|
@ -56,3 +56,7 @@ input, textarea {
|
|||||||
margin: 1em;
|
margin: 1em;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.add-activity {
|
||||||
|
margin-top: 50px;
|
||||||
|
}
|
||||||
|
@ -3,6 +3,7 @@ import { Redirect, Route, Switch } from 'react-router-dom'
|
|||||||
|
|
||||||
import './App.css'
|
import './App.css'
|
||||||
import Admin from './Admin'
|
import Admin from './Admin'
|
||||||
|
import AddWorkout from './Activities/AddActivity'
|
||||||
import Dashboard from './Dashboard'
|
import Dashboard from './Dashboard'
|
||||||
import Logout from './User/Logout'
|
import Logout from './User/Logout'
|
||||||
import NavBar from './NavBar'
|
import NavBar from './NavBar'
|
||||||
@ -83,6 +84,7 @@ export default class App extends React.Component {
|
|||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
<Route exact path="/activities/add" component={AddWorkout} />
|
||||||
<Route path="/admin" component={Admin} />
|
<Route path="/admin" component={Admin} />
|
||||||
<Route component={NotFound} />
|
<Route component={NotFound} />
|
||||||
</Switch>
|
</Switch>
|
||||||
|
@ -33,6 +33,18 @@ function NavBar (props) {
|
|||||||
Dashboard
|
Dashboard
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
|
{props.user.isAuthenticated && (
|
||||||
|
<li className="nav-item">
|
||||||
|
<Link
|
||||||
|
className="nav-link"
|
||||||
|
to={{
|
||||||
|
pathname: '/activities/add',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Add a workout
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
{props.user.isAdmin && (
|
{props.user.isAdmin && (
|
||||||
<li className="nav-item">
|
<li className="nav-item">
|
||||||
<Link
|
<Link
|
||||||
|
18
mpwo_client/src/mwpoApi/activities.js
Normal file
18
mpwo_client/src/mwpoApi/activities.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { apiUrl } from '../utils'
|
||||||
|
|
||||||
|
export default class MpwoApi {
|
||||||
|
|
||||||
|
static addActivity(formData) {
|
||||||
|
const request = new Request(`${apiUrl}activities`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: new Headers({
|
||||||
|
Authorization: `Bearer ${window.localStorage.getItem('authToken')}`,
|
||||||
|
}),
|
||||||
|
body: formData,
|
||||||
|
})
|
||||||
|
return fetch(request)
|
||||||
|
.then(response => response.json())
|
||||||
|
.catch(error => error)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user