From 1b34442bee10b6e8457074479265ea32d8ad996a Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Tue, 21 Jan 2020 21:47:06 +0100
Subject: [PATCH 01/19] test noscript
---
rowers/templates/menuscript.html | 1 +
1 file changed, 1 insertion(+)
diff --git a/rowers/templates/menuscript.html b/rowers/templates/menuscript.html
index 9ba9250f..16994896 100644
--- a/rowers/templates/menuscript.html
+++ b/rowers/templates/menuscript.html
@@ -33,3 +33,4 @@
});
});
+
From 247cad6ee38f6775e4dfaa237cb75d4528dc441d Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Sat, 25 Jan 2020 10:13:48 +0100
Subject: [PATCH 02/19] python to 3.6
---
rowers/tests/.~lock.viewnames.csv# | 1 +
1 file changed, 1 insertion(+)
create mode 100644 rowers/tests/.~lock.viewnames.csv#
diff --git a/rowers/tests/.~lock.viewnames.csv# b/rowers/tests/.~lock.viewnames.csv#
new file mode 100644
index 00000000..c1dec79a
--- /dev/null
+++ b/rowers/tests/.~lock.viewnames.csv#
@@ -0,0 +1 @@
+,sander,sander-pc,25.01.2020 09:37,file:///home/sander/.config/libreoffice/4;
\ No newline at end of file
From 6b313be06a0235be1ada68975b12b7b4246ec781 Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Sat, 25 Jan 2020 15:23:50 +0100
Subject: [PATCH 03/19] updated requirements
---
requirements.txt | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/requirements.txt b/requirements.txt
index 58eb6402..707dd8b5 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -148,6 +148,7 @@ psycopg2==2.8.1
ptyprocess==0.6.0
py==1.8.0
pyarrow==0.15.0
+pycairo==1.19.0
pycparser==2.19
Pygments==2.3.1
pyparsing==2.3.1
@@ -173,9 +174,10 @@ ratelim==0.1.6
redis==3.2.1
requests==2.21.0
requests-oauthlib==1.2.0
-rowingdata==2.5.7
+rowingdata==2.6.4
rowingphysics==0.5.0
rq==0.13.0
+rules==2.1
scipy==1.2.1
SecretStorage==3.1.1
Send2Trash==1.5.0
@@ -194,6 +196,7 @@ testpath==0.4.2
text-unidecode==1.2
thrift==0.11.0
timezonefinder==4.0.1
+tk==0.1.0
toolz==0.10.0
tornado==6.0.1
tqdm==4.31.1
From 466383410d0de4676bcb5b3cefd89467c0c304df Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Sat, 25 Jan 2020 15:59:48 +0100
Subject: [PATCH 04/19] a few more tests
---
23099b58-7632-4d34-97e2-2f4890cf5773.tcx | 2523 ++++++++++++++++++++++
rowers/tests/.~lock.viewnames.csv# | 1 +
rowers/tests/viewnames.csv | 24 +-
rowers/urls.py | 9 +-
rowers/views/analysisviews.py | 190 +-
rowers/views/workoutviews.py | 61 +-
6 files changed, 2650 insertions(+), 158 deletions(-)
create mode 100644 23099b58-7632-4d34-97e2-2f4890cf5773.tcx
create mode 100644 rowers/tests/.~lock.viewnames.csv#
diff --git a/23099b58-7632-4d34-97e2-2f4890cf5773.tcx b/23099b58-7632-4d34-97e2-2f4890cf5773.tcx
new file mode 100644
index 00000000..e7df305a
--- /dev/null
+++ b/23099b58-7632-4d34-97e2-2f4890cf5773.tcx
@@ -0,0 +1,2523 @@
+
+
+
+
+ 2016-05-20T13:41:26.962390+00:00
+
+ 537
+ 2000
+ 118
+
+ 148
+
+
+ 156
+
+ Active
+ 21
+ Manual
+
+
+ <Element 'Notes' at 0x7f433c451b38>
+
+
+
+ rowsandall.com/rowingdata
+
+
+ rowingdata
+
+
+ 0
+ 75
+
+ Release
+
+ EN
+ 000-00000-00
+
+
diff --git a/rowers/tests/.~lock.viewnames.csv# b/rowers/tests/.~lock.viewnames.csv#
new file mode 100644
index 00000000..6dee4878
--- /dev/null
+++ b/rowers/tests/.~lock.viewnames.csv#
@@ -0,0 +1 @@
+,sander,sander-pc,25.01.2020 15:42,file:///home/sander/.config/libreoffice/4;
\ No newline at end of file
diff --git a/rowers/tests/viewnames.csv b/rowers/tests/viewnames.csv
index 4b609ebd..1611ffa6 100644
--- a/rowers/tests/viewnames.csv
+++ b/rowers/tests/viewnames.csv
@@ -28,18 +28,18 @@
26,28,workouts_join_view,join workouts,TRUE,302,pro,302,302,pro,403,403,coach,302,403,FALSE,TRUE,FALSE,TRUE
27,29,workouts_join_select,select workouts to join,TRUE,404,pro,200,302,pro,403,403,coach,200,403,FALSE,TRUE,FALSE,TRUE
28,30,user_boxplot_select,select boxplots,TRUE,302,pro,200,302,pro,403,403,coach,200,302,FALSE,TRUE,FALSE,TRUE
-29,31,analysis_new,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE
-30,32,user_multiflex_select,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE
-31,33,session_jobs_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-32,34,session_jobs_status,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-33,35,kill_async_job,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-34,36,post_progress,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-35,37,graphs_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-36,38,fitnessmetric_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-37,39,rankings_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-38,40,rankings_view2,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-39,41,otwrankings_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-40,42,oterankings_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
+29,31,analysis_new,analysis front page,TRUE,302,pro,200,302,FALSE,200,302,coach,200,302,FALSE,TRUE,FALSE,TRUE
+30,32,user_multiflex_select,select multiflex data,TRUE,302,pro,200,302,FALSE,200,302,coach,200,302,FALSE,TRUE,FALSE,TRUE
+31,33,session_jobs_view,view jobs,TRUE,302,basic,200,302,FALSE,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE
+32,34,session_jobs_status,view jobs,TRUE,302,basic,200,302,FALSE,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE
+33,35,kill_async_job,kill job,TRUE,302,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
+34,36,post_progress,post progress,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
+35,37,graphs_view,view charts,TRUE,302,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,TRUE
+36,38,fitnessmetric_view,view fitness metric,TRUE,302,plan,200,302,plan,403,302,coach,200,302,FALSE,TRUE,FALSE,TRUE
+37,39,rankings_view,view ranking,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,TRUE,FALSE,TRUE
+38,40,rankings_view2,view ranking,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,TRUE,FALSE,TRUE
+39,41,otwrankings_view,view ranking,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,TRUE,FALSE,TRUE
+40,42,oterankings_view,view ranking,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,TRUE,FALSE,TRUE
41,43,cum_flex,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
42,44,analysis_view_data,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
43,47,cum_flex_data,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
diff --git a/rowers/urls.py b/rowers/urls.py
index dbae602e..78072d0d 100644
--- a/rowers/urls.py
+++ b/rowers/urls.py
@@ -246,6 +246,7 @@ urlpatterns = [
re_path(r'^record-progress/(?P.*)/$',views.post_progress),
re_path(r'^record-progress/$',views.post_progress),
re_path(r'^list-graphs/$',views.graphs_view,name='graphs_view'),
+ re_path(r'^list-graphs/user/(?P\d+)/$',views.graphs_view,name='graphs_view'),
re_path(r'^fitness-progress/$',views.fitnessmetric_view,name='fitnessmetric_view'),
re_path(r'^fitness-progress/user/(?P\d+)/$',views.fitnessmetric_view,name='fitnessmetric_view'),
re_path(r'^fitness-progress/user/(?P\d+)/(?P\w+.*)/$',views.fitnessmetric_view,name='fitnessmetric_view'),
@@ -255,17 +256,17 @@ urlpatterns = [
re_path(r'^ote-bests/$',views.rankings_view,name='rankings_view'),
re_path(r'^(?P\d+)/ote-bests/$',views.rankings_view,name='rankings_view'),
# re_path(r'^(?P\d+)/ote-bests2/(?P\d+-\d+-\d+)/(?P\d+-\d+-\d+)/$',views.rankings_view2,name='rankings_view2'),
- re_path(r'^ote-bests2/user/(?P\d+)/$',views.rankings_view2,name='rankings_view2'),
+ re_path(r'^ote-bests2/user/(?P\d+)/$',views.rankings_view2,name='rankings_view2'),
# re_path(r'^ote-bests2/(?P\d+-\d+-\d+)/(?P\d+-\d+-\d+)/$',views.rankings_view2,name='rankings_view2'),
re_path(r'^ote-bests2/$',views.rankings_view2,name='rankings_view2'),
# re_path(r'^otw-bests/user/(?P\d+)/(?P\d+-\d+-\d+)/(?P\d+-\d+-\d+)/$',views.otwrankings_view,name='otwrankings_view'),
# re_path(r'^otw-bests/(?P\d+-\d+-\d+)/(?P\d+-\d+-\d+)/$',views.otwrankings_view,name='otwrankings_view'),
- re_path(r'^otw-bests/user/(?P\d+)/$',views.otwrankings_view,name='otwrankings_view'),
+ re_path(r'^otw-bests/user/(?P\d+)/$',views.otwrankings_view,name='otwrankings_view'),
re_path(r'^otw-bests/$',views.otwrankings_view,name='otwrankings_view'),
# re_path(r'^ote-ranking/user/(?P\d+)/(?P\d+-\d+-\d+)/(?P\d+-\d+-\d+)/$',views.oterankings_view,name='oterankings_view'),
# re_path(r'^ote-ranking/(?P\d+-\d+-\d+)/(?P\d+-\d+-\d+)/$',views.oterankings_view,name='oterankings_view'),
re_path(r'^ote-ranking/$',views.oterankings_view,name='oterankings_view'),
- re_path(r'^ote-ranking/user/(?P\d+)/$',views.oterankings_view,name='oterankings_view'),
+ re_path(r'^ote-ranking/user/(?P\d+)/$',views.oterankings_view,name='oterankings_view'),
# re_path(r'^flexall/(?P\w+.*)/(?P\w+.*)/(?P\w+.*)/(?P\d+-\d+-\d+)/(?P\d+-\d+-\d+)/user/(?P\d+)/$',views.cum_flex,name='cum_flex'),
# re_path(r'^flexall/(?P\w+.*)/(?P\w+.*)/(?P\w+.*)/(?P\d+-\d+-\d+)/(?P\d+-\d+-\d+)/$',views.cum_flex,name='cum_flex'),
re_path(r'^flexall/(?P\w+.*)/(?P\w+.*)/(?P\w+.*)/$',views.cum_flex,name='cum_flex'),
@@ -450,7 +451,7 @@ urlpatterns = [
re_path(r'^user-multiflex-data/$',views.multiflex_data,name='multiflex_data'),
re_path(r'^me/deactivate/$',views.deactivate_user,name='deactivate_user'),
re_path(r'^me/delete/$',views.remove_user,name='remove_user'),
-# re_path(r'^survey/$',views.survey,name='survey'),
+ re_path(r'^survey/$',views.survey,name='survey'),
re_path(r'^me/gdpr-optin-confirm/?/$',views.user_gdpr_confirm,name='user_gdpr_confirm'),
re_path(r'^me/gdpr-optin-confirm/$',views.user_gdpr_confirm,name='user_gdpr_confirm'),
re_path(r'^me/gdpr-optin/?/$',views.user_gdpr_optin,name='user_gdpr_optin'),
diff --git a/rowers/views/analysisviews.py b/rowers/views/analysisviews.py
index be1190da..b8a79ad3 100644
--- a/rowers/views/analysisviews.py
+++ b/rowers/views/analysisviews.py
@@ -1741,7 +1741,7 @@ def ajax_agegrouprecords(request,
# Show ranking distances including predicted paces
@login_required()
-def rankings_view2(request,theuser=0,
+def rankings_view2(request,userid=0,
startdate=timezone.now()-datetime.timedelta(days=365),
enddate=timezone.now(),
deltadays=-1,
@@ -1762,83 +1762,84 @@ def rankings_view2(request,theuser=0,
enddate = startdate
startdate = s
- if theuser == 0:
- theuser = request.user.id
+ if userid == 0:
+ userid = request.user.id
else:
lastupdated = "01-01-1900"
promember=0
- if not request.user.is_anonymous:
- r = getrower(request.user)
+ r = getrequestrower(request,userid=userid)
+ theuser = r.user
+
+ wcdurations = []
+ wcpower = []
+
+ lastupdated = "01-01-1900"
+ userid = 0
+ if 'options' in request.session:
+ options = request.session['options']
+ try:
+ wcdurations = options['wcdurations']
+ wcpower = options['wcpower']
+ lastupdated = options['lastupdated']
+ except KeyError:
+ pass
+ try:
+ userid = options['userid']
+ except KeyError:
+ userid = 0
+ else:
+ options = {}
+
+
+
+ lastupdatedtime = arrow.get(lastupdated).timestamp
+ current_time = arrow.utcnow().timestamp
+
+ deltatime_seconds = current_time - lastupdatedtime
+ recalc = False
+ if str(userid) != str(theuser) or deltatime_seconds > 3600:
+ recalc = True
+ options['lastupdated'] = arrow.utcnow().isoformat()
+ else:
+ recalc = False
+
+ options['userid'] = theuser.id
+
+ if r.birthdate:
+ age = calculate_age(r.birthdate)
+ else:
+ worldclasspower = None
+ age = 0
+
+ agerecords = CalcAgePerformance.objects.filter(
+ age = age,
+ sex = r.sex,
+ weightcategory = r.weightcategory)
+
+ if len(agerecords) == 0:
+ recalc = True
+ wcpower = []
+ wcduration = []
+ else:
wcdurations = []
wcpower = []
+ for record in agerecords:
+ wcdurations.append(record.duration)
+ wcpower.append(record.power)
- lastupdated = "01-01-1900"
- userid = 0
- if 'options' in request.session:
- options = request.session['options']
- try:
- wcdurations = options['wcdurations']
- wcpower = options['wcpower']
- lastupdated = options['lastupdated']
- except KeyError:
- pass
- try:
- userid = options['userid']
- except KeyError:
- userid = 0
- else:
- options = {}
+ options['wcpower'] = wcpower
+ options['wcdurations'] = wcdurations
+ if theuser:
+ options['userid'] = theuser.id
+
+ request.session['options'] = options
-
- lastupdatedtime = arrow.get(lastupdated).timestamp
- current_time = arrow.utcnow().timestamp
-
- deltatime_seconds = current_time - lastupdatedtime
- recalc = False
- if str(userid) != str(theuser) or deltatime_seconds > 3600:
- recalc = True
- options['lastupdated'] = arrow.utcnow().isoformat()
- else:
- recalc = False
-
- options['userid'] = theuser
-
- if r.birthdate:
- age = calculate_age(r.birthdate)
- else:
- worldclasspower = None
- age = 0
-
- agerecords = CalcAgePerformance.objects.filter(
- age = age,
- sex = r.sex,
- weightcategory = r.weightcategory)
-
- if len(agerecords) == 0:
- recalc = True
- wcpower = []
- wcduration = []
- else:
- wcdurations = []
- wcpower = []
- for record in agerecords:
- wcdurations.append(record.duration)
- wcpower.append(record.power)
-
- options['wcpower'] = wcpower
- options['wcdurations'] = wcdurations
- if theuser:
- options['userid'] = theuser
-
- request.session['options'] = options
-
-
- result = request.user.is_authenticated and ispromember(request.user)
- if result:
- promember=1
+ result = request.user.is_authenticated and ispromember(request.user)
+ if result:
+ promember=1
# get all indoor rows in date range
@@ -1887,10 +1888,7 @@ def rankings_view2(request,theuser=0,
r=0
- try:
- uu = User.objects.get(id=theuser)
- except User.DoesNotExist:
- uu = ''
+ uu = theuser
# test to fix bug
@@ -2155,7 +2153,7 @@ def rankings_view2(request,theuser=0,
message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality",
redirect_field_name=None)
@permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True)
-def otwrankings_view(request,theuser=0,
+def otwrankings_view(request,userid=0,
startdate=timezone.now()-datetime.timedelta(days=365),
enddate=timezone.now(),
startdatestring="",
@@ -2178,22 +2176,9 @@ def otwrankings_view(request,theuser=0,
enddate = startdate
startdate = s
- if theuser == 0:
- if 'rowerid' in request.session:
- try:
- r = Rower.objects.get(id=request.session['rowerid'])
- theuser = r.user.id
- except Rower.DoesNotExist:
- theuser = request.user.id
- else:
- theuser = request.user.id
+ r = getrequestrower(request,userid=userid)
- promember=0
- if not request.user.is_anonymous:
- r = Rower.objects.get(user=request.user)
- result = request.user.is_authenticated and ispromember(request.user)
- if result:
- promember=1
+ theuser = r.user
# get all OTW rows in date range
@@ -2247,10 +2232,7 @@ def otwrankings_view(request,theuser=0,
- try:
- uu = User.objects.get(id=theuser)
- except User.DoesNotExist:
- uu = ''
+ uu = theuser
# test to fix bug
@@ -2561,7 +2543,7 @@ def otwcp_toadmin_view(request,theuser=0,
message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality",
redirect_field_name=None)
@permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True)
-def oterankings_view(request,theuser=0,
+def oterankings_view(request,userid=0,
startdate=timezone.now()-datetime.timedelta(days=365),
enddate=timezone.now(),
startdatestring="",
@@ -2584,23 +2566,11 @@ def oterankings_view(request,theuser=0,
enddate = startdate
startdate = s
- if theuser == 0:
- if 'rowerid' in request.session:
- try:
- r = Rower.objects.get(id=request.session['rowerid'])
- theuser = r.user.id
- except Rower.DoesNotExist:
- theuser = request.user.id
- else:
- theuser = request.user.id
+ r = getrequestrower(request,userid=userid)
+ theuser = r.user
promember=0
- if not request.user.is_anonymous:
- r = Rower.objects.get(user=request.user)
- result = request.user.is_authenticated and ispromember(request.user)
- if result:
- promember=1
# get all OTW rows in date range
@@ -2674,10 +2644,8 @@ def oterankings_view(request,theuser=0,
raise Http404("Rower doesn't exist")
- try:
- uu = User.objects.get(id=theuser)
- except User.DoesNotExist:
- uu = ''
+ uu = theuser
+
# test to fix bug
diff --git a/rowers/views/workoutviews.py b/rowers/views/workoutviews.py
index 376f563e..2b506203 100644
--- a/rowers/views/workoutviews.py
+++ b/rowers/views/workoutviews.py
@@ -5062,46 +5062,45 @@ def list_videos(request):
})
@login_required()
-def graphs_view(request):
+def graphs_view(request,userid=0):
request.session['referer'] = reverse('graphs_view')
+ r = getrequestrower(request,userid=userid)
+ workouts = Workout.objects.filter(user=r).order_by("-date", "-starttime")
+ query = request.GET.get('q')
+ if query:
+ query_list = query.split()
+ workouts = workouts.filter(
+ reduce(operator.and_,
+ (Q(name__icontains=q) for q in query_list)) |
+ reduce(operator.and_,
+ (Q(notes__icontains=q) for q in query_list))
+ )
+ searchform = SearchForm(initial={'q':query})
+ else:
+ searchform = SearchForm()
+
+ g = GraphImage.objects.filter(workout__in=workouts).order_by("-creationdatetime")
+
+
+ paginator = Paginator(g,8)
+ page = request.GET.get('page')
+
try:
- r = getrower(request.user)
- workouts = Workout.objects.filter(user=r).order_by("-date", "-starttime")
- query = request.GET.get('q')
- if query:
- query_list = query.split()
- workouts = workouts.filter(
- reduce(operator.and_,
- (Q(name__icontains=q) for q in query_list)) |
- reduce(operator.and_,
- (Q(notes__icontains=q) for q in query_list))
- )
- searchform = SearchForm(initial={'q':query})
- else:
- searchform = SearchForm()
+ g = paginator.page(page)
+ except PageNotAnInteger:
+ g = paginator.page(1)
+ except EmptyPage:
+ g = paginator.page(paginator.num_pages)
- g = GraphImage.objects.filter(workout__in=workouts).order_by("-creationdatetime")
-
-
- paginator = Paginator(g,8)
- page = request.GET.get('page')
-
- try:
- g = paginator.page(page)
- except PageNotAnInteger:
- g = paginator.page(1)
- except EmptyPage:
- g = paginator.page(paginator.num_pages)
-
- return render(request, 'list_graphs.html',
+ return render(request, 'list_graphs.html',
{'graphs': g,
'searchform':searchform,
'active':'nav-workouts',
'teams':get_my_teams(request.user),
+ 'rower':r,
})
- except Rower.DoesNotExist:
- raise Http404("User has no rower instance")
+
# Show the chart (png image)
def graph_show_view(request,id):
From 5e8701792ffdc1814f31bc4d065ea8a8ba891b4b Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Sat, 25 Jan 2020 16:33:45 +0100
Subject: [PATCH 05/19] bla
---
rowers/views/userviews.py | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/rowers/views/userviews.py b/rowers/views/userviews.py
index d3f4903d..d82f5b47 100644
--- a/rowers/views/userviews.py
+++ b/rowers/views/userviews.py
@@ -5,6 +5,31 @@ from __future__ import unicode_literals
from rowers.views.statements import *
+@login_required()
+def survey(request):
+
+ r = getrower(request.user)
+
+ surveyform = SurveyForm()
+
+ if request.method == 'POST':
+ form = SurveyForm(request.POST)
+ r.surveydone = True
+ r.surveydonedate = timezone.now()
+ r.save()
+
+ nexturl = request.GET.get('next')
+ return HttpResponseRedirect(nexturl)
+
+ context = {
+ 'teams':get_my_teams(request.user),
+ 'rower':r,
+ 'form':surveyform,
+ }
+
+
+ return render(request,'survey.html',context)
+
@login_required()
def start_trial_view(request):
r = getrower(request.user)
From 1ff5ce827f68d3af6ed92d5d893e4e35ff9377de Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Sat, 25 Jan 2020 16:46:25 +0100
Subject: [PATCH 06/19] passing a few more tests
---
rowers/tests/.~lock.viewnames.csv# | 1 +
rowers/urls.py | 6 ++---
rowers/views/analysisviews.py | 42 ++++++++++++++++--------------
3 files changed, 26 insertions(+), 23 deletions(-)
create mode 100644 rowers/tests/.~lock.viewnames.csv#
diff --git a/rowers/tests/.~lock.viewnames.csv# b/rowers/tests/.~lock.viewnames.csv#
new file mode 100644
index 00000000..02dab132
--- /dev/null
+++ b/rowers/tests/.~lock.viewnames.csv#
@@ -0,0 +1 @@
+,sander,sander-pc,25.01.2020 16:35,file:///home/sander/.config/libreoffice/4;
\ No newline at end of file
diff --git a/rowers/urls.py b/rowers/urls.py
index 78072d0d..9bee767c 100644
--- a/rowers/urls.py
+++ b/rowers/urls.py
@@ -248,13 +248,13 @@ urlpatterns = [
re_path(r'^list-graphs/$',views.graphs_view,name='graphs_view'),
re_path(r'^list-graphs/user/(?P\d+)/$',views.graphs_view,name='graphs_view'),
re_path(r'^fitness-progress/$',views.fitnessmetric_view,name='fitnessmetric_view'),
- re_path(r'^fitness-progress/user/(?P\d+)/$',views.fitnessmetric_view,name='fitnessmetric_view'),
- re_path(r'^fitness-progress/user/(?P\d+)/(?P\w+.*)/$',views.fitnessmetric_view,name='fitnessmetric_view'),
+ re_path(r'^fitness-progress/user/(?P\d+)/$',views.fitnessmetric_view,name='fitnessmetric_view'),
+ re_path(r'^fitness-progress/user/(?P\d+)/(?P\w+.*)/$',views.fitnessmetric_view,name='fitnessmetric_view'),
# re_path(r'^ote-bests/user/(?P\d+)/(?P\d+-\d+-\d+)/(?P\d+-\d+-\d+)/$',views.rankings_view,name='rankings_view'),
re_path(r'^ote-bests/user/(?P\d+)/$',views.rankings_view,name='rankings_view'),
# re_path(r'^ote-bests/(?P\d+-\d+-\d+)/(?P\d+-\d+-\d+)/$',views.rankings_view,name='rankings_view'),
re_path(r'^ote-bests/$',views.rankings_view,name='rankings_view'),
- re_path(r'^(?P\d+)/ote-bests/$',views.rankings_view,name='rankings_view'),
+ re_path(r'^(?P\d+)/ote-bests/$',views.rankings_view,name='rankings_view'),
# re_path(r'^(?P\d+)/ote-bests2/(?P\d+-\d+-\d+)/(?P\d+-\d+-\d+)/$',views.rankings_view2,name='rankings_view2'),
re_path(r'^ote-bests2/user/(?P\d+)/$',views.rankings_view2,name='rankings_view2'),
# re_path(r'^ote-bests2/(?P\d+-\d+-\d+)/(?P\d+-\d+-\d+)/$',views.rankings_view2,name='rankings_view2'),
diff --git a/rowers/views/analysisviews.py b/rowers/views/analysisviews.py
index b8a79ad3..03df34f1 100644
--- a/rowers/views/analysisviews.py
+++ b/rowers/views/analysisviews.py
@@ -1335,13 +1335,13 @@ def planrequired_view(request):
@user_passes_test(isplanmember,login_url="/rowers/paidplans",
message="This functionality requires a Coach or Self-Coach plan",
redirect_field_name=None)
-@permission_required('rower.is_coach',fn=get_user_by_id,raise_exception=True)
-def fitnessmetric_view(request,id=0,mode='rower',
+@permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True)
+def fitnessmetric_view(request,userid=0,mode='rower',
startdate=timezone.now()-timezone.timedelta(days=365),
enddate=timezone.now()):
- therower = getrequestrower(request,userid=id)
+ therower = getrequestrower(request,userid=userid)
theuser = therower.user
@@ -1391,7 +1391,8 @@ def fitnessmetric_view(request,id=0,mode='rower',
# Show ranking distances including predicted paces
@login_required()
-def rankings_view(request,theuser=0,
+@permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True)
+def rankings_view(request,userid=0,
startdate=timezone.now()-datetime.timedelta(days=365),
enddate=timezone.now(),
deltadays=-1,
@@ -1412,25 +1413,25 @@ def rankings_view(request,theuser=0,
enddate = startdate
startdate = s
- if theuser == 0:
- theuser = request.user.id
+
promember=0
- if not request.user.is_anonymous:
- r = getrower(request.user)
- if r.birthdate:
- age = calculate_age(r.birthdate)
- worldclasspower = int(metrics.getagegrouprecord(
- age,
- sex=r.sex,
- weightcategory=r.weightcategory,
- ))
- else:
- worldclasspower = None
+ r = getrequestrower(request,userid=userid)
+ theuser = r.user.id
- result = request.user.is_authenticated and ispromember(request.user)
- if result:
- promember=1
+ if r.birthdate:
+ age = calculate_age(r.birthdate)
+ worldclasspower = int(c2stuff.getagegrouprecord(
+ age,
+ sex=r.sex,
+ weightcategory=r.weightcategory,
+ ))
+ else:
+ worldclasspower = None
+
+ result = request.user.is_authenticated and ispromember(request.user)
+ if result:
+ promember=1
# get all indoor rows in date range
@@ -1741,6 +1742,7 @@ def ajax_agegrouprecords(request,
# Show ranking distances including predicted paces
@login_required()
+@permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True)
def rankings_view2(request,userid=0,
startdate=timezone.now()-datetime.timedelta(days=365),
enddate=timezone.now(),
From adaf362fadf3c59bd299db9a6df3e2acc610e3bf Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Sat, 25 Jan 2020 16:54:09 +0100
Subject: [PATCH 07/19] a few small fixes
---
646902ca-16e5-4ff6-b86a-62ae1dafa415.gpx | 574 +++++++++++++++++++++++
rowers/urls.py | 2 +-
rowers/views/analysisviews.py | 1 +
3 files changed, 576 insertions(+), 1 deletion(-)
create mode 100644 646902ca-16e5-4ff6-b86a-62ae1dafa415.gpx
diff --git a/646902ca-16e5-4ff6-b86a-62ae1dafa415.gpx b/646902ca-16e5-4ff6-b86a-62ae1dafa415.gpx
new file mode 100644
index 00000000..7069443f
--- /dev/null
+++ b/646902ca-16e5-4ff6-b86a-62ae1dafa415.gpx
@@ -0,0 +1,574 @@
+Garmin InternationalExport by rowingdata
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/rowers/urls.py b/rowers/urls.py
index 9bee767c..faf05629 100644
--- a/rowers/urls.py
+++ b/rowers/urls.py
@@ -251,7 +251,7 @@ urlpatterns = [
re_path(r'^fitness-progress/user/(?P\d+)/$',views.fitnessmetric_view,name='fitnessmetric_view'),
re_path(r'^fitness-progress/user/(?P\d+)/(?P\w+.*)/$',views.fitnessmetric_view,name='fitnessmetric_view'),
# re_path(r'^ote-bests/user/(?P\d+)/(?P\d+-\d+-\d+)/(?P\d+-\d+-\d+)/$',views.rankings_view,name='rankings_view'),
- re_path(r'^ote-bests/user/(?P\d+)/$',views.rankings_view,name='rankings_view'),
+ re_path(r'^ote-bests/user/(?P\d+)/$',views.rankings_view,name='rankings_view'),
# re_path(r'^ote-bests/(?P\d+-\d+-\d+)/(?P\d+-\d+-\d+)/$',views.rankings_view,name='rankings_view'),
re_path(r'^ote-bests/$',views.rankings_view,name='rankings_view'),
re_path(r'^(?P\d+)/ote-bests/$',views.rankings_view,name='rankings_view'),
diff --git a/rowers/views/analysisviews.py b/rowers/views/analysisviews.py
index 03df34f1..4048b9ac 100644
--- a/rowers/views/analysisviews.py
+++ b/rowers/views/analysisviews.py
@@ -2179,6 +2179,7 @@ def otwrankings_view(request,userid=0,
startdate = s
r = getrequestrower(request,userid=userid)
+ promember = True
theuser = r.user
From 3633913a5efcfa436d17371e6208c188f80484d4 Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Thu, 30 Jan 2020 15:12:06 +0100
Subject: [PATCH 08/19] deleting gpx
---
646902ca-16e5-4ff6-b86a-62ae1dafa415.gpx | 574 -----------------------
1 file changed, 574 deletions(-)
delete mode 100644 646902ca-16e5-4ff6-b86a-62ae1dafa415.gpx
diff --git a/646902ca-16e5-4ff6-b86a-62ae1dafa415.gpx b/646902ca-16e5-4ff6-b86a-62ae1dafa415.gpx
deleted file mode 100644
index 7069443f..00000000
--- a/646902ca-16e5-4ff6-b86a-62ae1dafa415.gpx
+++ /dev/null
@@ -1,574 +0,0 @@
-Garmin InternationalExport by rowingdata
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
From 75ceb89a53cff4949887d6a21401d469f7fb75c6 Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Thu, 30 Jan 2020 17:33:44 +0100
Subject: [PATCH 09/19] a few more views done
---
rowers/tests/.~lock.viewnames.csv# | 1 -
rowers/tests/viewnames.csv | 32 +++++++++++++++---------------
rowers/urls.py | 2 +-
rowers/views/analysisviews.py | 4 ++--
rowers/views/workoutviews.py | 31 ++++++++++-------------------
5 files changed, 30 insertions(+), 40 deletions(-)
delete mode 100644 rowers/tests/.~lock.viewnames.csv#
diff --git a/rowers/tests/.~lock.viewnames.csv# b/rowers/tests/.~lock.viewnames.csv#
deleted file mode 100644
index 02dab132..00000000
--- a/rowers/tests/.~lock.viewnames.csv#
+++ /dev/null
@@ -1 +0,0 @@
-,sander,sander-pc,25.01.2020 16:35,file:///home/sander/.config/libreoffice/4;
\ No newline at end of file
diff --git a/rowers/tests/viewnames.csv b/rowers/tests/viewnames.csv
index 1611ffa6..d291398d 100644
--- a/rowers/tests/viewnames.csv
+++ b/rowers/tests/viewnames.csv
@@ -40,22 +40,22 @@
38,40,rankings_view2,view ranking,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,TRUE,FALSE,TRUE
39,41,otwrankings_view,view ranking,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,TRUE,FALSE,TRUE
40,42,oterankings_view,view ranking,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,TRUE,FALSE,TRUE
-41,43,cum_flex,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-42,44,analysis_view_data,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-43,47,cum_flex_data,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-44,48,histo,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-45,49,histo_data,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-46,51,cumstats,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE
-47,53,graph_show_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-48,54,GraphDelete,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-49,55,get_thumbnails,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-50,56,otw_use_impeller,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-51,57,otw_use_gps,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-52,58,workout_toggle_ranking,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-53,59,team_workout_upload_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-54,60,workout_upload_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-55,61,workout_histo_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-56,62,workout_forcecurve_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
+41,43,cum_flex,flex all chart,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
+42,44,analysis_view_data,redirects to analysis direct,TRUE,302,pro,302,302,pro,302,302,coach,302,302,FALSE,FALSE,FALSE,TRUE
+43,47,cum_flex_data,flex all chart data (json),TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
+44,48,histo,histogram view,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,TRUE,FALSE,TRUE
+45,49,histo_data,histogram data,TRUE,302,pro,200,302,pro,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE
+46,51,cumstats,cumulative statistics,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,TRUE,FALSE,TRUE
+47,53,graph_show_view,show a chart,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
+48,54,GraphDelete,delete a chart,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
+49,55,get_thumbnails,get thumbnails,TRUE,403,basic,200,302,basic,403,403,coach,200,302,FALSE,FALSE,TRUE,TRUE
+50,56,otw_use_impeller,switch to impeller data,TRUE,403,basic,302,302,basic,403,302,coach,302,302,FALSE,FALSE,TRUE,TRUE
+51,57,otw_use_gps,switch to GPS data,TRUE,403,basic,302,302,basic,403,302,coach,302,302,FALSE,FALSE,TRUE,TRUE
+52,58,workout_toggle_ranking,toggle ranking,TRUE,302,basic,302,302,basic,403,302,coach,302,302,FALSE,FALSE,TRUE,TRUE
+53,59,team_workout_upload_view,upload workout for team member,TRUE,302,coach,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE
+54,60,workout_upload_view,upload a workout,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE
+55,61,workout_histo_view,histogram ,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,FALSE,TRUE,TRUE
+56,62,workout_forcecurve_view,force curve,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,FALSE,TRUE,TRUE
57,63,workout_unsubscribe_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
58,64,workout_comment_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
59,65,workout_tcxemail_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
diff --git a/rowers/urls.py b/rowers/urls.py
index faf05629..8450a408 100644
--- a/rowers/urls.py
+++ b/rowers/urls.py
@@ -274,7 +274,7 @@ urlpatterns = [
re_path(r'^flexall/user/(?P\d+)/$',views.cum_flex,name='cum_flex'),
re_path(r'^flexall/$',views.cum_flex,name='cum_flex'),
re_path(r'^flexalldata/$',views.cum_flex_data,name='cum_flex_data'),
- re_path(r'^histo/user/(?P\d+)/$',views.histo,name='histo'),
+ re_path(r'^histo/user/(?P\d+)/$',views.histo,name='histo'),
re_path(r'^histodata/$',views.histo_data,name='histo_data'),
# re_path(r'^histo/user/(?P\d+)/(?P\d+-\d+-\d+)/(?P\d+-\d+-\d+)/$',views.histo,name='histo'),
re_path(r'^histo/$',views.histo,name='histo'),
diff --git a/rowers/views/analysisviews.py b/rowers/views/analysisviews.py
index 4048b9ac..67392db8 100644
--- a/rowers/views/analysisviews.py
+++ b/rowers/views/analysisviews.py
@@ -730,7 +730,7 @@ def analysis_view_data(request,userid=0):
message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality",
redirect_field_name=None)
@permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True)
-def histo(request,theuser=0,
+def histo(request,userid=0,
startdate=timezone.now()-datetime.timedelta(days=365),
enddate=timezone.now(),
deltadays=-1,
@@ -744,7 +744,7 @@ def histo(request,theuser=0,
'histoparam':'power'
}):
- r = getrequestrower(request,userid=theuser)
+ r = getrequestrower(request,userid=userid)
theuser = r.user
if 'histoparam' in request.session:
diff --git a/rowers/views/workoutviews.py b/rowers/views/workoutviews.py
index 2b506203..34819d89 100644
--- a/rowers/views/workoutviews.py
+++ b/rowers/views/workoutviews.py
@@ -386,21 +386,18 @@ def workout_video_create_view(request,id=0):
@user_passes_test(ispromember,login_url="/rowers/paidplans/",
message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality. If you are already a Pro user, please log in to access this functionality",
redirect_field_name=None)
+@permission_required('workout.view_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def workout_forcecurve_view(request,id=0,workstrokesonly=False):
row = get_workout(id)
promember=0
mayedit=0
- if not request.user.is_anonymous:
- r = getrower(request.user)
- result = request.user.is_authenticated and ispromember(request.user)
- if result:
- promember=1
- if request.user == row.user.user:
- mayedit=1
- if not promember:
- return HttpResponseRedirect("/rowers/about/")
+ r = getrequestrower(request)
+ promember = 1
+
+ if r == row.user:
+ mayedit = 1
if request.method == 'POST':
form = ForceCurveOptionsForm(request.POST)
@@ -503,21 +500,15 @@ def otw_use_gps(request,id=0):
# Show Stroke power histogram for a workout
@login_required()
+@permission_required('workout.view_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def workout_histo_view(request,id=0):
w = get_workout(id)
+ r = getrequestrower(request)
+ promember = 1
- promember=0
mayedit=0
- if not request.user.is_anonymous:
- r = getrower(request.user)
- result = request.user.is_authenticated and ispromember(request.user)
- if result:
- promember=1
- if request.user == w.user.user:
- mayedit=1
-
- if not promember:
- return HttpResponseRedirect("/rowers/about/")
+ if w.user == r:
+ mayedit = 1
res = interactive_histoall([w],'power',False)
script = res[0]
From 4a99d74188ae4e3215663f4b905e2652c1f08c56 Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Thu, 30 Jan 2020 17:36:32 +0100
Subject: [PATCH 10/19] small fix
---
rowers/views/workoutviews.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/rowers/views/workoutviews.py b/rowers/views/workoutviews.py
index 34819d89..a0208381 100644
--- a/rowers/views/workoutviews.py
+++ b/rowers/views/workoutviews.py
@@ -386,7 +386,7 @@ def workout_video_create_view(request,id=0):
@user_passes_test(ispromember,login_url="/rowers/paidplans/",
message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality. If you are already a Pro user, please log in to access this functionality",
redirect_field_name=None)
-@permission_required('workout.view_workout',fn=get_workout_by_opaqueid,raise_exception=True)
+@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def workout_forcecurve_view(request,id=0,workstrokesonly=False):
row = get_workout(id)
@@ -500,7 +500,7 @@ def otw_use_gps(request,id=0):
# Show Stroke power histogram for a workout
@login_required()
-@permission_required('workout.view_workout',fn=get_workout_by_opaqueid,raise_exception=True)
+@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
def workout_histo_view(request,id=0):
w = get_workout(id)
r = getrequestrower(request)
From f248f5cc28a83c470c218fb64b574a08ab3f5470 Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Thu, 30 Jan 2020 17:57:36 +0100
Subject: [PATCH 11/19] small bug fixes
---
rowers/tests/.~lock.viewnames.csv# | 1 +
rowers/tests/viewnames.csv | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
create mode 100644 rowers/tests/.~lock.viewnames.csv#
diff --git a/rowers/tests/.~lock.viewnames.csv# b/rowers/tests/.~lock.viewnames.csv#
new file mode 100644
index 00000000..2142ac9e
--- /dev/null
+++ b/rowers/tests/.~lock.viewnames.csv#
@@ -0,0 +1 @@
+,sander,sander-pc,30.01.2020 17:54,file:///home/sander/.config/libreoffice/4;
\ No newline at end of file
diff --git a/rowers/tests/viewnames.csv b/rowers/tests/viewnames.csv
index d291398d..0ceaf09e 100644
--- a/rowers/tests/viewnames.csv
+++ b/rowers/tests/viewnames.csv
@@ -54,7 +54,7 @@
52,58,workout_toggle_ranking,toggle ranking,TRUE,302,basic,302,302,basic,403,302,coach,302,302,FALSE,FALSE,TRUE,TRUE
53,59,team_workout_upload_view,upload workout for team member,TRUE,302,coach,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE
54,60,workout_upload_view,upload a workout,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE
-55,61,workout_histo_view,histogram ,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,FALSE,TRUE,TRUE
+55,61,workout_histo_view,histogram ,TRUE,302,basic,200,302,basic,403,403,coach,200,302,FALSE,FALSE,TRUE,TRUE
56,62,workout_forcecurve_view,force curve,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,FALSE,TRUE,TRUE
57,63,workout_unsubscribe_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
58,64,workout_comment_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
From 8ef78dc7cea09922e0f5f105f27eabe0276799b2 Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Thu, 30 Jan 2020 17:57:51 +0100
Subject: [PATCH 12/19] removing temps
---
rowers/tests/.~lock.viewnames.csv# | 1 -
1 file changed, 1 deletion(-)
delete mode 100644 rowers/tests/.~lock.viewnames.csv#
diff --git a/rowers/tests/.~lock.viewnames.csv# b/rowers/tests/.~lock.viewnames.csv#
deleted file mode 100644
index 2142ac9e..00000000
--- a/rowers/tests/.~lock.viewnames.csv#
+++ /dev/null
@@ -1 +0,0 @@
-,sander,sander-pc,30.01.2020 17:54,file:///home/sander/.config/libreoffice/4;
\ No newline at end of file
From 3f210f38bf3e48e0a8f1e871d86d240aa5bc77e3 Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Sat, 1 Feb 2020 09:23:09 +0100
Subject: [PATCH 13/19] two more links tested
---
rowers/tests/.~lock.viewnames.csv# | 1 +
rowers/tests/viewnames.csv | 624 ++++++++++++++---------------
2 files changed, 313 insertions(+), 312 deletions(-)
create mode 100644 rowers/tests/.~lock.viewnames.csv#
diff --git a/rowers/tests/.~lock.viewnames.csv# b/rowers/tests/.~lock.viewnames.csv#
new file mode 100644
index 00000000..5aff9c40
--- /dev/null
+++ b/rowers/tests/.~lock.viewnames.csv#
@@ -0,0 +1 @@
+,sander,sander-pc,01.02.2020 09:22,file:///home/sander/.config/libreoffice/4;
\ No newline at end of file
diff --git a/rowers/tests/viewnames.csv b/rowers/tests/viewnames.csv
index 0ceaf09e..9d4432f9 100644
--- a/rowers/tests/viewnames.csv
+++ b/rowers/tests/viewnames.csv
@@ -1,312 +1,312 @@
-,id,view,function,anonymous,anonymous_response,own,own_response,own_nonperm,member,member_response,member_nonperm,coachee,coachee_response,coachee_nonperm,is_staff,userid,workoutid,dotest
-0,0,workouts_summaries_email_view,sends summary excel with workouts list and links to data to user,TRUE,302,basic,200,302,FALSE,403,403,FALSE,403,403,FALSE,FALSE,FALSE,TRUE
-1,1,rower_update_empower_view,updates old Empower Oarlock files (corrects Power bug),TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE
-2,2,agegroupcpview,needs age,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-3,4,ajax_agegrouprecords,gets age group records from C2 ,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-4,5,fitness_metric_view,updates a person's fitness metric,TRUE,302,basic,302,302,FALSE,403,302,FALSE,403,403,FALSE,FALSE,FALSE,TRUE
-5,6,agegrouprecordview,shows ergo age group records,TRUE,200,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE
-6,7,workouts_view,workouts list,TRUE,302,basic,200,302,basic,200,403,coach,200,403,FALSE,TRUE,FALSE,TRUE
-7,8,virtualevents_view,virtual races list,TRUE,200,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE
-8,9,virtualevent_create_view,create virtual event,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE
-9,10,indoorvirtualevent_create_view,create indoor virtual event,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE
-10,11,virtualevent_toggle_email_view,toggle email notifications,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE
-11,12,indoorvirtualevent_toggle_email_view,toggle email notifications,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE
-12,13,virtualevent_view,view virtual race,TRUE,200,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE
-13,14,virtualevent_ranking_view,view ranking,TRUE,200,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE
-14,15,virtualevent_edit_view,edit race,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE
-15,16,indoorvirtualevent_edit_view,edit race,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE
-16,17,virtualevent_register_view,register for race,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE
-17,18,indoorvirtualevent_register_view,register for race,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE
-18,19,virtualevent_addboat_view,add a new boat type,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE
-19,20,virtualevent_withdraw_view,withdraw,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE
-20,21,virtualevent_submit_result_view,submit a result,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,TRUE,FALSE
-21,22,virtualevent_disqualify_view,disqualify a racer,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE
-22,24,courses_view,see race courses,TRUE,200,FALSE,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE
-23,25,course_upload_view,upload a new course,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE
-24,26,addmanual_view,upload a manual workout,TRUE,302,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE
-25,27,team_comparison_select,compare with a team member workout,TRUE,302,pro,200,302,pro,200,302,coach,200,302,FALSE,TRUE,TRUE,TRUE
-26,28,workouts_join_view,join workouts,TRUE,302,pro,302,302,pro,403,403,coach,302,403,FALSE,TRUE,FALSE,TRUE
-27,29,workouts_join_select,select workouts to join,TRUE,404,pro,200,302,pro,403,403,coach,200,403,FALSE,TRUE,FALSE,TRUE
-28,30,user_boxplot_select,select boxplots,TRUE,302,pro,200,302,pro,403,403,coach,200,302,FALSE,TRUE,FALSE,TRUE
-29,31,analysis_new,analysis front page,TRUE,302,pro,200,302,FALSE,200,302,coach,200,302,FALSE,TRUE,FALSE,TRUE
-30,32,user_multiflex_select,select multiflex data,TRUE,302,pro,200,302,FALSE,200,302,coach,200,302,FALSE,TRUE,FALSE,TRUE
-31,33,session_jobs_view,view jobs,TRUE,302,basic,200,302,FALSE,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE
-32,34,session_jobs_status,view jobs,TRUE,302,basic,200,302,FALSE,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE
-33,35,kill_async_job,kill job,TRUE,302,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-34,36,post_progress,post progress,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-35,37,graphs_view,view charts,TRUE,302,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,TRUE
-36,38,fitnessmetric_view,view fitness metric,TRUE,302,plan,200,302,plan,403,302,coach,200,302,FALSE,TRUE,FALSE,TRUE
-37,39,rankings_view,view ranking,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,TRUE,FALSE,TRUE
-38,40,rankings_view2,view ranking,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,TRUE,FALSE,TRUE
-39,41,otwrankings_view,view ranking,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,TRUE,FALSE,TRUE
-40,42,oterankings_view,view ranking,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,TRUE,FALSE,TRUE
-41,43,cum_flex,flex all chart,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-42,44,analysis_view_data,redirects to analysis direct,TRUE,302,pro,302,302,pro,302,302,coach,302,302,FALSE,FALSE,FALSE,TRUE
-43,47,cum_flex_data,flex all chart data (json),TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-44,48,histo,histogram view,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,TRUE,FALSE,TRUE
-45,49,histo_data,histogram data,TRUE,302,pro,200,302,pro,200,302,coach,200,302,FALSE,FALSE,FALSE,TRUE
-46,51,cumstats,cumulative statistics,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,TRUE,FALSE,TRUE
-47,53,graph_show_view,show a chart,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-48,54,GraphDelete,delete a chart,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-49,55,get_thumbnails,get thumbnails,TRUE,403,basic,200,302,basic,403,403,coach,200,302,FALSE,FALSE,TRUE,TRUE
-50,56,otw_use_impeller,switch to impeller data,TRUE,403,basic,302,302,basic,403,302,coach,302,302,FALSE,FALSE,TRUE,TRUE
-51,57,otw_use_gps,switch to GPS data,TRUE,403,basic,302,302,basic,403,302,coach,302,302,FALSE,FALSE,TRUE,TRUE
-52,58,workout_toggle_ranking,toggle ranking,TRUE,302,basic,302,302,basic,403,302,coach,302,302,FALSE,FALSE,TRUE,TRUE
-53,59,team_workout_upload_view,upload workout for team member,TRUE,302,coach,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE
-54,60,workout_upload_view,upload a workout,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,TRUE
-55,61,workout_histo_view,histogram ,TRUE,302,basic,200,302,basic,403,403,coach,200,302,FALSE,FALSE,TRUE,TRUE
-56,62,workout_forcecurve_view,force curve,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,FALSE,TRUE,TRUE
-57,63,workout_unsubscribe_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-58,64,workout_comment_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-59,65,workout_tcxemail_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-60,66,workout_gpxemail_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-61,67,workout_csvemail_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-62,68,workout_csvtoadmin_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-63,69,workout_edit_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-64,70,workout_map_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-65,71,workout_update_cp_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-66,72,instroke_chart,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-67,73,instroke_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-68,74,workout_stats_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-69,75,workout_data_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-70,76,workout_otwsetpower_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-71,77,workout_otwpowerplot_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-72,78,workout_wind_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-73,79,workout_uploadimage_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-74,80,virtualevent_compare_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-75,81,virtualevent_uploadimage_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-76,82,virtualevent_setlogo_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-77,83,logo_delete_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-78,84,workout_downloadwind_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-79,85,workout_downloadmetar_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-80,86,workout_stream_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-81,87,workout_summary_edit_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-82,88,workout_summary_restore_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-83,89,workout_split_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-84,90,workout_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-85,91,workout_video_create_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-86,92,VideoDelete,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-87,93,workout_video_view_mini,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-88,94,workout_video_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-89,95,list_videos,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-90,96,video_selectworkout,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-91,98,workout_fusion_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-92,99,workout_fusion_list,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-93,100,TemplateView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-94,103,workout_add_chart_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-95,112,WorkoutDelete,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-96,113,workout_smoothenpace_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-97,114,workout_undo_smoothenpace_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-98,115,workout_c2import_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE
-99,120,workout_stravaimport_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE
-100,122,workout_getc2workout_all,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-101,124,workout_getimportview,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-102,125,workout_getstravaworkout_all,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-103,126,workout_getstravaworkout_next,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-104,127,workout_sporttracksimport_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE
-105,129,workout_getsporttracksworkout_all,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-106,130,workout_polarimport_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE
-107,132,workout_runkeeperimport_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE
-108,134,workout_underarmourimport_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-109,135,workout_c2_upload_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-110,136,workout_strava_upload_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-111,137,workout_recalcsummary_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-112,138,workout_sporttracks_upload_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-113,139,workout_runkeeper_upload_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-114,140,workout_underarmour_upload_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-115,141,workout_tp_upload_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-116,142,multi_compare_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-117,145,alerts_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE
-118,147,AlertDelete,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-119,148,alert_edit_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-120,150,alert_create_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE
-121,152,alert_report_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-122,155,boxplot_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE
-123,157,boxplot_view_data,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-124,158,multiflex_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE
-125,160,multiflex_data,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-126,161,deactivate_user,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-127,162,remove_user,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-128,163,user_gdpr_confirm,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-129,165,user_gdpr_optin,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-130,167,rower_teams_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-131,168,rower_calcdps_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-132,169,rower_exportsettings_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-133,171,team_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-134,172,team_members_stats_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-135,173,team_edit_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-136,174,team_leaveconfirm_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-137,175,team_leave_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-138,176,team_deleteconfirm_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-139,177,team_requestmembership_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-140,178,reject_revoke_coach_request,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-141,179,coach_drop_athlete_confirm_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-142,180,coach_drop_athlete_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-143,181,athlete_drop_coach_confirm_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-144,182,athlete_drop_coach_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-145,184,reject_revoke_coach_offer,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-146,186,request_coaching_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-147,187,offer_coaching_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE
-148,188,coach_accept_coachrequest_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-149,189,rower_accept_coachoffer_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-150,190,team_delete_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-151,191,team_create_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-152,192,manager_member_drop_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-153,193,invitation_reject_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-154,194,invitation_revoke_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-155,195,rower_invitations_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-156,196,raise_500,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-157,198,request_revoke_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-158,199,request_reject_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-159,200,manager_requests_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-160,202,rower_edit_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-161,204,rower_prefs_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-162,205,transactions_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-163,208,rower_c2_authorize,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-164,209,rower_polar_authorize,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-165,210,rower_revokeapp_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-166,211,rower_strava_authorize,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-167,212,rower_sporttracks_authorize,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-168,213,rower_underarmour_authorize,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-169,214,rower_tp_authorize,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-170,215,rower_runkeeper_authorize,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-171,216,rower_sporttracks_token_refresh,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-172,217,rower_underarmour_token_refresh,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-173,218,rower_tp_token_refresh,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-174,219,rower_c2_token_refresh,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-175,220,rower_favoritecharts_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-176,222,workout_workflow_config2_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE
-177,224,workflow_default_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-178,225,sendmail,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-179,231,analysis_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-180,232,laboratory_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-181,233,errormessage_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-182,237,payment_confirm_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-183,238,upgrade_confirm_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-184,240,downgrade_confirm_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-185,241,billing_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-186,242,upgrade_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-187,243,downgrade_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-188,244,payment_completed_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-189,245,downgrade_completed_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-190,246,paidplans_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-191,247,plan_stop_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-192,248,plan_tobasic_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-193,249,checkouts_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-194,250,upgrade_checkouts_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-195,251,downgrade_checkouts_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-196,252,planrequired_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-197,253,start_trial_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-198,254,start_plantrial_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-199,256,rower_register_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-200,257,freecoach_register_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-201,259,workout_workflow_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-202,260,workout_flexchart3_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-203,264,rower_process_testcallback,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-204,265,rower_create_trainingplan,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-205,267,TrainingPlanDelete,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-206,268,MicroCycleDelete,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-207,269,MesoCycleDelete,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-208,270,MacroCycleDelete,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-209,271,rower_trainingplan_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-210,279,rower_trainingplan_execution_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-211,281,TrainingMacroCycleUpdate,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-212,282,TrainingMesoCycleUpdate,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-213,283,planmacrocyclebymonth,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-214,285,planmesocyclebyweek,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-215,287,TrainingMicroCycleUpdate,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-216,288,rower_delete_trainingtarget,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-217,289,TrainingPlanUpdate,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-218,290,TrainingTargetUpdate,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-219,291,strokedataform,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-220,292,plannedsession_teamcreate_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE
-221,296,plannedsession_teamedit_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-222,298,plannedsession_create_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE
-223,300,plannedsession_multiclone_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE
-224,302,plannedsession_multicreate_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE
-225,305,plannedsession_edit_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-226,306,plannedsession_totemplate_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-227,307,plannedsession_compare_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-228,310,plannedsession_clone_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-229,311,plannedsession_teamclone_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-230,313,plannedsession_detach_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-231,315,plannedsession_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-232,317,PlannedSessionDelete,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-233,319,plannedsessions_manage_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE
-234,323,plannedsessions_coach_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE
-235,325,plannedsessions_coach_icsemail_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE
-236,326,plannedsessions_print_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE
-237,327,plannedsession_comment_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-238,330,plannedsessions_icsemail_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE
-239,332,plannedsessions_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE
-240,334,course_edit_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-241,335,course_delete_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-242,336,course_kmldownload_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-243,337,course_replace_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-244,338,course_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-245,339,course_map_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-246,341,c2listdebug_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-247,343,rower_process_callback,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-248,344,rower_process_stravacallback,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-249,345,rower_process_sporttrackscallback,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-250,346,rower_process_underarmourcallback,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-251,347,rower_process_polarcallback,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-252,348,rower_process_runkeepercallback,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-253,349,rower_process_tpcallback,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-254,350,rower_process_twittercallback,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-255,351,set_language,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-256,352,SetOffsetView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-257,353,stats,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-258,354,stats_json,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-259,355,jobs,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-260,356,workers,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-261,357,worker_details,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-262,358,finished_jobs,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-263,359,started_jobs,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-264,360,deferred_jobs,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-265,361,clear_queue,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-266,362,requeue_all,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-267,363,job_detail,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-268,364,delete_job,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-269,365,actions,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-270,366,requeue_job_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-271,367,enqueue_job,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-272,368,JavaScriptCatalog,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-273,369,serve,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-274,371,LoginView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-275,372,LogoutView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-276,373,PasswordChangeView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-277,374,PasswordChangeDoneView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-278,375,PasswordResetView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-279,376,PasswordResetDoneView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-280,377,PasswordResetConfirmView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-281,378,PasswordResetCompleteView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-282,386,index,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-283,387,login,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-284,388,logout,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-285,389,password_change,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-286,390,password_change_done,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-287,391,i18n_javascript,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-288,392,shortcut,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-289,393,changelist_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-290,394,add_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-291,395,autocomplete_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-292,396,history_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-293,397,delete_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-294,398,change_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-295,399,RedirectView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-296,568,app_index,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-297,571,landingview,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-298,573,get_blog_posts,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-299,576,AuthorizationView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-300,577,TokenView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-301,578,WorkoutViewSet,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-302,582,RowerViewSet,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-303,586,FavoriteChartViewSet,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-304,590,APIRootView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-305,592,SwaggerSchemaView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-306,595,strokedatajson,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
-307,596,error500_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-308,603,failed_queue_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-309,604,failed_queue_empty,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE
-310,605,failed_job_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE
+,id,view,function,anonymous,anonymous_response,own,own_response,own_nonperm,member,member_response,member_nonperm,coachee,coachee_response,coachee_nonperm,is_staff,userid,workoutid,dotest,realtest
+0,0,workouts_summaries_email_view,sends summary excel with workouts list and links to data to user,TRUE,302,basic,200,302,FALSE,403,403,FALSE,403,403,FALSE,FALSE,FALSE,FALSE,TRUE
+1,1,rower_update_empower_view,updates old Empower Oarlock files (corrects Power bug),TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE,TRUE
+2,2,agegroupcpview,needs age,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+3,4,ajax_agegrouprecords,gets age group records from C2 ,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+4,5,fitness_metric_view,updates a person's fitness metric,TRUE,302,basic,302,302,FALSE,403,302,FALSE,403,403,FALSE,FALSE,FALSE,FALSE,TRUE
+5,6,agegrouprecordview,shows ergo age group records,TRUE,200,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE,TRUE
+6,7,workouts_view,workouts list,TRUE,302,basic,200,302,basic,200,403,coach,200,403,FALSE,TRUE,FALSE,FALSE,TRUE
+7,8,virtualevents_view,virtual races list,TRUE,200,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE,TRUE
+8,9,virtualevent_create_view,create virtual event,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE,TRUE
+9,10,indoorvirtualevent_create_view,create indoor virtual event,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE,TRUE
+10,11,virtualevent_toggle_email_view,toggle email notifications,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+11,12,indoorvirtualevent_toggle_email_view,toggle email notifications,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+12,13,virtualevent_view,view virtual race,TRUE,200,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+13,14,virtualevent_ranking_view,view ranking,TRUE,200,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+14,15,virtualevent_edit_view,edit race,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+15,16,indoorvirtualevent_edit_view,edit race,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+16,17,virtualevent_register_view,register for race,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+17,18,indoorvirtualevent_register_view,register for race,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+18,19,virtualevent_addboat_view,add a new boat type,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+19,20,virtualevent_withdraw_view,withdraw,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+20,21,virtualevent_submit_result_view,submit a result,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+21,22,virtualevent_disqualify_view,disqualify a racer,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+22,24,courses_view,see race courses,TRUE,200,FALSE,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE,TRUE
+23,25,course_upload_view,upload a new course,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE,TRUE
+24,26,addmanual_view,upload a manual workout,TRUE,302,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,TRUE
+25,27,team_comparison_select,compare with a team member workout,TRUE,302,pro,200,302,pro,200,302,coach,200,302,FALSE,TRUE,TRUE,FALSE,TRUE
+26,28,workouts_join_view,join workouts,TRUE,302,pro,302,302,pro,403,403,coach,302,403,FALSE,TRUE,FALSE,FALSE,TRUE
+27,29,workouts_join_select,select workouts to join,TRUE,404,pro,200,302,pro,403,403,coach,200,403,FALSE,TRUE,FALSE,FALSE,TRUE
+28,30,user_boxplot_select,select boxplots,TRUE,302,pro,200,302,pro,403,403,coach,200,302,FALSE,TRUE,FALSE,FALSE,TRUE
+29,31,analysis_new,analysis front page,TRUE,302,pro,200,302,FALSE,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,TRUE
+30,32,user_multiflex_select,select multiflex data,TRUE,302,pro,200,302,FALSE,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,TRUE
+31,33,session_jobs_view,view jobs,TRUE,302,basic,200,302,FALSE,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,TRUE
+32,34,session_jobs_status,view jobs,TRUE,302,basic,200,302,FALSE,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,TRUE
+33,35,kill_async_job,kill job,TRUE,302,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+34,36,post_progress,post progress,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+35,37,graphs_view,view charts,TRUE,302,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,TRUE
+36,38,fitnessmetric_view,view fitness metric,TRUE,302,plan,200,302,plan,403,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,TRUE
+37,39,rankings_view,view ranking,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,TRUE
+38,40,rankings_view2,view ranking,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,TRUE
+39,41,otwrankings_view,view ranking,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,TRUE
+40,42,oterankings_view,view ranking,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,TRUE
+41,43,cum_flex,flex all chart,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+42,44,analysis_view_data,redirects to analysis direct,TRUE,302,pro,302,302,pro,302,302,coach,302,302,FALSE,FALSE,FALSE,FALSE,TRUE
+43,47,cum_flex_data,flex all chart data (json),TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+44,48,histo,histogram view,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,TRUE
+45,49,histo_data,histogram data,TRUE,302,pro,200,302,pro,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,TRUE
+46,51,cumstats,cumulative statistics,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,TRUE
+47,53,graph_show_view,show a chart,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+48,54,GraphDelete,delete a chart,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+49,55,get_thumbnails,get thumbnails,TRUE,403,basic,200,302,basic,403,403,coach,200,302,FALSE,FALSE,TRUE,FALSE,TRUE
+50,56,otw_use_impeller,switch to impeller data,TRUE,403,basic,302,302,basic,403,302,coach,302,302,FALSE,FALSE,TRUE,FALSE,TRUE
+51,57,otw_use_gps,switch to GPS data,TRUE,403,basic,302,302,basic,403,302,coach,302,302,FALSE,FALSE,TRUE,FALSE,TRUE
+52,58,workout_toggle_ranking,toggle ranking,TRUE,302,basic,302,302,basic,403,302,coach,302,302,FALSE,FALSE,TRUE,FALSE,TRUE
+53,59,team_workout_upload_view,upload workout for team member,TRUE,302,coach,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE,TRUE
+54,60,workout_upload_view,upload a workout,TRUE,302,basic,200,302,FALSE,200,302,FALSE,200,302,FALSE,FALSE,FALSE,FALSE,TRUE
+55,61,workout_histo_view,histogram ,TRUE,302,basic,200,302,basic,403,403,coach,200,302,FALSE,FALSE,TRUE,FALSE,TRUE
+56,62,workout_forcecurve_view,force curve,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,TRUE
+57,63,workout_unsubscribe_view,unsubscribe from comments,TRUE,302,basic,200,302,basic,200,302,basic,200,302,FALSE,FALSE,TRUE,FALSE,TRUE
+58,64,workout_comment_view,comment on workout,TRUE,302,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,TRUE
+59,65,workout_tcxemail_view,download TCX file,TRUE,403,basic,200,302,basic,403,403,coach,200,403,FALSE,FALSE,TRUE,TRUE,FALSE
+60,66,workout_gpxemail_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+61,67,workout_csvemail_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+62,68,workout_csvtoadmin_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+63,69,workout_edit_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+64,70,workout_map_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+65,71,workout_update_cp_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+66,72,instroke_chart,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+67,73,instroke_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+68,74,workout_stats_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+69,75,workout_data_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+70,76,workout_otwsetpower_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+71,77,workout_otwpowerplot_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+72,78,workout_wind_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+73,79,workout_uploadimage_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+74,80,virtualevent_compare_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+75,81,virtualevent_uploadimage_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+76,82,virtualevent_setlogo_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+77,83,logo_delete_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+78,84,workout_downloadwind_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+79,85,workout_downloadmetar_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+80,86,workout_stream_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+81,87,workout_summary_edit_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+82,88,workout_summary_restore_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+83,89,workout_split_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+84,90,workout_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+85,91,workout_video_create_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+86,92,VideoDelete,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+87,93,workout_video_view_mini,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+88,94,workout_video_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+89,95,list_videos,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+90,96,video_selectworkout,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+91,98,workout_fusion_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+92,99,workout_fusion_list,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+93,100,TemplateView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+94,103,workout_add_chart_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+95,112,WorkoutDelete,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+96,113,workout_smoothenpace_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+97,114,workout_undo_smoothenpace_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+98,115,workout_c2import_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,FALSE
+99,120,workout_stravaimport_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,FALSE
+100,122,workout_getc2workout_all,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+101,124,workout_getimportview,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+102,125,workout_getstravaworkout_all,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+103,126,workout_getstravaworkout_next,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+104,127,workout_sporttracksimport_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,FALSE
+105,129,workout_getsporttracksworkout_all,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+106,130,workout_polarimport_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,FALSE
+107,132,workout_runkeeperimport_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,FALSE
+108,134,workout_underarmourimport_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+109,135,workout_c2_upload_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+110,136,workout_strava_upload_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+111,137,workout_recalcsummary_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+112,138,workout_sporttracks_upload_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+113,139,workout_runkeeper_upload_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+114,140,workout_underarmour_upload_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+115,141,workout_tp_upload_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+116,142,multi_compare_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+117,145,alerts_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,FALSE
+118,147,AlertDelete,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+119,148,alert_edit_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+120,150,alert_create_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,FALSE
+121,152,alert_report_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+122,155,boxplot_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,FALSE
+123,157,boxplot_view_data,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+124,158,multiflex_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,FALSE
+125,160,multiflex_data,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+126,161,deactivate_user,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+127,162,remove_user,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+128,163,user_gdpr_confirm,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+129,165,user_gdpr_optin,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+130,167,rower_teams_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+131,168,rower_calcdps_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+132,169,rower_exportsettings_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+133,171,team_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+134,172,team_members_stats_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+135,173,team_edit_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+136,174,team_leaveconfirm_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+137,175,team_leave_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+138,176,team_deleteconfirm_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+139,177,team_requestmembership_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+140,178,reject_revoke_coach_request,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+141,179,coach_drop_athlete_confirm_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+142,180,coach_drop_athlete_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+143,181,athlete_drop_coach_confirm_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+144,182,athlete_drop_coach_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+145,184,reject_revoke_coach_offer,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+146,186,request_coaching_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+147,187,offer_coaching_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,FALSE
+148,188,coach_accept_coachrequest_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+149,189,rower_accept_coachoffer_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+150,190,team_delete_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+151,191,team_create_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+152,192,manager_member_drop_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+153,193,invitation_reject_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+154,194,invitation_revoke_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+155,195,rower_invitations_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+156,196,raise_500,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+157,198,request_revoke_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+158,199,request_reject_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+159,200,manager_requests_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+160,202,rower_edit_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+161,204,rower_prefs_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+162,205,transactions_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+163,208,rower_c2_authorize,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+164,209,rower_polar_authorize,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+165,210,rower_revokeapp_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+166,211,rower_strava_authorize,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+167,212,rower_sporttracks_authorize,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+168,213,rower_underarmour_authorize,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+169,214,rower_tp_authorize,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+170,215,rower_runkeeper_authorize,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+171,216,rower_sporttracks_token_refresh,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+172,217,rower_underarmour_token_refresh,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+173,218,rower_tp_token_refresh,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+174,219,rower_c2_token_refresh,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+175,220,rower_favoritecharts_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+176,222,workout_workflow_config2_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,FALSE
+177,224,workflow_default_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+178,225,sendmail,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+179,231,analysis_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+180,232,laboratory_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+181,233,errormessage_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+182,237,payment_confirm_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+183,238,upgrade_confirm_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+184,240,downgrade_confirm_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+185,241,billing_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+186,242,upgrade_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+187,243,downgrade_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+188,244,payment_completed_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+189,245,downgrade_completed_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+190,246,paidplans_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+191,247,plan_stop_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+192,248,plan_tobasic_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+193,249,checkouts_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+194,250,upgrade_checkouts_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+195,251,downgrade_checkouts_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+196,252,planrequired_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+197,253,start_trial_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+198,254,start_plantrial_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+199,256,rower_register_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+200,257,freecoach_register_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+201,259,workout_workflow_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+202,260,workout_flexchart3_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+203,264,rower_process_testcallback,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+204,265,rower_create_trainingplan,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+205,267,TrainingPlanDelete,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+206,268,MicroCycleDelete,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+207,269,MesoCycleDelete,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+208,270,MacroCycleDelete,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+209,271,rower_trainingplan_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+210,279,rower_trainingplan_execution_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+211,281,TrainingMacroCycleUpdate,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+212,282,TrainingMesoCycleUpdate,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+213,283,planmacrocyclebymonth,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+214,285,planmesocyclebyweek,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+215,287,TrainingMicroCycleUpdate,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+216,288,rower_delete_trainingtarget,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+217,289,TrainingPlanUpdate,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+218,290,TrainingTargetUpdate,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+219,291,strokedataform,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+220,292,plannedsession_teamcreate_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,FALSE
+221,296,plannedsession_teamedit_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+222,298,plannedsession_create_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,FALSE
+223,300,plannedsession_multiclone_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,FALSE
+224,302,plannedsession_multicreate_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,FALSE
+225,305,plannedsession_edit_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+226,306,plannedsession_totemplate_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+227,307,plannedsession_compare_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+228,310,plannedsession_clone_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+229,311,plannedsession_teamclone_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+230,313,plannedsession_detach_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+231,315,plannedsession_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+232,317,PlannedSessionDelete,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+233,319,plannedsessions_manage_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,FALSE
+234,323,plannedsessions_coach_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,FALSE
+235,325,plannedsessions_coach_icsemail_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,FALSE
+236,326,plannedsessions_print_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,FALSE
+237,327,plannedsession_comment_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+238,330,plannedsessions_icsemail_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,FALSE
+239,332,plannedsessions_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,TRUE,FALSE,FALSE,FALSE
+240,334,course_edit_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+241,335,course_delete_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+242,336,course_kmldownload_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+243,337,course_replace_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+244,338,course_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+245,339,course_map_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+246,341,c2listdebug_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+247,343,rower_process_callback,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+248,344,rower_process_stravacallback,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+249,345,rower_process_sporttrackscallback,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+250,346,rower_process_underarmourcallback,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+251,347,rower_process_polarcallback,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+252,348,rower_process_runkeepercallback,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+253,349,rower_process_tpcallback,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+254,350,rower_process_twittercallback,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+255,351,set_language,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+256,352,SetOffsetView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+257,353,stats,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+258,354,stats_json,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+259,355,jobs,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+260,356,workers,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+261,357,worker_details,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+262,358,finished_jobs,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+263,359,started_jobs,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+264,360,deferred_jobs,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+265,361,clear_queue,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+266,362,requeue_all,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+267,363,job_detail,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+268,364,delete_job,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+269,365,actions,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+270,366,requeue_job_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+271,367,enqueue_job,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+272,368,JavaScriptCatalog,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+273,369,serve,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+274,371,LoginView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+275,372,LogoutView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+276,373,PasswordChangeView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+277,374,PasswordChangeDoneView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+278,375,PasswordResetView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+279,376,PasswordResetDoneView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+280,377,PasswordResetConfirmView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+281,378,PasswordResetCompleteView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+282,386,index,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+283,387,login,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+284,388,logout,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+285,389,password_change,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+286,390,password_change_done,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+287,391,i18n_javascript,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+288,392,shortcut,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+289,393,changelist_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+290,394,add_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+291,395,autocomplete_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+292,396,history_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+293,397,delete_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+294,398,change_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+295,399,RedirectView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+296,568,app_index,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+297,571,landingview,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+298,573,get_blog_posts,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+299,576,AuthorizationView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+300,577,TokenView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+301,578,WorkoutViewSet,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+302,582,RowerViewSet,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+303,586,FavoriteChartViewSet,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+304,590,APIRootView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+305,592,SwaggerSchemaView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+306,595,strokedatajson,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+307,596,error500_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+308,603,failed_queue_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+309,604,failed_queue_empty,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+310,605,failed_job_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
From 122aff320f47aaf9ca5a17a816bb828a6e82db38 Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Sat, 1 Feb 2020 11:33:21 +0100
Subject: [PATCH 14/19] A few more fixes
---
rowers/rower_rules.py | 5 ++
rowers/tests/.~lock.viewnames.csv# | 2 +-
rowers/tests/viewnames.csv | 12 ++---
rowers/views/exportviews.py | 1 +
rowers/views/paymentviews.py | 84 +++++++++++++++---------------
5 files changed, 55 insertions(+), 49 deletions(-)
diff --git a/rowers/rower_rules.py b/rowers/rower_rules.py
index 93bbdcd7..924376bf 100644
--- a/rowers/rower_rules.py
+++ b/rowers/rower_rules.py
@@ -98,6 +98,10 @@ def can_start_plantrial(user):
return user.rower.plantrialexpires == datetime.date(1970,1,1)
+@rules.predicate
+def is_staff(user):
+ return user.is_staff
+
@rules.predicate
def is_coach(user):
return user.rower.rowerplan in ['coach','freecoach']
@@ -274,6 +278,7 @@ def can_plan_user(user,rower):
rules.add_perm('rower.add_plan',can_plan_user) # replaces checkaccessplanuser
rules.add_perm('rower.is_coach',is_coach_user) # replaces checkaccessuser
rules.add_perm('rower.is_pro',ispromember)
+rules.add_perm('rower.is_staff',is_staff)
# WORKOUT permissions
diff --git a/rowers/tests/.~lock.viewnames.csv# b/rowers/tests/.~lock.viewnames.csv#
index 5aff9c40..c1247cdc 100644
--- a/rowers/tests/.~lock.viewnames.csv#
+++ b/rowers/tests/.~lock.viewnames.csv#
@@ -1 +1 @@
-,sander,sander-pc,01.02.2020 09:22,file:///home/sander/.config/libreoffice/4;
\ No newline at end of file
+,sander,sander-pc,01.02.2020 11:32,file:///home/sander/.config/libreoffice/4;
\ No newline at end of file
diff --git a/rowers/tests/viewnames.csv b/rowers/tests/viewnames.csv
index 9d4432f9..18cbf41a 100644
--- a/rowers/tests/viewnames.csv
+++ b/rowers/tests/viewnames.csv
@@ -58,12 +58,12 @@
56,62,workout_forcecurve_view,force curve,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,TRUE
57,63,workout_unsubscribe_view,unsubscribe from comments,TRUE,302,basic,200,302,basic,200,302,basic,200,302,FALSE,FALSE,TRUE,FALSE,TRUE
58,64,workout_comment_view,comment on workout,TRUE,302,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,TRUE
-59,65,workout_tcxemail_view,download TCX file,TRUE,403,basic,200,302,basic,403,403,coach,200,403,FALSE,FALSE,TRUE,TRUE,FALSE
-60,66,workout_gpxemail_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
-61,67,workout_csvemail_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
-62,68,workout_csvtoadmin_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
-63,69,workout_edit_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
-64,70,workout_map_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+59,65,workout_tcxemail_view,download TCX file,TRUE,403,basic,200,302,basic,403,403,coach,200,403,FALSE,FALSE,TRUE,FALSE,TRUE
+60,66,workout_gpxemail_view,download GPX file,TRUE,403,basic,200,302,basic,403,403,coach,200,403,FALSE,FALSE,TRUE,FALSE,TRUE
+61,67,workout_csvemail_view,download CSV file,TRUE,403,basic,200,302,basic,403,403,coach,200,403,FALSE,FALSE,TRUE,FALSE,TRUE
+62,68,workout_csvtoadmin_view,send CSV to admin,TRUE,403,basic,200,200,basic,200,200,coach,200,200,TRUE,FALSE,TRUE,FALSE,TRUE
+63,69,workout_edit_view,Edit Workout,TRUE,403,basic,200,403,basic,403,403,coach,200,403,FALSE,FALSE,TRUE,FALSE,TRUE
+64,70,workout_map_view,View workout Map,TRUE,302,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,TRUE,TRUE
65,71,workout_update_cp_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
66,72,instroke_chart,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
67,73,instroke_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
diff --git a/rowers/views/exportviews.py b/rowers/views/exportviews.py
index afdfc7c9..b415696a 100644
--- a/rowers/views/exportviews.py
+++ b/rowers/views/exportviews.py
@@ -261,6 +261,7 @@ def workout_csvemail_view(request,id=0):
# Get Workout CSV file and send it to user's email address
@login_required()
+@permission_required('rower.is_staff',fn=get_user_by_userid,raise_exception=True)
def workout_csvtoadmin_view(request,id=0):
message = ""
r = getrower(request.user)
diff --git a/rowers/views/paymentviews.py b/rowers/views/paymentviews.py
index 34a1f133..344f84ac 100644
--- a/rowers/views/paymentviews.py
+++ b/rowers/views/paymentviews.py
@@ -13,8 +13,8 @@ def paidplans_view(request):
else:
r = None
-
-
+
+
return render(request,
'paidplans.html',
{'rower':r})
@@ -24,7 +24,7 @@ def billing_view(request):
if not PAYMENT_PROCESSING_ON:
url = reverse('promembership')
return HttpResponseRedirect(url)
-
+
r = request.user.rower
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring':
@@ -42,7 +42,7 @@ def billing_view(request):
for attr, value in cd.items():
setattr(r, attr, value)
r.save()
-
+
if billingaddressform.is_valid():
if planselectform.is_valid():
plan = planselectform.cleaned_data['plan']
@@ -58,7 +58,7 @@ def billing_view(request):
})
return HttpResponseRedirect(url)
-
+
else:
billingaddressform = RowerBillingAddressForm(instance=r)
planselectform = PlanSelectForm(paymentprocessor='braintree')
@@ -69,13 +69,13 @@ def billing_view(request):
'billingaddressform':billingaddressform,
'planselectform':planselectform,
})
-
+
@login_required()
def upgrade_view(request):
if not PAYMENT_PROCESSING_ON:
url = reverse('promembership')
return HttpResponseRedirect(url)
-
+
r = request.user.rower
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring':
@@ -93,7 +93,7 @@ def upgrade_view(request):
for attr, value in cd.items():
setattr(r, attr, value)
r.save()
-
+
if planselectform.is_valid():
plan = planselectform.cleaned_data['plan']
if billingaddressform.is_valid():
@@ -102,7 +102,7 @@ def upgrade_view(request):
'planid':plan.id
})
return HttpResponseRedirect(url)
-
+
else:
billingaddressform = RowerBillingAddressForm(instance=r)
planselectform = PlanSelectForm(paymentprocessor='braintree',
@@ -114,13 +114,13 @@ def upgrade_view(request):
'billingaddressform':billingaddressform,
'planselectform':planselectform,
})
-
+
@login_required()
def downgrade_view(request):
if not PAYMENT_PROCESSING_ON:
url = reverse('promembership')
return HttpResponseRedirect(url)
-
+
r = request.user.rower
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring':
@@ -138,7 +138,7 @@ def downgrade_view(request):
for attr, value in cd.items():
setattr(r, attr, value)
r.save()
-
+
if planselectform.is_valid():
plan = planselectform.cleaned_data['plan']
@@ -150,14 +150,14 @@ def downgrade_view(request):
return HttpResponseRedirect(url)
else:
nextview = downgrade_confirm_view
-
+
if billingaddressform.is_valid():
url = reverse(nextview,
kwargs={
'planid':plan.id
})
return HttpResponseRedirect(url)
-
+
else:
billingaddressform = RowerBillingAddressForm(instance=r)
planselectform = PlanSelectForm(paymentprocessor='braintree',
@@ -169,17 +169,17 @@ def downgrade_view(request):
'billingaddressform':billingaddressform,
'planselectform':planselectform,
})
-
+
@login_required()
def plan_stop_view(request):
if not PAYMENT_PROCESSING_ON:
url = reverse('promembership')
return HttpResponseRedirect(url)
-
+
r = request.user.rower
subscriptions = []
-
+
if r.paymentprocessor != 'braintree' and r.paymenttype == 'recurring':
messages.error(request,'Automated payment processing is currently only available through BrainTree (by PayPal). You are currently on a recurring payment plan with PayPal. Contact the site administrator at support@rowsandall.com before you proceed')
@@ -189,7 +189,7 @@ def plan_stop_view(request):
except ProcessorCustomerError:
r.paymentprocessor = None
r.save()
-
+
return render(request,
@@ -203,7 +203,7 @@ def plan_tobasic_view(request,id=0):
if not PAYMENT_PROCESSING_ON:
url = reverse('promembership')
return HttpResponseRedirect(url)
-
+
r = request.user.rower
if r.paidplan.paymentprocessor == 'braintree':
@@ -217,15 +217,15 @@ def plan_tobasic_view(request,id=0):
url = reverse(plan_stop_view)
return HttpResponseRedirect(url)
-
-
+
+
@login_required()
def upgrade_confirm_view(request,planid = 0):
if not PAYMENT_PROCESSING_ON:
url = reverse('promembership')
return HttpResponseRedirect(url)
-
+
try:
plan = PaidPlan.objects.get(id=planid)
except PaidPlan.DoesNotExist:
@@ -253,7 +253,7 @@ def downgrade_confirm_view(request,planid = 0):
if not PAYMENT_PROCESSING_ON:
url = reverse('promembership')
return HttpResponseRedirect(url)
-
+
try:
plan = PaidPlan.objects.get(id=planid)
except PaidPlan.DoesNotExist:
@@ -279,7 +279,7 @@ def payment_confirm_view(request,planid = 0):
if not PAYMENT_PROCESSING_ON:
url = reverse('promembership')
return HttpResponseRedirect(url)
-
+
try:
plan = PaidPlan.objects.get(id=planid)
except PaidPlan.DoesNotExist:
@@ -350,13 +350,13 @@ def checkouts_view(request):
url = reverse(paidplans_view)
return HttpResponseRedirect(url)
-
+
@login_required()
def upgrade_checkouts_view(request):
if not PAYMENT_PROCESSING_ON:
url = reverse('promembership')
return HttpResponseRedirect(url)
-
+
r = request.user.rower
@@ -402,7 +402,7 @@ def downgrade_checkouts_view(request):
if not PAYMENT_PROCESSING_ON:
url = reverse('promembership')
return HttpResponseRedirect(url)
-
+
r = request.user.rower
@@ -450,7 +450,7 @@ def payment_completed_view(request):
amount = request.GET.get('amount',0)
-
+
r = request.user.rower
return render(request,
@@ -465,7 +465,7 @@ def downgrade_completed_view(request):
if not PAYMENT_PROCESSING_ON:
url = reverse('promembership')
return HttpResponseRedirect(url)
-
+
r = request.user.rower
return render(request,
@@ -480,7 +480,7 @@ def rower_register_view(request):
nextpage = request.GET.get('next','/rowers/list-workouts/')
if nextpage == '':
nextpage = '/rowers/list-workouts/'
-
+
if request.method == 'POST':
#form = RegistrationFormUniqueEmail(request.POST)
form = RegistrationFormSex(request.POST)
@@ -517,7 +517,7 @@ def rower_register_view(request):
timestr = strftime("%Y%m%d-%H%M%S")
f2 = f[:-7]+timestr+'.csv.gz'
copyfile(f,f2)
-
+
response = dataprep.new_workout_from_file(therower,f2,
title='New User Sample Data',
notes='This is an example workout to get you started')
@@ -527,17 +527,17 @@ def rower_register_view(request):
w.startdatetime = timezone.now()
w.date = timezone.now().date()
w.save()
-
+
# Create and send email
fullemail = first_name + " " + last_name + " " + "<" + email + ">"
subject = "Thank you for registering on rowsandall.com"
from_address = 'Sander Roosendaal '
d = {'first_name':theuser.first_name}
-
+
send_template_email(from_address,[fullemail],
subject,'registeremail.html',d)
-
+
subject2 = "New User"
message2 = "New user registered.\n"
@@ -550,7 +550,7 @@ def rower_register_view(request):
theuser = authenticate(username=username,password=password)
login(request,theuser)
-
+
return HttpResponseRedirect(nextpage)
# '/rowers/register/thankyou/')
@@ -572,7 +572,7 @@ def freecoach_register_view(request):
nextpage = request.GET.get('next','/rowers/me/teams/')
if nextpage == '':
nextpage = '/rowers/me/teams/'
-
+
if request.method == 'POST':
#form = RegistrationFormUniqueEmail(request.POST)
form = RegistrationFormSex(request.POST)
@@ -605,17 +605,17 @@ def freecoach_register_view(request):
# create default favorite charts
add_defaultfavorites(therower)
-
+
# Create and send email
fullemail = first_name + " " + last_name + " " + "<" + email + ">"
subject = "Thank you for registering on rowsandall.com"
from_address = 'Sander Roosendaal '
d = {'first_name':theuser.first_name}
-
+
send_template_email(from_address,[fullemail],
subject,'coachregisteremail.html',d)
-
+
subject2 = "New Free Coach"
message2 = "New Free Coach registered.\n"
@@ -628,7 +628,7 @@ def freecoach_register_view(request):
theuser = authenticate(username=username,password=password)
login(request,theuser)
-
+
return HttpResponseRedirect(nextpage)
else:
@@ -647,6 +647,7 @@ def freecoach_register_view(request):
'next':nextpage,})
@login_required()
+@permission_required('rower.is_staff',fn=get_user_by_userid,raise_exception=True)
def transactions_view(request):
if not request.user.is_staff:
raise PermissionDenied("Not Allowed")
@@ -662,7 +663,7 @@ def transactions_view(request):
response = HttpResponse(df.to_csv())
response['Content-Disposition'] = 'attachment; filename="%s"' % filename
response['Content-Type'] = 'application/octet-stream'
-
+
return response
else:
@@ -673,4 +674,3 @@ def transactions_view(request):
{
'dateform':dateform
})
-
From 497b6204d068f35757ed97b92128543b89da91ff Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Sat, 1 Feb 2020 11:45:01 +0100
Subject: [PATCH 15/19] up to stats
---
rowers/tests/.~lock.viewnames.csv# | 1 -
rowers/tests/viewnames.csv | 10 +++++-----
rowers/views/workoutviews.py | 1 +
3 files changed, 6 insertions(+), 6 deletions(-)
delete mode 100644 rowers/tests/.~lock.viewnames.csv#
diff --git a/rowers/tests/.~lock.viewnames.csv# b/rowers/tests/.~lock.viewnames.csv#
deleted file mode 100644
index c1247cdc..00000000
--- a/rowers/tests/.~lock.viewnames.csv#
+++ /dev/null
@@ -1 +0,0 @@
-,sander,sander-pc,01.02.2020 11:32,file:///home/sander/.config/libreoffice/4;
\ No newline at end of file
diff --git a/rowers/tests/viewnames.csv b/rowers/tests/viewnames.csv
index 18cbf41a..f36066ca 100644
--- a/rowers/tests/viewnames.csv
+++ b/rowers/tests/viewnames.csv
@@ -63,11 +63,11 @@
61,67,workout_csvemail_view,download CSV file,TRUE,403,basic,200,302,basic,403,403,coach,200,403,FALSE,FALSE,TRUE,FALSE,TRUE
62,68,workout_csvtoadmin_view,send CSV to admin,TRUE,403,basic,200,200,basic,200,200,coach,200,200,TRUE,FALSE,TRUE,FALSE,TRUE
63,69,workout_edit_view,Edit Workout,TRUE,403,basic,200,403,basic,403,403,coach,200,403,FALSE,FALSE,TRUE,FALSE,TRUE
-64,70,workout_map_view,View workout Map,TRUE,302,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,TRUE,TRUE
-65,71,workout_update_cp_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
-66,72,instroke_chart,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
-67,73,instroke_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
-68,74,workout_stats_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+64,70,workout_map_view,View workout Map,TRUE,302,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,TRUE
+65,71,workout_update_cp_view,Update CP data based on new workout,TRUE,403,pro,302,302,pro,403,403,coach,302,302,FALSE,FALSE,TRUE,FALSE,TRUE
+66,72,instroke_chart,View In-Stroke data chart,TRUE,302,pro,302,302,pro,403,403,coach,302,302,FALSE,FALSE,FALSE,FALSE,FALSE
+67,73,instroke_view,Create in stroke chart,TRUE,403,basic,200,302,basic,403,403,coach,200,302,FALSE,FALSE,TRUE,FALSE,TRUE
+68,74,workout_stats_view,View Workout Stats,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,TRUE,TRUE
69,75,workout_data_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
70,76,workout_otwsetpower_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
71,77,workout_otwpowerplot_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
diff --git a/rowers/views/workoutviews.py b/rowers/views/workoutviews.py
index a0208381..7ccce1be 100644
--- a/rowers/views/workoutviews.py
+++ b/rowers/views/workoutviews.py
@@ -736,6 +736,7 @@ def fitness_metric_view(request,mode='rower',days=42):
@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
+@permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True)
@user_passes_test(ispromember,login_url="/rowers/paidplans",
message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality. If you are already a Pro user, please log in to access this functionality",
redirect_field_name=None)
From aca8f28457ccfd8c7a594a95467c769862cee9b5 Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Sat, 1 Feb 2020 15:25:52 +0100
Subject: [PATCH 16/19] adding template edit functionality
---
rowers/models.py | 29 +++
rowers/templates/plannedsessioncreate.html | 4 +
.../templates/plannedsessionteamcreate.html | 4 +
.../templates/plannedsessiontemplateedit.html | 197 ++++++++++++++++++
rowers/templates/plannedsessionview.html | 6 +-
rowers/urls.py | 1 +
rowers/views/planviews.py | 115 +++++++++-
rowers/views/statements.py | 2 +-
8 files changed, 346 insertions(+), 12 deletions(-)
create mode 100644 rowers/templates/plannedsessiontemplateedit.html
diff --git a/rowers/models.py b/rowers/models.py
index 6d9b7ac9..01f49265 100644
--- a/rowers/models.py
+++ b/rowers/models.py
@@ -2342,6 +2342,35 @@ class PlannedSessionForm(ModelForm):
self.fields['sessiontype'].choices = regularsessiontypechoices
+class PlannedSessionTemplateForm(ModelForm):
+
+ class Meta:
+ model = PlannedSession
+ fields = [
+ 'name',
+ 'sessiontype',
+ 'sessionmode',
+ 'criterium',
+ 'sessionvalue',
+ 'sessionunit',
+ 'course',
+ 'comment',
+ ]
+
+ dateTimeOptions = {
+ 'format': 'yyyy-mm-dd',
+ 'autoclose': True,
+ }
+
+ widgets = {
+ 'comment': forms.Textarea,
+ }
+
+ def __init__(self,*args,**kwargs):
+ super(PlannedSessionTemplateForm, self).__init__(*args, **kwargs)
+ self.fields['course'].queryset = GeoCourse.objects.all().order_by("country","name")
+ self.fields['sessiontype'].choices = regularsessiontypechoices
+
def get_course_timezone(course):
polygons = GeoPolygon.objects.filter(course = course)
points = GeoPoint.objects.filter(polygon = polygons[0])
diff --git a/rowers/templates/plannedsessioncreate.html b/rowers/templates/plannedsessioncreate.html
index 5c5f7ff1..fc6ac992 100644
--- a/rowers/templates/plannedsessioncreate.html
+++ b/rowers/templates/plannedsessioncreate.html
@@ -108,6 +108,7 @@
| Name |
Value |
|
+ Edit |
Delete |
@@ -125,6 +126,9 @@
{{ ps.sessionvalue }} |
{{ ps.sessionunit }} |
+
+ Edit Template
+ |
Delete
|
diff --git a/rowers/templates/plannedsessionteamcreate.html b/rowers/templates/plannedsessionteamcreate.html
index 2cba5493..55dabe13 100644
--- a/rowers/templates/plannedsessionteamcreate.html
+++ b/rowers/templates/plannedsessionteamcreate.html
@@ -115,6 +115,7 @@
Name |
Value |
|
+ Edit |
Delete |
@@ -132,6 +133,9 @@
{{ ps.sessionvalue }} |
{{ ps.sessionunit }} |
+
+ Edit Template
+ |
Delete
|
diff --git a/rowers/templates/plannedsessiontemplateedit.html b/rowers/templates/plannedsessiontemplateedit.html
new file mode 100644
index 00000000..34dde816
--- /dev/null
+++ b/rowers/templates/plannedsessiontemplateedit.html
@@ -0,0 +1,197 @@
+{% extends "newbase.html" %}
+{% load staticfiles %}
+{% load rowerfilters %}
+
+{% block title %}Update Template Session{% endblock %}
+
+{% block main %}
+Edit Session Template
+
+
+
+
+ -
+
{{ thesession.name }}
+
+ {% csrf_token %}
+
+
+
+
+ Delete
+
+
+
+
+
+
+ Templates
+
+ Click on session name to clone to current period
+
+
+
+
+ | Name |
+ Value |
+ |
+ Edit |
+ Delete |
+
+
+
+ {% for ps in sessiontemplates %}
+
+ |
+ {% if ps.name != '' %}
+ {{ ps.name }}
+ {% else %}
+ Unnamed Session
+ {% endif %}
+ |
+ {{ ps.sessionvalue }} |
+ {{ ps.sessionunit }} |
+
+ Edit Template
+ |
+
+ Delete
+ |
+
+ {% endfor %}
+
+
+
+
+
+{% endblock %}
+
+{% block sidebar %}
+{% include 'menu_plan.html' %}
+{% endblock %}
+
+
+{% block scripts %}
+
+
+
+{% endblock %}
diff --git a/rowers/templates/plannedsessionview.html b/rowers/templates/plannedsessionview.html
index a8d0ad65..e6e9666d 100644
--- a/rowers/templates/plannedsessionview.html
+++ b/rowers/templates/plannedsessionview.html
@@ -16,6 +16,8 @@
Edit Session
+ /
+ Save to template
{% endif %}
Session {{ psdict.name.1 }}
@@ -157,11 +159,11 @@
Course
{{ coursediv|safe }}
-
+
{{ coursescript|safe }}
{% endif %}
-
+
diff --git a/rowers/urls.py b/rowers/urls.py
index 7146d4da..8d652646 100644
--- a/rowers/urls.py
+++ b/rowers/urls.py
@@ -666,6 +666,7 @@ urlpatterns = [
views.plannedsession_multicreate_view,
name='plannedsession_multicreate_view'),
re_path(r'^sessions/(?P\d+)/edit/$',views.plannedsession_edit_view),
+ re_path(r'^sessions/(?P\d+)/templateedit/',views.plannedsession_templateedit_view),
re_path(r'^sessions/(?P\d+)/maketemplate/$',views.plannedsession_totemplate_view),
re_path(r'^sessions/(?P\d+)/compare/$',
views.plannedsession_compare_view,
diff --git a/rowers/views/planviews.py b/rowers/views/planviews.py
index 05910fbc..7dabf62f 100644
--- a/rowers/views/planviews.py
+++ b/rowers/views/planviews.py
@@ -704,7 +704,9 @@ def plannedsession_teamcreate_view(request,
enddatestring = enddate.strftime('%Y-%m-%d')
url += '?when='+startdatestring+'/'+enddatestring
- return HttpResponseRedirect(url)
+ next = request.GET.get('next', url)
+
+ return HttpResponseRedirect(next)
else:
timeperiod = startdate.strftime('%Y-%m-%d')+'/'+enddate.strftime('%Y-%m-%d')
breadcrumbs = [
@@ -897,8 +899,8 @@ def plannedsession_teamedit_view(request,
enddatestring = enddate.strftime('%Y-%m-%d')
url += '?when='+startdatestring+'/'+enddatestring
-
- return HttpResponseRedirect(url)
+ next = request.GET.get('next', url)
+ return HttpResponseRedirect(next)
else:
sessioncreateform = PlannedSessionForm(instance=ps)
sessionteamselectform = PlannedSessionTeamForm(
@@ -1465,8 +1467,8 @@ def plannedsession_clone_view(request,id=0,userid=0):
enddatestring = enddate.strftime('%Y-%m-%d')
url += '?when='+startdatestring+'/'+enddatestring
-
- return HttpResponseRedirect(url)
+ next = request.GET.get('next', url)
+ return HttpResponseRedirect(next)
# Clone an existing planned session
# need clarity on cloning behavior time shift
@@ -1531,8 +1533,101 @@ def plannedsession_teamclone_view(request,id=0):
enddatestring = enddate.strftime('%Y-%m-%d')
url += '?when='+startdatestring+'/'+enddatestring
+ next = request.GET.get('next', url)
+ return HttpResponseRedirect(next)
+
+@user_passes_test(hasplannedsessions, login_url="/rowers/paidplans/",
+message="This functionality requires a Coach or Self-Coach plan",
+redirect_field_name=None)
+def plannedsession_templateedit_view(request,id=0):
+ r = getrequestrower(request)
+ startdate,enddate = get_dates_timeperiod(request)
+ try:
+ trainingplan = TrainingPlan.objects.filter(
+ startdate__lte = startdate,
+ rowers = r,
+ enddate__gte = enddate)[0]
+ except IndexError:
+ trainingplan = None
+
+ try:
+ ps = PlannedSession.objects.get(id=id)
+ except PlannedSession.DoesNotExist:
+ raise Http404("Planned Session does not exist")
+
+ if ps.manager != request.user:
+ raise PermissionDenied("You are not allowed to edit this planned session")
+
+ if ps.sessiontype in ['race','indoorrace']:
+ raise PermissionDenied("You are not allowed to edit this planned session because it is a race")
+
+ if not ps.is_template:
+ ps.pk = None
+ ps.id = None
+ ps.is_template = True
+ ps.startdate = datetime.date(1970,1,1)
+ ps.enddate = datetime.date(1970,1,1)
+ ps.team.clear()
+ ps.save()
+
+ sessioncreateform = PlannedSessionTemplateForm(instance=ps)
+
+ if request.method == 'POST':
+ sessioncreateform = PlannedSessionTemplateForm(request.POST,instance=ps)
+ if sessioncreateform.is_valid():
+ cd = sessioncreateform.cleaned_data
+ if cd['sessionunit'] == 'min':
+ cd['sessionmode'] = 'time'
+ elif cd['sessionunit'] in ['km','m']:
+ cd['sessionmode'] = 'distance'
+
+ res, message = update_plannedsession(ps,cd)
+
+ if res:
+ messages.info(request,message)
+ else:
+ messages.error(request,message)
+
+ url = reverse(plannedsession_templateedit_view,
+ kwargs = {
+ 'id':int(ps.id),
+ })
+
+ startdatestring = startdate.strftime('%Y-%m-%d')
+ enddatestring = enddate.strftime('%Y-%m-%d')
+ url += '?when='+startdatestring+'/'+enddatestring
+ next = request.GET.get('next', url)
+ return HttpResponseRedirect(next)
+
+ breadcrumbs = [
+ {
+ 'url': reverse(plannedsessions_view),
+ 'name': 'Sessions'
+ },
+ {
+ 'url':reverse(plannedsession_templateedit_view,
+ kwargs={
+ 'id':id,
+ }
+ ),
+ 'name': 'Edit'
+ }
+ ]
+
+ sessiontemplates = PlannedSession.objects.filter(manager=request.user,is_template=True)
+
+ return render(request,'plannedsessiontemplateedit.html',
+ {
+ 'teams':get_my_teams(request.user),
+ 'plan': trainingplan,
+ 'breadcrumbs': breadcrumbs,
+ 'form': sessioncreateform,
+ 'active':'nav-plan',
+ 'thesession': ps,
+ 'sessiontemplates': sessiontemplates,
+ 'rower': r,
+ })
- return HttpResponseRedirect(url)
@user_passes_test(hasplannedsessions, login_url="/rowers/paidplans/",
message="This functionality requires a Coach or Self-Coach plan",
@@ -1564,7 +1659,9 @@ def plannedsession_totemplate_view(request,id=0):
enddatestring = enddate.strftime('%Y-%m-%d')
url += '?when='+startdatestring+'/'+enddatestring
- return HttpResponseRedirect(url)
+ next = request.GET.get('next', url)
+
+ return HttpResponseRedirect(next)
# Edit an existing planned session
@user_passes_test(hasplannedsessions,login_url="/rowers/paidplans/",
@@ -1715,8 +1812,8 @@ def plannedsession_detach_view(request,id=0,psid=0):
remove_workout_plannedsession(w,ps)
url = reverse(plannedsession_view,kwargs={'id':psid})
-
- return HttpResponseRedirect(url)
+ next = request.GET.get('next', url)
+ return HttpResponseRedirect(next)
@login_required()
def plannedsession_view(request,id=0,userid=0):
diff --git a/rowers/views/statements.py b/rowers/views/statements.py
index aab50741..25a27c9c 100644
--- a/rowers/views/statements.py
+++ b/rowers/views/statements.py
@@ -107,7 +107,7 @@ from rowers.models import (
WorkoutComment,WorkoutCommentForm,RowerExportForm,
CalcAgePerformance,
PowerTimeFitnessMetric,BlogPost,
- PlannedSessionForm,
+ PlannedSessionForm,PlannedSessionTemplateForm,
PlannedSessionFormSmall,GeoCourseEditForm,VirtualRace,
VirtualRaceForm,VirtualRaceResultForm,RowerImportExportForm,
IndoorVirtualRaceResultForm,IndoorVirtualRaceResult,
From 2e145a737c9376fdf8205f6eed783357ad51e69c Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Sat, 1 Feb 2020 15:40:06 +0100
Subject: [PATCH 17/19] adding
---
rowers/templates/plannedsessioncreate.html | 2 +-
rowers/views/planviews.py | 6 ++++--
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/rowers/templates/plannedsessioncreate.html b/rowers/templates/plannedsessioncreate.html
index fc6ac992..38f29545 100644
--- a/rowers/templates/plannedsessioncreate.html
+++ b/rowers/templates/plannedsessioncreate.html
@@ -130,7 +130,7 @@
Edit Template
- Delete
+ Delete
|
{% endfor %}
diff --git a/rowers/views/planviews.py b/rowers/views/planviews.py
index 48985c74..b5ec6dad 100644
--- a/rowers/views/planviews.py
+++ b/rowers/views/planviews.py
@@ -1502,7 +1502,8 @@ def plannedsession_teamclone_view(request,id=0):
next = request.GET.get('next', url)
return HttpResponseRedirect(next)
-@user_passes_test(hasplannedsessions, login_url="/rowers/paidplans/",
+@permission_required('plannedsession.change_session',fn=get_session_by_pk,raise_exception=True)
+@user_passes_test(can_plan, login_url="/rowers/paidplans/",
message="This functionality requires a Coach or Self-Coach plan",
redirect_field_name=None)
def plannedsession_templateedit_view(request,id=0):
@@ -1989,8 +1990,9 @@ class PlannedSessionDelete(DeleteView):
w.save()
url = reverse(plannedsessions_view)
+ next = self.request.GET.get('next',url)
- return url
+ return next
def get_object(self, *args, **kwargs):
obj = super(PlannedSessionDelete, self).get_object(*args, **kwargs)
From 0366e8ee69abf997c00b289f667aed847edb2fed Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Sun, 2 Feb 2020 16:45:40 +0100
Subject: [PATCH 18/19] a few more views checked
---
rowers/tests/.~lock.viewnames.csv# | 1 +
rowers/tests/viewnames.csv | 53 +++++++++++++++---------------
rowers/urls.py | 1 +
rowers/views/workoutviews.py | 33 +++++++++----------
4 files changed, 44 insertions(+), 44 deletions(-)
create mode 100644 rowers/tests/.~lock.viewnames.csv#
diff --git a/rowers/tests/.~lock.viewnames.csv# b/rowers/tests/.~lock.viewnames.csv#
new file mode 100644
index 00000000..bd542c4c
--- /dev/null
+++ b/rowers/tests/.~lock.viewnames.csv#
@@ -0,0 +1 @@
+,sander,sander-pc,02.02.2020 16:37,file:///home/sander/.config/libreoffice/4;
\ No newline at end of file
diff --git a/rowers/tests/viewnames.csv b/rowers/tests/viewnames.csv
index f36066ca..0d67bacc 100644
--- a/rowers/tests/viewnames.csv
+++ b/rowers/tests/viewnames.csv
@@ -67,33 +67,32 @@
65,71,workout_update_cp_view,Update CP data based on new workout,TRUE,403,pro,302,302,pro,403,403,coach,302,302,FALSE,FALSE,TRUE,FALSE,TRUE
66,72,instroke_chart,View In-Stroke data chart,TRUE,302,pro,302,302,pro,403,403,coach,302,302,FALSE,FALSE,FALSE,FALSE,FALSE
67,73,instroke_view,Create in stroke chart,TRUE,403,basic,200,302,basic,403,403,coach,200,302,FALSE,FALSE,TRUE,FALSE,TRUE
-68,74,workout_stats_view,View Workout Stats,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,TRUE,TRUE
-69,75,workout_data_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
-70,76,workout_otwsetpower_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
-71,77,workout_otwpowerplot_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
-72,78,workout_wind_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
-73,79,workout_uploadimage_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
-74,80,virtualevent_compare_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
-75,81,virtualevent_uploadimage_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
-76,82,virtualevent_setlogo_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
-77,83,logo_delete_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
-78,84,workout_downloadwind_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
-79,85,workout_downloadmetar_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
-80,86,workout_stream_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
-81,87,workout_summary_edit_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
-82,88,workout_summary_restore_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
-83,89,workout_split_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
-84,90,workout_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
-85,91,workout_video_create_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
-86,92,VideoDelete,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
-87,93,workout_video_view_mini,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
-88,94,workout_video_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
-89,95,list_videos,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
-90,96,video_selectworkout,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
-91,98,workout_fusion_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
-92,99,workout_fusion_list,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
-93,100,TemplateView,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
-94,103,workout_add_chart_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+68,74,workout_stats_view,View Workout Stats,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,TRUE
+69,75,workout_data_view,shows the detailed data for a workout,TRUE,403,basic,200,403,basic,403,403,coach,200,403,FALSE,FALSE,TRUE,FALSE,TRUE
+70,76,workout_otwsetpower_view,set weight and start offline OTW power calculations,TRUE,403,pro,200,302,pro,403,403,coach,200,403,FALSE,FALSE,TRUE,FALSE,TRUE
+71,77,workout_otwpowerplot_view,generates OTW power chart,TRUE,200,basic,200,200,basic,200,200,coach,200,302,FALSE,FALSE,TRUE,FALSE,TRUE
+72,78,workout_wind_view,set wind,TRUE,403,pro,200,302,pro,403,403,coach,200,403,FALSE,FALSE,TRUE,FALSE,TRUE
+73,79,workout_uploadimage_view,upload image,TRUE,403,basic,200,403,basic,403,403,coach,200,403,FALSE,FALSE,TRUE,FALSE,TRUE
+74,80,virtualevent_compare_view,compare workouts from a virtual event,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+75,81,virtualevent_uploadimage_view,upload image to virtual event,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+76,82,virtualevent_setlogo_view,set logo of virtual event,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+77,83,logo_delete_view,delete logo,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+78,84,workout_downloadwind_view,download Wind,TRUE,403,pro,302,302,pro,403,403,coach,302,403,FALSE,FALSE,TRUE,FALSE,FALSE
+79,85,workout_downloadmetar_view,download METAR,TRUE,403,pro,200,302,pro,403,403,coach,200,403,FALSE,FALSE,TRUE,FALSE,FALSE
+80,86,workout_stream_view,edit stream (redirects as no data in test suite),TRUE,403,pro,200,302,pro,403,403,coach,200,302,FALSE,FALSE,TRUE,FALSE,TRUE
+81,87,workout_summary_edit_view,edit workout summary,TRUE,403,basic,200,403,basic,403,403,coach,200,403,FALSE,FALSE,TRUE,FALSE,TRUE
+82,88,workout_summary_restore_view,restore workout summary,TRUE,403,basic,302,403,basic,403,403,coach,302,403,FALSE,FALSE,TRUE,FALSE,TRUE
+83,89,workout_split_view,split workout,TRUE,403,pro,200,302,pro,403,403,coach,200,302,FALSE,FALSE,TRUE,FALSE,TRUE
+84,90,workout_view,view workout ,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,TRUE
+85,91,workout_video_create_view,add video ,TRUE,403,pro,200,302,pro,403,403,coach,200,302,FALSE,FALSE,TRUE,FALSE,TRUE
+86,92,VideoDelete,delete video,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+87,93,workout_video_view_mini,minimal view,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+88,94,workout_video_view,"video view (not tested, no video in test suite)",TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
+89,95,list_videos,list my videos,TRUE,302,pro,200,302,pro,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,TRUE
+90,96,video_selectworkout,select workout to create video,TRUE,302,pro,200,302,pro,403,403,coach,200,302,FALSE,TRUE,FALSE,FALSE,TRUE
+91,98,workout_fusion_view,needs to workouts,TRUE,403,pro,200,302,pro,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
+92,99,workout_fusion_list,list workouts to fuse with,TRUE,302,pro,200,302,pro,403,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,TRUE
+94,103,workout_add_chart_view,add chart,TRUE,403,basic,302,403,basic,403,403,coach,302,403,FALSE,FALSE,TRUE,TRUE,FALSE
95,112,WorkoutDelete,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,FALSE,FALSE,FALSE
96,113,workout_smoothenpace_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
97,114,workout_undo_smoothenpace_view,,TRUE,200,basic,200,302,basic,200,302,coach,200,302,FALSE,FALSE,TRUE,FALSE,FALSE
diff --git a/rowers/urls.py b/rowers/urls.py
index dc813203..d07c68e9 100644
--- a/rowers/urls.py
+++ b/rowers/urls.py
@@ -357,6 +357,7 @@ urlpatterns = [
re_path(r'^video/(?P\w.+)/$',views.workout_video_view,
name='workout_video_view'),
re_path(r'^videos/',views.list_videos,name='list_videos'),
+ re_path(r'^add-video/user/(?P\d+)/$',views.video_selectworkout,name='video_selectworkout'),
re_path(r'^add-video/',views.video_selectworkout,name='video_selectworkout'),
# re_path(r'^workout/(?P\d+)/$',views.workout_view,name='workout_view'),
re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/$',views.workout_view,name='workout_view'),
diff --git a/rowers/views/workoutviews.py b/rowers/views/workoutviews.py
index 7ccce1be..a52d31e4 100644
--- a/rowers/views/workoutviews.py
+++ b/rowers/views/workoutviews.py
@@ -846,6 +846,7 @@ defaultoptions = {
@user_passes_test(ispromember, login_url="/rowers/paidplans",
message="This functionality requires a Pro plan or higher",
redirect_field_name=None)
+@permission_required('rower.is_coach',fn=get_user_by_userid,raise_exception=True)
def video_selectworkout(request,userid=0,teamid=0):
r = getrequestrower(request, userid=userid)
user = r.user
@@ -1967,17 +1968,15 @@ def workouts_view(request,message='',successmessage='',
@user_passes_test(ispromember,login_url="/rowers/paidplans",
message="This functionality requires a Pro plan or higher. If you are already a Pro user, please log in to access this functionality. If you are already a Pro user, please log in to access this functionality",
redirect_field_name=None)
-def workout_fusion_list(request,id=0,message='',successmessage='',
+@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True)
+def workout_fusion_list(request,id=0,
startdatestring="",enddatestring="",
startdate=timezone.now()-datetime.timedelta(days=365),
enddate=timezone.now()):
- try:
- r = getrower(request.user)
- except Rower.DoesNotExist:
- raise Http404("User has no rower instance")
+ r = getrequestrower(request)
- u = User.objects.get(id=r.user.id)
+ u = r.user
if request.method == 'POST':
dateform = DateRangeForm(request.POST)
if dateform.is_valid():
@@ -2005,6 +2004,8 @@ def workout_fusion_list(request,id=0,message='',successmessage='',
if id:
theid = encoder.decode_hex(id)
+ w = get_workout(id)
+ r = w.user
workouts = Workout.objects.filter(user=r,
startdatetime__gte=startdate,
@@ -2034,8 +2035,6 @@ def workout_fusion_list(request,id=0,message='',successmessage='',
workouts = paginator.page(paginator.num_pages)
row = get_workout(id)
- messages.info(request,successmessage)
- messages.error(request,message)
breadcrumbs = [
{
@@ -2610,7 +2609,9 @@ def workout_stream_view(request,id=0,message="",successmessage=""):
rowdata = rdata(f1)
if rowdata == 0:
- return HttpResponse("Error: CSV Data File Not Found")
+ messages.info(request,"Error: CSV data file not found")
+ url = reverse('workout_edit_view',kwargs={'id':encoder.encode_hex(row.id)})
+ return HttpResponseRedirect(url)
if request.method == 'POST':
# process form
@@ -3702,14 +3703,12 @@ def workout_otwpowerplot_view(request,id=0,message="",successmessage=""):
# r = getrower(u)
promember=0
- mayedit=0
- if not request.user.is_anonymous:
- r = getrower(request.user)
- result = request.user.is_authenticated and ispromember(request.user)
- if result:
- promember=1
- if request.user == w.user.user:
- mayedit=1
+ mayedit = 0
+ result = request.user.is_authenticated and ispromember(request.user)
+ if result:
+ promember=1
+ if request.user == w.user.user:
+ mayedit=1
# create interactive plot
res = interactive_otw_advanced_pace_chart(encoder.decode_hex(id),promember=promember)
From cc85e920be86f6054bbbe99511db204a97f49802 Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Sun, 2 Feb 2020 16:45:55 +0100
Subject: [PATCH 19/19] removing temp file
---
rowers/tests/.~lock.viewnames.csv# | 1 -
1 file changed, 1 deletion(-)
delete mode 100644 rowers/tests/.~lock.viewnames.csv#
diff --git a/rowers/tests/.~lock.viewnames.csv# b/rowers/tests/.~lock.viewnames.csv#
deleted file mode 100644
index bd542c4c..00000000
--- a/rowers/tests/.~lock.viewnames.csv#
+++ /dev/null
@@ -1 +0,0 @@
-,sander,sander-pc,02.02.2020 16:37,file:///home/sander/.config/libreoffice/4;
\ No newline at end of file