Client: upload a zip archive containing gpx files
This commit is contained in:
parent
373d20f0b7
commit
bddb86d765
@ -2,7 +2,7 @@ import mpwoGenericApi from '../mwpoApi'
|
||||
import mpwoApi from '../mwpoApi/activities'
|
||||
import { history } from '../index'
|
||||
import { formatChartData } from '../utils'
|
||||
import { setError } from './index'
|
||||
import { setError, setLoading } from './index'
|
||||
|
||||
export const pushActivities = activities => ({
|
||||
type: 'PUSH_ACTIVITIES',
|
||||
@ -23,10 +23,17 @@ export const addActivity = form => dispatch => mpwoApi
|
||||
.addActivity(form)
|
||||
.then(ret => {
|
||||
if (ret.status === 'created') {
|
||||
history.push(`/activities/${ret.data.activities[0].id}`)
|
||||
if (ret.data.activities.length === 0) {
|
||||
dispatch(setError('activities: no correct file'))
|
||||
} else if (ret.data.activities.length === 1) {
|
||||
history.push(`/activities/${ret.data.activities[0].id}`)
|
||||
} else { // ret.data.activities.length > 1
|
||||
history.push('/')
|
||||
}
|
||||
} else {
|
||||
dispatch(setError(`activities: ${ret.message}`))
|
||||
}
|
||||
dispatch(setLoading())
|
||||
})
|
||||
.catch(error => dispatch(setError(`activities: ${error}`)))
|
||||
|
||||
@ -97,6 +104,7 @@ export const editActivity = form => dispatch => mpwoGenericApi
|
||||
} else {
|
||||
dispatch(setError(`activities: ${ret.message}`))
|
||||
}
|
||||
dispatch(setLoading())
|
||||
})
|
||||
.catch(error => dispatch(setError(`activities: ${error}`)))
|
||||
|
||||
|
@ -13,6 +13,10 @@ export const setError = message => ({
|
||||
message,
|
||||
})
|
||||
|
||||
export const setLoading = () => ({
|
||||
type: 'SET_LOADING',
|
||||
})
|
||||
|
||||
export const getData = (target, id = null, data = null) => dispatch => {
|
||||
if (id !== null && isNaN(id)) {
|
||||
return dispatch(setError(target, `${target}: Incorrect id`))
|
||||
|
@ -1,10 +1,11 @@
|
||||
import React from 'react'
|
||||
import { Helmet } from 'react-helmet'
|
||||
import { connect } from 'react-redux'
|
||||
|
||||
import FormWithGpx from './ActivityForms/FormWithGpx'
|
||||
import FormWithoutGpx from './ActivityForms/FormWithoutGpx'
|
||||
|
||||
export default class ActivityAddEdit extends React.Component {
|
||||
class ActivityAddEdit extends React.Component {
|
||||
constructor(props, context) {
|
||||
super(props, context)
|
||||
this.state = {
|
||||
@ -21,7 +22,7 @@ export default class ActivityAddEdit extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { activity, message, sports } = this.props
|
||||
const { activity, loading, message, sports } = this.props
|
||||
const { withGpx } = this.state
|
||||
return (
|
||||
<div>
|
||||
@ -59,6 +60,7 @@ export default class ActivityAddEdit extends React.Component {
|
||||
<input
|
||||
type="radio"
|
||||
name="withGpx"
|
||||
disabled={loading}
|
||||
checked={withGpx}
|
||||
onChange={event => this.handleRadioChange(event)}
|
||||
/>
|
||||
@ -70,6 +72,7 @@ export default class ActivityAddEdit extends React.Component {
|
||||
<input
|
||||
type="radio"
|
||||
name="withoutGpx"
|
||||
disabled={loading}
|
||||
checked={!withGpx}
|
||||
onChange={event => this.handleRadioChange(event)}
|
||||
/>
|
||||
@ -96,3 +99,8 @@ export default class ActivityAddEdit extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default connect(
|
||||
state => ({
|
||||
loading: state.loading
|
||||
}),
|
||||
)(ActivityAddEdit)
|
||||
|
@ -1,12 +1,15 @@
|
||||
import React from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
|
||||
import { setLoading } from '../../../actions/index'
|
||||
import { addActivity, editActivity } from '../../../actions/activities'
|
||||
import { history } from '../../../index'
|
||||
|
||||
|
||||
function FormWithGpx (props) {
|
||||
const { activity, onAddActivity, onEditActivity, sports } = props
|
||||
const {
|
||||
activity, loading, onAddActivity, onEditActivity, sports
|
||||
} = props
|
||||
const sportId = activity ? activity.sport_id : ''
|
||||
return (
|
||||
<form
|
||||
@ -20,6 +23,7 @@ function FormWithGpx (props) {
|
||||
<select
|
||||
className="form-control input-lg"
|
||||
defaultValue={sportId}
|
||||
disabled={loading}
|
||||
name="sport"
|
||||
required
|
||||
>
|
||||
@ -39,6 +43,7 @@ function FormWithGpx (props) {
|
||||
<input
|
||||
name="title"
|
||||
defaultValue={activity ? activity.title : ''}
|
||||
disabled={loading}
|
||||
className="form-control input-lg"
|
||||
/>
|
||||
</label>
|
||||
@ -46,10 +51,12 @@ function FormWithGpx (props) {
|
||||
) : (
|
||||
<div className="form-group">
|
||||
<label>
|
||||
GPX file:
|
||||
<strong>gpx</strong> file or <strong>zip</strong>{' '}
|
||||
file containing <strong>gpx</strong> (no folder inside):
|
||||
<input
|
||||
accept=".gpx"
|
||||
accept=".gpx, .zip"
|
||||
className="form-control input-lg"
|
||||
disabled={loading}
|
||||
name="gpxFile"
|
||||
required
|
||||
type="file"
|
||||
@ -57,30 +64,39 @@ function FormWithGpx (props) {
|
||||
</label>
|
||||
</div>
|
||||
)}
|
||||
<input
|
||||
type="submit"
|
||||
className="btn btn-primary btn-lg btn-block"
|
||||
onClick={
|
||||
event => activity
|
||||
? onEditActivity(event, activity)
|
||||
: onAddActivity(event)
|
||||
}
|
||||
value="Submit"
|
||||
/>
|
||||
<input
|
||||
type="submit"
|
||||
className="btn btn-secondary btn-lg btn-block"
|
||||
onClick={() => history.go(-1)}
|
||||
value="Cancel"
|
||||
/>
|
||||
{loading ? (
|
||||
<div className="loader" />
|
||||
) : (
|
||||
<div>
|
||||
<input
|
||||
type="submit"
|
||||
className="btn btn-primary btn-lg btn-block"
|
||||
onClick={
|
||||
event => activity
|
||||
? onEditActivity(event, activity)
|
||||
: onAddActivity(event)
|
||||
}
|
||||
value="Submit"
|
||||
/>
|
||||
<input
|
||||
type="submit"
|
||||
className="btn btn-secondary btn-lg btn-block"
|
||||
onClick={() => history.go(-1)}
|
||||
value="Cancel"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
export default connect(
|
||||
() => ({ }),
|
||||
state => ({
|
||||
loading: state.loading
|
||||
}),
|
||||
dispatch => ({
|
||||
onAddActivity: e => {
|
||||
dispatch(setLoading())
|
||||
const form = new FormData()
|
||||
form.append('file', e.target.form.gpxFile.files[0])
|
||||
form.append(
|
||||
@ -89,6 +105,7 @@ export default connect(
|
||||
dispatch(addActivity(form))
|
||||
},
|
||||
onEditActivity: (e, activity) => {
|
||||
dispatch(setLoading())
|
||||
dispatch(editActivity({
|
||||
id: activity.id,
|
||||
sport_id: +e.target.form.sport.value,
|
||||
|
@ -173,3 +173,18 @@ input, textarea {
|
||||
.unlink {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.loader {
|
||||
animation: spin 2s linear infinite;
|
||||
border: 16px solid #f3f3f3;
|
||||
border-top: 16px solid #3498db;
|
||||
border-radius: 50%;
|
||||
height: 120px;
|
||||
margin-left: 41%;
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
@ -93,6 +93,15 @@ const gpx = (state = initial.gpx, action) => {
|
||||
}
|
||||
}
|
||||
|
||||
const loading = (state = initial.loading, action) => {
|
||||
switch (action.type) {
|
||||
case 'SET_LOADING':
|
||||
return !state
|
||||
default:
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
const message = (state = initial.message, action) => {
|
||||
switch (action.type) {
|
||||
case 'AUTH_ERROR':
|
||||
@ -176,6 +185,7 @@ const reducers = combineReducers({
|
||||
formData,
|
||||
formProfile,
|
||||
gpx,
|
||||
loading,
|
||||
message,
|
||||
messages,
|
||||
records,
|
||||
|
@ -44,6 +44,7 @@ export default {
|
||||
chartData: [],
|
||||
// check if storing gpx content is OK
|
||||
gpx: null,
|
||||
loading: false,
|
||||
records: {
|
||||
...emptyData,
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user