diff --git a/rowers/admin.py b/rowers/admin.py
index f18a3760..cd14f468 100644
--- a/rowers/admin.py
+++ b/rowers/admin.py
@@ -18,10 +18,48 @@ class RowerInline(admin.StackedInline):
verbose_name_plural = 'rower'
filter_horizontal = ('team','friends')
+ fieldsets = (
+ ('Rower Plan',
+ {'fields':('rowerplan','teamplanexpires','clubsize','protrialexpires','plantrialexpires',)}),
+ ('Rower Settings',
+ {'fields':
+ ('gdproptin','gdproptindate','weightcategory','sex','birthdate','getemailnotifications',
+ 'getimportantemails','emailbounced','defaultlandingpage',
+ 'defaulttimezone','showfavoritechartnotes')}),
+ ('Rower Zones',
+ {'fields':
+ ('ftp','otwslack','pw_ut2','pw_ut1','pw_at','pw_tr','pw_an','max',
+ 'rest','ut2','ut1','at','tr','an','hrftp',)}),
+ ('Import/Export Keys',
+ {'fields':('c2token','tokenexpirydate','c2refreshtoken','c2_auto_export',
+ 'sporttrackstoken','sporttrackstokenexpirydate','sporttracksrefreshtoken',
+ 'sporttracks_auto_export',
+ 'underarmourtoken','underarmourtokenexpirydate','underarmourrefreshtoken',
+ 'mapmyfitness_auto_export',
+ 'tptoken','tptokenexpirydate','tprefreshtoken',
+ 'trainingpeaks_auto_export',
+ 'polartoken','polartokenexpirydate','polarrefreshtoken','polaruserid',
+ 'polar_auto_import',
+ 'stravatoken','stravaexportas','strava_auto_export',
+ 'runkeepertoken','runkeeper_auto_export',)}),
+ ('Team',
+ {'fields':('friends','privacy','team')}),
+ )
+
+
#class UserAdmin(UserAdmin):
class UserAdmin(admin.ModelAdmin):
inlines = (RowerInline,)
list_display = ('username','email','first_name','last_name','rowerplan')
+
+ fieldsets = (
+ ('Personal info',
+ {'fields':
+ ('first_name', 'last_name', 'email', 'date_joined', 'last_login',)}),
+ ('Permissions',
+ {'fields':
+ ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions',)}),)
+
search_fields = ["username","first_name","last_name","email"]
def rowerplan(self, obj):
diff --git a/rowers/dataprep.py b/rowers/dataprep.py
index ca63cac2..24869490 100644
--- a/rowers/dataprep.py
+++ b/rowers/dataprep.py
@@ -2364,3 +2364,23 @@ def workout_rscore(w):
tss = 0
return tss,normp
+
+def workout_normv(w,pp=4.0):
+ df,row = getrowdata_db(id=w.id)
+ df = clean_df_stats(df,workstrokesonly=False)
+ if df.empty:
+ df,row = getrowdata_db(id=w.id)
+ df = clean_df_stats(df,workstrokesonly=False)
+
+ df['deltat'] = df['time'].diff()
+ duration = df['time'].max()-df['time'].min()
+ duration /= 1.0e3
+ df['v4'] = df['velo']**(pp)
+ v4mean = wavg(df,'v4','deltat')
+ normv = v4mean**(1./pp)
+
+ if np.isnan(normv):
+ return 500./120.
+
+ return normv
+
diff --git a/rowers/forms.py b/rowers/forms.py
index 71c93283..ae4fcc53 100644
--- a/rowers/forms.py
+++ b/rowers/forms.py
@@ -488,8 +488,8 @@ class PowerIntervalUpdateForm(forms.Form):
('pace','Pace')
)
- pace = forms.DurationField(label='Pace',required=False)
- power = forms.IntegerField(label='Power',required=False)
+ pace = forms.DurationField(required=False,label='Pace (/500m)')
+ power = forms.IntegerField(required=False,label='Power (W)')
selector = forms.ChoiceField(choices=selectorchoices,
required=True,
initial='power',
diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py
index ba3eba9e..a8600598 100644
--- a/rowers/interactiveplots.py
+++ b/rowers/interactiveplots.py
@@ -2138,8 +2138,8 @@ def interactive_chart(id=0,promember=0):
try:
spm = datadf['spm']
except KeyError:
- datadf['spm'] = 0*datadf['pace']
-
+ datadf['spm'] = 0
+
#datadf,row = dataprep.getrowdata_db(id=id)
#if datadf.empty:
#return "","No Valid Data Available"
diff --git a/rowers/templates/registration/password_reset.html b/rowers/templates/registration/password_reset.html
new file mode 100644
index 00000000..1941a27b
--- /dev/null
+++ b/rowers/templates/registration/password_reset.html
@@ -0,0 +1,18 @@
+{% load i18n %}
+
+
+
+ Forgot your password?
+
+
+ Forgot your password?
+
+
+
diff --git a/rowers/templates/summary_edit.html b/rowers/templates/summary_edit.html
index 59510b18..3419f077 100644
--- a/rowers/templates/summary_edit.html
+++ b/rowers/templates/summary_edit.html
@@ -164,6 +164,9 @@
{% csrf_token %}
+ {% for key,value in formvalues.items %}
+
+ {% endfor %}
{% for field in detailform %}
{{ field.as_hidden }}
{% endfor %}
diff --git a/rowers/views.py b/rowers/views.py
index 8a4d22fe..f38426c7 100644
--- a/rowers/views.py
+++ b/rowers/views.py
@@ -11295,7 +11295,23 @@ def workout_summary_edit_view(request,id,message="",successmessage=""
pass
savebutton = 'nosavebutton'
+ formvalues = {}
+ form = SummaryStringForm()
+ tss,normp = dataprep.workout_rscore(row)
+
+ normv = dataprep.workout_normv(row,pp=8.0)
+
+ avpace = datetime.timedelta(seconds=int(500./normv))
+
+ data = {
+ 'power': int(normp),
+ 'pace': avpace,
+ 'selector': normp,
+ }
+
+ powerupdateform = PowerIntervalUpdateForm(initial=data)
+
# We have submitted the mini language interpreter
if request.method == 'POST' and "intervalstring" in request.POST:
form = SummaryStringForm(request.POST)
@@ -11310,7 +11326,58 @@ def workout_summary_edit_view(request,id,message="",successmessage=""
itime,idist,itype = rowdata.intervalstats_values()
nrintervals = len(idist)
savebutton = 'savestringform'
-
+ powerupdateform = PowerIntervalUpdateForm()
+
+ # we are saving the results obtained from the split by power/pace interpreter
+ elif request.method == 'POST' and "savepowerpaceform" in request.POST:
+ powerorpace = request.POST['powerorpace']
+ value_pace = request.POST['value_pace']
+ value_power = request.POST['value_power']
+ if powerorpace == 'power':
+ power = int(value_power)
+ pace_secs = 120.0
+ else:
+ power = 0
+ pace_secs = float(value_pace)
+
+ if powerorpace == 'power' and power is not None:
+ try:
+ rowdata.updateinterval_metric(' Power (watts)',power,mode='larger',
+ debug=False,smoothwindow=15)
+ except:
+ messages.error(request,'Error updating power')
+ elif powerorpace == 'pace':
+ try:
+ velo = 500./pace_secs
+ rowdata.updateinterval_metric(' AverageBoatSpeed (m/s)',velo,mode='larger',
+ debug=False,smoothwindow=15)
+ except:
+ messages.error(request,'Error updating pace')
+
+ intervalstats = rowdata.allstats()
+ itime,idist,itype = rowdata.intervalstats_values()
+ nrintervals = len(idist)
+
+ row.summary = intervalstats
+ row.save()
+
+ rowdata.write_csv(f1,gzip=True)
+ messages.info(request,"Updated interval data saved")
+ data = {
+ 'power': power,
+ 'pace': datetime.timedelta(seconds=int(pace_secs)),
+ 'selector': powerorpace
+ }
+ form = SummaryStringForm()
+ powerupdateform = PowerIntervalUpdateForm(initial=data)
+ savebutton = 'savepowerpaceform'
+ formvalues = {
+ 'powerorpace': powerorpace,
+ 'value_power': power,
+ 'value_pace': pace_secs
+ }
+
+
# we are saving the results obtained from the mini language interpreter
elif request.method == 'POST' and "savestringform" in request.POST:
s = request.POST["savestringform"]
@@ -11339,6 +11406,7 @@ def workout_summary_edit_view(request,id,message="",successmessage=""
messages.info(request,"Updated interval data saved")
data = {'intervalstring':s}
form = SummaryStringForm(initial=data)
+ powerupdateform = PowerIntervalUpdateForm()
savebutton = 'savestringform'
# we are saving the results obtained from the power update form
@@ -11371,8 +11439,14 @@ def workout_summary_edit_view(request,id,message="",successmessage=""
intervalstats = rowdata.allstats()
itime,idist,itype = rowdata.intervalstats_values()
nrintervals = len(idist)
- savebutton = 'savestringform'
+ savebutton = 'savepowerpaceform'
+ formvalues = {
+ 'powerorpace': powerorpace,
+ 'value_power': power,
+ 'value_pace': pace_secs
+ }
powerupdateform = PowerIntervalUpdateForm(initial=cd)
+ form = SummaryStringForm()
form = SummaryStringForm()
@@ -11428,6 +11502,7 @@ def workout_summary_edit_view(request,id,message="",successmessage=""
messages.info(request,"Updated interval data saved")
form = SummaryStringForm()
+ powerupdateform = PowerIntervalUpdateForm()
# we are processing the details form
elif request.method == 'POST' and "nrintervals" in request.POST:
@@ -11472,10 +11547,9 @@ def workout_summary_edit_view(request,id,message="",successmessage=""
form = SummaryStringForm()
-
- else:
- form = SummaryStringForm()
- powerupdateform = PowerIntervalUpdateForm()
+ powerupdateform = PowerIntervalUpdateForm()
+
+
initial = {}
for i in xrange(nrintervals):
@@ -11500,6 +11574,7 @@ def workout_summary_edit_view(request,id,message="",successmessage=""
'the_div':div,
'intervalstring':s,
'savebutton':savebutton,
+ 'formvalues':formvalues,
})
# Page where user can manage his favorite charts
diff --git a/rowsandall_app/urls.py b/rowsandall_app/urls.py
index 5fdc8511..f129a657 100644
--- a/rowsandall_app/urls.py
+++ b/rowsandall_app/urls.py
@@ -34,11 +34,13 @@ handler500 = 'rowers.views.error500_view'
urlpatterns = [
url(r'^admin/jsi18n', 'django.views.i18n.javascript_catalog'),
+ url('^', include('django.contrib.auth.urls')),
url(r'^django-rq/',include('django_rq.urls')),
url(r'^password_change_done/$',auth_views.password_change_done,name='password_change_done'),
url(r'^password_change/$',auth_views.password_change),
url(r'^password_reset/$',
auth_views.password_reset,
+ {'template_name': 'rowers/templates/registration/password_reset.html'},
name='password_reset'),
url(r'^password_reset/done/$',
auth_views.password_reset_done,
@@ -58,12 +60,6 @@ urlpatterns += [
url(r'^$',rootview),
url(r'^login/',auth_views.login, name='login'),
url(r'^logout/',auth_views.logout_then_login,name='logout'),
-# url(r'^password_reset/$',auth_views.password_reset,name='password_reset'),
-# url(r'^password_reset_done/$',auth_views.password_reset_done,name='password_reset_done'),
-# url(r'^password_reset_confirm/(?P[0-9A-Za-z_\-]+)/(?P[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', auth_views.password_reset_confirm,name='password_reset_confirm'),
-# url(r'^password_reset_confirm/$',auth_views.password_reset_confirm,name='password_reset_confirm'),
-# url(r'^password_reset_complete/(?P[0-9A-Za-z_\-]+)/(?P[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', auth_views.password_reset_complete,name='password_reset_complete'),
-# url(r'^password_reset_complete/$',auth_views.password_reset_complete,name='password_reset_complete'),
url(r'^rowers/',include('rowers.urls')),
url(r'^cvkbrno/',include('cvkbrno.urls')),
url(r'^admin/rq/',include('django_rq_dashboard.urls')),