From fdc4ec15ea66269b611ab2cb0c1fb318b3690889 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Sat, 10 Feb 2018 17:16:10 +0100 Subject: [PATCH 1/3] added other rowers result to session view --- rowers/plannedsessions.py | 47 +++++++++++++++++++++++- rowers/templates/plannedsessionview.html | 39 +++++++++++++++++--- rowers/views.py | 6 ++- 3 files changed, 85 insertions(+), 7 deletions(-) diff --git a/rowers/plannedsessions.py b/rowers/plannedsessions.py index 1f9c708d..e1495525 100644 --- a/rowers/plannedsessions.py +++ b/rowers/plannedsessions.py @@ -70,7 +70,52 @@ 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' diff --git a/rowers/templates/plannedsessionview.html b/rowers/templates/plannedsessionview.html index be61c544..c01326e3 100644 --- a/rowers/templates/plannedsessionview.html +++ b/rowers/templates/plannedsessionview.html @@ -9,6 +9,7 @@ {% include "planningbuttons.html" %} +

Session {{ psdict.name.1 }}

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

Result

-

Status: {{ status }}

-

Percentage complete: {{ ratio }}

- - +
+
+
+

Result

+

Status: {{ status }}

+

Percentage complete: {{ ratio }}

+
+ +
{% endblock %} diff --git a/rowers/views.py b/rowers/views.py index 8dfe64dc..2c9fee76 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -12162,6 +12162,7 @@ def plannedsession_view(request,id=0,rowerid=0): m = getrower(request.user) + if not rowerid: r = m else: @@ -12176,6 +12177,8 @@ 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) @@ -12196,7 +12199,8 @@ def plannedsession_view(request,id=0,rowerid=0): 'manager':m, 'rower':r, 'ratio':ratio, - 'status':status + 'status':status, + 'results':resultsdict, } ) From 8884e2f7b12035cd3a2078e1b15456cc11eccf53 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Sun, 11 Feb 2018 13:55:51 +0100 Subject: [PATCH 2/3] session coach view v1 --- rowers/plannedsessions.py | 35 ++++-- rowers/templates/plannedsessionscoach.html | 126 +++++++++++++++++++++ rowers/templates/plannedsessionview.html | 10 ++ rowers/templatetags/rowerfilters.py | 10 ++ rowers/urls.py | 5 + rowers/utils.py | 1 + rowers/views.py | 53 +++++++++ 7 files changed, 228 insertions(+), 12 deletions(-) create mode 100644 rowers/templates/plannedsessionscoach.html diff --git a/rowers/plannedsessions.py b/rowers/plannedsessions.py index e1495525..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, ) @@ -118,6 +118,9 @@ def get_session_metrics(ps): 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) @@ -253,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)): @@ -264,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..dceb066a --- /dev/null +++ b/rowers/templates/plannedsessionscoach.html @@ -0,0 +1,126 @@ +{% 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 %} +
+
+ + + + +{% endblock %} diff --git a/rowers/templates/plannedsessionview.html b/rowers/templates/plannedsessionview.html index c01326e3..b15bbde9 100644 --- a/rowers/templates/plannedsessionview.html +++ b/rowers/templates/plannedsessionview.html @@ -9,6 +9,16 @@ {% include "planningbuttons.html" %} +
+
+ {% if user.is_authenticated and psdict.id.1|is_session_manager:user %} + + Edit Session + {% else %} +   + {% endif %} +
+

Session {{ psdict.name.1 }}

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 2c9fee76..77cbd9ba 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -11854,6 +11854,58 @@ 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 + + myteams = Team.objects.filter(manager=request.user) + + return render(request,'plannedsessionscoach.html', + { + 'myteams':myteams, + 'plannedsessions':sps, + 'statusdict':statusdict, + 'timeperiod':timeperiod, + 'rowers':rowers, + 'theteam':theteam, + } + ) @login_required() def plannedsessions_view(request,timeperiod='thisweek',rowerid=0): @@ -12181,6 +12233,7 @@ def plannedsession_view(request,id=0,rowerid=0): resultsdict = pd.DataFrame(resultsdict).transpose().to_dict() psdict = my_dict_from_instance(ps,PlannedSession) + print psdict ws = get_workouts_session(r,ps) From c185d680c6a3044581f1c201704e4ada434923a0 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Sun, 11 Feb 2018 14:23:33 +0100 Subject: [PATCH 3/3] navigation for coach view --- rowers/templates/plannedsessionscoach.html | 57 +++++++++++++++++++++- rowers/templates/planningbuttons.html | 15 +++++- rowers/views.py | 10 ++++ static/css/rowsandall.css | 3 +- 4 files changed, 81 insertions(+), 4 deletions(-) diff --git a/rowers/templates/plannedsessionscoach.html b/rowers/templates/plannedsessionscoach.html index dceb066a..8a888c22 100644 --- a/rowers/templates/plannedsessionscoach.html +++ b/rowers/templates/plannedsessionscoach.html @@ -43,7 +43,7 @@ {% if user.is_authenticated and user|is_manager %} -
+
{% 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/views.py b/rowers/views.py index 77cbd9ba..eb9a46bc 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -11894,6 +11894,14 @@ def plannedsessions_coach_view(request,timeperiod='thisweek', } 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', @@ -11904,6 +11912,8 @@ def plannedsessions_coach_view(request,timeperiod='thisweek', 'timeperiod':timeperiod, 'rowers':rowers, 'theteam':theteam, + 'unmatchedworkouts':unmatchedworkouts, + 'rower':getrower(request.user) } ) 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 }