Merge branch 'master' into v0.3.0
Conflicts: docs/objects.inv docs/searchindex.js fittrackee_api/poetry.lock fittrackee_api/pyproject.toml fittrackee_client/src/actions/index.js fittrackee_client/src/components/App.jsx fittrackee_client/src/utils/index.js
This commit is contained in:
@ -52,7 +52,10 @@ export const addActivity = form => dispatch =>
|
||||
}
|
||||
dispatch(setLoading(false))
|
||||
})
|
||||
.catch(error => dispatch(setError(`activities|${error}`)))
|
||||
.catch(error => {
|
||||
dispatch(setLoading(false))
|
||||
dispatch(setError(`activities|${error}`))
|
||||
})
|
||||
|
||||
export const addActivityWithoutGpx = form => dispatch =>
|
||||
FitTrackeeGenericApi.addData('activities/no_gpx', form)
|
||||
@ -154,7 +157,10 @@ export const editActivity = form => dispatch =>
|
||||
}
|
||||
dispatch(setLoading(false))
|
||||
})
|
||||
.catch(error => dispatch(setError(`activities|${error}`)))
|
||||
.catch(error => {
|
||||
dispatch(setLoading(false))
|
||||
dispatch(setError(`activities|${error}`))
|
||||
})
|
||||
|
||||
export const getMoreActivities = params => dispatch =>
|
||||
FitTrackeeGenericApi.getData('activities', params)
|
||||
|
@ -28,14 +28,15 @@ export const updateSportsData = data => ({
|
||||
type: 'UPDATE_SPORT_DATA',
|
||||
data,
|
||||
})
|
||||
|
||||
export const getOrUpdateData = (
|
||||
action,
|
||||
target,
|
||||
data,
|
||||
canDispatch = true
|
||||
) => dispatch => {
|
||||
dispatch(setLoading(true))
|
||||
if (data && data.id && isNaN(data.id)) {
|
||||
dispatch(setLoading(false))
|
||||
return dispatch(setError(`${target}|Incorrect id`))
|
||||
}
|
||||
dispatch(setError(''))
|
||||
@ -50,8 +51,12 @@ export const getOrUpdateData = (
|
||||
} else {
|
||||
dispatch(setError(`${target}|${ret.message || ret.status}`))
|
||||
}
|
||||
dispatch(setLoading(false))
|
||||
})
|
||||
.catch(error => {
|
||||
dispatch(setLoading(false))
|
||||
dispatch(setError(`${target}|${error}`))
|
||||
})
|
||||
.catch(error => dispatch(setError(`${target}|${error}`)))
|
||||
}
|
||||
|
||||
export const addData = (target, data) => dispatch =>
|
||||
|
@ -7,7 +7,7 @@ import { getDateWithTZ } from '../../utils'
|
||||
|
||||
export default class ActivitiesList extends React.PureComponent {
|
||||
render() {
|
||||
const { activities, sports, t, user } = this.props
|
||||
const { activities, loading, sports, t, user } = this.props
|
||||
return (
|
||||
<div className="card activity-card">
|
||||
<div className="card-body">
|
||||
@ -24,7 +24,8 @@ export default class ActivitiesList extends React.PureComponent {
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{sports &&
|
||||
{!loading &&
|
||||
sports &&
|
||||
activities.map((activity, idx) => (
|
||||
// eslint-disable-next-line react/no-array-index-key
|
||||
<tr key={idx}>
|
||||
@ -61,6 +62,7 @@ export default class ActivitiesList extends React.PureComponent {
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
{loading && <div className="loader" />}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
@ -38,6 +38,7 @@ class Activities extends React.Component {
|
||||
render() {
|
||||
const {
|
||||
activities,
|
||||
loading,
|
||||
loadActivities,
|
||||
loadMoreActivities,
|
||||
message,
|
||||
@ -71,6 +72,7 @@ class Activities extends React.Component {
|
||||
<div className="col-md-9 activities-result">
|
||||
<ActivitiesList
|
||||
activities={activities}
|
||||
loading={loading}
|
||||
sports={sports}
|
||||
t={t}
|
||||
user={user}
|
||||
@ -101,6 +103,7 @@ export default withTranslation()(
|
||||
connect(
|
||||
state => ({
|
||||
activities: state.activities.data,
|
||||
loading: state.loading,
|
||||
message: state.message,
|
||||
sports: state.sports.data,
|
||||
user: state.user,
|
||||
|
@ -364,12 +364,12 @@ label {
|
||||
|
||||
.loader {
|
||||
animation: spin 2s linear infinite;
|
||||
border: 16px solid #f3f3f3;
|
||||
border-top: 16px solid #3498db;
|
||||
border: 8px solid #f3f3f3;
|
||||
border-top: 8px solid #3498db;
|
||||
border-radius: 50%;
|
||||
height: 120px;
|
||||
height: 60px;
|
||||
margin-left: 41%;
|
||||
width: 120px;
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
import { Redirect, Route, Switch } from 'react-router-dom'
|
||||
import { Route, Switch } from 'react-router-dom'
|
||||
|
||||
import './App.css'
|
||||
import Admin from './Admin'
|
||||
@ -16,7 +16,6 @@ import ProfileEdit from './User/ProfileEdit'
|
||||
import Statistics from './Statistics'
|
||||
import UserForm from './User/UserForm'
|
||||
import { getAppData } from '../actions/application'
|
||||
import { isLoggedIn } from '../utils'
|
||||
|
||||
class App extends React.Component {
|
||||
constructor(props) {
|
||||
@ -32,59 +31,24 @@ class App extends React.Component {
|
||||
<div className="App">
|
||||
<NavBar />
|
||||
<Switch>
|
||||
<Route
|
||||
exact
|
||||
path="/"
|
||||
render={() =>
|
||||
isLoggedIn() ? <Dashboard /> : <Redirect to="/login" />
|
||||
}
|
||||
/>
|
||||
<Route exact path="/" component={Dashboard} />
|
||||
<Route
|
||||
exact
|
||||
path="/register"
|
||||
render={() =>
|
||||
isLoggedIn() ? (
|
||||
<Redirect to="/" />
|
||||
) : (
|
||||
<UserForm formType={'register'} />
|
||||
)
|
||||
}
|
||||
render={() => <UserForm formType={'register'} />}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/login"
|
||||
render={() =>
|
||||
isLoggedIn() ? (
|
||||
<Redirect to="/" />
|
||||
) : (
|
||||
<UserForm formType={'login'} />
|
||||
)
|
||||
}
|
||||
render={() => <UserForm formType={'login'} />}
|
||||
/>
|
||||
<Route exact path="/logout" component={Logout} />
|
||||
<Route
|
||||
exact
|
||||
path="/profile/edit"
|
||||
render={() =>
|
||||
isLoggedIn() ? <ProfileEdit /> : <UserForm formType={'login'} />
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
path="/profile"
|
||||
render={() =>
|
||||
isLoggedIn() ? <Profile /> : <UserForm formType={'login'} />
|
||||
}
|
||||
/>
|
||||
<Route exact path="/profile/edit" component={ProfileEdit} />
|
||||
<Route exact path="/profile" component={Profile} />
|
||||
<Route exact path="/activities/history" component={Activities} />
|
||||
<Route exact path="/activities/statistics" component={Statistics} />
|
||||
<Route path="/activities" component={Activity} />
|
||||
<Route
|
||||
path="/admin"
|
||||
render={() =>
|
||||
isLoggedIn() ? <Admin /> : <UserForm formType={'login'} />
|
||||
}
|
||||
/>
|
||||
<Route path="/admin" component={Admin} />
|
||||
<Route component={NotFound} />
|
||||
</Switch>
|
||||
<Footer />
|
||||
|
@ -13,8 +13,9 @@ import Root from './components/Root'
|
||||
import registerServiceWorker from './registerServiceWorker'
|
||||
import createRootReducer from './reducers'
|
||||
import { loadProfile } from './actions/user'
|
||||
import { historyEnhancer } from './utils/history'
|
||||
|
||||
export const history = createBrowserHistory()
|
||||
export const history = historyEnhancer(createBrowserHistory())
|
||||
|
||||
history.listen(() => {
|
||||
window.scrollTo(0, 0)
|
||||
|
@ -18,6 +18,8 @@ const handleDataAndError = (state, type, action) => {
|
||||
|
||||
const activities = (state = initial.activities, action) => {
|
||||
switch (action.type) {
|
||||
case 'LOGOUT':
|
||||
return initial.activities
|
||||
case 'PUSH_ACTIVITIES':
|
||||
return {
|
||||
...state,
|
||||
@ -50,13 +52,17 @@ const application = (state = initial.application, action) => {
|
||||
}
|
||||
|
||||
const calendarActivities = (state = initial.calendarActivities, action) => {
|
||||
if (action.type === 'UPDATE_CALENDAR') {
|
||||
return {
|
||||
...state,
|
||||
data: action.activities,
|
||||
}
|
||||
switch (action.type) {
|
||||
case 'LOGOUT':
|
||||
return initial.calendarActivities
|
||||
case 'UPDATE_CALENDAR':
|
||||
return {
|
||||
...state,
|
||||
data: action.activities,
|
||||
}
|
||||
default:
|
||||
return handleDataAndError(state, 'calendarActivities', action)
|
||||
}
|
||||
return handleDataAndError(state, 'calendarActivities', action)
|
||||
}
|
||||
|
||||
const chartData = (state = initial.chartData, action) => {
|
||||
@ -118,8 +124,12 @@ const messages = (state = initial.messages, action) => {
|
||||
}
|
||||
}
|
||||
|
||||
const records = (state = initial.records, action) =>
|
||||
handleDataAndError(state, 'records', action)
|
||||
const records = (state = initial.records, action) => {
|
||||
if (action.type === 'LOGOUT') {
|
||||
return initial.records
|
||||
}
|
||||
return handleDataAndError(state, 'records', action)
|
||||
}
|
||||
|
||||
const sports = (state = initial.sports, action) => {
|
||||
if (action.type === 'UPDATE_SPORT_DATA') {
|
||||
@ -150,8 +160,12 @@ const user = (state = initial.user, action) => {
|
||||
}
|
||||
}
|
||||
|
||||
const statistics = (state = initial.statistics, action) =>
|
||||
handleDataAndError(state, 'statistics', action)
|
||||
const statistics = (state = initial.statistics, action) => {
|
||||
if (action.type === 'LOGOUT') {
|
||||
return initial.statistics
|
||||
}
|
||||
return handleDataAndError(state, 'statistics', action)
|
||||
}
|
||||
|
||||
export default history =>
|
||||
combineReducers({
|
||||
|
35
fittrackee_client/src/utils/history.js
Normal file
35
fittrackee_client/src/utils/history.js
Normal file
@ -0,0 +1,35 @@
|
||||
const updatePath = (toPath, newPath) => {
|
||||
if (typeof toPath === 'string' || toPath instanceof String) {
|
||||
toPath = newPath
|
||||
} else {
|
||||
toPath.pathname = newPath
|
||||
}
|
||||
return toPath
|
||||
}
|
||||
|
||||
const pathInterceptor = toPath => {
|
||||
if (
|
||||
!window.localStorage.authToken &&
|
||||
!['/login', '/register'].includes(toPath.pathname)
|
||||
) {
|
||||
toPath = updatePath(toPath, '/login')
|
||||
}
|
||||
if (
|
||||
window.localStorage.authToken &&
|
||||
['/login', '/register'].includes(toPath.pathname)
|
||||
) {
|
||||
toPath = updatePath(toPath, '/')
|
||||
}
|
||||
return toPath
|
||||
}
|
||||
|
||||
export const historyEnhancer = originalHistory => {
|
||||
originalHistory.location = pathInterceptor(originalHistory.location)
|
||||
return {
|
||||
...originalHistory,
|
||||
push: (path, ...args) =>
|
||||
originalHistory.push(pathInterceptor(path), ...args),
|
||||
replace: (path, ...args) =>
|
||||
originalHistory.replace(pathInterceptor(path), ...args),
|
||||
}
|
||||
}
|
@ -15,7 +15,7 @@ export const getFileSizeInMB = fileSize => {
|
||||
return (!fileSize && 0) || +value.toFixed(2)
|
||||
}
|
||||
|
||||
export const version = '0.2.4-beta' // version stored in 'utils' for now
|
||||
export const version = '0.2.5-beta' // version stored in 'utils' for now
|
||||
export const apiUrl = `${process.env.REACT_APP_API_URL}/api/`
|
||||
/* prettier-ignore */
|
||||
export const thunderforestApiKey = `${
|
||||
|
Reference in New Issue
Block a user