From 0e9c9105e68ca04ce43e6d787dc784ea96ff30e4 Mon Sep 17 00:00:00 2001 From: Sam Date: Thu, 10 May 2018 23:39:59 +0200 Subject: [PATCH] API & Client: activities - pagination + minor fix --- mpwo_api/mpwo_api/activities/activities.py | 34 +++++++--- mpwo_client/src/actions/activities.js | 25 +++++++ mpwo_client/src/actions/index.js | 10 +-- .../components/Activities/ActivityDisplay.jsx | 2 +- .../components/Activities/ActivityEdit.jsx | 2 +- .../components/Admin/Sports/AdminSport.jsx | 2 +- .../components/Admin/Sports/AdminSports.jsx | 2 +- .../src/components/Dashboard/index.jsx | 68 +++++++++++++------ mpwo_client/src/mwpoApi/index.js | 10 ++- mpwo_client/src/reducers/index.js | 18 ++++- mpwo_client/src/reducers/initial.js | 1 + 11 files changed, 130 insertions(+), 44 deletions(-) diff --git a/mpwo_api/mpwo_api/activities/activities.py b/mpwo_api/mpwo_api/activities/activities.py index cff8dd12..a0bfc037 100644 --- a/mpwo_api/mpwo_api/activities/activities.py +++ b/mpwo_api/mpwo_api/activities/activities.py @@ -18,18 +18,30 @@ activities_blueprint = Blueprint('activities', __name__) @authenticate def get_activities(auth_user_id): """Get all activities for authenticated user""" - activities = Activity.query.filter_by(user_id=auth_user_id)\ - .order_by(Activity.activity_date.desc()).all() - activities_list = [] - for activity in activities: - activities_list.append(activity.serialize()) - response_object = { - 'status': 'success', - 'data': { - 'activities': activities_list + try: + params = request.args.copy() + page = 1 if len(params) == 0 else int(params.pop('page')) + activities = Activity.query.filter_by(user_id=auth_user_id)\ + .order_by(Activity.activity_date.desc()).paginate( + page, 5, False).items + activities_list = [] + for activity in activities: + activities_list.append(activity.serialize()) + response_object = { + 'status': 'success', + 'data': { + 'activities': activities_list + } } - } - return jsonify(response_object), 200 + code = 200 + except Exception as e: + appLog.error(e) + response_object = { + 'status': 'error', + 'message': 'Error. Please try again or contact the administrator.' + } + code = 500 + return jsonify(response_object), code @activities_blueprint.route('/activities/', methods=['GET']) diff --git a/mpwo_client/src/actions/activities.js b/mpwo_client/src/actions/activities.js index 653ae00b..ae984152 100644 --- a/mpwo_client/src/actions/activities.js +++ b/mpwo_client/src/actions/activities.js @@ -3,6 +3,15 @@ import mpwoApi from '../mwpoApi/activities' import { history } from '../index' import { setError } from './index' +export const endPagination = () => ({ + type: 'END_PAGINATION' +}) + +export const pushActivities = activities => ({ + type: 'PUSH_ACTIVITIES', + activities, +}) + export const setGpx = gpxContent => ({ type: 'SET_GPX', gpxContent, @@ -70,3 +79,19 @@ export const editActivity = form => dispatch => mpwoGenericApi } }) .catch(error => dispatch(setError(`activities: ${error}`))) + + +export const getMoreActivities = page => dispatch => mpwoGenericApi + .getData('activities', null, page) + .then(ret => { + if (ret.status === 'success') { + if (ret.data.activities.length > 0) { + dispatch(pushActivities(ret.data.activities)) + } else { + dispatch(endPagination()) + } + } else { + dispatch(setError(`activities: ${ret.message}`)) + } + }) + .catch(error => dispatch(setError(`activities: ${error}`))) diff --git a/mpwo_client/src/actions/index.js b/mpwo_client/src/actions/index.js index e1740930..e8255a3b 100644 --- a/mpwo_client/src/actions/index.js +++ b/mpwo_client/src/actions/index.js @@ -13,17 +13,17 @@ export const setError = message => ({ message, }) -export const getData = (target, id = null) => dispatch => { +export const getData = (target, id = null, data = null) => dispatch => { if (id !== null && isNaN(id)) { return dispatch(setError(target, `${target}: Incorrect id`)) } return mpwoApi - .getData(target, id) + .getData(target, id, data) .then(ret => { if (ret.status === 'success') { dispatch(setData(target, ret.data)) } else { - dispatch(setError(`${target}: ${ret.status}`)) + dispatch(setError(`${target}: ${ret.message}`)) } }) .catch(error => dispatch(setError(`${target}: ${error}`))) @@ -50,7 +50,7 @@ export const updateData = (target, data) => dispatch => { if (ret.status === 'success') { dispatch(setData(target, ret.data)) } else { - dispatch(setError(`${target}: ${ret.status}`)) + dispatch(setError(`${target}: ${ret.message}`)) } }) .catch(error => dispatch(setError(`${target}: ${error}`))) @@ -66,7 +66,7 @@ export const deleteData = (target, id) => dispatch => { if (ret.status === 204) { history.push(`/admin/${target}`) } else { - dispatch(setError(`${target}: ${ret.status}`)) + dispatch(setError(`${target}: ${ret.message}`)) } }) .catch(error => dispatch(setError(`${target}: ${error}`))) diff --git a/mpwo_client/src/components/Activities/ActivityDisplay.jsx b/mpwo_client/src/components/Activities/ActivityDisplay.jsx index fcfdf83e..e8afe30c 100644 --- a/mpwo_client/src/components/Activities/ActivityDisplay.jsx +++ b/mpwo_client/src/components/Activities/ActivityDisplay.jsx @@ -5,7 +5,7 @@ import { Link } from 'react-router-dom' import ActivityMap from './ActivityMap' import CustomModal from './../Others/CustomModal' -import { getData } from '../../actions/index' +import { getData } from '../../actions' import { deleteActivity } from '../../actions/activities' class ActivityDisplay extends React.Component { diff --git a/mpwo_client/src/components/Activities/ActivityEdit.jsx b/mpwo_client/src/components/Activities/ActivityEdit.jsx index 21bedf29..cf030649 100644 --- a/mpwo_client/src/components/Activities/ActivityEdit.jsx +++ b/mpwo_client/src/components/Activities/ActivityEdit.jsx @@ -2,7 +2,7 @@ import React from 'react' import { connect } from 'react-redux' import ActivityAddOrEdit from './ActivityAddOrEdit' -import { getData } from '../../actions/index' +import { getData } from '../../actions' class ActivityEdit extends React.Component { diff --git a/mpwo_client/src/components/Admin/Sports/AdminSport.jsx b/mpwo_client/src/components/Admin/Sports/AdminSport.jsx index 6a291228..c6a16b6d 100644 --- a/mpwo_client/src/components/Admin/Sports/AdminSport.jsx +++ b/mpwo_client/src/components/Admin/Sports/AdminSport.jsx @@ -1,7 +1,7 @@ import React from 'react' import { connect } from 'react-redux' -import { getData } from '../../../actions/index' +import { getData } from '../../../actions' import AdminDetail from '../generic/AdminDetail' class AdminSports extends React.Component { diff --git a/mpwo_client/src/components/Admin/Sports/AdminSports.jsx b/mpwo_client/src/components/Admin/Sports/AdminSports.jsx index 2fb36f39..5fd24211 100644 --- a/mpwo_client/src/components/Admin/Sports/AdminSports.jsx +++ b/mpwo_client/src/components/Admin/Sports/AdminSports.jsx @@ -1,7 +1,7 @@ import React from 'react' import { connect } from 'react-redux' -import { getData } from '../../../actions/index' +import { getData } from '../../../actions' import AdminPage from '../generic/AdminPage' class AdminSports extends React.Component { diff --git a/mpwo_client/src/components/Dashboard/index.jsx b/mpwo_client/src/components/Dashboard/index.jsx index 87fdd4fc..3b6e204f 100644 --- a/mpwo_client/src/components/Dashboard/index.jsx +++ b/mpwo_client/src/components/Dashboard/index.jsx @@ -4,41 +4,66 @@ import { connect } from 'react-redux' import ActivityCard from './ActivityCard' import Statistics from './Statistics' -import { getData } from '../../actions/index' +import { getData } from '../../actions' +import { getMoreActivities } from '../../actions/activities' class DashBoard extends React.Component { + constructor(props, context) { + super(props, context) + this.state = { + page: 1, + } + } + componentDidMount() { this.props.loadActivities() } render() { - const { activities, sports } = this.props + const { + activities, loadMoreActivities, message, paginationEnd, sports + } = this.props + const { page } = this.state return (
mpwo - Dashboard

Dashboard

- {activities.length > 0 ? ( -
-
-
- {activities.map(activity => ( - - ))} -
-
- + {message ? ( + {message} + ) : ( + activities.length > 0 ? ( +
+
+
+ {activities.map(activity => ( + + ))} + {!paginationEnd && + { + loadMoreActivities(page + 1) + this.setState({ page: page + 1 }) + }} + /> + } +
+
+ +
-
) : ( 'No activities for now' - )} + ))}
) } @@ -47,13 +72,16 @@ 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, - user: state.user, }), dispatch => ({ loadActivities: () => { - dispatch(getData('activities')) + dispatch(getData('activities', null, 1)) + }, + loadMoreActivities: page => { + dispatch(getMoreActivities(page)) }, }) )(DashBoard) diff --git a/mpwo_client/src/mwpoApi/index.js b/mpwo_client/src/mwpoApi/index.js index ee69654a..9b18f4b1 100644 --- a/mpwo_client/src/mwpoApi/index.js +++ b/mpwo_client/src/mwpoApi/index.js @@ -2,8 +2,14 @@ import { apiUrl } from '../utils' export default class MpwoApi { - static getData(target, id = null) { - const request = new Request(`${apiUrl}${target}${id ? `/${id}` : ''}`, { + static getData(target, id = null, page = null) { + let url = `${apiUrl}${target}` + if (id) { + url = `${url}/${id}` + } else if (page) { + url = `${url}?page=${page}` + } + const request = new Request(url, { method: 'GET', headers: new Headers({ 'Content-Type': 'application/json', diff --git a/mpwo_client/src/reducers/index.js b/mpwo_client/src/reducers/index.js index 1f0fced7..f65db5aa 100644 --- a/mpwo_client/src/reducers/index.js +++ b/mpwo_client/src/reducers/index.js @@ -19,8 +19,22 @@ const handleDataAndError = (state, type, action) => { } } -const activities = (state = initial.activities, action) => - handleDataAndError(state, 'activities', action) +const activities = (state = initial.activities, action) => { + switch (action.type) { + case 'END_PAGINATION': + return { + ...state, + pagination_end: true + } + case 'PUSH_ACTIVITIES': + return { + ...state, + data: state.data.concat(action.activities), + } + default: + return handleDataAndError(state, 'activities', action) + } +} const formData = (state = initial.formData, action) => { switch (action.type) { diff --git a/mpwo_client/src/reducers/initial.js b/mpwo_client/src/reducers/initial.js index dffdda82..8959cb6d 100644 --- a/mpwo_client/src/reducers/initial.js +++ b/mpwo_client/src/reducers/initial.js @@ -40,6 +40,7 @@ export default { }, activities: { ...emptyData, + pagination_end: false }, // check if storing gpx content is OK gpx: null,