Private
Public Access
1
0

initial multi clone functionality

This commit is contained in:
Sander Roosendaal
2018-02-18 12:15:51 +01:00
parent d45b674a15
commit 7badc03935
17 changed files with 412 additions and 10 deletions

View File

@@ -1,6 +1,6 @@
from django import forms
from django.contrib.admin.widgets import FilteredSelectMultiple
from rowers.models import Workout,Rower,Team
from rowers.models import Workout,Rower,Team,PlannedSession
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
@@ -338,6 +338,15 @@ class DateRangeForm(forms.Form):
class Meta:
fields = ['startdate','enddate']
class SessionDateShiftForm(forms.Form):
shiftstartdate = forms.DateField(
initial=timezone.now(),
widget=AdminDateWidget(),
label='Shift to start on')
class Meta:
fields = ['shiftstartdate']
# Form used to select workouts for the past N days
class DeltaDaysForm(forms.Form):
deltadays = forms.IntegerField(initial=7,required=False,label='')
@@ -490,6 +499,13 @@ class WorkoutMultipleCompareForm(forms.Form):
workouts = forms.ModelMultipleChoiceField(queryset=Workout.objects.all(),
widget=forms.CheckboxSelectMultiple())
class PlannedSessionMultipleCloneForm(forms.Form):
plannedsessions = forms.ModelMultipleChoiceField(
queryset=PlannedSession.objects.all(),
widget=forms.CheckboxSelectMultiple(),
label='Planned Sessions'
)
from rowers.metrics import axlabels
formaxlabels = axlabels.copy()

View File

@@ -288,6 +288,10 @@ def get_dates_timeperiod(timeperiod):
today = date.today()
enddate = today-timezone.timedelta(days=today.weekday())-timezone.timedelta(days=1)
startdate = enddate-timezone.timedelta(days=6)
elif timeperiod=='nextweek':
today = date.today()
enddate = today-timezone.timedelta(days=today.weekday())-timezone.timedelta(days=1)+timezone.timedelta(days=7)
startdate = enddate-timezone.timedelta(days=13)
elif timeperiod=='lastmonth':
today = date.today()
startdate = today.replace(day=1)
@@ -296,6 +300,14 @@ def get_dates_timeperiod(timeperiod):
enddate = startdate+timezone.timedelta(days=32)
enddate = enddate.replace(day=1)
enddate = enddate-timezone.timedelta(days=1)
elif timeperiod=='nextmonth':
today = date.today()
startdate = today.replace(day=1)
startdate = startdate+timezone.timedelta(days=32)
startdate = startdate.replace(day=1)
enddate = startdate+timezone.timedelta(days=32)
enddate = enddate.replace(day=1)
enddate = enddate-timezone.timedelta(days=1)
else:
startdate = date.today()
enddate = date.today()

View File

@@ -100,7 +100,7 @@
</div>
{% endif %}
</div>
</div>
<div class="grid_12 alpha">
<div id="form" class="grid_6 alpha">
<p>Warning: Large date ranges may take a long time to load. Huge date ranges may crash your browser.</p>

View File

@@ -36,6 +36,14 @@
href="/rowers/sessions/multicreate/lastmonth/rower/{{ rower.id }}">
Last Month
</a>
<a class="button gray small alpha"
href="/rowers/sessions/multicreate/nextweek/rower/{{ rower.id }}">
Next Week
</a>
<a class="button gray small alpha"
href="/rowers/sessions/multicreate/nextmonth/rower/{{ rower.id }}">
Next Month
</a>
</div>
</div>
{% if user.is_authenticated and user|is_manager %}

View File

@@ -36,6 +36,14 @@
href="/rowers/sessions/create/lastmonth/rower/{{ rower.id }}">
Last Month
</a>
<a class="button gray small alpha"
href="/rowers/sessions/create/nextweek/rower/{{ rower.id }}">
Next Week
</a>
<a class="button gray small alpha"
href="/rowers/sessions/create/nextmonth/rower/{{ rower.id }}">
Next Month
</a>
</div>
</div>
{% if user.is_authenticated and user|is_manager %}

View File

@@ -36,6 +36,14 @@
href="/rowers/sessions/create/lastmonth/rower/{{ rower.id }}">
Last Month
</a>
<a class="button gray small alpha"
href="/rowers/sessions/create/nextweek/rower/{{ rower.id }}">
Next Week
</a>
<a class="button gray small alpha"
href="/rowers/sessions/create/nextmonth/rower/{{ rower.id }}">
Next Month
</a>
</div>
</div>
{% if user.is_authenticated and user|is_manager %}

View File

@@ -34,6 +34,14 @@
href="/rowers/sessions/lastmonth/rower/{{ rower.id }}">
Last Month
</a>
<a class="button gray small alpha"
href="/rowers/sessions/nextweek/rower/{{ rower.id }}">
Next Week
</a>
<a class="button gray small alpha"
href="/rowers/sessions/nextmonth/rower/{{ rower.id }}">
Next Month
</a>
</div>
</div>
{% if user.is_authenticated and user|is_manager %}

View File

@@ -0,0 +1,190 @@
{% extends "base.html" %}
{% load staticfiles %}
{% load rowerfilters %}
{% block title %}Workouts{% endblock %}
{% block content %}
<script>
function toggle(source) {
checkboxes = document.querySelectorAll("input[name='plannedsessions']");
for(var i=0, n=checkboxes.length;i<n;i++) {
checkboxes[i].checked = source.checked;
}
}
</script>
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
<script>
$(function() {
// Get the form fields and hidden div
var modality = $("#id_modality");
var hidden = $("#id_waterboattype");
// Hide the fields.
// Use JS to do this in case the user doesn't have JS
// enabled.
hidden.hide();
// Setup an event listener for when the state of the
// checkbox changes.
modality.change(function() {
// Check to see if the checkbox is checked.
// If it is, show the fields and populate the input.
// If not, hide the fields.
var Value = modality.val();
if (Value=='water') {
// Show the hidden fields.
hidden.show();
} else {
// Make sure that the hidden fields are indeed
// hidden.
hidden.hide();
// You may also want to clear the value of the
// hidden fields here. Just in case somebody
// shows the fields, enters data to them and then
// unticks the checkbox.
//
// This would do the job:
//
// $("#hidden_field").val("");
}
});
});
</script>
<div class="grid_12 alpha">
{% include "planningbuttons.html" %}
</div>
<div class="grid_4 alpha">
{% if theteam %}
<h1>Coach Overview. Team {{ theteam.name }}</h1>
{% else %}
<h1>Coach Overview</h1>
{% endif %}
</div>
<div id="timeperiod" class="grid_2 dropdown">
<button class="grid_2 alpha button gray small dropbtn">Select Time Period ({{ timeperiod|verbosetimeperiod }})</button>
<div class="dropdown-content">
<a class="button gray small alpha"
href="/rowers/sessions/multiclone/today">
Today
</a>
<a class="button gray small alpha"
href="/rowers/sessions/multiclone/thisweek">
This Week
</a>
<a class="button gray small alpha"
href="/rowers/sessions/multiclone/thismonth">
This Month
</a>
<a class="button gray small alpha"
href="/rowers/sessions/multiclone/lastweek">
Last Week
</a>
<a class="button gray small alpha"
href="/rowers/sessions/multiclone/lastmonth/">
Last Month
</a>
<a class="button gray small alpha"
href="/rowers/sessions/multiclone/nextweek/">
Next Week
</a>
<a class="button gray small alpha"
href="/rowers/sessions/multiclone/nextmonth/">
Next Month
</a>
</div>
</div>
{% if user.is_authenticated and user|is_manager %}
<div class="grid_2 dropdown">
<button class="grid_2 alpha button green small dropbtn">
Select Rower
</button>
<div class="dropdown-content">
{% for member in user|team_rowers %}
<a class="button green small" href="/rowers/sessions/multiclone/{{ timeperiod }}/rower/{{ member.id }}">{{ member.user.first_name }} {{ member.user.last_name }}</a>
{% endfor %}
</div>
</div>
<div class="grid_12 alpha">
<div class="grid_6 alpha">
<form enctype="multipart/form-data" method="post">
{% endif %}
<div class="grid_4 alpha">
<table>
{{ dateform.as_table }}
</table>
{% csrf_token %}
</div>
<div class="grid_2 omega">
<input name='daterange' class="button green" type="submit" value="Submit">
</div>
</form>
</div>
<div class="grid_5 prefix_1 omega">
<form id="searchform" method="get" accept-charset="utf-8">
<div class="grid_3 prefix_1 alpha">
<input class="searchfield" id="searchbox" name="q" type="text" placeholder="Search">
</div>
<div class="grid_1 omega">
<button class="button blue small" type="submit">
Search
</button>
</div>
</form>
</div>
</div>
<form enctype="multipart/form-data" method="post">
<div id="workouts_table" class="grid_8 alpha">
{% if plannedsessions %}
<input type="checkbox" onClick="toggle(this)" /> Toggle All<br/>
<table width="100%" class="listtable">
{{ form.as_table }}
</table>
{% else %}
<p> No sessions found </p>
{% endif %}
</div>
<div id="form_settings" class="grid_4 alpha">
<p>Select two or more planned sessions on the left,
select the date when the new cycle starts below
and press submit</p>
{% csrf_token %}
<table>
{{ dateshiftform.as_table }}
</table>
<div class="grid_1 prefix_2 suffix_1">
<p>
<input name='workoutselectform' class="button green" type="submit" value="Submit">
</p>
</div>
<div class="grid_4">
<p>You can use the date and search forms above to search through all
sessions.</p>
</div>
</div>
</form>
{% endblock %}

View File

@@ -38,6 +38,14 @@
href="/rowers/sessions/coach/lastmonth/">
Last Month
</a>
<a class="button gray small alpha"
href="/rowers/sessions/coach/nextweek/">
Next Week
</a>
<a class="button gray small alpha"
href="/rowers/sessions/coach/nextmonth/">
Next Month
</a>
</div>
</div>
{% if user.is_authenticated and user|is_manager %}

View File

@@ -48,6 +48,14 @@
href="/rowers/sessions/manage/lastmonth/rower/{{ rower.id }}">
Last Month
</a>
<a class="button gray small alpha"
href="/rowers/sessions/manage/nextweek/rower/{{ rower.id }}">
Next Week
</a>
<a class="button gray small alpha"
href="/rowers/sessions/manage/nextmonth/rower/{{ rower.id }}">
Next Month
</a>
</div>
</div>
{% if user.is_authenticated and user|is_manager %}

View File

@@ -36,6 +36,14 @@
href="/rowers/sessions/create/lastmonth/rower/{{ rower.id }}">
Last Month
</a>
<a class="button gray small alpha"
href="/rowers/sessions/create/nextweek/rower/{{ rower.id }}">
Next Week
</a>
<a class="button gray small alpha"
href="/rowers/sessions/create/nextmonth/rower/{{ rower.id }}">
Next Month
</a>
</div>
</div>
</div>

View File

@@ -36,6 +36,14 @@
href="/rowers/sessions/create/lastmonth/rower/{{ rower.id }}">
Last Month
</a>
<a class="button gray small alpha"
href="/rowers/sessions/create/nextweek/rower/{{ rower.id }}">
Next Week
</a>
<a class="button gray small alpha"
href="/rowers/sessions/create/nextmonth/rower/{{ rower.id }}">
Next Month
</a>
</div>
</div>
</div>

View File

@@ -144,7 +144,6 @@
{% endif %}
</div>
<div id="form_settings" class="grid_4 alpha">
<p><b>Warning: You are on an experimental part of the site. Use at your own risk.</b></p>
<p>Select two or more workouts on the left, set your plot settings below,
and press submit</p>
{% csrf_token %}

View File

@@ -193,6 +193,8 @@ def verbosetimeperiod(timeperiod):
'thismonth': 'This Month',
'lastmonth': 'Last Month',
'lastweek': 'Last Week',
'nextweek': 'Next Week',
'nextmonth': 'Next Month',
}
try:

View File

@@ -419,6 +419,17 @@ urlpatterns = [
url(r'^sessions/create/(?P<timeperiod>[\w\ ]+.*)$',
views.plannedsession_create_view),
url(r'^sessions/multiclone$',views.plannedsession_multiclone_view),
url(r'^sessions/multiclone/(?P<timeperiod>[\w\ ]+.*)/rower/(?P<rowerid>\d+)/extra/(?P<extrasessions>\d+)$',
views.plannedsession_multiclone_view),
url(r'^sessions/multiclone/rower/(?P<rowerid>\d+)$',
views.plannedsession_multiclone_view),
url(
r'^sessions/multiclone/(?P<timeperiod>[\w\ ]+.*)/rower/(?P<rowerid>\d+)$',
views.plannedsession_multiclone_view),
url(r'^sessions/multiclone/(?P<timeperiod>[\w\ ]+.*)$',
views.plannedsession_multiclone_view),
url(r'^sessions/multicreate$',views.plannedsession_multicreate_view),
url(r'^sessions/multicreate/(?P<timeperiod>[\w\ ]+.*)/rower/(?P<rowerid>\d+)/extra/(?P<extrasessions>\d+)$',
views.plannedsession_multicreate_view),

View File

@@ -50,6 +50,7 @@ from rowers.forms import (
UpdateStreamForm,WorkoutMultipleCompareForm,ChartParamChoiceForm,
FusionMetricChoiceForm,BoxPlotChoiceForm,MultiFlexChoiceForm,
TrendFlexModalForm,WorkoutSplitForm,WorkoutJoinParamForm,
PlannedSessionMultipleCloneForm,SessionDateShiftForm,
)
from rowers.models import (
Workout, User, Rower, WorkoutForm,FavoriteChart,
@@ -11576,6 +11577,113 @@ def agegrouprecordview(request,sex='male',weightcategory='hwt',
'the_div':div,
})
# Cloning sessions
@user_passes_test(hasplannedsessions,login_url="/rowers/planmembership/",
redirect_field_name=None)
def plannedsession_multiclone_view(
request,timeperiod='nextweek',
rowerid=0,
startdate=timezone.now()-datetime.timedelta(days=30),
enddate=timezone.now()+datetime.timedelta(days=1)):
if rowerid==0:
r = getrower(request.user)
else:
try:
r = Rower.objects.get(id=rowerid)
except Rower.DoesNotExist:
raise Http404("This rower doesn't exist")
if not checkaccessuser(request.user,r):
raise PermissionDenied("You don't have access to this plan")
if 'startdate' in request.session:
startdate = iso8601.parse_date(request.session['startdate'])
if 'enddate' in request.session:
enddate = iso8601.parse_date(request.session['enddate'])
if request.method == 'POST' and 'daterange' in request.POST:
dateform = DateRangeForm(request.POST)
if dateform.is_valid():
startdate = dateform.cleaned_data['startdate']
enddate = dateform.cleaned_data['enddate']
startdatestring = startdate.strftime('%Y-%m-%d')
enddatestring = enddate.strftime('%Y-%m-%d')
request.session['startdate'] = startdatestring
request.session['enddate'] = enddatestring
else:
dateform = DateRangeForm(initial={
'startdate':startdate,
'enddate':enddate,
})
if request.method == 'POST' and 'plannedsessions' in request.POST:
form = PlannedSessionMultipleCloneForm(request.POST)
dateshiftform = SessionDateShiftForm(request.POST)
if form.is_valid() and dateshiftform.is_valid():
cd = form.cleaned_data
sps = cd['plannedsessions']
std = min([ps.startdate for ps in sps])
shiftstartdate = dateshiftform.cleaned_data['shiftstartdate']
delta = shiftstartdate-std
for ps in sps:
rowers = ps.rower.all()
teams = ps.team.all()
ps.pk = None
ps.startdate += delta
ps.enddate += delta
ps.save()
for rower in rowers:
add_rower_session(rower,ps)
for team in teams:
add_team_session(team,ps)
url = reverse(plannedsession_multicreate_view,
kwargs = {
'rowerid':r.id,
'timeperiod':timeperiod,
})
return HttpResponseRedirect(url)
startdate = datetime.datetime.combine(startdate,datetime.time())
enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59))
enddate = enddate+datetime.timedelta(days=1)
sps = PlannedSession.objects.filter(
manager=request.user,
rower__in=[r],
startdate__lte=enddate,
enddate__gte=startdate).order_by("startdate","enddate")
query = request.GET.get('q')
if query:
query_list = query.split()
sps = sps.filter(
reduce(operator.and_,
(Q(name__icontains=q) for q in query_list)) |
reduce(operator.and_,
(Q(comment__icontains=q) for q in query_list))
)
form = PlannedSessionMultipleCloneForm()
form.fields["plannedsessions"].queryset = sps
dateshiftform = SessionDateShiftForm()
return render(request, 'plannedsessions_multiclone_select.html',
{'plannedsessions':sps,
'dateform':dateform,
'startdate':startdate,
'enddate':enddate,
'form':form,
'dateshiftform':dateshiftform,
'rower':r,
'timeperiod':timeperiod,
}
)
# Individual user creates training for himself
@user_passes_test(hasplannedsessions,login_url="/rowers/planmembership/",
redirect_field_name=None)

View File

@@ -205,6 +205,13 @@
<p>&nbsp;</p>
{% endif %}
</div>
<div class="grid_1 tooltip">
{% if user.is_authenticated %}
<p><a class="button gray small" href="/rowers/sessions/">Plans</a></p>
{% else %}
<p>&nbsp;</p>
{% endif %}
</div>
<div class="grid_2 tooltip">
{% if user.is_authenticated %}
<p>
@@ -219,13 +226,6 @@
{% block teams %}
{% endblock %}
</div>
<div class="grid_1 tooltip">
{% if user.is_authenticated %}
<p><a class="button gray small" href="/rowers/sessions/">Plans</a></p>
{% else %}
<p>&nbsp;</p>
{% endif %}
</div>
<div class="grid_1 tooltip">
{% block challenges %}
{% endblock %}