diff --git a/rowers/forms.py b/rowers/forms.py index faa5d108..b6191619 100644 --- a/rowers/forms.py +++ b/rowers/forms.py @@ -1,6 +1,6 @@ from django import forms from django.contrib.admin.widgets import FilteredSelectMultiple -from rowers.models import Workout +from rowers.models import Workout,Rower,Team from rowers.rows import validate_file_extension,must_be_csv,validate_image_extension from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.models import User @@ -629,3 +629,26 @@ class WorkoutSessionSelectForm(forms.Form): widget = forms.CheckboxSelectMultiple, ) +class PlannedSessionTeamForm(forms.Form): + team = forms.ModelMultipleChoiceField( + queryset=Team.objects.all(), + required=False, + widget=forms.CheckboxSelectMultiple()) + + def __init__(self, user, *args, **kwargs): + super(PlannedSessionTeamForm,self).__init__(*args, **kwargs) + + self.fields['team'].queryset = Team.objects.filter(manager=user) + + +class PlannedSessionTeamMemberForm(forms.Form): + members = forms.ModelMultipleChoiceField( + queryset=Rower.objects.all(), + widget=forms.CheckboxSelectMultiple()) + + def __init__(self, thesession, *args, **kwargs): + super(PlannedSessionTeamMemberForm,self).__init__(*args,**kwargs) + + self.fields['members'].queryset = thesession.rower.all() + + diff --git a/rowers/models.py b/rowers/models.py index bed877e9..60dbce2e 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -523,8 +523,11 @@ class Rower(models.Model): verbose_name='Show Notes for Favorite Charts') def __str__(self): - return self.user.username + return self.user.firstname+' '+self.user.last_name + def __unicode__(self): + return self.user.first_name+' '+self.user.last_name + def clean_email(self): return self.user.email.lower() diff --git a/rowers/plannedsessions.py b/rowers/plannedsessions.py index caca9821..1f9c708d 100644 --- a/rowers/plannedsessions.py +++ b/rowers/plannedsessions.py @@ -215,8 +215,19 @@ def get_sessions(r,startdate=date.today(), rower__in=[r], startdate__lte=enddate, enddate__gte=startdate, - ).order_by("startdate","enddate") + ).order_by("startdate","enddate") + + 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): diff --git a/rowers/templates/plannedsessioncreate.html b/rowers/templates/plannedsessioncreate.html index 63bba657..97cfb0a9 100644 --- a/rowers/templates/plannedsessioncreate.html +++ b/rowers/templates/plannedsessioncreate.html @@ -7,8 +7,8 @@ {% block content %}
{% include "planningbuttons.html" %} -
+

Create Session for {{ rower.user.first_name }} {{ rower.user.last_name }}

@@ -119,7 +119,7 @@ {% csrf_token %}
- +
diff --git a/rowers/templates/plannedsessionedit.html b/rowers/templates/plannedsessionedit.html index 8bf00feb..306028b8 100644 --- a/rowers/templates/plannedsessionedit.html +++ b/rowers/templates/plannedsessionedit.html @@ -39,15 +39,10 @@
{% if user.is_authenticated and user|is_manager %} - diff --git a/rowers/templates/plannedsessions.html b/rowers/templates/plannedsessions.html index d4b1cf6a..ed5fda38 100644 --- a/rowers/templates/plannedsessions.html +++ b/rowers/templates/plannedsessions.html @@ -117,6 +117,57 @@ You have no planned workouts for this period. Planned workouts are created by your coach if you are part of a team. You can create your own planned workouts by purchasing the "Coach" or "Self-Coach" plans. + {% 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 %} + +
Date Time Name Type Distance Duration Avg HR Max HR
{{ 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 %} diff --git a/rowers/templates/plannedsessionsmanage.html b/rowers/templates/plannedsessionsmanage.html index 879fe3cd..fdb8bc6e 100644 --- a/rowers/templates/plannedsessionsmanage.html +++ b/rowers/templates/plannedsessionsmanage.html @@ -59,10 +59,10 @@ {% for member in user|team_rowers %} {{ member.user.first_name }} {{ member.user.last_name }} {% endfor %} + {% endif %} -

Select one session on the left, and one or more workouts on the right to match the workouts to the session. For tests and training sessions, @@ -92,8 +92,6 @@ {% csrf_token %}

- - diff --git a/rowers/templates/plannedsessionteamcreate.html b/rowers/templates/plannedsessionteamcreate.html new file mode 100644 index 00000000..2ecb9a80 --- /dev/null +++ b/rowers/templates/plannedsessionteamcreate.html @@ -0,0 +1,121 @@ +{% extends "base.html" %} +{% load staticfiles %} +{% load rowerfilters %} + +{% block title %}New Planned Session{% endblock %} + +{% block content %} +
+ {% include "planningbuttons.html" %} +
+ +
+
+

Create Team Session

+
+ +
+ +
+
+ {% if form.errors %} +

+ Please correct the error{{ form.errors|pluralize }} below. +

+ {% endif %} + {% csrf_token %} + + + + + +
+

New Session

+ + {{ form.as_table }} +
+
+ +
+ +
+
+{% endblock %} diff --git a/rowers/templates/plannedsessionteamedit.html b/rowers/templates/plannedsessionteamedit.html new file mode 100644 index 00000000..774a4218 --- /dev/null +++ b/rowers/templates/plannedsessionteamedit.html @@ -0,0 +1,137 @@ +{% extends "base.html" %} +{% load staticfiles %} +{% load rowerfilters %} + +{% block title %}New Planned Session{% endblock %} + +{% block content %} +
+ {% include "planningbuttons.html" %} +
+ +
+
+

Edit Team Session

+
+ +
+ +
+
+ {% if form.errors %} +

+ Please correct the error{{ form.errors|pluralize }} below. +

+ {% endif %} + {% csrf_token %} + + + + + +
+

Session {{ plannedsession.name }}

+ + {{ form.as_table }} +
+
+ Delete +
+
+ Clone +
+
+ +
+ +
+
+{% endblock %} diff --git a/rowers/templates/planningbuttons.html b/rowers/templates/planningbuttons.html index 798085eb..6f57cfd4 100644 --- a/rowers/templates/planningbuttons.html +++ b/rowers/templates/planningbuttons.html @@ -21,7 +21,7 @@ {% endif %}

-
+

{% if timeperiod and rower %} Add Session @@ -32,3 +32,15 @@ {% endif %}

+
+ {% if user.is_authenticated and user|is_manager %} + {% if timeperiod %} + Add Team Session + {% else %} + Add Team Session + {% endif %} + {% else %} +   + {% endif %} +
+ diff --git a/rowers/urls.py b/rowers/urls.py index aa23fbc8..d502a7d2 100644 --- a/rowers/urls.py +++ b/rowers/urls.py @@ -398,6 +398,18 @@ urlpatterns = [ url(r'^workout/compare/(?P\d+)/(?P\d+)/(?P\w+.*)/(?P[\w\ ]+.*)/$',views.workout_comparison_view2), url(r'^test\_callback',views.rower_process_testcallback), url(r'^workout/(?P\d+)/test\_strokedata$',views.strokedataform), + + url(r'^sessions/teamcreate$',views.plannedsession_teamcreate_view), + url(r'^sessions/teamcreate/(?P[\w\ ]+.*)$', + views.plannedsession_teamcreate_view), + url(r'^sessions/teamcreate/(?P[\w\ ]+.*)/team/(?P\d+)$', + views.plannedsession_teamcreate_view), + url(r'^sessions/teamcreate/team/(?P\d+)$', + views.plannedsession_teamcreate_view), + + url(r'^sessions/teamedit/(?P\d+)$',views.plannedsession_teamedit_view), + url(r'^sessions/teamedit/(?P\d+)/(?P[\w\ ]+.*)$',views.plannedsession_teamedit_view), + url(r'^sessions/create$',views.plannedsession_create_view), url(r'^sessions/create/rower/(?P\d+)$', views.plannedsession_create_view), diff --git a/rowers/views.py b/rowers/views.py index 9dad3771..64faceb5 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -30,7 +30,8 @@ from rowers.forms import ( LoginForm,DocumentsForm,UploadOptionsForm,ImageForm, TeamUploadOptionsForm,WorkFlowLeftPanelForm,WorkFlowMiddlePanelForm, WorkFlowLeftPanelElement,WorkFlowMiddlePanelElement, - LandingPageForm,PlannedSessionSelectForm,WorkoutSessionSelectForm + LandingPageForm,PlannedSessionSelectForm,WorkoutSessionSelectForm, + PlannedSessionTeamForm,PlannedSessionTeamMemberForm, ) from django.core.urlresolvers import reverse from django.core.exceptions import PermissionDenied @@ -11809,6 +11810,208 @@ def plannedsession_create_view(request,timeperiod='thisweek',rowerid=0): 'timeperiod':timeperiod, }) +# Manager creates sessions for entire team +@user_passes_test(iscoachmember,login_url="/rowers/planmembership/", + redirect_field_name=None) +def plannedsession_teamcreate_view(request,timeperiod='thisweek', + teamid=0): + + + teams = Team.objects.filter(manager=request.user) + teamchoices = [(team.id, team.name) for team in teams] + teaminitial = [str(teams[0].id)] + + startdate,enddate = get_dates_timeperiod(timeperiod) + + sps = [] + for team in teams: + res = get_sessions_manager(request.user,startdate=startdate,enddate=enddate) + sps += res + + sps = list(set(sps)) + + if request.method == 'POST': + sessioncreateform = PlannedSessionForm(request.POST) + sessionteamselectform = PlannedSessionTeamForm( + request.user,request.POST + ) + if sessioncreateform.is_valid(): + cd = sessioncreateform.cleaned_data + startdate = cd['startdate'] + enddate = cd['enddate'] + sessiontype = cd['sessiontype'] + sessionmode = cd['sessionmode'] + criterium = cd['criterium'] + sessionvalue = cd['sessionvalue'] + sessionunit = cd['sessionunit'] + comment = cd['comment'] + name = cd['name'] + + if sessionunit == 'min': + sessionmode = 'time' + elif sessionunit in ['km','m']: + sessionmode = 'distance' + + ps = PlannedSession( + name=name, + startdate=startdate, + enddate=enddate, + sessiontype=sessiontype, + sessionmode=sessionmode, + sessionvalue=sessionvalue, + sessionunit=sessionunit, + comment=comment, + criterium=criterium, + manager=request.user) + + ps.save() + + # some logic when to add all selected rowers + if sessionteamselectform.is_valid(): + cd = sessionteamselectform.cleaned_data + teams = cd['team'] + for team in teams: + add_team_session(team,ps) + rs = Rower.objects.filter(team__in=[team]) + for r in rs: + add_rower_session(r,ps) + + + url = reverse(plannedsession_teamcreate_view, + kwargs = { + 'timeperiod':timeperiod, + }) + return HttpResponseRedirect(url) + else: + sessioncreateform = PlannedSessionForm() + sessionteamselectform = PlannedSessionTeamForm( + request.user + ) + + return render(request,'plannedsessionteamcreate.html', + { + 'teams':get_my_teams(request.user), + 'form':sessioncreateform, + 'teamform':sessionteamselectform, + 'timeperiod':timeperiod, + 'plannedsessions':sps, + }) + +# Manager edits sessions for entire team +@user_passes_test(iscoachmember,login_url="/rowers/planmembership/", + redirect_field_name=None) +def plannedsession_teamedit_view(request,timeperiod='thisweek', + sessionid=0): + + try: + ps = PlannedSession.objects.get(id=sessionid) + except PlannedSession.DoesNotExist: + raise Http404("This session doesn't exist") + if not ps.manager == request.user: + raise Http404("You are not the manager of this session") + + teams = Team.objects.filter(manager=request.user) + teamchoices = [(team.id, team.name) for team in teams] + + teaminitial = ps.team.all() + + startdate,enddate = get_dates_timeperiod(timeperiod) + + sps = [] + rowers = [] + for team in teams: + res = get_sessions_manager(request.user,startdate=startdate,enddate=enddate) + sps += res + rowers += Rower.objects.filter(team__in=[team]) + + rowers = list(set(rowers)) + + + sps = list(set(sps)) + + if request.method == 'POST': + sessioncreateform = PlannedSessionForm(request.POST,instance=ps) + sessionteamselectform = PlannedSessionTeamForm( + request.user,request.POST + ) + sessionrowerform = PlannedSessionTeamMemberForm(ps,request.POST) + if sessioncreateform.is_valid(): + cd = sessioncreateform.cleaned_data + + if cd['sessionunit'] == 'min': + cd['sessionmode'] = 'time' + elif cd['sessionunit'] in ['km','m']: + cd['sessionmode'] = 'distance' + + + res,message = update_plannedsession(ps,cd) + + if res: + messages.info(request,message) + else: + messages.error(request,message) + + + # some logic when to add all selected rowers + if sessionteamselectform.is_valid(): + cd = sessionteamselectform.cleaned_data + selectedteams = cd['team'] + for team in teams: + if team in selectedteams: + add_team_session(team,ps) + rs = Rower.objects.filter(team__in=[team]) + for r in rs: + add_rower_session(r,ps) + else: + remove_team_session(team,ps) + else: + selectedteams = [] + + + if sessionrowerform.is_valid(): + cd = sessionrowerform.cleaned_data + selectedrowers = cd['members'] + for r in rowers: + if r in selectedrowers: + add_rower_session(r,ps) + else: + remove_rower_session(r,ps) + for t in selectedteams: + if t in r.team.all(): + add_rower_session(r,ps) + + + url = reverse(plannedsession_teamedit_view, + kwargs = { + 'sessionid':sessionid, + 'timeperiod':timeperiod, + }) + return HttpResponseRedirect(url) + else: + sessioncreateform = PlannedSessionForm(instance=ps) + sessionteamselectform = PlannedSessionTeamForm( + request.user + ) + sessionteamselectform.fields['team'].initial = teaminitial + sessionrowerform = PlannedSessionTeamMemberForm( + ps + ) + + + sessionrowerform.fields['members'].initial = ps.rower.all() + + return render(request,'plannedsessionteamedit.html', + { + 'plannedsession':ps, + 'teams':get_my_teams(request.user), + 'form':sessioncreateform, + 'teamform':sessionteamselectform, + 'rowersform':sessionrowerform, + 'timeperiod':timeperiod, + 'plannedsessions':sps, + }) + + @login_required() def plannedsessions_view(request,timeperiod='thisweek',rowerid=0): @@ -11840,7 +12043,12 @@ def plannedsessions_view(request,timeperiod='thisweek',rowerid=0): completiondate[ps.id] = date else: completiondate[ps.id] = '' - + + unmatchedworkouts = Workout.objects.filter( + user=r, + plannedsession=None, + date__gte=startdate,date__lte=enddate) + return render(request,'plannedsessions.html', { 'teams':get_my_teams(request.user), @@ -11850,6 +12058,7 @@ def plannedsessions_view(request,timeperiod='thisweek',rowerid=0): 'completeness':completeness, 'actualvalue':actualvalue, 'completiondate':completiondate, + 'unmatchedworkouts':unmatchedworkouts, }) @login_required() @@ -11926,7 +12135,10 @@ def plannedsessions_manage_view(request,timeperiod='thisweek',rowerid=0, else: selectedworkouts = [] - + if len(selectedworkouts)==0: + for w in ws: + remove_workout_plannedsession(w,ps) + if selectedworkouts: workouts = Workout.objects.filter(user=r,id__in=selectedworkouts) for w in ws: @@ -11997,6 +12209,9 @@ def plannedsession_clone_view(request,id=0,rowerid=0, if ps.manager != request.user: raise Http404("You are not allowed to clone this planned session") + rowers = ps.rower.all() + teams = ps.team.all() + ps.pk = None deltadays = ps.enddate-ps.startdate @@ -12007,7 +12222,10 @@ def plannedsession_clone_view(request,id=0,rowerid=0, ps.save() - add_rower_session(r,ps) + for rower in rowers: + add_rower_session(rower,ps) + for team in teams: + add_team_session(team,ps) url = reverse(plannedsession_edit_view, kwargs = { @@ -12024,7 +12242,7 @@ def plannedsession_clone_view(request,id=0,rowerid=0, @user_passes_test(hasplannedsessions,login_url="/rowers/planmembership/", redirect_field_name=None) def plannedsession_edit_view(request,id=0,timeperiod='thisweek',rowerid=0): - + if rowerid==0: r = getrower(request.user) else: @@ -12046,6 +12264,14 @@ def plannedsession_edit_view(request,id=0,timeperiod='thisweek',rowerid=0): if ps.manager != request.user: raise Http404("You are not allowed to edit this planned session") + if ps.team.all() or len(ps.rower.all())>1: + url = reverse(plannedsession_teamedit_view, + kwargs={ + 'timeperiod':timeperiod, + 'sessionid':id, + }) + return HttpResponseRedirect(url) + if request.method == 'POST': sessioncreateform = PlannedSessionForm(request.POST,instance=ps) if sessioncreateform.is_valid():