API & Client: filter activities - fix #3
This commit is contained in:
parent
f45db7b969
commit
76b2d5aad2
@ -10,9 +10,10 @@ from sqlalchemy import exc
|
|||||||
from ..users.utils import authenticate, verify_extension
|
from ..users.utils import authenticate, verify_extension
|
||||||
from .models import Activity
|
from .models import Activity
|
||||||
from .utils import (
|
from .utils import (
|
||||||
ActivityException, convert_in_duration, create_activity, edit_activity,
|
ActivityException, create_activity, edit_activity, get_chart_data,
|
||||||
get_chart_data, process_files
|
process_files
|
||||||
)
|
)
|
||||||
|
from .utils_format import convert_in_duration
|
||||||
|
|
||||||
activities_blueprint = Blueprint('activities', __name__)
|
activities_blueprint = Blueprint('activities', __name__)
|
||||||
|
|
||||||
@ -62,7 +63,8 @@ def get_activities(auth_user_id):
|
|||||||
response_object = {
|
response_object = {
|
||||||
'status': 'success',
|
'status': 'success',
|
||||||
'data': {
|
'data': {
|
||||||
'activities': [activity.serialize() for activity in activities]
|
'activities': [activity.serialize(params)
|
||||||
|
for activity in activities]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
code = 200
|
code = 200
|
||||||
|
@ -8,6 +8,8 @@ from sqlalchemy.ext.hybrid import hybrid_property
|
|||||||
from sqlalchemy.orm.session import object_session
|
from sqlalchemy.orm.session import object_session
|
||||||
from sqlalchemy.types import Enum
|
from sqlalchemy.types import Enum
|
||||||
|
|
||||||
|
from .utils_format import convert_in_duration, convert_value_to_integer
|
||||||
|
|
||||||
record_types = [
|
record_types = [
|
||||||
'AS', # 'Best Average Speed'
|
'AS', # 'Best Average Speed'
|
||||||
'FD', # 'Farthest Distance'
|
'FD', # 'Farthest Distance'
|
||||||
@ -16,23 +18,6 @@ record_types = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def convert_timedelta_to_integer(value):
|
|
||||||
hours, minutes, seconds = str(value).split(':')
|
|
||||||
return int(hours) * 3600 + int(minutes) * 60 + int(seconds)
|
|
||||||
|
|
||||||
|
|
||||||
def convert_value_to_integer(record_type, val):
|
|
||||||
if val is None:
|
|
||||||
return None
|
|
||||||
|
|
||||||
if record_type == 'LD':
|
|
||||||
return convert_timedelta_to_integer(val)
|
|
||||||
elif record_type in ['AS', 'MS']:
|
|
||||||
return int(val * 100)
|
|
||||||
else: # 'FD'
|
|
||||||
return int(val * 1000)
|
|
||||||
|
|
||||||
|
|
||||||
def update_records(user_id, sport_id, connection, session):
|
def update_records(user_id, sport_id, connection, session):
|
||||||
record_table = Record.__table__
|
record_table = Record.__table__
|
||||||
new_records = Activity.get_user_activity_records(
|
new_records = Activity.get_user_activity_records(
|
||||||
@ -161,18 +146,61 @@ class Activity(db.Model):
|
|||||||
self.distance = distance
|
self.distance = distance
|
||||||
self.duration = duration
|
self.duration = duration
|
||||||
|
|
||||||
def serialize(self):
|
def serialize(self, params=None):
|
||||||
|
date_from = params.get('from') if params else None
|
||||||
|
date_to = params.get('to') if params else None
|
||||||
|
distance_from = params.get('distance_from') if params else None
|
||||||
|
distance_to = params.get('distance_to') if params else None
|
||||||
|
duration_from = params.get('duration_from') if params else None
|
||||||
|
duration_to = params.get('duration_to') if params else None
|
||||||
|
ave_speed_from = params.get('ave_speed_from') if params else None
|
||||||
|
ave_speed_to = params.get('ave_speed_to') if params else None
|
||||||
|
sport_id = params.get('sport_id') if params else None
|
||||||
previous_activity = Activity.query.filter(
|
previous_activity = Activity.query.filter(
|
||||||
Activity.id != self.id,
|
Activity.id != self.id,
|
||||||
Activity.user_id == self.user_id,
|
Activity.user_id == self.user_id,
|
||||||
Activity.activity_date <= self.activity_date
|
Activity.sport_id == sport_id if sport_id else True,
|
||||||
|
Activity.activity_date <= self.activity_date,
|
||||||
|
Activity.activity_date >= datetime.datetime.strptime(
|
||||||
|
date_from, '%Y-%m-%d'
|
||||||
|
) if date_from else True,
|
||||||
|
Activity.activity_date <= datetime.datetime.strptime(
|
||||||
|
date_to, '%Y-%m-%d'
|
||||||
|
) if date_to else True,
|
||||||
|
Activity.distance >= int(distance_from) if distance_from else True,
|
||||||
|
Activity.distance <= int(distance_to) if distance_to else True,
|
||||||
|
Activity.duration >= convert_in_duration(duration_from)
|
||||||
|
if duration_from else True,
|
||||||
|
Activity.duration <= convert_in_duration(duration_to)
|
||||||
|
if duration_to else True,
|
||||||
|
Activity.ave_speed >= float(ave_speed_from)
|
||||||
|
if ave_speed_from else True,
|
||||||
|
Activity.ave_speed <= float(ave_speed_to)
|
||||||
|
if ave_speed_to else True,
|
||||||
).order_by(
|
).order_by(
|
||||||
Activity.activity_date.desc()
|
Activity.activity_date.desc()
|
||||||
).first()
|
).first()
|
||||||
next_activity = Activity.query.filter(
|
next_activity = Activity.query.filter(
|
||||||
Activity.id != self.id,
|
Activity.id != self.id,
|
||||||
Activity.user_id == self.user_id,
|
Activity.user_id == self.user_id,
|
||||||
Activity.activity_date >= self.activity_date
|
Activity.sport_id == sport_id if sport_id else True,
|
||||||
|
Activity.activity_date >= self.activity_date,
|
||||||
|
Activity.activity_date >= datetime.datetime.strptime(
|
||||||
|
date_from, '%Y-%m-%d'
|
||||||
|
) if date_from else True,
|
||||||
|
Activity.activity_date <= datetime.datetime.strptime(
|
||||||
|
date_to, '%Y-%m-%d'
|
||||||
|
) if date_to else True,
|
||||||
|
Activity.distance >= int(distance_from) if distance_from else True,
|
||||||
|
Activity.distance <= int(distance_to) if distance_to else True,
|
||||||
|
Activity.duration >= convert_in_duration(duration_from)
|
||||||
|
if duration_from else True,
|
||||||
|
Activity.duration <= convert_in_duration(duration_to)
|
||||||
|
if duration_to else True,
|
||||||
|
Activity.ave_speed >= float(ave_speed_from)
|
||||||
|
if ave_speed_from else True,
|
||||||
|
Activity.ave_speed <= float(ave_speed_to)
|
||||||
|
if ave_speed_to else True,
|
||||||
).order_by(
|
).order_by(
|
||||||
Activity.activity_date.asc()
|
Activity.activity_date.asc()
|
||||||
).first()
|
).first()
|
||||||
|
@ -5,7 +5,8 @@ from flask import Blueprint, jsonify, request
|
|||||||
|
|
||||||
from ..users.models import User
|
from ..users.models import User
|
||||||
from ..users.utils import authenticate
|
from ..users.utils import authenticate
|
||||||
from .models import Activity, Sport, convert_timedelta_to_integer
|
from .models import Activity, Sport
|
||||||
|
from .utils_format import convert_timedelta_to_integer
|
||||||
|
|
||||||
stats_blueprint = Blueprint('stats', __name__)
|
stats_blueprint = Blueprint('stats', __name__)
|
||||||
|
|
||||||
|
@ -360,9 +360,3 @@ def process_files(auth_user_id, activity_data, activity_file, folders):
|
|||||||
return [process_one_gpx_file(common_params, filename)]
|
return [process_one_gpx_file(common_params, filename)]
|
||||||
else:
|
else:
|
||||||
return process_zip_archive(common_params, folders['extract_dir'])
|
return process_zip_archive(common_params, folders['extract_dir'])
|
||||||
|
|
||||||
|
|
||||||
def convert_in_duration(value):
|
|
||||||
hours = int(value.split(':')[0])
|
|
||||||
minutes = int(value.split(':')[1])
|
|
||||||
return timedelta(seconds=(hours*3600 + minutes*60))
|
|
||||||
|
24
fittrackee_api/fittrackee_api/activities/utils_format.py
Normal file
24
fittrackee_api/fittrackee_api/activities/utils_format.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
|
|
||||||
|
def convert_in_duration(value):
|
||||||
|
hours = int(value.split(':')[0])
|
||||||
|
minutes = int(value.split(':')[1])
|
||||||
|
return timedelta(seconds=(hours*3600 + minutes*60))
|
||||||
|
|
||||||
|
|
||||||
|
def convert_timedelta_to_integer(value):
|
||||||
|
hours, minutes, seconds = str(value).split(':')
|
||||||
|
return int(hours) * 3600 + int(minutes) * 60 + int(seconds)
|
||||||
|
|
||||||
|
|
||||||
|
def convert_value_to_integer(record_type, val):
|
||||||
|
if val is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if record_type == 'LD':
|
||||||
|
return convert_timedelta_to_integer(val)
|
||||||
|
elif record_type in ['AS', 'MS']:
|
||||||
|
return int(val * 100)
|
||||||
|
else: # 'FD'
|
||||||
|
return int(val * 1000)
|
@ -6,7 +6,7 @@ export default function ActivitiesList (props) {
|
|||||||
const { activities, sports } = props
|
const { activities, sports } = props
|
||||||
return (
|
return (
|
||||||
<div className="card">
|
<div className="card">
|
||||||
<div className="card-bord">
|
<div className="card-body">
|
||||||
<table className="table">
|
<table className="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Helmet } from 'react-helmet'
|
import { Helmet } from 'react-helmet'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
|
import { Link } from 'react-router-dom'
|
||||||
|
|
||||||
import ActivitiesFilter from './ActivitiesFilter'
|
import ActivitiesFilter from './ActivitiesFilter'
|
||||||
import ActivitiesList from './ActivitiesList'
|
import ActivitiesList from './ActivitiesList'
|
||||||
@ -75,6 +76,16 @@ class Activities extends React.Component {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
|
{activities.length === 0 && (
|
||||||
|
<div className="card text-center">
|
||||||
|
<div className="card-body">
|
||||||
|
No workouts. {' '}
|
||||||
|
<Link to={{ pathname: '/activities/add' }}>
|
||||||
|
Upload one !
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -54,7 +54,7 @@ function NavBar(props) {
|
|||||||
pathname: '/activities/add',
|
pathname: '/activities/add',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Add workout
|
<strong>Add workout</strong>
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
)}
|
)}
|
||||||
|
Loading…
Reference in New Issue
Block a user