API & Client: filter activities - #3 (WIP)

This commit is contained in:
Sam 2018-06-07 20:31:44 +02:00
parent 479b47455f
commit f45db7b969
4 changed files with 79 additions and 21 deletions

View File

@ -33,9 +33,11 @@ def get_activities(auth_user_id):
ave_speed_from = params.get('ave_speed_from') ave_speed_from = params.get('ave_speed_from')
ave_speed_to = params.get('ave_speed_to') ave_speed_to = params.get('ave_speed_to')
order = params.get('order') order = params.get('order')
sport_id = params.get('sport_id')
per_page = int(params.get('per_page')) if params.get('per_page') else 5 per_page = int(params.get('per_page')) if params.get('per_page') else 5
activities = Activity.query.filter( activities = Activity.query.filter(
Activity.user_id == auth_user_id, Activity.user_id == auth_user_id,
Activity.sport_id == sport_id if sport_id else True,
Activity.activity_date >= datetime.strptime(date_from, '%Y-%m-%d') Activity.activity_date >= datetime.strptime(date_from, '%Y-%m-%d')
if date_from else True, if date_from else True,
Activity.activity_date <= datetime.strptime(date_to, '%Y-%m-%d') Activity.activity_date <= datetime.strptime(date_to, '%Y-%m-%d')

View File

@ -487,6 +487,35 @@ def test_get_activities_ave_speed_filter(
assert 'Fri, 23 Feb 2018 00:00:00 GMT' == data['data']['activities'][0]['activity_date'] # noqa assert 'Fri, 23 Feb 2018 00:00:00 GMT' == data['data']['activities'][0]['activity_date'] # noqa
def test_get_activities_sport_filter(
app, user_1, sport_1_cycling, seven_activities_user_1, sport_2_running,
activity_running_user_1
):
client = app.test_client()
resp_login = client.post(
'/api/auth/login',
data=json.dumps(dict(
email='test@test.com',
password='12345678'
)),
content_type='application/json'
)
response = client.get(
'/api/activities?sport_id=2',
headers=dict(
Authorization='Bearer ' + json.loads(
resp_login.data.decode()
)['auth_token']
)
)
data = json.loads(response.data.decode())
assert response.status_code == 200
assert 'success' in data['status']
assert len(data['data']['activities']) == 1
assert 'Sun, 01 Apr 2018 00:00:00 GMT' == data['data']['activities'][0]['activity_date'] # noqa
def test_get_an_activity( def test_get_an_activity(
app, user_1, sport_1_cycling, activity_cycling_user_1 app, user_1, sport_1_cycling, activity_cycling_user_1
): ):

View File

@ -1,7 +1,7 @@
import React from 'react' import React from 'react'
export default function ActivitiesList (props) { export default function ActivitiesList (props) {
const { sports } = props const { loadActivities, sports, updateParams } = props
return ( return (
<div className="card"> <div className="card">
<div className="card-body activity-filter"> <div className="card-body activity-filter">
@ -10,16 +10,18 @@ export default function ActivitiesList (props) {
<label> <label>
From: From:
<input <input
name="start"
className="form-control col-md" className="form-control col-md"
name="from"
onChange={e => updateParams(e)}
type="date" type="date"
/> />
</label> </label>
<label> <label>
To: To:
<input <input
name="end"
className="form-control col-md" className="form-control col-md"
name="to"
onChange={e => updateParams(e)}
type="date" type="date"
/> />
</label> </label>
@ -30,6 +32,7 @@ export default function ActivitiesList (props) {
<select <select
className="form-control input-lg" className="form-control input-lg"
name="sport_id" name="sport_id"
onChange={e => updateParams(e)}
> >
<option value="" /> <option value="" />
{sports.map(sport => ( {sports.map(sport => (
@ -47,9 +50,10 @@ export default function ActivitiesList (props) {
<div className="row"> <div className="row">
<div className="col-5"> <div className="col-5">
<input <input
name="distance-from"
className="form-control" className="form-control"
min={0} min={0}
name="distance_from"
onChange={e => updateParams(e)}
step="1" step="1"
type="number" type="number"
/> />
@ -57,9 +61,10 @@ export default function ActivitiesList (props) {
<div className="col-2 align-middle text-center">to</div> <div className="col-2 align-middle text-center">to</div>
<div className="col-5"> <div className="col-5">
<input <input
name="distance-to"
className="form-control" className="form-control"
min={0} min={0}
name="distance_to"
onChange={e => updateParams(e)}
step="1" step="1"
type="number" type="number"
/> />
@ -75,8 +80,9 @@ export default function ActivitiesList (props) {
<div className="row"> <div className="row">
<div className="col-5"> <div className="col-5">
<input <input
name="duration-from"
className="form-control" className="form-control"
name="duration_from"
onChange={e => updateParams(e)}
pattern="^([0-9]*[0-9]):([0-5][0-9])$" pattern="^([0-9]*[0-9]):([0-5][0-9])$"
placeholder="hh:mm" placeholder="hh:mm"
type="text" type="text"
@ -85,8 +91,9 @@ export default function ActivitiesList (props) {
<div className="col-2 align-middle text-center">to</div> <div className="col-2 align-middle text-center">to</div>
<div className="col-5"> <div className="col-5">
<input <input
name="duration-to"
className="form-control" className="form-control"
name="duration_to"
onChange={e => updateParams(e)}
pattern="^([0-9]*[0-9]):([0-5][0-9])$" pattern="^([0-9]*[0-9]):([0-5][0-9])$"
placeholder="hh:mm" placeholder="hh:mm"
type="text" type="text"
@ -103,9 +110,10 @@ export default function ActivitiesList (props) {
<div className="row"> <div className="row">
<div className="col-5"> <div className="col-5">
<input <input
name="speed-from"
className="form-control" className="form-control"
min={0} min={0}
name="ave_speed_from"
onChange={e => updateParams(e)}
step="1" step="1"
type="number" type="number"
/> />
@ -113,9 +121,10 @@ export default function ActivitiesList (props) {
<div className="col-2 align-middle text-center">to</div> <div className="col-2 align-middle text-center">to</div>
<div className="col-5"> <div className="col-5">
<input <input
name="speed-to"
className="form-control" className="form-control"
min={0} min={0}
name="ave_speed_to"
onChange={e => updateParams(e)}
step="1" step="1"
type="number" type="number"
/> />
@ -125,8 +134,9 @@ export default function ActivitiesList (props) {
</label> </label>
</div> </div>
<input <input
type="submit"
className="btn btn-primary btn-lg btn-block" className="btn btn-primary btn-lg btn-block"
onClick={() => loadActivities()}
type="submit"
value="Filter" value="Filter"
/> />
</form> </form>

View File

@ -12,17 +12,32 @@ class Activities extends React.Component {
constructor(props, context) { constructor(props, context) {
super(props, context) super(props, context)
this.state = { this.state = {
page: 1, params: {
page: 1,
per_page: 10,
},
} }
} }
componentDidMount() { componentDidMount() {
this.props.loadActivities() this.props.loadActivities(this.state.params)
} }
setParams(e) {
const { params } = this.state
if (e.target.value === '') {
delete params[e.target.name]
} else {
params[e.target.name] = e.target.value
}
params.page = 1
this.setState(params)
}
render() { render() {
const { activities, loadMoreActivities, message, sports } = this.props const {
const { page } = this.state activities, loadActivities, loadMoreActivities, message, sports
} = this.props
const { params } = this.state
const paginationEnd = activities.length > 0 const paginationEnd = activities.length > 0
? activities[activities.length - 1].previous_activity === null ? activities[activities.length - 1].previous_activity === null
: true : true
@ -39,6 +54,8 @@ class Activities extends React.Component {
<div className="col-md-3"> <div className="col-md-3">
<ActivitiesFilter <ActivitiesFilter
sports={sports} sports={sports}
loadActivities={() => loadActivities(params)}
updateParams={e => this.setParams(e)}
/> />
</div> </div>
<div className="col-md-9"> <div className="col-md-9">
@ -52,8 +69,9 @@ class Activities extends React.Component {
className="btn btn-default btn-md btn-block" className="btn btn-default btn-md btn-block"
value="Load more activities" value="Load more activities"
onClick={() => { onClick={() => {
loadMoreActivities(page + 1) params.page += 1
this.setState({ page: page + 1 }) loadMoreActivities(params)
this.setState(params)
}} }}
/> />
} }
@ -73,12 +91,11 @@ export default connect(
sports: state.sports.data, sports: state.sports.data,
}), }),
dispatch => ({ dispatch => ({
loadActivities: () => { loadActivities: params => {
dispatch(getData('activities', { page: 1, per_page: 10 })) dispatch(getData('activities', params))
dispatch(getData('records'))
}, },
loadMoreActivities: page => { loadMoreActivities: params => {
dispatch(getMoreActivities({ page, per_page: 10 })) dispatch(getMoreActivities(params))
}, },
}) })
)(Activities) )(Activities)