Private
Public Access
1
0

Merge branch 'release/v12.27'

This commit is contained in:
Sander Roosendaal
2020-05-06 22:14:15 +02:00
4 changed files with 254 additions and 82 deletions

View File

@@ -5,20 +5,43 @@
{% block title %}Rowsandall {% endblock %}
{% block main %}
<h1>History for {{ rower.user.first_name }} {{ rower.user.last_name }}</h1>
<ul class="main-content">
<link rel="stylesheet" href="https://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.css" type="text/css" />
<div id="id_css_res">
<link rel="stylesheet" href="https://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.css" type="text/css" />
<link rel="stylesheet" href="https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.0.4.min.css" type="text/css" />
<script async="true" src="https://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
</div>
<div id="id_js_res">
<script src="https://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
<script src="https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.0.4.min.js"></script>
</div>
<script async="true" type="text/javascript">
Bokeh.set_log_level("info");
</script>
<div id="id_script">
</div>
<ul class="main-content">
<li class="grid_2">
<h1>History for {{ rower.user.first_name }} {{ rower.user.last_name }}</h1>
</li>
<li class="grid_2">
<a href="/rowers/history/?enddate={{ today|date:"Y-m-d" }}&startdate={{ lastseven|date:"Y-m-d" }}&workouttype={{ workouttype }}">Past 7 days</a>
&nbsp;
<a href="/rowers/history/?enddate={{ today|date:"Y-m-d" }}&startdate={{ lastfourteen|date:"Y-m-d" }}&workouttype={{ workouttype }}">Past 14 days</a>
&nbsp;
<a href="/rowers/history/?enddate={{ today|date:"Y-m-d" }}&startdate={{ last28|date:"Y-m-d" }}&workouttype={{ workouttype }}">Past 28 days</a>
&nbsp;
<a href="/rowers/history/?enddate={{ today|date:"Y-m-d" }}&startdate={{ firstmay|date:"Y-m-d" }}&workouttype={{ workouttype }}">Current Concept2 Season</a>
</li>
<li class="grid_2">
<p>
<form enctype="multipart/form-data" method="post">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<input type="submit" value="Submit">
</form>
<form enctype="multipart/form-data" method="get">
<table>
{{ form.as_table }}
</table>
<input type="submit" value="Submit"/>
</form>
</p>
<h2>All workouts</h2>
@@ -35,23 +58,25 @@
<td>Number of workouts</td><td>{{ totalsdict|lookup:"nrworkouts"}}</td>
</tr>
<tr>
<td>Average heart rate</td><td>{{ totalsdict|lookup:"hrmean"}} bpm</td>
<td>Average heart rate</td><td><span id="total_hr"></span> bpm</td>
</tr>
<tr>
<td>Maximum heart rate</td><td>{{ totalsdict|lookup:"hrmax"}} bpm</td>
<td>Maximum heart rate</td><td><span id="total_maxhr"></span> bpm</td>
</tr>
<tr>
<td>Average power</td><td>{{ totalsdict|lookup:"powermean"}} W</td>
<td>Average power</td><td><span id="total_power"></span> W</td>
</tr>
<tr>
<td>Maximum power</td><td>{{ totalsdict|lookup:"powermax"}} W</td>
<td>Maximum power</td><td><span id="total_maxpower"></span> W</td>
</tr>
</tbody>
</table>
</p>
</li>
<li class="grid_2">
<div>{{ totalscript|safe }}{{ totaldiv|safe }}</div>
<div id="id_chart">
{{ totaldiv|safe }}
</div>
</li>
{% for ddict in typedicts %}
@@ -71,16 +96,16 @@
<td>Number of workouts</td><td>{{ ddict|lookup:"nrworkouts"}}</td>
</tr>
<tr>
<td>Average heart rate</td><td>{{ ddict|lookup:"hrmean"}} bpm</td>
<td>Average heart rate</td><td><span id="{{ ddict|lookup:'id'}}_hr"></span> bpm</td>
</tr>
<tr>
<td>Maximum heart rate</td><td>{{ ddict|lookup:"hrmax"}} bpm</td>
<td>Maximum heart rate</td><td><span id="{{ ddict|lookup:'id' }}_hrmax"></span> bpm</td>
</tr>
<tr>
<td>Average power</td><td>{{ ddict|lookup:"powermean"}} W</td>
<td>Average power</td><td><span id="{{ ddict|lookup:'id'}}_power"></span> W</td>
</tr>
<tr>
<td>Maximum power</td><td>{{ ddict|lookup:"powermax"}} W</td>
<td>Maximum power</td><td><span id="{{ ddict|lookup:'id'}}_powermax"></span> W</td>
</tr>
</tbody>
</table>
@@ -92,6 +117,45 @@
{% endblock %}
{% block scripts %}
<script type='text/javascript'
src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js'>
</script>
<script>
$(function($) {
console.log('loading script for chart');
$.getJSON(window.location.protocol + '//'+window.location.host + '/rowers/history/user/{{ rower.user.id }}/data/?startdate={{ startdate|date:"Y-m-d" }}&{{ enddate|date:"Y-m-d" }}&workouttype={{ workouttype }}', function(json) {
var script = json.script;
var div = json.div;
var totalsdict = json.totalsdict
var listofdicts = json.listofdicts
$("#id_sitready").remove();
$("#id_chart").append(div);
console.log(div);
// $("#id_script").append("<s"+"cript>"+script+"</s"+"cript>");
$("#id_script").append(script);
$("#total_hr").append(totalsdict.hrmean);
$("#total_maxhr").append(totalsdict.hrmax);
$("#total_power").append(totalsdict.powermean);
$("#total_maxpower").append(totalsdict.powermax);
listofdicts.forEach(function(item){
var id = "#"+item.id+"_hr";
$(id).append(item.hrmean);
id = "#"+item.id+"_hrmax";
$(id).append(item.hrmax);
id = "#"+item.id+"_power";
$(id).append(item.powermean);
id = "#"+item.id+"_powermax";
$(id).append(item.powermax);
})
});
});
</script>
{% endblock %}
{% block sidebar %}

View File

@@ -755,6 +755,8 @@ urlpatterns = [
re_path(r'^access/(?P<key>\w+)/$', views.sharedPage, name="sharedPage"),
re_path(r'^history/user/(?P<userid>\d+)/$',views.history_view,name="history_view"),
re_path(r'^history/$',views.history_view,name="history_view"),
re_path(r'^history/user/(?P<userid>\d+)/data/$',views.history_view_data,name="history_view_data"),
re_path(r'^history/data/$',views.history_view_data,name="history_view_data"),
]
if settings.DEBUG:

View File

@@ -4658,32 +4658,156 @@ class AlertDelete(DeleteView):
def history_view(request,userid=0):
r = getrequestrower(request,userid=userid)
form = HistorySelectForm()
usertimezone = pytz.timezone(r.defaulttimezone)
if request.GET.get('startdate'):
startdate,enddate = get_dates_timeperiod(request)
activity_startdate = datetime.datetime(
startdate.year,startdate.month,startdate.day
).replace(hour=0,minute=0,second=0).astimezone(usertimezone)
activity_enddate = datetime.datetime(
enddate.year,enddate.month,enddate.day
).replace(hour=23,minute=59,second=59).astimezone(usertimezone)
else:
activity_enddate = timezone.now()
activity_enddate = activity_enddate.replace(hour=23,minute=59,second=59).astimezone(usertimezone)
activity_startdate = activity_enddate-datetime.timedelta(days=15)
activity_startdate = activity_startdate.replace(hour=0,minute=0,second=0).astimezone(usertimezone)
typeselect = 'All'
if request.GET.get('workouttype'):
typeselect = request.GET.get('workouttype')
if typeselect not in mytypes.checktypes:
typeselect = 'All'
form = HistorySelectForm(initial={'startdate':activity_startdate,
'enddate':activity_enddate,
'workouttype':typeselect})
g_workouts = Workout.objects.filter(
user=r,
startdatetime__gte=activity_startdate,
startdatetime__lte=activity_enddate,
duplicate=False,
privacy='visible'
).order_by("-startdatetime")
ids = [w.id for w in g_workouts]
columns = ['hr','power','time']
totalmeters,totalhours, totalminutes = get_totals(g_workouts)
totalminutes = "{totalminutes:02d}".format(totalminutes=totalminutes)
# meters, duration per workout type
wtypes = list(set([w.workouttype for w in g_workouts]))
typechoices = [("All","All")]
for wtype in wtypes:
typechoices.append((wtype,mytypes.workouttypes_ordered[wtype]))
form.fields['workouttype'].choices = typechoices
listofdicts = []
for wtype in wtypes:
a_workouts = g_workouts.filter(workouttype=wtype)
wmeters, whours, wminutes = get_totals(a_workouts)
ddict = {}
ddict['id'] = wtype
ddict['wtype'] = mytypes.workouttypes_ordered[wtype]
ddict['distance'] = wmeters
ddict['duration'] = "{whours}:{wminutes:02d}".format(
whours=whours,
wminutes=wminutes
)
ddict['nrworkouts'] = a_workouts.count()
listofdicts.append(ddict)
# interactive hr pie chart
totalscript = ''
totaldiv = get_call()
totalsdict = {}
totalsdict['duration'] = "{totalhours}:{totalminutes}".format(
totalhours=totalhours,
totalminutes=totalminutes
)
totalsdict['distance'] = totalmeters
totalsdict['nrworkouts'] = g_workouts.count()
breadcrumbs = [
{
'url':'rowers/analysis',
'name':'Analysis',
},
{
'url':reverse('history_view'),
'name': 'History',
},
]
lastseven = timezone.now()-datetime.timedelta(days=7)
lastfourteen = timezone.now()-datetime.timedelta(days=14)
last28 = timezone.now()-datetime.timedelta(days=28)
today = timezone.now()
firstmay = datetime.datetime(year=today.year,month=5,day=1).astimezone(usertimezone)
if firstmay>today:
firstmay = datetime.datetime(year=today.year-1,month=5,day=1)
return render(request,'history.html',
{
'rower':r,
'breadcrumbs':breadcrumbs,
'active':'nav-analysis',
'totalsdict':totalsdict,
'typedicts':listofdicts,
'totalscript':totalscript,
'totaldiv':totaldiv,
'form':form,
'startdate':activity_startdate,
'enddate':activity_enddate,
'lastseven':lastseven,
'lastfourteen':lastfourteen,
'last28':last28,
'today':today,
'workouttype':typeselect,
'firstmay':firstmay,
})
@login_required()
def history_view_data(request,userid=0):
r = getrequestrower(request,userid=userid)
usertimezone = pytz.timezone(r.defaulttimezone)
activity_enddate = timezone.now()
activity_enddate = activity_enddate.replace(hour=23,minute=59,second=59).astimezone(usertimezone)
activity_startdate = activity_enddate-datetime.timedelta(days=15)
activity_startdate = activity_startdate.replace(hour=0,minute=0,second=0).astimezone(usertimezone)
if request.GET.get('startdate'):
startdate,enddate = get_dates_timeperiod(request)
activity_startdate = datetime.datetime(
startdate.year,startdate.month,startdate.day
).replace(hour=0,minute=0,second=0).astimezone(usertimezone)
activity_enddate = datetime.datetime(
enddate.year,enddate.month,enddate.day
).replace(hour=23,minute=59,second=59).astimezone(usertimezone)
else:
activity_enddate = timezone.now()
activity_enddate = activity_enddate.replace(hour=23,minute=59,second=59).astimezone(usertimezone)
activity_startdate = activity_enddate-datetime.timedelta(days=15)
activity_startdate = activity_startdate.replace(hour=0,minute=0,second=0).astimezone(usertimezone)
typeselect = 'All'
if request.GET.get('workouttype'):
typeselect = request.GET.get('workouttype')
if request.method=='POST':
form = HistorySelectForm(request.POST)
if form.is_valid():
startdate = form.cleaned_data['startdate']
enddate = form.cleaned_data['enddate']
typeselect = form.cleaned_data['workouttype']
activity_startdate = datetime.datetime(
startdate.year,startdate.month,startdate.day
).replace(hour=0,minute=0,second=0).astimezone(usertimezone)
activity_enddate = datetime.datetime(
enddate.year,enddate.month,enddate.day
).replace(hour=23,minute=59,second=59).astimezone(usertimezone)
if typeselect not in mytypes.checktypes:
typeselect = 'All'
g_workouts = Workout.objects.filter(
user=r,
@@ -4705,7 +4829,6 @@ def history_view(request,userid=0):
df = dataprep.clean_df_stats(df,workstrokesonly=True,
ignoreadvanced=True)
totalmeters,totalhours, totalminutes = get_totals(g_workouts)
totalminutes = "{totalminutes:02d}".format(totalminutes=totalminutes)
@@ -4716,8 +4839,6 @@ def history_view(request,userid=0):
for wtype in wtypes:
typechoices.append((wtype,mytypes.workouttypes_ordered[wtype]))
form.fields['workouttype'].choices = typechoices
listofdicts = []
for wtype in wtypes:
@@ -4725,6 +4846,7 @@ def history_view(request,userid=0):
wmeters, whours, wminutes = get_totals(a_workouts)
ddict = {}
ddict['wtype'] = mytypes.workouttypes_ordered[wtype]
ddict['id'] = wtype
ddict['distance'] = wmeters
ddict['duration'] = "{whours}:{wminutes:02d}".format(
whours=whours,
@@ -4745,23 +4867,6 @@ def history_view(request,userid=0):
ddict['nrworkouts'] = a_workouts.count()
listofdicts.append(ddict)
# interactive hr pie chart
if typeselect == 'All':
totalscript,totaldiv = interactive_hr_piechart(df,r,'All Workouts')
else:
a_workouts = g_workouts.filter(workouttype=typeselect)
ddf = getsmallrowdata_db(columns,ids=[w.id for w in a_workouts])
try:
ddf['deltat'] = ddf['time'].diff()
except KeyError:
pass
ddf = dataprep.clean_df_stats(ddf,workstrokesonly=True,
ignoreadvanced=True)
totalscript, totaldiv = interactive_hr_piechart(ddf,r,mytypes.workouttypes_ordered[typeselect])
# interactive power pie chart
totalsdict = {}
totalsdict['duration'] = "{totalhours}:{totalminutes}".format(
totalhours=totalhours,
@@ -4784,25 +4889,24 @@ def history_view(request,userid=0):
totalsdict['nrworkouts'] = g_workouts.count()
breadcrumbs = [
{
'url':'rowers/analysis',
'name':'Analysis',
},
{
'url':reverse('history_view'),
'name': 'History',
},
]
return render(request,'history.html',
{
'rower':r,
'breadcrumbs':breadcrumbs,
'active':'nav-analysis',
'totalsdict':totalsdict,
'typedicts':listofdicts,
'totalscript':totalscript,
'totaldiv':totaldiv,
'form':form,
})
# interactive hr pie chart
if typeselect == 'All':
totalscript,totaldiv = interactive_hr_piechart(df,r,'All Workouts')
else:
a_workouts = g_workouts.filter(workouttype=typeselect)
ddf = getsmallrowdata_db(columns,ids=[w.id for w in a_workouts])
try:
ddf['deltat'] = ddf['time'].diff()
except KeyError:
pass
ddf = dataprep.clean_df_stats(ddf,workstrokesonly=True,
ignoreadvanced=True)
totalscript, totaldiv = interactive_hr_piechart(ddf,r,mytypes.workouttypes_ordered[typeselect])
return JSONResponse({
'script':totalscript,
'div':totaldiv,
'totalsdict':totalsdict,
'listofdicts':listofdicts,
})

View File

@@ -467,6 +467,7 @@ def getrequestrower(request,rowerid=0,userid=0,notpermanent=False):
raise Http404("Rower doesn't exist")
if r.user == request.user:
request.session['rowerid'] = r.id
return r
if userid != 0 and not is_rower_team_member(request.user,u.rower):
@@ -476,6 +477,7 @@ def getrequestrower(request,rowerid=0,userid=0,notpermanent=False):
if notpermanent == False:
request.session['rowerid'] = r.id
request.session['rowerid'] = r.id
return r
def getrequestplanrower(request,rowerid=0,userid=0,notpermanent=False):