API & Client: fix and update (pagination, style)
This commit is contained in:
parent
ca80a8b6d5
commit
f744eb0769
@ -160,6 +160,20 @@ class Activity(db.Model):
|
||||
self.duration = duration
|
||||
|
||||
def serialize(self):
|
||||
previous_activity = Activity.query.filter(
|
||||
Activity.id != self.id,
|
||||
Activity.user_id == self.user_id,
|
||||
Activity.activity_date <= self.activity_date
|
||||
).order_by(
|
||||
Activity.activity_date.desc()
|
||||
).first()
|
||||
next_activity = Activity.query.filter(
|
||||
Activity.id != self.id,
|
||||
Activity.user_id == self.user_id,
|
||||
Activity.activity_date >= self.activity_date
|
||||
).order_by(
|
||||
Activity.activity_date.asc()
|
||||
).first()
|
||||
return {
|
||||
"id": self.id,
|
||||
"user_id": self.user_id,
|
||||
@ -180,6 +194,8 @@ class Activity(db.Model):
|
||||
"ave_speed": float(self.ave_speed) if self.ave_speed else None,
|
||||
"with_gpx": self.gpx is not None,
|
||||
"bounds": [float(bound) for bound in self.bounds] if self.bounds else [], # noqa
|
||||
"previous_activity": previous_activity.id if previous_activity else None, # noqa
|
||||
"next_activity": next_activity.id if next_activity else None,
|
||||
"segments": [segment.serialize() for segment in self.segments],
|
||||
"records": [record.serialize() for record in self.records]
|
||||
}
|
||||
|
@ -3,11 +3,6 @@ import mpwoApi from '../mwpoApi/activities'
|
||||
import { history } from '../index'
|
||||
import { setError } from './index'
|
||||
|
||||
export const endPagination = status => ({
|
||||
type: 'END_PAGINATION',
|
||||
status,
|
||||
})
|
||||
|
||||
export const pushActivities = activities => ({
|
||||
type: 'PUSH_ACTIVITIES',
|
||||
activities,
|
||||
@ -90,9 +85,6 @@ export const getMoreActivities = page => dispatch => mpwoGenericApi
|
||||
if (ret.data.activities.length > 0) {
|
||||
dispatch(pushActivities(ret.data.activities))
|
||||
}
|
||||
if (ret.data.activities.length < 5) {
|
||||
dispatch(endPagination(true))
|
||||
}
|
||||
} else {
|
||||
dispatch(setError(`activities: ${ret.message}`))
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ class ActivityDisplay extends React.Component {
|
||||
}}
|
||||
close={() => this.setState({ displayModal: false })}
|
||||
/>}
|
||||
{activity && sport && (
|
||||
{activity && sport && activities.length === 1 && (
|
||||
<div className="row">
|
||||
<div className="col">
|
||||
<div className="card">
|
||||
@ -194,11 +194,11 @@ export default connect(
|
||||
user: state.user,
|
||||
}),
|
||||
dispatch => ({
|
||||
onDeleteActivity: activityId => {
|
||||
dispatch(deleteActivity(activityId))
|
||||
},
|
||||
loadActivity: activityId => {
|
||||
dispatch(getData('activities', activityId))
|
||||
},
|
||||
onDeleteActivity: activityId => {
|
||||
dispatch(deleteActivity(activityId))
|
||||
},
|
||||
})
|
||||
)(ActivityDisplay)
|
||||
|
@ -8,6 +8,10 @@ class AdminSports extends React.Component {
|
||||
componentDidMount() {
|
||||
this.props.loadSport(this.props.match.params.sportId)
|
||||
}
|
||||
componentWillUnmount() {
|
||||
// reload all Sports
|
||||
this.props.loadSport(null)
|
||||
}
|
||||
render() {
|
||||
const { sports } = this.props
|
||||
|
||||
|
@ -1,4 +1,6 @@
|
||||
.App {
|
||||
background-color: #eaeaea;
|
||||
min-height: 100vh;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@ -99,7 +101,7 @@ input, textarea {
|
||||
border-radius: 5px;
|
||||
max-width: 500px;
|
||||
margin: 20% auto;
|
||||
z-index: 100;
|
||||
z-index: 1250;
|
||||
}
|
||||
|
||||
.custom-modal-backdrop {
|
||||
@ -110,7 +112,7 @@ input, textarea {
|
||||
right: 0;
|
||||
background-color: rgba(0,0,0,0.3);
|
||||
padding: 50px;
|
||||
z-index: 90;
|
||||
z-index: 1240;
|
||||
}
|
||||
|
||||
.custom-fa {
|
||||
|
@ -5,7 +5,7 @@ import { connect } from 'react-redux'
|
||||
import ActivityCard from './ActivityCard'
|
||||
import Statistics from './Statistics'
|
||||
import { getData } from '../../actions'
|
||||
import { endPagination, getMoreActivities } from '../../actions/activities'
|
||||
import { getMoreActivities } from '../../actions/activities'
|
||||
|
||||
class DashBoard extends React.Component {
|
||||
constructor(props, context) {
|
||||
@ -19,14 +19,13 @@ class DashBoard extends React.Component {
|
||||
this.props.loadActivities()
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.props.resetPaginationStatus(false)
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
activities, loadMoreActivities, message, paginationEnd, sports
|
||||
activities, loadMoreActivities, message, sports
|
||||
} = this.props
|
||||
const paginationEnd = activities.length > 0
|
||||
? activities[activities.length - 1].previous_activity === null
|
||||
: true
|
||||
const { page } = this.state
|
||||
return (
|
||||
<div>
|
||||
@ -76,14 +75,10 @@ class DashBoard extends React.Component {
|
||||
export default connect(
|
||||
state => ({
|
||||
activities: state.activities.data,
|
||||
paginationEnd: state.activities.pagination_end,
|
||||
message: state.message,
|
||||
sports: state.sports.data,
|
||||
}),
|
||||
dispatch => ({
|
||||
resetPaginationStatus: () => {
|
||||
dispatch(endPagination(false))
|
||||
},
|
||||
loadActivities: () => {
|
||||
dispatch(getData('activities', null, 1))
|
||||
},
|
||||
|
@ -5,12 +5,13 @@ import { Link } from 'react-router-dom'
|
||||
import { apiUrl } from '../../utils'
|
||||
|
||||
|
||||
function NavBar (props) {
|
||||
function NavBar(props) {
|
||||
return (
|
||||
<header>
|
||||
<nav className="navbar navbar-expand-lg navbar-light bg-light">
|
||||
<span className="navbar-brand">mpwo</span>
|
||||
<button
|
||||
<div className="container">
|
||||
<span className="navbar-brand">mpwo</span>
|
||||
<button
|
||||
className="navbar-toggler"
|
||||
type="button"
|
||||
data-toggle="collapse"
|
||||
@ -18,109 +19,111 @@ function NavBar (props) {
|
||||
aria-controls="navbarSupportedContent"
|
||||
aria-expanded="false"
|
||||
aria-label="Toggle navigation"
|
||||
>
|
||||
<span className="navbar-toggler-icon" />
|
||||
</button>
|
||||
<div className="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<ul className="navbar-nav mr-auto">
|
||||
<li className="nav-item">
|
||||
<Link
|
||||
className="nav-link"
|
||||
to={{
|
||||
pathname: '/',
|
||||
}}
|
||||
>
|
||||
Dashboard
|
||||
</Link>
|
||||
</li>
|
||||
{props.user.isAuthenticated && (
|
||||
<li className="nav-item">
|
||||
<Link
|
||||
className="nav-link"
|
||||
to={{
|
||||
pathname: '/activities/add',
|
||||
}}
|
||||
>
|
||||
Add a workout
|
||||
</Link>
|
||||
</li>
|
||||
)}
|
||||
{props.user.isAdmin && (
|
||||
<li className="nav-item">
|
||||
<Link
|
||||
className="nav-link"
|
||||
to={{
|
||||
pathname: '/admin',
|
||||
}}
|
||||
>
|
||||
Admin
|
||||
</Link>
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
<ul className="navbar-nav flex-row ml-md-auto d-none d-md-flex">
|
||||
{!props.user.isAuthenticated && (
|
||||
>
|
||||
<span className="navbar-toggler-icon" />
|
||||
</button>
|
||||
<div className="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<ul className="navbar-nav mr-auto">
|
||||
<li className="nav-item">
|
||||
<Link
|
||||
className="nav-link"
|
||||
to={{
|
||||
pathname: '/register',
|
||||
pathname: '/',
|
||||
}}
|
||||
>
|
||||
Register
|
||||
Dashboard
|
||||
</Link>
|
||||
</li>
|
||||
)}
|
||||
{!props.user.isAuthenticated && (
|
||||
<li className="nav-item">
|
||||
<Link
|
||||
className="nav-link"
|
||||
to={{
|
||||
pathname: '/login',
|
||||
}}
|
||||
>
|
||||
Login
|
||||
</Link>
|
||||
</li>
|
||||
)}
|
||||
{props.user.picture === true && (
|
||||
<img
|
||||
alt="Avatar"
|
||||
src={`${apiUrl}users/${props.user.id}/picture` +
|
||||
{props.user.isAuthenticated && (
|
||||
<li className="nav-item">
|
||||
<Link
|
||||
className="nav-link"
|
||||
to={{
|
||||
pathname: '/activities/add',
|
||||
}}
|
||||
>
|
||||
Add a workout
|
||||
</Link>
|
||||
</li>
|
||||
)}
|
||||
{props.user.isAdmin && (
|
||||
<li className="nav-item">
|
||||
<Link
|
||||
className="nav-link"
|
||||
to={{
|
||||
pathname: '/admin',
|
||||
}}
|
||||
>
|
||||
Admin
|
||||
</Link>
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
<ul className="navbar-nav flex-row ml-md-auto d-none d-md-flex">
|
||||
{!props.user.isAuthenticated && (
|
||||
<li className="nav-item">
|
||||
<Link
|
||||
className="nav-link"
|
||||
to={{
|
||||
pathname: '/register',
|
||||
}}
|
||||
>
|
||||
Register
|
||||
</Link>
|
||||
</li>
|
||||
)}
|
||||
{!props.user.isAuthenticated && (
|
||||
<li className="nav-item">
|
||||
<Link
|
||||
className="nav-link"
|
||||
to={{
|
||||
pathname: '/login',
|
||||
}}
|
||||
>
|
||||
Login
|
||||
</Link>
|
||||
</li>
|
||||
)}
|
||||
{props.user.picture === true && (
|
||||
<img
|
||||
alt="Avatar"
|
||||
src={`${apiUrl}users/${props.user.id}/picture` +
|
||||
`?${Date.now()}`}
|
||||
className="img-fluid App-nav-profile-img"
|
||||
/>
|
||||
)}
|
||||
{props.user.isAuthenticated && (
|
||||
<li className="nav-item">
|
||||
<Link
|
||||
className="nav-link"
|
||||
to={{
|
||||
pathname: '/profile',
|
||||
}}
|
||||
>
|
||||
{props.user.username}
|
||||
</Link>
|
||||
</li>
|
||||
)}
|
||||
{props.user.isAuthenticated && (
|
||||
<li className="nav-item">
|
||||
<Link
|
||||
className="nav-link"
|
||||
to={{
|
||||
pathname: '/logout',
|
||||
}}
|
||||
>
|
||||
Logout
|
||||
</Link>
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
className="img-fluid App-nav-profile-img"
|
||||
/>
|
||||
)}
|
||||
{props.user.isAuthenticated && (
|
||||
<li className="nav-item">
|
||||
<Link
|
||||
className="nav-link"
|
||||
to={{
|
||||
pathname: '/profile',
|
||||
}}
|
||||
>
|
||||
{props.user.username}
|
||||
</Link>
|
||||
</li>
|
||||
)}
|
||||
{props.user.isAuthenticated && (
|
||||
<li className="nav-item">
|
||||
<Link
|
||||
className="nav-link"
|
||||
to={{
|
||||
pathname: '/logout',
|
||||
}}
|
||||
>
|
||||
Logout
|
||||
</Link>
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
|
||||
export default connect(
|
||||
state => ({
|
||||
user: state.user,
|
||||
|
@ -21,11 +21,6 @@ const handleDataAndError = (state, type, action) => {
|
||||
|
||||
const activities = (state = initial.activities, action) => {
|
||||
switch (action.type) {
|
||||
case 'END_PAGINATION':
|
||||
return {
|
||||
...state,
|
||||
pagination_end: action.status
|
||||
}
|
||||
case 'PUSH_ACTIVITIES':
|
||||
return {
|
||||
...state,
|
||||
|
@ -40,7 +40,6 @@ export default {
|
||||
},
|
||||
activities: {
|
||||
...emptyData,
|
||||
pagination_end: false
|
||||
},
|
||||
// check if storing gpx content is OK
|
||||
gpx: null,
|
||||
|
Loading…
Reference in New Issue
Block a user