From 357193c9c88457860bbb3d282c882f1e5d613789 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Mon, 10 Sep 2018 15:10:43 +0200 Subject: [PATCH] next steps in training plan/target - delete cycles - change user --- rowers/models.py | 2 +- rowers/templates/trainingplan.html | 42 +++++- rowers/templates/trainingplan_create.html | 22 ++- rowers/templates/trainingplan_delete.html | 30 ++++ rowers/urls.py | 8 +- rowers/views.py | 159 ++++++++++++++++------ static/css/rowsandall.css | 8 ++ 7 files changed, 219 insertions(+), 52 deletions(-) create mode 100644 rowers/templates/trainingplan_delete.html diff --git a/rowers/models.py b/rowers/models.py index c33b46d8..924c4a4a 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -992,7 +992,7 @@ class TrainingPlan(models.Model): firstname = self.rower.user.first_name lastname = self.rower.user.last_name - stri = u'Training Plan for {firstname} {lastname} {s} - {e}: {n}'.format( + stri = u'Training Plan for {firstname} {lastname} {s} - {e}: {name}'.format( s = startdate.strftime('%Y-%m-%d'), e = enddate.strftime('%Y-%m-%d'), firstname = firstname, diff --git a/rowers/templates/trainingplan.html b/rowers/templates/trainingplan.html index 4477b255..62dbb83c 100644 --- a/rowers/templates/trainingplan.html +++ b/rowers/templates/trainingplan.html @@ -18,7 +18,18 @@

Training Plan - {{ plan.name }}

-

Edit

+

This plan starts on {{ plan.startdate }} and ends on {{ plan.enddate }}. The training plan target is: {{ plan.target.name }} on {{ plan.target.date }}.

+

Edit the plan

+

Click on the plan cycles below to edit their names, start and end dates. The gray "filler" + cycles are generated, adjusted and deleted automatically to ensure the entire plan + duration is covered with non-overlapping cycles. + Once you edit a filler cycle, it become a user-defined cycle, which cannot be deleted + by the system.

+

A good way to organize the plan is to think of micro cycles as training weeks. Macro cycles + are typically used to address specific phases of preparation and to indicate the racing + season and may span several months. + Meso cycles can be used to group sequences of three to five light, medium and + hard weeks.

Macro Cycles

@@ -33,26 +44,45 @@
{% for key,macrocycle in cycles.items %}
-
+ {% if macrocycle.0.type == 'filler' %} +
+ {% else %} +
+ {% endif %}

{{ macrocycle.0.name }} ({{ macrocycle.0.startdate }} - {{ macrocycle.0.enddate }})

-

edit

+

edit + / + delete

{% for key, mesocycle in macrocycle.1.items %} + {% if mesocycle.0.type == 'filler' %} +
+ {% else %}
+ {% endif %}

{{ mesocycle.0.name }} ({{ mesocycle.0.startdate }} - {{ mesocycle.0.enddate }})

-

edit

+

edit + / + delete

{% for microcycle in mesocycle.1 %} -
+ {% if microcycle.type == 'filler' %} +
+ {% else %} +
+ {% endif %}

{{ microcycle.name }} ({{ microcycle.startdate }} - {{ microcycle.enddate }})

-

edit

+

+ edit + / + delete

{% endfor %} diff --git a/rowers/templates/trainingplan_create.html b/rowers/templates/trainingplan_create.html index 3d32874b..83a7654b 100644 --- a/rowers/templates/trainingplan_create.html +++ b/rowers/templates/trainingplan_create.html @@ -15,7 +15,23 @@ } -
+
+ {% if user.is_authenticated and user|is_manager %} + + {% endif %} +
+ + +

Training Targets

@@ -64,8 +80,8 @@
-
- +
+

Plans

diff --git a/rowers/templates/trainingplan_delete.html b/rowers/templates/trainingplan_delete.html new file mode 100644 index 00000000..ffb9362c --- /dev/null +++ b/rowers/templates/trainingplan_delete.html @@ -0,0 +1,30 @@ +{% extends "base.html" %} +{% load staticfiles %} +{% load rowerfilters %} + +{% block title %}Rowsandall Training Plans{% endblock %} + +{% block scripts %} + +{% endblock %} + +{% block content %} + + +
+ +
+ {% csrf_token %} +

Are you sure you want to delete {{ object }}?

+
+ +
+
+ + +
+ {% endblock %} diff --git a/rowers/urls.py b/rowers/urls.py index 7210e921..f89c1716 100644 --- a/rowers/urls.py +++ b/rowers/urls.py @@ -420,8 +420,12 @@ 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'^createplan$',views.rower_create_trainingplan), - url(r'^createplan/(?P\d+)$',views.rower_create_trainingplan), - url(r'^deleteplan/(?P\d+)$',views.rower_delete_trainingplan), + url(r'^createplan/(?P\d+)$',views.rower_create_trainingplan), + url(r'^deleteplan/(?P\d+)$',views.TrainingPlanDelete.as_view()), + url(r'^deletemicrocycle/(?P\d+)$',views.MicroCycleDelete.as_view()), + url(r'^deletemesocycle/(?P\d+)$',views.MesoCycleDelete.as_view()), + url(r'^deletemacrocycle/(?P\d+)$',views.MacroCycleDelete.as_view()), +# url(r'^deleteplan/(?P\d+)$',views.rower_delete_trainingplan), url(r'^plan/(?P\d+)$',views.rower_trainingplan_view), url(r'^macrocycle/(?P\d+)$',views.TrainingMacroCycleUpdate.as_view()), url(r'^mesocycle/(?P\d+)$',views.TrainingMesoCycleUpdate.as_view()), diff --git a/rowers/views.py b/rowers/views.py index 63d16ae5..4f5795f5 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -28,7 +28,7 @@ import isodate from django.shortcuts import render -from django.views.generic.edit import UpdateView +from django.views.generic.edit import UpdateView,DeleteView from django.http import ( HttpResponse, HttpResponseRedirect, @@ -45,7 +45,8 @@ from rowers.forms import ( VirtualRaceSelectForm,WorkoutRaceSelectForm,CourseSelectForm, RaceResultFilterForm,PowerIntervalUpdateForm ) -from django.core.urlresolvers import reverse +from django.core.urlresolvers import reverse, reverse_lazy + from django.core.exceptions import PermissionDenied from django.template import RequestContext from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger @@ -207,6 +208,7 @@ class JSONResponse(HttpResponse): def getrequestrower(request,rowerid=0,userid=0,notpermanent=False): + if notpermanent == False: if rowerid == 0 and 'rowerid' in request.session: rowerid = request.session['rowerid'] @@ -14181,47 +14183,11 @@ def virtualevent_submit_result_view(request,id=0): }) @user_passes_test(hasplannedsessions,login_url="/", redirect_field_name=None) -def rower_delete_trainingtarget(request,id=0): - try: - target = TrainingTarget.objects.get(id=id) - except TrainingPlan.DoesNotExist: - raise Http404("Training Plan Does Not Exist") - - if checkaccessuser(request.user,target.rower): - target.delete() - messages.info(request,"We have deleted the training plan") - else: - raise PermissionDenied("Access denied") +def rower_create_trainingplan(request,userid=0): - url = reverse(rower_create_trainingplan) - - return HttpResponseRedirect(url) - - -@user_passes_test(hasplannedsessions,login_url="/", redirect_field_name=None) -def rower_delete_trainingplan(request,id=0): - try: - plan = TrainingPlan.objects.get(id=id) - except TrainingPlan.DoesNotExist: - raise Http404("Training Plan Does Not Exist") - - if checkaccessuser(request.user,plan.rower): - plan.delete() - messages.info(request,"We have deleted the training plan") - else: - raise PermissionDenied("Access denied") - - url = reverse(rower_create_trainingplan) - - return HttpResponseRedirect(url) - -@user_passes_test(hasplannedsessions,login_url="/", redirect_field_name=None) -def rower_create_trainingplan(request,id=0): - - therower = getrequestrower(request,userid=id) + therower = getrequestrower(request,userid=userid) theuser = therower.user - if request.method == 'POST' and 'date' in request.POST: targetform = TrainingTargetForm(request.POST) if targetform.is_valid(): @@ -14266,10 +14232,119 @@ def rower_create_trainingplan(request,id=0): return render(request,'trainingplan_create.html', { 'form':form, + 'rower':therower, 'plans':plans, 'targets':targets, 'targetform':targetform, }) + +@user_passes_test(hasplannedsessions,login_url="/", redirect_field_name=None) +def rower_delete_trainingtarget(request,id=0): + try: + target = TrainingTarget.objects.get(id=id) + except TrainingPlan.DoesNotExist: + raise Http404("Training Plan Does Not Exist") + + if checkaccessuser(request.user,target.rower): + target.delete() + messages.info(request,"We have deleted the training plan") + else: + raise PermissionDenied("Access denied") + + url = reverse(rower_create_trainingplan) + + return HttpResponseRedirect(url) + + +@user_passes_test(hasplannedsessions,login_url="/", redirect_field_name=None) +def rower_delete_trainingplan(request,id=0): + try: + plan = TrainingPlan.objects.get(id=id) + except TrainingPlan.DoesNotExist: + raise Http404("Training Plan Does Not Exist") + + if checkaccessuser(request.user,plan.rower): + plan.delete() + messages.info(request,"We have deleted the training plan") + else: + raise PermissionDenied("Access denied") + + url = reverse(rower_create_trainingplan) + + return HttpResponseRedirect(url) + +class TrainingPlanDelete(DeleteView): + model = TrainingPlan + template_name = 'trainingplan_delete.html' + success_url = reverse_lazy(rower_create_trainingplan) + + def get_object(self, *args, **kwargs): + obj = super(TrainingPlanDelete, self).get_object(*args, **kwargs) + if not checkaccessuser(self.request.user,obj.plan.rower): + raise Http404 + + return obj + +class MicroCycleDelete(DeleteView): + model = TrainingMicroCycle + template_name = 'trainingplan_delete.html' + + def get_success_url(self): + plan = self.object.plan.plan.plan + createmacrofillers(plan) + return reverse(rower_trainingplan_view, + kwargs = { + 'id':plan.id + }) + + def get_object(self, *args, **kwargs): + obj = super(MicroCycleDelete, self).get_object(*args, **kwargs) + if not checkaccessuser(self.request.user,obj.plan.plan.plan.rower): + raise Http404 + + return obj + + +class MesoCycleDelete(DeleteView): + model = TrainingMesoCycle + template_name = 'trainingplan_delete.html' + + def get_success_url(self): + plan = self.object.plan.plan + createmacrofillers(plan) + return reverse(rower_trainingplan_view, + kwargs = { + 'id':plan.id + }) + + def get_object(self, *args, **kwargs): + obj = super(MesoCycleDelete, self).get_object(*args, **kwargs) + if not checkaccessuser(self.request.user,obj.plan.plan.rower): + raise Http404 + + return obj + + +class MacroCycleDelete(DeleteView): + model = TrainingMacroCycle + template_name = 'trainingplan_delete.html' + + def get_success_url(self): + plan = self.object.plan + createmacrofillers(plan) + return reverse(rower_trainingplan_view, + kwargs = { + 'id':plan.id + }) + + def get_object(self, *args, **kwargs): + obj = super(MacroCycleDelete, self).get_object(*args, **kwargs) + if not checkaccessuser(self.request.user,obj.plan.rower): + raise Http404 + + return obj + + @user_passes_test(hasplannedsessions,login_url="/", redirect_field_name=None) @@ -14371,6 +14446,8 @@ class TrainingMesoCycleUpdate(UpdateView): else: obj.type = 'userdefined' obj.save() + obj.plan.type = 'userdefined' + obj.plan.save() return obj class TrainingMicroCycleUpdate(UpdateView): @@ -14401,6 +14478,8 @@ class TrainingMicroCycleUpdate(UpdateView): else: obj.type = 'userdefined' obj.save() + obj.plan.type = 'userdefined' + obj.plan.save() return obj class TrainingPlanUpdate(UpdateView): diff --git a/static/css/rowsandall.css b/static/css/rowsandall.css index dfcc8a06..95fd1d8b 100644 --- a/static/css/rowsandall.css +++ b/static/css/rowsandall.css @@ -516,6 +516,14 @@ a.button { box-shadow:inset 0px 0px 0px 6px #fff; } +/* filler */ +.filler { + background: darkgray; + box-shadow:inset 0px 0px 0px 6px #fff; + -moz-box-shadow:inset 0px 0px 0px 6px #fff; + box-shadow:inset 0px 0px 0px 6px #fff; +} + .padded { padding: 10px; }