Private
Public Access
1
0

Merge branch 'release/v9.98'

This commit is contained in:
Sander Roosendaal
2019-06-12 21:08:50 +02:00
15 changed files with 95 additions and 81 deletions
+6
View File
@@ -578,6 +578,12 @@ class RegistrationForm(UserCreationForm):
model = User model = User
fields = ("username", "first_name", "last_name", "email", "password1", "password2") fields = ("username", "first_name", "last_name", "email", "password1", "password2")
widgets = {
'username': forms.TextInput(attrs={'autocomplete':'new-password'}),
'password1': forms.PasswordInput(attrs={'autocomplete':'new-password'}),
'password2': forms.PasswordInput(attrs={'autocomplete':'new-password'}),
}
class RegistrationFormTermsOfService(RegistrationForm): class RegistrationFormTermsOfService(RegistrationForm):
""" """
Subclass of ``RegistrationForm`` which adds a required checkbox Subclass of ``RegistrationForm`` which adds a required checkbox
+10 -4
View File
@@ -652,6 +652,10 @@ class CoachingGroup(models.Model):
name = self.name name = self.name
) )
def __len__(self):
rs = Rower.objects.filter(coachinggroups__in=[self])
return len(rs)
# Extension of User with rowing specific data # Extension of User with rowing specific data
@python_2_unicode_compatible @python_2_unicode_compatible
class Rower(models.Model): class Rower(models.Model):
@@ -2486,14 +2490,16 @@ class PlannedSessionFormSmall(ModelForm):
] ]
dateTimeOptions = { dateTimeOptions = {
'format': 'yyyy-mm-dd', 'format': '%Y-%m-%d',
'autoclose': True, 'autoclose': True,
} }
input_formats=('%Y-%m-%d')
widgets = { widgets = {
'startdate': DateInput(attrs={'size':10}), 'startdate': DateInput(attrs={'size':10, 'class':'datepicker'}, format='%Y-%m-%d'),
'enddate': DateInput(attrs={'size':10}), 'enddate': DateInput(attrs={'size':10, 'class':'datepicker'}, format='%Y-%m-%d'),
'preferreddate': DateInput(attrs={'size':10}), 'preferreddate': DateInput(attrs={'size':10, 'class':'datepicker'}, format='%Y-%m-%d'),
'name': forms.TextInput(attrs={'size':10}), 'name': forms.TextInput(attrs={'size':10}),
'sessionvalue': forms.TextInput(attrs={'style':'width:5em', 'sessionvalue': forms.TextInput(attrs={'style':'width:5em',
'type':'number'}), 'type':'number'}),
@@ -10,7 +10,14 @@
<li class="grid_4"> <li class="grid_4">
<h1>New Coach Registration (free Coach Plan)</h1> <h1>New Coach Registration (free Coach Plan)</h1>
</li> </li>
<li class="grid_2"> <li class="grid_4">
<p>
This form is for registration as a coach.
Click <a href="/rowers/register">here to register as a rower</a>.
</p>
<p>
Already signed up? Click <a href="/login/">here to sign in.</a>
</p>
<div id="registrationform"> <div id="registrationform">
{% if form.errors %} {% if form.errors %}
@@ -19,14 +26,18 @@
</p> </p>
{% endif %} {% endif %}
<form enctype="multipart/form-data" action="" method="post"> <form enctype="multipart/form-data" action="" method="post" autocomplete="off">
{% csrf_token %} {% csrf_token %}
<table width=100%> <table width=100%>
{{ form.as_table }} {{ form.as_table }}
</table> </table>
<a href="/rowers/legal/">Terms of Service</a> <p>
<input type="hidden" name="next" value="{{ next }}"/> <a href="/rowers/legal/">Terms of Service</a>
<input type="submit" value="Submit"> </p>
<p>
<input type="hidden" name="next" value="{{ next }}"/>
<input type="submit" value="Submit">
</p>
</form> </form>
</div> </div>
</li> </li>
@@ -43,32 +54,6 @@
<p>Also, we are restricting access to the site to 16 years and older <p>Also, we are restricting access to the site to 16 years and older
because of EU data protection regulations.</p> because of EU data protection regulations.</p>
</li> </li>
<li class="rounder grid_2">
<a href="/rowers/coachregister">
<h1>Register as a coach (free)</h1>
<p>Click here and fill out the form to start with a free Coach plan. This allows you
to manage up to 10 athletes (who have to be on the Pro plan). You cannot upload your own
workouts.
</p>
<p>
From this free plan, you can upgrade to any of the paid plans, including coach plans for larger
athlete groups or rower plans for managing your own training plan and workouts.
</p>
</a>
</li>
<li class="rounder grid_2">
<a href="/rowers/register">
<h1>Register as an athlete (free)</h1>
<p>Click here and fill out the form to start with a free Athlete plan. This allows you
to store and analyze your own workouts.
</p>
<p>
From this free plan, you can upgrade to any of the paid plans, including
coach plans for managing larger athlete groups or rower plans for expanded
analytics.
</p>
</a>
</li>
</ul> </ul>
+1 -1
View File
@@ -179,7 +179,7 @@
</div> </div>
{% else %} {% else %}
<div class="signin"> <div class="signin">
<span style="padding:10px"><a href="/rowers/list-workouts/">Enter&nbsp;</a></span> <span style="padding:10px"><a href="/rowers/list-workouts/">Launch App&nbsp;</a></span>
</div> </div>
{% endif %} {% endif %}
<div class="logo"> <div class="logo">
+21 -2
View File
@@ -27,6 +27,7 @@
<th>PRO</th> <th>PRO</th>
<th>SELF-COACH</th> <th>SELF-COACH</th>
<th>COACH</th> <th>COACH</th>
<th>Free COACH</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@@ -36,6 +37,7 @@
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td>
</tr> </tr>
<tr> <tr>
<td>Manual Import, Export, Synchronization and download of all your data</td> <td>Manual Import, Export, Synchronization and download of all your data</td>
@@ -43,6 +45,7 @@
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td>
</tr> </tr>
<tr> <tr>
<td>Heart rate and power zones</td> <td>Heart rate and power zones</td>
@@ -50,6 +53,7 @@
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td>
</tr> </tr>
<tr> <tr>
<td>Ranking Pieces, Stroke Analysis</td> <td>Ranking Pieces, Stroke Analysis</td>
@@ -57,6 +61,7 @@
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td>
</tr> </tr>
<tr> <tr>
<td>Automatic Synchronization with other fitness sites</td> <td>Automatic Synchronization with other fitness sites</td>
@@ -64,6 +69,7 @@
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&nbsp;</td>
</tr> </tr>
<tr> <tr>
<td>Advanced Analysis (Critical Power, Stats, Box Chart, Trend Flex)</td> <td>Advanced Analysis (Critical Power, Stats, Box Chart, Trend Flex)</td>
@@ -71,6 +77,7 @@
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;<a href="#freecoach">*</a></td>
</tr> </tr>
<tr> <tr>
<td>Compare Workouts</td> <td>Compare Workouts</td>
@@ -78,6 +85,7 @@
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;<a href="#freecoach">*</a></td>
</tr> </tr>
<tr> <tr>
<td>Empower Stroke Profile</td> <td>Empower Stroke Profile</td>
@@ -85,6 +93,7 @@
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;<a href="#freecoach">*</a></td>
</tr> </tr>
<tr> <tr>
<td>Sensor Fusion, Split Workout, In-stroke metrics</td> <td>Sensor Fusion, Split Workout, In-stroke metrics</td>
@@ -92,6 +101,7 @@
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;<a href="#freecoach">*</a></td>
</tr> </tr>
<tr> <tr>
<td>Create and manage groups.</td> <td>Create and manage groups.</td>
@@ -99,6 +109,7 @@
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td>
</tr> </tr>
<tr> <tr>
<td>Create Training plans, tests and challenges for yourself and your training group. Track your performance <td>Create Training plans, tests and challenges for yourself and your training group. Track your performance
@@ -107,6 +118,7 @@
<td>&nbsp;</td> <td>&nbsp;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&nbsp;</td>
</tr> </tr>
<tr> <tr>
<td>Create Training plans, tests and challenges for your athletes. Track their performance <td>Create Training plans, tests and challenges for your athletes. Track their performance
@@ -115,6 +127,7 @@
<td>&nbsp;</td> <td>&nbsp;</td>
<td>&nbsp;</td> <td>&nbsp;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td>
</tr> </tr>
<tr> <tr>
<td>Manage your athlete's workouts</td> <td>Manage your athlete's workouts</td>
@@ -122,6 +135,7 @@
<td>&nbsp;</td> <td>&nbsp;</td>
<td>&nbsp;</td> <td>&nbsp;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td>
</tr> </tr>
<tr> <tr>
<td>Run analytics for your athletes</td> <td>Run analytics for your athletes</td>
@@ -129,6 +143,7 @@
<td>&nbsp;</td> <td>&nbsp;</td>
<td>&nbsp;</td> <td>&nbsp;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;<a href="#freecoach">*</a></td>
</tr> </tr>
<tr> <tr>
<td>Change zone intensities and other workout related settings for your athletes</td> <td>Change zone intensities and other workout related settings for your athletes</td>
@@ -136,6 +151,7 @@
<td>&nbsp;</td> <td>&nbsp;</td>
<td>&nbsp;</td> <td>&nbsp;</td>
<td>&#10004;</td> <td>&#10004;</td>
<td>&#10004;</td>
</tr> </tr>
<tr> <tr>
<td>Pricing</td> <td>Pricing</td>
@@ -143,6 +159,7 @@
<td nowrap="nowrap">From 25&euro;/year</td> <td nowrap="nowrap">From 25&euro;/year</td>
<td nowrap="nowrap">From 75&euro;/year</td> <td nowrap="nowrap">From 75&euro;/year</td>
<td nowrap="nowrap">From 90&euro;/year</td> <td nowrap="nowrap">From 90&euro;/year</td>
<td nowrap="nowrap">Free</td>
</tr> </tr>
<tr> <tr>
<td>&nbsp;</td> <td>&nbsp;</td>
@@ -310,10 +327,12 @@
can purchase upgrades to "Pro" and "Self-Coach" plans. can purchase upgrades to "Pro" and "Self-Coach" plans.
</p> </p>
<p> <p id="freecoach">
The Coach plans come in two versions: free and paid. On the free coach plan, The Coach plans come in two versions: free and paid. On the free coach plan,
you can only have athletes who are on the PRO paid plans or higher, and you you can only have athletes who are on the PRO paid plans or higher, and you
cannot upload any workouts to your own account. On the paid cannot upload any workouts to your own account. Some of the advanced Analysis functionality
becomes available when the athlete group is larger than 4.
On the paid
plans, your athletes can be on the free plan, and you have full access to the plans, your athletes can be on the free plan, and you have full access to the
site functionality for your own workouts and those of your athletes. site functionality for your own workouts and those of your athletes.
</p> </p>
+17 -32
View File
@@ -8,9 +8,16 @@
{% block main %} {% block main %}
<ul class="main-content"> <ul class="main-content">
<li class="grid_4"> <li class="grid_4">
<h1>New User Registration</h1> <h1>New Rower Registration</h1>
</li> </li>
<li class="grid_2"> <li class="grid_4">
<p>
This form is for registration as a rower.
Click <a href="/rowers/coachregister">here to register as a coach</a>.
</p>
<p>
Already signed up? Click <a href="/login/">here to sign in.</a>
</p>
<div id="registrationform"> <div id="registrationform">
{% if form.errors %} {% if form.errors %}
@@ -19,14 +26,18 @@
</p> </p>
{% endif %} {% endif %}
<form enctype="multipart/form-data" action="" method="post"> <form enctype="multipart/form-data" action="" method="post" autocomplete="false">
{% csrf_token %} {% csrf_token %}
<table width=100%> <table width=100%>
{{ form.as_table }} {{ form.as_table }}
</table> </table>
<a href="/rowers/legal/">Terms of Service</a> <p>
<input type="hidden" name="next" value="{{ next }}"/> <a href="/rowers/legal/">Terms of Service</a>
<input type="submit" value="Submit"> </p>
<p>
<input type="hidden" name="next" value="{{ next }}"/>
<input type="submit" value="Submit">
</p>
</form> </form>
</div> </div>
</li> </li>
@@ -43,32 +54,6 @@
<p>Also, we are restricting access to the site to 16 years and older <p>Also, we are restricting access to the site to 16 years and older
because of EU data protection regulations.</p> because of EU data protection regulations.</p>
</li> </li>
<li class="rounder grid_2">
<a href="/rowers/coachregister">
<h1>Register as a coach (free)</h1>
<p>Click here and fill out the form to start with a free Coach plan. This allows you
to manage up to 10 athletes (who have to be on the Pro plan). You cannot upload your own
workouts.
</p>
<p>
From this free plan, you can upgrade to any of the paid plans, including coach plans for larger
athlete groups or rower plans for managing your own training plan and workouts.
</p>
</a>
</li>
<li class="rounder grid_2">
<a href="/rowers/register">
<h1>Register as an athlete (free)</h1>
<p>Click here and fill out the form to start with a free Athlete plan. This allows you
to store and analyze your own workouts.
</p>
<p>
From this free plan, you can upgrade to any of the paid plans, including
coach plans for managing larger athlete groups or rower plans for expanded
analytics.
</p>
</a>
</li>
</ul> </ul>
Binary file not shown.
+5
View File
@@ -20,6 +20,7 @@ import requests
from django.http import HttpResponse from django.http import HttpResponse
lbstoN = 4.44822 lbstoN = 4.44822
landingpages = ( landingpages = (
@@ -407,8 +408,12 @@ def totaltime_sec_to_string(totaltime):
def isprorower(r): def isprorower(r):
result = False result = False
result = r.rowerplan in ['pro','coach','plan'] result = r.rowerplan in ['pro','coach','plan']
if not result and r.protrialexpires: if not result and r.protrialexpires:
result = r.rowerplan == 'basic' and r.protrialexpires >= datetime.date.today() result = r.rowerplan == 'basic' and r.protrialexpires >= datetime.date.today()
if not result and r.rowerplan == 'freecoach':
if r.mycoachgroup is not None:
result = len(r.mycoachgroup)>=4
return result return result
+7 -6
View File
@@ -5,6 +5,7 @@ from __future__ import unicode_literals
from __future__ import unicode_literals, absolute_import from __future__ import unicode_literals, absolute_import
from rowers.views.statements import * from rowers.views.statements import *
import collections
from jinja2 import Template,Environment,FileSystemLoader from jinja2 import Template,Environment,FileSystemLoader
def floatformat(x,prec=2): def floatformat(x,prec=2):
@@ -2796,12 +2797,12 @@ def oterankings_view(request,theuser=0,
except: except:
pwr2 = pwr pwr2 = pwr
a = { a = collections.OrderedDict()
'distance':int(d), a['duration'] = timedeltaconv(t)
'duration':timedeltaconv(t), a['distance'] = int(d)
'power':int(pwr), a['pace'] = timedeltaconv(p)
'upper':int(pwr2), a['power'] = int(pwr)
'pace':timedeltaconv(p)} a['upper'] = int(pwr2)
cpredictions.append(a) cpredictions.append(a)
+1 -1
View File
@@ -96,7 +96,7 @@ def remove_user(request):
success, themessages,errormessages = braintreestuff.cancel_subscription(r,id) success, themessages,errormessages = braintreestuff.cancel_subscription(r,id)
for message in themessages: for message in themessages:
messages.info(request,message) messages.info(request,message)
except ProcessorCustomerError: except:
pass pass
if cd['delete_user']: if cd['delete_user']:
+2 -1
View File
@@ -1049,7 +1049,8 @@ def hasplannedsessions(user):
return result return result
from rowers.utils import isprorower,ProcessorCustomerError from rowers.utils import ProcessorCustomerError
from rowers.utils import isprorower
# Check if a user is a Pro member # Check if a user is a Pro member
def ispromember(user): def ispromember(user):
+1 -1
View File
@@ -3563,8 +3563,8 @@ def workout_edit_view(request,id=0,message="",successmessage=""):
else: else:
indoorraces = [] indoorraces = []
r = getrower(request.user)
r = row.user
# render page # render page
return render(request, 'workout_form.html', return render(request, 'workout_form.html',
{'form':form, {'form':form,
+1 -1
View File
@@ -53,7 +53,7 @@ urlpatterns += [
content_type='text/plain')), content_type='text/plain')),
re_path(r'^admin/', admin.site.urls), re_path(r'^admin/', admin.site.urls),
re_path(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework2')), re_path(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework2')),
re_path(r'^$',rootview), re_path(r'^$',landingview),
re_path(r'^landing/$',landingview), re_path(r'^landing/$',landingview),
re_path(r'^getblogs/$',rowersviews.get_blog_posts), re_path(r'^getblogs/$',rowersviews.get_blog_posts),
re_path(r'^login/', re_path(r'^login/',
+1
View File
@@ -26,6 +26,7 @@
background-image: url("/static/img/landing8b.jpg"); background-image: url("/static/img/landing8b.jpg");
} }
.watermark { .watermark {
position: absolute; position: absolute;
float: center; float: center;
+5
View File
@@ -26,6 +26,11 @@
background-image: url("/static/img/landing8b.jpg"); background-image: url("/static/img/landing8b.jpg");
} }
.errorlist {
color: red;
}
.watermark { .watermark {
position: absolute; position: absolute;
float: center; float: center;