form in place, not working yet
This commit is contained in:
@@ -481,6 +481,20 @@ class MyTimeField(forms.TimeField):
|
|||||||
super(MyTimeField, self).__init__(*args, **kwargs)
|
super(MyTimeField, self).__init__(*args, **kwargs)
|
||||||
supports_microseconds = True
|
supports_microseconds = True
|
||||||
|
|
||||||
|
# Form used to automatically define intervals by pace or power
|
||||||
|
class PowerIntervalUpdateForm(forms.Form):
|
||||||
|
selectorchoices = (
|
||||||
|
('power','Power'),
|
||||||
|
('pace','Pace')
|
||||||
|
)
|
||||||
|
|
||||||
|
pace = forms.DurationField(label='Pace',required=False)
|
||||||
|
power = forms.IntegerField(label='Power',required=False)
|
||||||
|
selector = forms.ChoiceField(choices=selectorchoices,
|
||||||
|
required=True,
|
||||||
|
initial='power',
|
||||||
|
label='Use')
|
||||||
|
|
||||||
# Form used to update interval stats
|
# Form used to update interval stats
|
||||||
class IntervalUpdateForm(forms.Form):
|
class IntervalUpdateForm(forms.Form):
|
||||||
|
|
||||||
|
|||||||
@@ -8,200 +8,220 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<div id="workouts" class="grid_6 alpha">
|
<div id="workouts" class="grid_6 alpha">
|
||||||
|
|
||||||
{% if form.errors %}
|
{% if form.errors %}
|
||||||
<p style="color: red;">
|
<p style="color: red;">
|
||||||
Please correct the error{{ form.errors|pluralize }} below.
|
Please correct the error{{ form.errors|pluralize }} below.
|
||||||
</p>
|
</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<h1>Edit Workout Interval Data</h1>
|
<h1>Edit Workout Interval Data</h1>
|
||||||
<div class="grid_6 alpha">
|
<div class="grid_6 alpha">
|
||||||
<div class="grid_2 alpha">
|
<div class="grid_2 alpha">
|
||||||
<p>
|
<p>
|
||||||
<a class="button gray small" href="/rowers/workout/{{ workout.id }}/edit">Edit</a>
|
<a class="button gray small" href="/rowers/workout/{{ workout.id }}/edit">Edit</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid_2">
|
<div class="grid_2">
|
||||||
<p>
|
<p>
|
||||||
<a class="button gray small" href="/rowers/workout/{{ workout.id }}/workflow">Workflow View</a>
|
<a class="button gray small" href="/rowers/workout/{{ workout.id }}/workflow">Workflow View</a>
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid_2 omega tooltip">
|
<div class="grid_2 omega tooltip">
|
||||||
<p>
|
<p>
|
||||||
<a class="button gray small" href="/rowers/workout/{{ workout.id }}/advanced">Advanced</a>
|
<a class="button gray small" href="/rowers/workout/{{ workout.id }}/advanced">Advanced</a>
|
||||||
</p>
|
</p>
|
||||||
<span class="tooltiptext">Advanced Functionality (More interactive Charts)</span>
|
<span class="tooltiptext">Advanced Functionality (More interactive Charts)</span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{% localtime on %}
|
||||||
{% localtime on %}
|
<table width=100%>
|
||||||
<table width=100%>
|
<tr>
|
||||||
<tr>
|
<th>Date/Time:</th><td>{{ workout.startdatetime }}</td>
|
||||||
<th>Date/Time:</th><td>{{ workout.startdatetime }}</td>
|
</tr><tr>
|
||||||
</tr><tr>
|
<th>Distance:</th><td>{{ workout.distance }}m</td>
|
||||||
<th>Distance:</th><td>{{ workout.distance }}m</td>
|
</tr><tr>
|
||||||
</tr><tr>
|
<th>Duration:</th><td>{{ workout.duration |durationprint:"%H:%M:%S.%f" }}</td>
|
||||||
<th>Duration:</th><td>{{ workout.duration |durationprint:"%H:%M:%S.%f" }}</td>
|
</tr><tr>
|
||||||
</tr><tr>
|
<th>Public link to this workout</th>
|
||||||
<th>Public link to this workout</th>
|
<td>
|
||||||
<td>
|
|
||||||
<a href="/rowers/workout/{{ workout.id }}">https://rowsandall.com/rowers/workout/{{ workout.id }}</a>
|
<a href="/rowers/workout/{{ workout.id }}">https://rowsandall.com/rowers/workout/{{ workout.id }}</a>
|
||||||
<td>
|
<td>
|
||||||
</tr><tr>
|
</tr><tr>
|
||||||
<th>Public link to interactive chart</th>
|
<th>Public link to interactive chart</th>
|
||||||
<td>
|
<td>
|
||||||
<a href="/rowers/workout/{{ workout.id }}/interactiveplot">https://rowsandall.com/rowers/workout/{{ workout.id }}/interactiveplot</a>
|
<a href="/rowers/workout/{{ workout.id }}/interactiveplot">https://rowsandall.com/rowers/workout/{{ workout.id }}/interactiveplot</a>
|
||||||
<td>
|
<td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
{% endlocaltime %}
|
{% endlocaltime %}
|
||||||
<h1>Interval Translator</h1>
|
<h1>Interval Translator</h1>
|
||||||
<p>This is a quick way to enter the intervals using a special mini-language.</p>
|
<p>This is a quick way to enter the intervals using a special mini-language.</p>
|
||||||
<p>You enter something like <em>8x500m/3min</em>, press "Update" and the site will interpret this for you and update the summary on the right. If you're happy with the result, press the green Save button to update the values. Nothing will be changed permanently until you hit Save.</p>
|
<p>You enter something like <em>8x500m/3min</em>, press "Update" and the site will interpret this for you and update the summary on the right. If you're happy with the result, press the green Save button to update the values. Nothing will be changed permanently until you hit Save.</p>
|
||||||
|
|
||||||
|
<p>Special characters are <em>x</em> (times), <em>+</em> and <em>/</em> (denotes a rest interval), as well as <em>(</em> and <em>)</em>. Units are <em>min</em> (minutes), <em>sec</em> (seconds), <em>m</em> (meters) and <em>km</em> (km). </p>
|
||||||
|
|
||||||
|
<p>A typical interval is described as "<b>10min/5min</b>", with the work part before the "<b>/</b>" and the rest part after it. A zero rest can be omitted, so a single 1000m piece could be described either as "<b>1km</b>" or "<b>1000m</b>". The basic units can be combined with "<b>+</b>" and "<b>Nx</b>". You can use parentheses as in the example below.</p>
|
||||||
|
|
||||||
|
<p>Here are a few examples.</p>
|
||||||
|
<table class="listtable" width=100%>
|
||||||
|
<tr>
|
||||||
|
<td>8x500m/2min</td><td>8 times 500m with 2 minutes rest</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>10km</td><td>Single distance of 10km</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>6min/3min + 5min/3min + 3min/3min + 3min </td>
|
||||||
|
<td>Four intervals of 6, 5, 3 and 3 minutes length, 3 minutes rest</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>8x500m/3:30min </td>
|
||||||
|
<td>8 times 500m with 3 minutes 30 seconds rest</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>4x((500m+500m)/5min)</td><td>4 times 1km, but each km is reported as two 500m intervals without rest. Note the nested parentheses.</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>2x500m/500m</td><td>A 2k rowed as 500m "on", 500m "off"</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
<p>Special characters are <em>x</em> (times), <em>+</em> and <em>/</em> (denotes a rest interval), as well as <em>(</em> and <em>)</em>. Units are <em>min</em> (minutes), <em>sec</em> (seconds), <em>m</em> (meters) and <em>km</em> (km). </p>
|
<form enctype="multipart/form-data" action="/rowers/workout/{{ workout.id }}/editintervals" method="post">
|
||||||
|
<table width=100%>
|
||||||
|
{{ form.as_table }}
|
||||||
|
</table>
|
||||||
|
{% csrf_token %}
|
||||||
|
<div id="formbutton" class="grid_1 prefix_4 suffix_1">
|
||||||
|
<input class="button green" type="submit" value="Update">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
<p>A typical interval is described as "<b>10min/5min</b>", with the work part before the "<b>/</b>" and the rest part after it. A zero rest can be omitted, so a single 1000m piece could be described either as "<b>1km</b>" or "<b>1000m</b>". The basic units can be combined with "<b>+</b>" and "<b>Nx</b>". You can use parentheses as in the example below.</p>
|
<h1>Intervals by Power/Pace</h1>
|
||||||
|
|
||||||
<p>Here are a few examples.</p>
|
<p>With this form, you can specify a power or pace level. Everything faster/harder than the
|
||||||
<table class="listtable" width=100%>
|
specified pace/power will become a work interval. Everything slower will become a rest
|
||||||
<tr>
|
interval.
|
||||||
<td>8x500m/2min</td><td>8 times 500m with 2 minutes rest</td>
|
</p>
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>10km</td><td>Single distance of 10km</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>6min/3min + 5min/3min + 3min/3min + 3min </td>
|
|
||||||
<td>Four intervals of 6, 5, 3 and 3 minutes length, 3 minutes rest</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>8x500m/3:30min </td>
|
|
||||||
<td>8 times 500m with 3 minutes 30 seconds rest</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>4x((500m+500m)/5min)</td><td>4 times 1km, but each km is reported as two 500m intervals without rest. Note the nested parentheses.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>2x500m/500m</td><td>A 2k rowed as 500m "on", 500m "off"</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<form enctype="multipart/form-data" action="/rowers/workout/{{ workout.id }}/editintervals" method="post">
|
<form ecntype="multipart/form-data" method="post">
|
||||||
<table width=100%>
|
<table>
|
||||||
{{ form.as_table }}
|
{{ powerupdateform.as_table }}
|
||||||
</table>
|
</table>
|
||||||
{% csrf_token %}
|
|
||||||
<div id="formbutton" class="grid_1 prefix_4 suffix_1">
|
{% csrf_token %}
|
||||||
<input class="button green" type="submit" value="Update">
|
<div id="formbutton" class="grid_1 prefix_4 suffix_1">
|
||||||
</div>
|
<input class="button green" type="submit" value="Submit">
|
||||||
</form>
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="advancedplots" class="grid_6 omega">
|
<div id="advancedplots" class="grid_6 omega">
|
||||||
<div class="grid_6 alpha">
|
<div class="grid_6 alpha">
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
<script async="true" type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{{ interactiveplot |safe }}
|
{{ interactiveplot |safe }}
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Set things up to resize the plot on a window resize. You can play with
|
// Set things up to resize the plot on a window resize. You can play with
|
||||||
// the arguments of resize_width_height() to change the plot's behavior.
|
// the arguments of resize_width_height() to change the plot's behavior.
|
||||||
var plot_resize_setup = function () {
|
var plot_resize_setup = function () {
|
||||||
var plotid = Object.keys(Bokeh.index)[0]; // assume we have just one plot
|
var plotid = Object.keys(Bokeh.index)[0]; // assume we have just one plot
|
||||||
var plot = Bokeh.index[plotid];
|
var plot = Bokeh.index[plotid];
|
||||||
var plotresizer = function() {
|
var plotresizer = function() {
|
||||||
// arguments: use width, use height, maintain aspect ratio
|
// arguments: use width, use height, maintain aspect ratio
|
||||||
plot.resize_width_height(true, true, true);
|
plot.resize_width_height(true, true, true);
|
||||||
};
|
};
|
||||||
window.addEventListener('resize', plotresizer);
|
window.addEventListener('resize', plotresizer);
|
||||||
plotresizer();
|
plotresizer();
|
||||||
};
|
};
|
||||||
window.addEventListener('load', plot_resize_setup);
|
window.addEventListener('load', plot_resize_setup);
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
/* Need this to get the page in "desktop mode"; not having an infinite height.*/
|
/* Need this to get the page in "desktop mode"; not having an infinite height.*/
|
||||||
html, body {height: 100%; margin:5px;}
|
html, body {height: 100%; margin:5px;}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
<div id="interactiveplot" class="grid_6 omega">
|
<div id="interactiveplot" class="grid_6 omega">
|
||||||
{{ the_div |safe }}
|
{{ the_div |safe }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div id="summary" class="grid_6 omega">
|
<div id="summary" class="grid_6 omega">
|
||||||
<h1>Updated Summary</h1>
|
<h1>Updated Summary</h1>
|
||||||
<form enctype="multipart/form-data" action="/rowers/workout/{{ workout.id }}/editintervals" method="post">
|
<form enctype="multipart/form-data" action="/rowers/workout/{{ workout.id }}/editintervals" method="post">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<input type="hidden" name="{{ savebutton }}" value="{{ intervalstring }}">
|
<input type="hidden" name="{{ savebutton }}" value="{{ intervalstring }}">
|
||||||
<input type="hidden" name="nrintervals" value={{ nrintervals }}>
|
<input type="hidden" name="nrintervals" value={{ nrintervals }}>
|
||||||
{% for field in detailform %}
|
{% for field in detailform %}
|
||||||
{{ field.as_hidden }}
|
{{ field.as_hidden }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<div class="grid_1 alpha">
|
<div class="grid_1 alpha">
|
||||||
<input class="button green" type="submit" value="Save">
|
<input class="button green" type="submit" value="Save">
|
||||||
</div>
|
</div>
|
||||||
<div class="grid_2">
|
<div class="grid_2">
|
||||||
<a class="button green" href="">Reset to last saved</a>
|
<a class="button green" href="">Reset to last saved</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid_2 omega">
|
<div class="grid_2 omega">
|
||||||
<a class="button green" href="/rowers/workout/{{ workout.id }}/restore">Restore Original data</a>
|
<a class="button green" href="/rowers/workout/{{ workout.id }}/restore">Restore Original data</a>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<div class="grid_6 alpha">
|
<div class="grid_6 alpha">
|
||||||
<p>
|
<p>
|
||||||
<pre>
|
<pre>
|
||||||
{{ intervalstats }}
|
{{ intervalstats }}
|
||||||
</pre>
|
</pre>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="summary" class="grid_6 omega">
|
<div id="summary" class="grid_6 omega">
|
||||||
<h1>Detailed Summary Edit</h1>
|
<h1>Detailed Summary Edit</h1>
|
||||||
<p>This is still experimental and there are known bugs. Use at your own risk. Nothing is stored permanently until you hit Save on the summary above. You can use the restore original button to restore the original values.</p>
|
<p>This is still experimental and there are known bugs. Use at your own risk. Nothing is stored permanently until you hit Save on the summary above. You can use the restore original button to restore the original values.</p>
|
||||||
<div class="grid_6 alpha">
|
<div class="grid_6 alpha">
|
||||||
<div class="grid_1 alpha"><strong>#</strong></div>
|
<div class="grid_1 alpha"><strong>#</strong></div>
|
||||||
<div class="grid_1">
|
<div class="grid_1">
|
||||||
<strong>Time</strong>
|
<strong>Time</strong>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid_1">
|
<div class="grid_1">
|
||||||
<strong>Distance</strong>
|
<strong>Distance</strong>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid_1 suffix_2 omega">
|
<div class="grid_1 suffix_2 omega">
|
||||||
<strong>Type</strong>
|
<strong>Type</strong>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<form enctype="multipart/form-data" action="/rowers/workout/{{ workout.id }}/editintervals" method="post">
|
<form enctype="multipart/form-data" action="/rowers/workout/{{ workout.id }}/editintervals" method="post">
|
||||||
{% for i in nrintervals|times %}
|
{% for i in nrintervals|times %}
|
||||||
<div class="grid_6 alpha">
|
<div class="grid_6 alpha">
|
||||||
<div class="grid_1 alpha">{{ i }}</div>
|
<div class="grid_1 alpha">{{ i }}</div>
|
||||||
<div class="grid_1">
|
<div class="grid_1">
|
||||||
{% get_field_id i "intervalt_" detailform %}
|
{% get_field_id i "intervalt_" detailform %}
|
||||||
</div>
|
</div>
|
||||||
<div class="grid_1">
|
<div class="grid_1">
|
||||||
{% get_field_id i "intervald_" detailform %}
|
{% get_field_id i "intervald_" detailform %}
|
||||||
</div>
|
</div>
|
||||||
<div class="grid_2 suffix_1 omega">
|
<div class="grid_2 suffix_1 omega">
|
||||||
{% get_field_id i "type_" detailform %}
|
{% get_field_id i "type_" detailform %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div id="formbutton" class="grid_1 prefix_4 suffix_1">
|
<div id="formbutton" class="grid_1 prefix_4 suffix_1">
|
||||||
<input type="hidden" name="nrintervals" value={{ nrintervals }}>
|
<input type="hidden" name="nrintervals" value={{ nrintervals }}>
|
||||||
<input class="button green" type="submit" value="Update">
|
<input class="button green" type="submit" value="Update">
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ from rowers.forms import (
|
|||||||
LandingPageForm,PlannedSessionSelectForm,WorkoutSessionSelectForm,
|
LandingPageForm,PlannedSessionSelectForm,WorkoutSessionSelectForm,
|
||||||
PlannedSessionTeamForm,PlannedSessionTeamMemberForm,
|
PlannedSessionTeamForm,PlannedSessionTeamMemberForm,
|
||||||
VirtualRaceSelectForm,WorkoutRaceSelectForm,CourseSelectForm,
|
VirtualRaceSelectForm,WorkoutRaceSelectForm,CourseSelectForm,
|
||||||
RaceResultFilterForm,
|
RaceResultFilterForm,PowerIntervalUpdateForm
|
||||||
)
|
)
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
@@ -11303,6 +11303,31 @@ def workout_summary_edit_view(request,id,message="",successmessage=""
|
|||||||
form = SummaryStringForm(initial=data)
|
form = SummaryStringForm(initial=data)
|
||||||
savebutton = 'savestringform'
|
savebutton = 'savestringform'
|
||||||
|
|
||||||
|
# we are saving the results obtained from the power update form
|
||||||
|
elif request.method == 'POST' and 'selector' in request.POST:
|
||||||
|
powerupdateform = PowerIntervalUpdateForm(request.POST)
|
||||||
|
if powerupdateform.is_valid():
|
||||||
|
cd = powerupdateform.cleaned_data
|
||||||
|
powerorpace = cd['selector']
|
||||||
|
power = cd['power']
|
||||||
|
pace = cd['pace']
|
||||||
|
|
||||||
|
if powerorpace == 'power':
|
||||||
|
try:
|
||||||
|
rowdata.updateinterval_power(power)
|
||||||
|
except:
|
||||||
|
messages.error(request,'Error updating power')
|
||||||
|
elif powerorpace == 'pace':
|
||||||
|
try:
|
||||||
|
rowdata.updateinterval_pace(pace)
|
||||||
|
except:
|
||||||
|
messages.error(request,'Error updating pace')
|
||||||
|
|
||||||
|
intervalstats = rowdata.allstats()
|
||||||
|
itime,idist,itype = rowdata.intervalstats_values()
|
||||||
|
nrintervals = len(idist)
|
||||||
|
savebutton = 'savestringform'
|
||||||
|
|
||||||
# we are saving the results obtained from the detailed form
|
# we are saving the results obtained from the detailed form
|
||||||
elif request.method == 'POST' and "savedetailform" in request.POST:
|
elif request.method == 'POST' and "savedetailform" in request.POST:
|
||||||
savebutton = 'savedetailform'
|
savebutton = 'savedetailform'
|
||||||
@@ -11410,13 +11435,14 @@ def workout_summary_edit_view(request,id,message="",successmessage=""
|
|||||||
|
|
||||||
|
|
||||||
detailform = IntervalUpdateForm(aantal=nrintervals,initial=initial)
|
detailform = IntervalUpdateForm(aantal=nrintervals,initial=initial)
|
||||||
|
powerupdateform = PowerIntervalUpdateForm()
|
||||||
|
|
||||||
# render page
|
# render page
|
||||||
|
|
||||||
return render(request, 'summary_edit.html',
|
return render(request, 'summary_edit.html',
|
||||||
{'form':form,
|
{'form':form,
|
||||||
'detailform':detailform,
|
'detailform':detailform,
|
||||||
|
'powerupdateform':powerupdateform,
|
||||||
'workout':row,
|
'workout':row,
|
||||||
'teams':get_my_teams(request.user),
|
'teams':get_my_teams(request.user),
|
||||||
'intervalstats':intervalstats,
|
'intervalstats':intervalstats,
|
||||||
|
|||||||
Reference in New Issue
Block a user