diff --git a/rowers/plannedsessions.py b/rowers/plannedsessions.py index 1f9c708d..6168cb56 100644 --- a/rowers/plannedsessions.py +++ b/rowers/plannedsessions.py @@ -16,7 +16,7 @@ queuelow = django_rq.get_queue('low') queuehigh = django_rq.get_queue('low') from rowers.models import ( - Rower, Workout, + Rower, Workout,Team, GeoCourse, TrainingMicroCycle,TrainingMesoCycle,TrainingMacroCycle, TrainingPlan,PlannedSession, ) @@ -70,9 +70,57 @@ def timefield_to_seconds_duration(t): duration += t.microsecond/1.e6 return duration - + +def get_session_metrics(ps): + rowers = ps.rower.all() + rscore = [] + trimp = [] + duration = [] + distance = [] + firstname = [] + lastname = [] + + for r in rowers: + rscorev = 0 + trimpv = 0 + durationv = 0 + distancev = 0 + + + ws = Workout.objects.filter(user=r,plannedsession=ps) + if len(ws) != 0: + for w in ws: + distancev += w.distance + durationv += timefield_to_seconds_duration(w.duration) + trimpv += dataprep.workout_trimp(w) + rscorev += dataprep.workout_rscore(w) + + + durationv /= 60. + + trimp.append(int(trimpv)) + duration.append(int(durationv)) + distance.append(int(distancev)) + rscore.append(int(rscorev)) + firstname.append(r.user.first_name) + lastname.append(r.user.last_name) + + thedict = { + 'first_name':firstname, + 'last_name':lastname, + 'duration':duration, + 'distance':distance, + 'rscore':rscore, + 'trimp':trimp + } + + return thedict + def is_session_complete(r,ps): status = 'not done' + + if r not in ps.rower.all(): + return 0,'not assigned' ws = Workout.objects.filter(user=r,plannedsession=ps) @@ -208,6 +256,25 @@ def get_dates_timeperiod(timeperiod): return startdate,enddate +def get_sessions_manager(m,teamid=0,startdate=date.today(), + enddate=date.today()+timezone.timedelta(+1000)): + if teamid: + t = Team.objects.get(id=teamid) + sps = PlannedSession.objects.filter( + team__in=[t], + manager=m, + startdate__lte=enddate, + enddate__gte=startdate, + ).order_by("startdate","enddate") + else: + sps = PlannedSession.objects.filter( + manager=m, + startdate__lte=enddate, + enddate__gte=startdate, + ).order_by("startdate","enddate") + + return sps + def get_sessions(r,startdate=date.today(), enddate=date.today()+timezone.timedelta(+1000)): @@ -219,17 +286,6 @@ def get_sessions(r,startdate=date.today(), return sps -def get_sessions_manager(manager,startdate=date.today(), - enddate=date.today()+timezone.timedelta(+1000)): - - sps = PlannedSession.objects.filter( - manager=manager, - startdate__lte=enddate, - enddate__gte=startdate, - ).order_by("startdate","enddate").exclude(team__isnull=True) - - return sps - def get_workouts_session(r,ps): ws = Workout.objects.filter(user=r,plannedsession=ps) diff --git a/rowers/templates/plannedsessionscoach.html b/rowers/templates/plannedsessionscoach.html new file mode 100644 index 00000000..8a888c22 --- /dev/null +++ b/rowers/templates/plannedsessionscoach.html @@ -0,0 +1,181 @@ +{% extends "base.html" %} +{% load staticfiles %} +{% load rowerfilters %} + +{% block title %}Planned Sessions{% endblock %} + +{% block content %} +
+ {% include "planningbuttons.html" %} +
+
+ {% if theteam %} +

Coach Overview. Team {{ theteam.name }}

+ {% else %} +

Coach Overview

+ {% endif %} +
+ +{% if user.is_authenticated and user|is_manager %} + + +{% endif %} + +
+ + + + + + + {% for r in rowers %} + + {% endfor %} + + + + {% for key, thedict in statusdict.items %} + + + + + {% for r in rowers %} + + {% endfor %} + + {% endfor %} + +
On or afterOn or beforeName
+ {{ r.user.first_name }} {{ r.user.last_name }} +
+ {{ thedict|lookup:'startdate'|date:"Y-m-d" }} + + {{ thedict|lookup:'enddate'|date:"Y-m-d" }} + + + {{ thedict|lookup:'name' }} + + + {% if thedict|lookup:'results'|lookup:r.id == 'completed' %} +   + {% elif thedict|lookup:'results'|lookup:r.id == 'partial' %} +   + {% elif thedict|lookup:'results'|lookup:r.id == 'not done' %} +   + {% elif thedict|lookup:'results'|lookup:r.id == 'not assigned' %} +   + {% else %} +   + {% endif %} +
+ + {% if unmatchedworkouts %} +

Workouts that are not linked to any session

+ + + + + + + + + + + + + + + + {% for workout in unmatchedworkouts %} + + + + + {% if workout.user.user == user or user == team.manager %} + {% if workout.name != '' %} + + {% else %} + + {% endif %} + {% else %} + {% if workout.name != '' %} + + {% else %} + + {% endif %} + {% endif %} + + + + + + + {% endfor %} + +
Rower Date Time Name Type Distance Duration Avg HR Max HR
{{ workout.user.user.first_name }} {{ workout.user.user.last_name }} {{ workout.date|date:"Y-m-d" }} {{ workout.starttime|date:"H:i" }} + + {{ workout.name }} + + + No Name + {{ workout.name }}No Name {{ workout.workouttype }} {{ workout.distance }}m {{ workout.duration |durationprint:"%H:%M:%S.%f" }} {{ workout.averagehr }} {{ workout.maxhr }}
+ + + {% endif %} + +
+ + + + +{% endblock %} diff --git a/rowers/templates/plannedsessionview.html b/rowers/templates/plannedsessionview.html index be61c544..b15bbde9 100644 --- a/rowers/templates/plannedsessionview.html +++ b/rowers/templates/plannedsessionview.html @@ -9,6 +9,17 @@ {% include "planningbuttons.html" %} +
+
+ {% if user.is_authenticated and psdict.id.1|is_session_manager:user %} + + Edit Session + {% else %} +   + {% endif %} +
+
+

Session {{ psdict.name.1 }}

@@ -22,9 +33,6 @@ {% endfor %} {% endfor %}
-

Result

-

Status: {{ status }}

-

Percentage complete: {{ ratio }}

- - +
+
+
+

Result

+

Status: {{ status }}

+

Percentage complete: {{ ratio }}

+
+ +
{% endblock %} diff --git a/rowers/templates/planningbuttons.html b/rowers/templates/planningbuttons.html index 6f57cfd4..20648d28 100644 --- a/rowers/templates/planningbuttons.html +++ b/rowers/templates/planningbuttons.html @@ -32,12 +32,23 @@ {% endif %}

-
+
{% if user.is_authenticated and user|is_manager %} {% if timeperiod %} Add Team Session {% else %} - Add Team Session + Add Team Session + {% endif %} + {% else %} +   + {% endif %} +
+
+ {% if user.is_authenticated and user|is_manager %} + {% if timeperiod %} + Coach Overview + {% else %} + Coach Overview {% endif %} {% else %}   diff --git a/rowers/templatetags/rowerfilters.py b/rowers/templatetags/rowerfilters.py index bfdf2751..cd9acd8b 100644 --- a/rowers/templatetags/rowerfilters.py +++ b/rowers/templatetags/rowerfilters.py @@ -100,6 +100,16 @@ def ualookup(dict, key): return s +from rowers.models import PlannedSession +@register.filter +def is_session_manager(id,user): + try: + ps = PlannedSession.objects.get(id=id) + except PlannedSession.DoesNotExist: + return False + + return ps.manager == user + @register.filter(name='times') def times(number): return range(number) diff --git a/rowers/urls.py b/rowers/urls.py index d502a7d2..b630c026 100644 --- a/rowers/urls.py +++ b/rowers/urls.py @@ -448,6 +448,11 @@ urlpatterns = [ views.plannedsessions_manage_view), url(r'^sessions/manage/(?P[\w\ ]+.*)$', views.plannedsessions_manage_view), + url(r'^sessions/coach$',views.plannedsessions_coach_view), + url(r'^sessions/coach/(?P[\w\ ]+.*)/team/(?P\d+)$', + views.plannedsessions_coach_view), + url(r'^sessions/coach/(?P[\w\ ]+.*)$', + views.plannedsessions_coach_view), url(r'^sessions/?$',views.plannedsessions_view), url(r'^sessions/rower/(?P\d+)$',views.plannedsessions_view), url(r'^sessions/(?P[\w\ ]+.*)/rower/(?P\d+)$',views.plannedsessions_view), diff --git a/rowers/utils.py b/rowers/utils.py index 27fad934..cdb92131 100644 --- a/rowers/utils.py +++ b/rowers/utils.py @@ -294,6 +294,7 @@ def calculate_age(born): def my_dict_from_instance(instance,model): thedict = {} + thedict['id'] = instance.id for attr, value in instance.__dict__.iteritems(): try: diff --git a/rowers/views.py b/rowers/views.py index 32cf2fb6..eb9a46bc 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -166,6 +166,8 @@ class JSONResponse(HttpResponse): super(JSONResponse, self).__init__(content, **kwargs) + + def getrower(user): try: r = Rower.objects.get(user=user) @@ -176,8 +178,21 @@ def getrower(user): return r +def get_workout(id): + try: + w = Workout.objects.get(id=id) + except Workout.DoesNotExist: + raise Http404("Workout doesn't exist") + return w +def get_workout_permitted(user,id): + w = get_workout(id) + + if (checkworkoutuser(user,w)==False): + raise PermissionDenied("Access denied") + + return w def getvalue(data): perc = 0 @@ -513,12 +528,8 @@ def get_stored_tasks_status(request): @login_required() def get_thumbnails(request,id): - try: - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") - if (checkworkoutuser(request.user,row)==False): - raise PermissionDenied("Access denied") + row = get_workout_permitted(request.user,id) + r = getrower(request.user) result = request.user.is_authenticated() and ispromember(request.user) @@ -557,13 +568,7 @@ def get_thumbnails(request,id): @login_required() def get_testscript(request,id): - try: - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") - if (checkworkoutuser(request.user,row)==False): - raise PermissionDenied("Access denied") - + row = get_workout_permitted(request.user,id) r = getrower(request.user) object = { @@ -780,17 +785,6 @@ def hasplannedsessions(user): return result -def getrower(user): - try: - r = Rower.objects.get(user=user) - except Rower.DoesNotExist: - r = Rower(user=user) - r.save() - - return r - - - # Check if a user is a Pro member def ispromember(user): if not user.is_anonymous(): @@ -1627,10 +1621,7 @@ def workout_tcxemail_view(request,id=0): message = "" successmessage = "" r = getrower(request.user) - try: - w = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + w = get_workout(id) if (checkworkoutuser(request.user,w)): tcxfile,tcxmessg = stravastuff.createstravaworkoutdata(w,dozip=False) if tcxfile == 0: @@ -1674,10 +1665,8 @@ def workout_gpxemail_view(request,id=0): message = "" successmessage = "" r = Rower.objects.get(user=request.user) - try: - w = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + w = get_workout(id) + if (checkworkoutuser(request.user,w)): filename = w.csvfilename row = rdata(filename) @@ -1714,10 +1703,8 @@ def workout_gpxemail_view(request,id=0): def workout_csvemail_view(request,id=0): message = "" r = getrower(request.user) - try: - w = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + w = get_workout(id) + if (checkworkoutuser(request.user,w)): csvfile = w.csvfilename res = myqueue(queuehigh,handle_sendemailcsv,r.user.first_name, @@ -1748,10 +1735,8 @@ def workout_csvemail_view(request,id=0): def workout_csvtoadmin_view(request,id=0): message = "" r = getrower(request.user) - try: - w = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + w = get_workout(id) + csvfile = w.csvfilename res = myqueue(queuehigh, @@ -1784,11 +1769,9 @@ def workout_tp_upload_view(request,id=0): return HttpResponseRedirect("/rowers/me/tpauthorize/") # ready to upload. Hurray - try: - w = Workout.objects.get(id=id) - r = w.user - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + w = get_workout_permitted(request.user,id) + r = w.user + if (checkworkoutuser(request.user,w)): tcxfile = tpstuff.createtpworkoutdata(w) if tcxfile: @@ -1841,11 +1824,8 @@ def workout_strava_upload_view(request,id=0): return HttpResponseRedirect("/rowers/me/stravaauthorize/") else: # ready to upload. Hurray - try: - w = Workout.objects.get(id=id) - r = w.user - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + w = get_workout_permitted(request.user,id) + r = w.user if (checkworkoutuser(request.user,w)): try: tcxfile,tcxmessg = stravastuff.createstravaworkoutdata(w) @@ -1931,11 +1911,9 @@ def workout_strava_upload_view(request,id=0): def workout_c2_upload_view(request,id=0): message = "" # ready to upload. Hurray - try: - w = Workout.objects.get(id=id) - r = w.user - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + w = get_workout(id) + r = w.user + try: message,c2id = c2stuff.workout_c2_upload(request.user,w) @@ -1959,11 +1937,8 @@ def workout_c2_upload_view(request,id=0): @login_required() def workout_runkeeper_upload_view(request,id=0): message = "" - try: - w = Workout.objects.get(id=id) - r = w.user - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + w = get_workout(id) + r = w.user try: thetoken = runkeeper_open(r.user) @@ -2024,11 +1999,8 @@ def workout_runkeeper_upload_view(request,id=0): @login_required() def workout_underarmour_upload_view(request,id=0): message = "" - try: - w = Workout.objects.get(id=id) - r = w.user - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + w = get_workout(id) + r = w.user try: thetoken = underarmour_open(r.user) @@ -2091,11 +2063,8 @@ def workout_underarmour_upload_view(request,id=0): def workout_sporttracks_upload_view(request,id=0): message = "" # ready to upload. Hurray - try: - w = Workout.objects.get(id=id) - r = w.user - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + w = get_workout(id) + r = w.user try: thetoken = sporttracks_open(r.user) @@ -2932,10 +2901,7 @@ def cum_flex(request,theuser=0, # Show the EMpower Oarlock generated Stroke Profile @user_passes_test(ispromember,login_url="/",redirect_field_name=None) def workout_forcecurve_view(request,id=0,workstrokesonly=False): - try: - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout(id) promember=0 mayedit=0 @@ -2989,10 +2955,7 @@ def workout_test_task_view(request,id=0): # Show Stroke power histogram for a workout @login_required() def workout_histo_view(request,id=0): - try: - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout(id) promember=0 mayedit=0 @@ -4081,10 +4044,7 @@ def rankings_view2(request,theuser=0, @user_passes_test(ispromember,login_url="/",redirect_field_name=None) def workout_update_cp_view(request,id=0): - try: - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout(id) if (checkworkoutuser(request.user,row)==False): message = "You are not allowed to edit this workout" @@ -4691,10 +4651,7 @@ def oterankings_view(request,theuser=0, # Reload the workout and calculate the summary from the stroke data (lapIDx) @login_required() def workout_recalcsummary_view(request,id=0): - try: - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout(id) if (checkworkoutuser(request.user,row)==False): message = "You are not allowed to edit this workout" @@ -4728,10 +4685,8 @@ def workout_recalcsummary_view(request,id=0): def workout_makepublic_view(request,id, message='', successmessage=''): - try: - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + + row = get_workout(id) if (checkworkoutuser(request.user,row)==False): message = "You are not allowed to edit this workout" @@ -4762,10 +4717,7 @@ def workout_makepublic_view(request,id, def workout_setprivate_view(request,id, message='', successmessage=''): - try: - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout(id) if (checkworkoutuser(request.user,row)==False): message = "You are not allowed to edit this workout" @@ -5498,10 +5450,18 @@ def multiflex_data(request,userid=0, datadf['days ago'] = map(lambda x : x.days, datadf.date - today) if groupby != 'date': - bins = np.arange(datadf[groupby].min()-binsize, - datadf[groupby].max()+binsize, - binsize) - groups = datadf.groupby(pd.cut(datadf[groupby],bins,labels=False)) + try: + bins = np.arange(datadf[groupby].min()-binsize, + datadf[groupby].max()+binsize, + binsize) + groups = datadf.groupby(pd.cut(datadf[groupby],bins,labels=False)) + except ValueError: + messages.error( + request, + "Unable to compete. Probably not enough data selected" + ) + url = reverse(user_multiflex_select) + return HttpResponseRedirect(url) else: bins = np.arange(datadf['days ago'].min()-binsize, datadf['days ago'].max()+binsize, @@ -6291,10 +6251,8 @@ def workout_comparison_list(request,id=0,message='',successmessage='', workouts = paginator.page(1) except EmptyPage: workouts = paginator.page(paginator.num_pages) - try: - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + + row = get_workout(id) messages.error(request,message) messages.info(request,successmessage) @@ -6371,11 +6329,7 @@ def workout_fusion_list(request,id=0,message='',successmessage='', workouts = paginator.page(1) except EmptyPage: workouts = paginator.page(paginator.num_pages) - try: - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") - + row = get_workout(id) messages.info(request,successmessage) messages.error(request,message) @@ -6490,11 +6444,10 @@ def workout_view(request,id=0): # Resets stroke data to raw data (pace) @user_passes_test(ispromember,login_url="/",redirect_field_name=None) -def workout_undo_smoothenpace_view(request,id=0,message="",successmessage=""): - try: - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") +def workout_undo_smoothenpace_view( + request,id=0,message="",successmessage="" +): + row = get_workout(id) if (checkworkoutuser(request.user,row)==False): message = "You are not allowed to edit this workout" @@ -6523,10 +6476,7 @@ def workout_undo_smoothenpace_view(request,id=0,message="",successmessage=""): # Data smoothing of pace data @user_passes_test(ispromember,login_url="/",redirect_field_name=None) def workout_smoothenpace_view(request,id=0,message="",successmessage=""): - try: - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout(id) if (checkworkoutuser(request.user,row)==False): message = "You are not allowed to edit this workout" @@ -6564,10 +6514,7 @@ def workout_smoothenpace_view(request,id=0,message="",successmessage=""): # Process CrewNerd Summary CSV and update summary @user_passes_test(ispromember,login_url="/",redirect_field_name=None) def workout_crewnerd_summary_view(request,id=0,message="",successmessage=""): - try: - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout(id) if request.method == 'POST': form = CNsummaryForm(request.POST,request.FILES) @@ -6620,10 +6567,7 @@ def workout_crewnerd_summary_view(request,id=0,message="",successmessage=""): def workout_downloadwind_view(request,id=0, airportcode=None, message="",successmessage=""): - try: - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout(id) f1 = row.csvfilename if (checkworkoutuser(request.user,row)==False): @@ -6689,10 +6633,7 @@ def workout_downloadwind_view(request,id=0, def workout_downloadmetar_view(request,id=0, airportcode=None, message="",successmessage=""): - try: - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout(id) f1 = row.csvfilename if (checkworkoutuser(request.user,row)==False): @@ -6757,10 +6698,7 @@ def workout_downloadmetar_view(request,id=0, # Show form to update wind data @user_passes_test(ispromember,login_url="/",redirect_field_name=None) def workout_wind_view(request,id=0,message="",successmessage=""): - try: - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout(id) if (checkworkoutuser(request.user,row)==False): message = "You are not allowed to edit this workout" @@ -6877,10 +6815,7 @@ def workout_wind_view(request,id=0,message="",successmessage=""): # Show form to update River stream data (for river dwellers) @user_passes_test(ispromember,login_url="/",redirect_field_name=None) def workout_stream_view(request,id=0,message="",successmessage=""): - try: - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout(id) if (checkworkoutuser(request.user,row)==False): message = "You are not allowed to edit this workout" @@ -6946,10 +6881,7 @@ def workout_stream_view(request,id=0,message="",successmessage=""): # Form to set average crew weight and boat type, then run power calcs @user_passes_test(ispromember, login_url="/",redirect_field_name=None) def workout_otwsetpower_view(request,id=0,message="",successmessage=""): - try: - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout(id) if (checkworkoutuser(request.user,row)==False): message = "You are not allowed to edit this workout" @@ -7052,10 +6984,7 @@ def workout_otwsetpower_view(request,id=0,message="",successmessage=""): @login_required() def instroke_view(request,id=0): - try: - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout(id) form = WorkoutForm(instance=row) g = GraphImage.objects.filter(workout=row).order_by("-creationdatetime") @@ -7085,10 +7014,7 @@ def instroke_view(request,id=0): # A special Edit page with all the Geeky functionality for the workout @login_required() def workout_geeky_view(request,id=0,message="",successmessage=""): - try: - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout(id) form = WorkoutForm(instance=row) g = GraphImage.objects.filter(workout=row).order_by("-creationdatetime") @@ -7150,10 +7076,7 @@ def workout_geeky_view(request,id=0,message="",successmessage=""): # generate instroke chart @login_required() def instroke_chart(request,id=0,metric=''): - try: - w = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + w = get_workout(id) if (checkworkoutuser(request.user,w)==False): message = "You are not allowed to edit this workout" @@ -7475,10 +7398,7 @@ def cumstats(request,theuser=0, def workout_stats_view(request,id=0,message="",successmessage=""): r = getrower(request.user) - try: - w = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + w = get_workout(id) workstrokesonly = True if request.method == 'POST' and 'workstrokesonly' in request.POST: @@ -7624,10 +7544,8 @@ def workout_stats_view(request,id=0,message="",successmessage=""): # The Advanced edit page @login_required() def workout_advanced_view(request,id=0,message="",successmessage=""): - try: - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout(id) + form = WorkoutForm(instance=row) g = GraphImage.objects.filter(workout=row).order_by("-creationdatetime") for i in g: @@ -7909,12 +7827,7 @@ def workout_workflow_view(request,id): request.session['referer'] = absolute(request)['PATH'] request.session['lastworkout'] = id request.session[translation.LANGUAGE_SESSION_KEY] = USER_LANGUAGE - try: - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") - if (checkworkoutuser(request.user,row)==False): - raise PermissionDenied("Access denied") + row = get_workout_permitted(request.user,id) r = getrower(request.user) result = request.user.is_authenticated() and ispromember(request.user) @@ -8005,11 +7918,7 @@ def workout_flexchart3_view(request,*args,**kwargs): except: favoritenr = -1 - - try: - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout(id) promember=0 mayedit=0 @@ -8228,10 +8137,7 @@ def workout_flexchart3_view(request,*args,**kwargs): # The interactive plot with the colored Heart rate zones def workout_biginteractive_view(request,id=0,message="",successmessage=""): - try: - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout(id) # check if user is owner of this workout @@ -8272,10 +8178,7 @@ def workout_biginteractive_view(request,id=0,message="",successmessage=""): # The interactive plot with wind corrected pace for OTW outings def workout_otwpowerplot_view(request,id=0,message="",successmessage=""): - try: - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout(id) # check if user is owner of this workout @@ -8315,10 +8218,7 @@ def workout_otwpowerplot_view(request,id=0,message="",successmessage=""): @login_required() def workout_export_view(request,id=0, message="", successmessage=""): request.session[translation.LANGUAGE_SESSION_KEY] = USER_LANGUAGE - try: - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout(id) try: thetoken = c2_open(request.user) @@ -8375,10 +8275,7 @@ def workout_export_view(request,id=0, message="", successmessage=""): # @login_required() def workout_unsubscribe_view(request,id=0): - try: - w = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + w = get_workout(id) if w.privacy == 'private' and w.user.user != request.user: return HttpResponseForbidden("Permission error") @@ -8408,10 +8305,7 @@ def workout_unsubscribe_view(request,id=0): # list of comments to a workout @login_required() def workout_comment_view(request,id=0): - try: - w = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + w = get_workout(id) if w.privacy == 'private' and w.user.user != request.user: return HttpResponseForbidden("Permission error") @@ -8511,12 +8405,9 @@ def workout_edit_view(request,id=0,message="",successmessage=""): request.session['referer'] = absolute(request)['PATH'] - try: - # check if valid ID exists (workout exists) - row = Workout.objects.get(id=id) - form = WorkoutForm(instance=row) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout(id) + + form = WorkoutForm(instance=row) if request.method == 'POST': # Form was submitted @@ -8598,11 +8489,7 @@ def workout_edit_view(request,id=0,message="",successmessage=""): #else: # form not POSTed form = WorkoutForm(instance=row) - - try: - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout(id) g = GraphImage.objects.filter(workout=row).order_by("-creationdatetime") for i in g: @@ -8690,12 +8577,7 @@ def workout_map_view(request,id=0): request.session[translation.LANGUAGE_SESSION_KEY] = USER_LANGUAGE request.session['referer'] = absolute(request)['PATH'] - - try: - # check if valid ID exists (workout exists) - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout(id) # create interactive plot f1 = row.csvfilename @@ -8745,13 +8627,8 @@ def workout_edit_view_navionics(request,id=0,message="",successmessage=""): request.session[translation.LANGUAGE_SESSION_KEY] = USER_LANGUAGE request.session['referer'] = absolute(request)['PATH'] - - try: - # check if valid ID exists (workout exists) - row = Workout.objects.get(id=id) - form = WorkoutForm(instance=row) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout(id) + form = WorkoutForm(instance=row) if request.method == 'POST': # Form was submitted @@ -8829,11 +8706,7 @@ def workout_edit_view_navionics(request,id=0,message="",successmessage=""): #else: # form not POSTed form = WorkoutForm(instance=row) - - try: - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout(id) g = GraphImage.objects.filter(workout=row).order_by("-creationdatetime") for i in g: @@ -8918,10 +8791,7 @@ def workout_uploadimage_view(request,id): r = getrower(request.user) - try: - w = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + w = get_workout(id) if not checkworkoutuser(request.user,w): raise PermissionDenied("You are not allowed to edit this workout") @@ -9002,10 +8872,8 @@ def workout_uploadimage_view(request,id): # Generic chart creation @login_required() def workout_add_chart_view(request,id,plotnr=1): - try: - w = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + + w = get_workout(id) plotnr = int(plotnr) @@ -9360,10 +9228,7 @@ def workout_getstravaworkout_view(request,stravaid): id,message = add_workout_from_strokedata(request.user,stravaid,data,strokedata, source='strava', workoutsource='strava') - try: - w = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + w = get_workout(id) w.uploadedtostrava=stravaid w.save() @@ -9664,16 +9529,8 @@ def workout_toggle_ranking(request,id=0): if request.is_ajax(): is_ajax = True - try: - # check if valid ID exists (workout exists) - row = Workout.objects.get(id=id) - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout_permitted(request.user,id) - if not checkworkoutuser(request.user,row): - raise PermissionDenied("You are not allowed to change this workout") - - # we are still here - we own the workout row.rankingpiece = not row.rankingpiece row.save() @@ -10398,12 +10255,7 @@ def workout_summary_restore_view(request,id,message="",successmessage=""): # Split a workout @user_passes_test(ispromember,login_url="/",redirect_field_name=None) def workout_split_view(request,id=id): - try: - row = Workout.objects.get(id=id) - if (checkworkoutuser(request.user,row)==False): - raise PermissionDenied("You are not allowed to edit this workout") - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout_permitted(request.user,id) r = row.user @@ -10533,12 +10385,7 @@ def workout_fusion_view(request,id1=0,id2=1): @login_required() def workout_summary_edit_view(request,id,message="",successmessage="" ): - try: - row = Workout.objects.get(id=id) - if (checkworkoutuser(request.user,row)==False): - raise PermissionDenied("You are not allowed to edit this workout") - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout_permitted(request.user,id) s = "" # still here - this is a workout we may edit @@ -11175,12 +11022,8 @@ def strokedatajson(request,id): POST: Add Stroke data to workout GET: Get stroke data of workout """ - try: - row = Workout.objects.get(id=id) - if (checkworkoutuser(request.user,row)==False): - return HttpResponseForbidden("Permission error") - except Workout.DoesNotExist: - raise Http404("Workout doesn't exist") + row = get_workout_permitted(request.user,id) + try: id = int(id) except ValueError: @@ -12011,6 +11854,68 @@ def plannedsession_teamedit_view(request,timeperiod='thisweek', 'plannedsessions':sps, }) +@user_passes_test(iscoachmember,login_url="/rowers/planmembership/", + redirect_field_name=None) +def plannedsessions_coach_view(request,timeperiod='thisweek', + teamid=0): + + startdate,enddate = get_dates_timeperiod(timeperiod) + + if teamid != 0: + try: + theteam = Team.objects.get(id=teamid) + except Team.DoesNotExist: + theteam = False + else: + theteam = False + + sps = get_sessions_manager(request.user,teamid=teamid, + enddate=enddate, + startdate=startdate) + + rowers = [] + for ps in sps: + rowers += ps.rower.all() + + rowers = list(set(rowers)) + + statusdict = {} + + for ps in sps: + rowerstatus = {} + for r in rowers: + ratio, status = is_session_complete(r,ps) + rowerstatus[r.id] = status + sessiondict = { + 'results':rowerstatus, + 'name': ps.name, + 'startdate': ps.startdate, + 'enddate': ps.enddate, + } + statusdict[ps.id] = sessiondict + + unmatchedworkouts = [] + for r in rowers: + unmatchedworkouts += Workout.objects.filter( + user=r, + plannedsession=None, + date__gte=startdate,date__lte=enddate) + + + myteams = Team.objects.filter(manager=request.user) + + return render(request,'plannedsessionscoach.html', + { + 'myteams':myteams, + 'plannedsessions':sps, + 'statusdict':statusdict, + 'timeperiod':timeperiod, + 'rowers':rowers, + 'theteam':theteam, + 'unmatchedworkouts':unmatchedworkouts, + 'rower':getrower(request.user) + } + ) @login_required() def plannedsessions_view(request,timeperiod='thisweek',rowerid=0): @@ -12319,6 +12224,7 @@ def plannedsession_view(request,id=0,rowerid=0): m = getrower(request.user) + if not rowerid: r = m else: @@ -12333,8 +12239,11 @@ def plannedsession_view(request,id=0,rowerid=0): if ps.manager != request.user and r not in ps.rower.all(): raise PermissionDenied("You do not have access to this session") + resultsdict = get_session_metrics(ps) + resultsdict = pd.DataFrame(resultsdict).transpose().to_dict() psdict = my_dict_from_instance(ps,PlannedSession) + print psdict ws = get_workouts_session(r,ps) @@ -12353,7 +12262,8 @@ def plannedsession_view(request,id=0,rowerid=0): 'manager':m, 'rower':r, 'ratio':ratio, - 'status':status + 'status':status, + 'results':resultsdict, } ) diff --git a/static/css/rowsandall.css b/static/css/rowsandall.css index 36fe4242..f8d66d68 100644 --- a/static/css/rowsandall.css +++ b/static/css/rowsandall.css @@ -139,9 +139,10 @@ cox { .listtable tbody tr:nth-of-type(even) { background-color: #DDD; } .listtable thead th { - font-weight: bold; + font-weight: bold; } + .shortpadded td { padding: 3px 3px } .paddedtable td { padding: 1px 20px }