Private
Public Access
1
0

next steps in training plan/target

- delete cycles
- change user
This commit is contained in:
Sander Roosendaal
2018-09-10 15:10:43 +02:00
parent 2c4c0030b4
commit 357193c9c8
7 changed files with 219 additions and 52 deletions

View File

@@ -992,7 +992,7 @@ class TrainingPlan(models.Model):
firstname = self.rower.user.first_name firstname = self.rower.user.first_name
lastname = self.rower.user.last_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'), s = startdate.strftime('%Y-%m-%d'),
e = enddate.strftime('%Y-%m-%d'), e = enddate.strftime('%Y-%m-%d'),
firstname = firstname, firstname = firstname,

View File

@@ -18,7 +18,18 @@
<div class="grid_12"> <div class="grid_12">
<div class="grid_12 alpha"> <div class="grid_12 alpha">
<h1>Training Plan - {{ plan.name }}</h1> <h1>Training Plan - {{ plan.name }}</h1>
<p><a href="/rowers/editplan/{{ plan.id }}">Edit</a></p> <p>This plan starts on {{ plan.startdate }} and ends on {{ plan.enddate }}. The training plan target is: {{ plan.target.name }} on {{ plan.target.date }}.</p>
<p><a href="/rowers/editplan/{{ plan.id }}">Edit the plan</a></p>
<p>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.</p>
<p>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. </p>
</div> </div>
<div class="grid_4 alpha"> <div class="grid_4 alpha">
<h2>Macro Cycles</h2> <h2>Macro Cycles</h2>
@@ -33,26 +44,45 @@
<div class="grid_12 alpha"> <div class="grid_12 alpha">
{% for key,macrocycle in cycles.items %} {% for key,macrocycle in cycles.items %}
<div class="grid_12 alpha"> <div class="grid_12 alpha">
<div class="grid_4 palegreen alpha"> {% if macrocycle.0.type == 'filler' %}
<div class="grid_4 filler alpha">
{% else %}
<div class="grid_4 palegreen alpha">
{% endif %}
<div class="padded"> <div class="padded">
<h3>{{ macrocycle.0.name }} ({{ macrocycle.0.startdate }} - {{ macrocycle.0.enddate }})</h3> <h3>{{ macrocycle.0.name }} ({{ macrocycle.0.startdate }} - {{ macrocycle.0.enddate }})</h3>
<p><a href="/rowers/macrocycle/{{ macrocycle.0.id }}">edit</a></p> <p><a href="/rowers/macrocycle/{{ macrocycle.0.id }}">edit</a>
/
<a href="/rowers/deletemacrocycle/{{ macrocycle.0.id }}">delete</a></p>
</div> </div>
</div> </div>
<div class="grid_8 alpha"> <div class="grid_8 alpha">
{% for key, mesocycle in macrocycle.1.items %} {% for key, mesocycle in macrocycle.1.items %}
{% if mesocycle.0.type == 'filler' %}
<div class="grid_4 filler alpha">
{% else %}
<div class="grid_4 lightsalmon alpha"> <div class="grid_4 lightsalmon alpha">
{% endif %}
<div class="padded"> <div class="padded">
<h3>{{ mesocycle.0.name }} ({{ mesocycle.0.startdate }} - {{ mesocycle.0.enddate }})</h3> <h3>{{ mesocycle.0.name }} ({{ mesocycle.0.startdate }} - {{ mesocycle.0.enddate }})</h3>
<p><a href="/rowers/mesocycle/{{ mesocycle.0.id }}">edit</a></p> <p><a href="/rowers/mesocycle/{{ mesocycle.0.id }}">edit</a>
/
<a href="/rowers/deletemesocycle/{{ mesocycle.0.id }}">delete</a></p>
</div> </div>
</div> </div>
<div class="grid_4 omega"> <div class="grid_4 omega">
{% for microcycle in mesocycle.1 %} {% for microcycle in mesocycle.1 %}
<div class="grid_4 paleblue "> {% if microcycle.type == 'filler' %}
<div class="grid_4 filler">
{% else %}
<div class="grid_4 paleblue ">
{% endif %}
<div class="padded"> <div class="padded">
<h3>{{ microcycle.name }} ({{ microcycle.startdate }} - {{ microcycle.enddate }})</h3> <h3>{{ microcycle.name }} ({{ microcycle.startdate }} - {{ microcycle.enddate }})</h3>
<p><a href="/rowers/microcycle/{{ microcycle.id }}">edit</a></p> <p>
<a href="/rowers/microcycle/{{ microcycle.id }}">edit</a>
/
<a href="/rowers/deletemicrocycle/{{ microcycle.id }}">delete</a></p>
</div> </div>
</div> </div>
{% endfor %} {% endfor %}

View File

@@ -15,7 +15,23 @@
} }
</style> </style>
<div class="grid_12"> <div class="grid_12 alpha">
{% if user.is_authenticated and user|is_manager %}
<div class="grid_2 prefix_8 dropdown">
<button class="grid_2 alpha button green small dropbtn">
{{ rower.user.first_name }} {{ rower.user.last_name }}
</button>
<div class="dropdown-content">
{% for member in user|team_members %}
<a class="button green small" href="/rowers/createplan/{{ member.id }}">{{ member.first_name }} {{ member.last_name }}</a>
{% endfor %}
</div>
</div>
{% endif %}
</div>
<div class="grid_12 alpha">
<div id="targets_table" class="grid_8 alpha"> <div id="targets_table" class="grid_8 alpha">
<h1>Training Targets</h1> <h1>Training Targets</h1>
@@ -64,8 +80,8 @@
</div> </div>
<div class="grid_12"> <div class="grid_12 alpha">
<div id="courses_table" class="grid_8 alpha"> <div id="courses_table" class="grid_8 alpha">
<h1>Plans</h1> <h1>Plans</h1>

View File

@@ -0,0 +1,30 @@
{% extends "base.html" %}
{% load staticfiles %}
{% load rowerfilters %}
{% block title %}Rowsandall Training Plans{% endblock %}
{% block scripts %}
{% endblock %}
{% block content %}
<style>
#mypointer {
cursor: pointer;
}
</style>
<div class="grid_12 alpha">
<form action="" method="post">
{% csrf_token %}
<p>Are you sure you want to delete <i>{{ object }}</i>?</p>
<div id="formbutton" class="grid_1 prefix_2">
<input class="button red" type="submit" value="Confirm">
</div>
</form>
</div>
{% endblock %}

View File

@@ -420,8 +420,12 @@ urlpatterns = [
url(r'^workout/compare/(?P<id1>\d+)/(?P<id2>\d+)/(?P<xparam>\w+.*)/(?P<yparam>[\w\ ]+.*)/$',views.workout_comparison_view2), url(r'^workout/compare/(?P<id1>\d+)/(?P<id2>\d+)/(?P<xparam>\w+.*)/(?P<yparam>[\w\ ]+.*)/$',views.workout_comparison_view2),
url(r'^test\_callback',views.rower_process_testcallback), url(r'^test\_callback',views.rower_process_testcallback),
url(r'^createplan$',views.rower_create_trainingplan), url(r'^createplan$',views.rower_create_trainingplan),
url(r'^createplan/(?P<id>\d+)$',views.rower_create_trainingplan), url(r'^createplan/(?P<userid>\d+)$',views.rower_create_trainingplan),
url(r'^deleteplan/(?P<id>\d+)$',views.rower_delete_trainingplan), url(r'^deleteplan/(?P<pk>\d+)$',views.TrainingPlanDelete.as_view()),
url(r'^deletemicrocycle/(?P<pk>\d+)$',views.MicroCycleDelete.as_view()),
url(r'^deletemesocycle/(?P<pk>\d+)$',views.MesoCycleDelete.as_view()),
url(r'^deletemacrocycle/(?P<pk>\d+)$',views.MacroCycleDelete.as_view()),
# url(r'^deleteplan/(?P<id>\d+)$',views.rower_delete_trainingplan),
url(r'^plan/(?P<id>\d+)$',views.rower_trainingplan_view), url(r'^plan/(?P<id>\d+)$',views.rower_trainingplan_view),
url(r'^macrocycle/(?P<pk>\d+)$',views.TrainingMacroCycleUpdate.as_view()), url(r'^macrocycle/(?P<pk>\d+)$',views.TrainingMacroCycleUpdate.as_view()),
url(r'^mesocycle/(?P<pk>\d+)$',views.TrainingMesoCycleUpdate.as_view()), url(r'^mesocycle/(?P<pk>\d+)$',views.TrainingMesoCycleUpdate.as_view()),

View File

@@ -28,7 +28,7 @@ import isodate
from django.shortcuts import render from django.shortcuts import render
from django.views.generic.edit import UpdateView from django.views.generic.edit import UpdateView,DeleteView
from django.http import ( from django.http import (
HttpResponse, HttpResponseRedirect, HttpResponse, HttpResponseRedirect,
@@ -45,7 +45,8 @@ from rowers.forms import (
VirtualRaceSelectForm,WorkoutRaceSelectForm,CourseSelectForm, VirtualRaceSelectForm,WorkoutRaceSelectForm,CourseSelectForm,
RaceResultFilterForm,PowerIntervalUpdateForm RaceResultFilterForm,PowerIntervalUpdateForm
) )
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse, reverse_lazy
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.template import RequestContext from django.template import RequestContext
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
@@ -207,6 +208,7 @@ class JSONResponse(HttpResponse):
def getrequestrower(request,rowerid=0,userid=0,notpermanent=False): def getrequestrower(request,rowerid=0,userid=0,notpermanent=False):
if notpermanent == False: if notpermanent == False:
if rowerid == 0 and 'rowerid' in request.session: if rowerid == 0 and 'rowerid' in request.session:
rowerid = request.session['rowerid'] 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) @user_passes_test(hasplannedsessions,login_url="/", redirect_field_name=None)
def rower_delete_trainingtarget(request,id=0): def rower_create_trainingplan(request,userid=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) therower = getrequestrower(request,userid=userid)
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)
theuser = therower.user theuser = therower.user
if request.method == 'POST' and 'date' in request.POST: if request.method == 'POST' and 'date' in request.POST:
targetform = TrainingTargetForm(request.POST) targetform = TrainingTargetForm(request.POST)
if targetform.is_valid(): if targetform.is_valid():
@@ -14266,10 +14232,119 @@ def rower_create_trainingplan(request,id=0):
return render(request,'trainingplan_create.html', return render(request,'trainingplan_create.html',
{ {
'form':form, 'form':form,
'rower':therower,
'plans':plans, 'plans':plans,
'targets':targets, 'targets':targets,
'targetform':targetform, '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) @user_passes_test(hasplannedsessions,login_url="/", redirect_field_name=None)
@@ -14371,6 +14446,8 @@ class TrainingMesoCycleUpdate(UpdateView):
else: else:
obj.type = 'userdefined' obj.type = 'userdefined'
obj.save() obj.save()
obj.plan.type = 'userdefined'
obj.plan.save()
return obj return obj
class TrainingMicroCycleUpdate(UpdateView): class TrainingMicroCycleUpdate(UpdateView):
@@ -14401,6 +14478,8 @@ class TrainingMicroCycleUpdate(UpdateView):
else: else:
obj.type = 'userdefined' obj.type = 'userdefined'
obj.save() obj.save()
obj.plan.type = 'userdefined'
obj.plan.save()
return obj return obj
class TrainingPlanUpdate(UpdateView): class TrainingPlanUpdate(UpdateView):

View File

@@ -516,6 +516,14 @@ a.button {
box-shadow:inset 0px 0px 0px 6px #fff; 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 { .padded {
padding: 10px; padding: 10px;
} }