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):