Merge branch 'release/v12.27'
This commit is contained in:
@@ -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>
|
||||
|
||||
<a href="/rowers/history/?enddate={{ today|date:"Y-m-d" }}&startdate={{ lastfourteen|date:"Y-m-d" }}&workouttype={{ workouttype }}">Past 14 days</a>
|
||||
|
||||
<a href="/rowers/history/?enddate={{ today|date:"Y-m-d" }}&startdate={{ last28|date:"Y-m-d" }}&workouttype={{ workouttype }}">Past 28 days</a>
|
||||
|
||||
<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 %}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user