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 8dfe64dc..eb9a46bc 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -11854,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): @@ -12162,6 +12224,7 @@ def plannedsession_view(request,id=0,rowerid=0): m = getrower(request.user) + if not rowerid: r = m else: @@ -12176,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) @@ -12196,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 }