diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py
index 5e358a15..7228a80e 100644
--- a/rowers/interactiveplots.py
+++ b/rowers/interactiveplots.py
@@ -5,6 +5,8 @@ from rowingdata import cumcpdata,histodata
from rowingdata import rowingdata as rrdata
+from django.utils import timezone
+
from bokeh.plotting import figure, ColumnDataSource, Figure,curdoc
from bokeh.models import CustomJS,Slider
from bokeh.charts import Histogram,HeatMap
@@ -570,7 +572,6 @@ def interactive_cum_flex_chart2(theworkouts,promember=0,
datadf = dataprep.smalldataprep(theworkouts,xparam,yparam1,yparam2)
-
axlabels = {
'time': 'Time',
'distance': 'Distance (m)',
@@ -631,11 +632,16 @@ def interactive_cum_flex_chart2(theworkouts,promember=0,
return ['','
No non-zero data in selection
','','']
- datadf['x1'] = datadf.ix[:,xparam]
-
- datadf['y1'] = datadf.ix[:,yparam1]
+ # datadf['x1'] = datadf.ix[:,xparam]
+ datadf = datadf.rename(columns={
+ xparam:'x1',
+ yparam1:'y1',
+ })
+
+ # datadf['y1'] = datadf.ix[:,yparam1]
if yparam2 != 'None':
- datadf['y2'] = datadf.ix[:,yparam2]
+ # datadf['y2'] = datadf.ix[:,yparam2]
+ datadf = datadf.rename(columns={yparam2:'y2'})
else:
datadf['y2'] = datadf['y1']
@@ -674,6 +680,8 @@ def interactive_cum_flex_chart2(theworkouts,promember=0,
datadf.copy()
)
+ print "jet",timezone.now()
+
# Add hover to this comma-separated string and see what changes
if (promember==1):
TOOLS = 'save,pan,box_zoom,wheel_zoom,reset,tap,resize,crosshair'
diff --git a/rowers/templates/advancededit.html b/rowers/templates/advancededit.html
index fc9bbedb..0e40362b 100644
--- a/rowers/templates/advancededit.html
+++ b/rowers/templates/advancededit.html
@@ -7,115 +7,132 @@
{% block content %}
- {% if form.errors %}
-
- Please correct the error{{ form.errors|pluralize }} below.
-
- {% endif %}
+ {% if form.errors %}
+
+ Please correct the error{{ form.errors|pluralize }} below.
+
+ {% endif %}
-
Advanced Workout Editor
- {% if user.rower.rowerplan == 'basic' %}
-
This is a preview of the page with advanced functionality for Pro users. See the page about Pro membership for more information and to sign up for Pro Membership
- {% endif %}
-
-
-
- Export
-
+
Advanced Workout Editor
+ {% if user.rower.rowerplan == 'basic' %}
+
This is a preview of the page with advanced functionality for Pro users.
+ See
+ the page about Pro membership for more information and to sign up for Pro Membership
+{% endif %}
+
+
-
+
+
-
- {% if user.rower.rowerplan == 'pro' %}
-
Compare Workouts
- {% else %}
-
Compare Workouts
- {% endif %}
-
- Compare this workout to other workouts. Plot HR, SPM, or pace vs time or distance for the two workouts.
-
-
-
+
+ {% if user.rower.rowerplan == 'pro' %}
+
Compare Workouts
+ {% else %}
+
Compare Workouts
+ {% endif %}
+
+ Compare this workout to other workouts. Plot HR, SPM, or pace vs time or distance for the two workouts.
+
+
+
-
+
+ Enter or change the interval and summary data for your workout
+
+
+
-
-
- {% if user.rower.rowerplan == 'pro' %}
- Dist Metrics Plot
- {% else %}
- Dist Metrics Plot
- {% endif %}
-
-
- Various advanced stroke metrics plotted versus distance.
-
-
-
-
- {% if user.rower.rowerplan == 'pro' %}
- Time Metrics Plot
- {% else %}
- Time Metrics Plot
- {% endif %}
-
-
- Various advanced stroke metrics plotted versus time.
-
-
-
+
+
+ {% if user.rower.rowerplan == 'pro' %}
+ Dist Metrics Plot
+ {% else %}
+ Dist Metrics Plot
+ {% endif %}
+
+
+ Various advanced stroke metrics plotted versus distance.
+
+
+
+
+ {% if user.rower.rowerplan == 'pro' %}
+ Time Metrics Plot
+ {% else %}
+ Time Metrics Plot
+ {% endif %}
+
+
+ Various advanced stroke metrics plotted versus time.
+
+
+
+
+
@@ -155,4 +172,4 @@ Enter or change the interval and summary data for your workout
-{% endblock %}
\ No newline at end of file
+{% endblock %}
diff --git a/rowers/templates/advancedotw.html b/rowers/templates/advancedotw.html
index 5ca99655..52d3751b 100644
--- a/rowers/templates/advancedotw.html
+++ b/rowers/templates/advancedotw.html
@@ -42,7 +42,7 @@
Public link to this workout
- http://rowsandall.com/rowers/workout/{{ workout.id }}
+ https://rowsandall.com/rowers/workout/{{ workout.id }}
diff --git a/rowers/templates/comparison_list.html b/rowers/templates/comparison_list.html
index a0fbcadb..08910d38 100644
--- a/rowers/templates/comparison_list.html
+++ b/rowers/templates/comparison_list.html
@@ -6,8 +6,7 @@
{% block content %}
-
-
+
Workout {{ id }}
@@ -30,6 +29,35 @@
Weight Category: {{ workout.weightcategory }}
+
+
+
+ Select start and end date for a date range:
+
+
+
+
+
+
+
@@ -73,5 +101,21 @@
{% else %}
No workouts found
{% endif %}
+
+
+
+ {% if workouts.has_previous %}
+ <
+ {% endif %}
+
+
+ Page {{ workouts.number }} of {{ workouts.paginator.num_pages }}.
+
+
+ {% if workouts.has_next %}
+ >
+ {% endif %}
+
+
{% endblock %}
diff --git a/rowers/templates/histo.html b/rowers/templates/histo.html
index 3e8feb63..8fa50f6f 100644
--- a/rowers/templates/histo.html
+++ b/rowers/templates/histo.html
@@ -46,7 +46,7 @@
between {{ startdate|date }} and {{ enddate|date }}
Direct link for other Pro users:
- http://rowsandall.com/rowers/{{ id }}/histo/{{ startdate|date:"Y-m-d" }}/{{ enddate|date:"Y-m-d" }}
+ https://rowsandall.com/rowers/{{ id }}/histo/{{ startdate|date:"Y-m-d" }}/{{ enddate|date:"Y-m-d" }}
@@ -82,4 +82,4 @@
-{% endblock %}
\ No newline at end of file
+{% endblock %}
diff --git a/rowers/templates/histo_single.html b/rowers/templates/histo_single.html
new file mode 100644
index 00000000..042acf0f
--- /dev/null
+++ b/rowers/templates/histo_single.html
@@ -0,0 +1,66 @@
+{% extends "base.html" %}
+{% load staticfiles %}
+{% load rowerfilters %}
+
+{% block title %}View Workout {% endblock %}
+
+{% block content %}
+
+
+
+
+ {{ interactiveplot |safe }}
+
+
+
+
+
+
+ {% if user.is_authenticated and mayedit %}
+
+
+ {% endif %}
+
+
+
+
+
+
Indoor Rower Power Histogram
+
+
+
+
+
+ {{ the_div|safe }}
+
+
+
+{% endblock %}
diff --git a/rowers/templates/histoall.html b/rowers/templates/histoall.html
index bfd1922f..11f7b63e 100644
--- a/rowers/templates/histoall.html
+++ b/rowers/templates/histoall.html
@@ -42,7 +42,7 @@
Summary of the past 12 months for {{ theuser.first_name }} {{ theuser.last_name }}
Direct link for other Pro users:
- http://rowsandall.com/rowers/{{ id }}/histo-all
+ https://rowsandall.com/rowers/{{ id }}/histo-all
diff --git a/rowers/templates/list_graphs.html b/rowers/templates/list_graphs.html
index 921960cc..bfc1e571 100644
--- a/rowers/templates/list_graphs.html
+++ b/rowers/templates/list_graphs.html
@@ -6,6 +6,14 @@
{% block content %}
Recent Graphs
+
+
{% if graphs1 %}
diff --git a/rowers/templates/list_workouts.html b/rowers/templates/list_workouts.html
index 0b4334ef..d3cf848e 100644
--- a/rowers/templates/list_workouts.html
+++ b/rowers/templates/list_workouts.html
@@ -5,8 +5,27 @@
{% block title %}Workouts{% endblock %}
{% block content %}
+
+
+ Select start and end date for a date range:
+
+
+
+
+
+
+
My Workouts
- {% if workouts %}
+
+{% if workouts %}
@@ -49,4 +68,35 @@
{% else %}
No workouts found
{% endif %}
+
+
+
+
+ {% if workouts.has_previous %}
+ <
+ {% endif %}
+
+
+ Page {{ workouts.number }} of {{ workouts.paginator.num_pages }}.
+
+
+ {% if workouts.has_next %}
+ >
+ {% endif %}
+
+
+
+
{% endblock %}
diff --git a/rowers/templates/otwgeeky.html b/rowers/templates/otwgeeky.html
index a7820797..d26fe113 100644
--- a/rowers/templates/otwgeeky.html
+++ b/rowers/templates/otwgeeky.html
@@ -48,7 +48,7 @@
Public link to this workout
- http://rowsandall.com/rowers/workout/{{ workout.id }}
+ https://rowsandall.com/rowers/workout/{{ workout.id }}
diff --git a/rowers/templates/rankings.html b/rowers/templates/rankings.html
index 28b2695f..441961d3 100644
--- a/rowers/templates/rankings.html
+++ b/rowers/templates/rankings.html
@@ -43,7 +43,7 @@
between {{ startdate|date }} and {{ enddate|date }}
Direct link for other users:
- http://rowsandall.com/rowers/{{ id }}/ote-bests/{{ startdate|date:"Y-m-d" }}/{{ enddate|date:"Y-m-d" }}
+ https://rowsandall.com/rowers/{{ id }}/ote-bests/{{ startdate|date:"Y-m-d" }}/{{ enddate|date:"Y-m-d" }}
The table gives the best efforts achieved on the official Concept2 ranking pieces in the selected date range.
diff --git a/rowers/templates/summary_edit.html b/rowers/templates/summary_edit.html
index de042397..5d7c98e3 100644
--- a/rowers/templates/summary_edit.html
+++ b/rowers/templates/summary_edit.html
@@ -48,12 +48,12 @@
Public link to this workout
- http://rowsandall.com/rowers/workout/{{ workout.id }}
+ https://rowsandall.com/rowers/workout/{{ workout.id }}
Public link to interactive chart
- http://rowsandall.com/rowers/workout/{{ workout.id }}/interactiveplot
+ https://rowsandall.com/rowers/workout/{{ workout.id }}/interactiveplot
diff --git a/rowers/templates/workout_form.html b/rowers/templates/workout_form.html
index 1e5cef44..27965b5e 100644
--- a/rowers/templates/workout_form.html
+++ b/rowers/templates/workout_form.html
@@ -48,12 +48,12 @@
Public link to this workout
- http://rowsandall.com/rowers/workout/{{ workout.id }}
+ https://rowsandall.com/rowers/workout/{{ workout.id }}
Public link to interactive chart
- http://rowsandall.com/rowers/workout/{{ workout.id }}/interactiveplot
+ https://rowsandall.com/rowers/workout/{{ workout.id }}/interactiveplot
diff --git a/rowers/tests.py b/rowers/tests.py
index 32d65884..8f075065 100644
--- a/rowers/tests.py
+++ b/rowers/tests.py
@@ -425,6 +425,9 @@ class ViewTest(TestCase):
response = self.c.get('/rowers/workout/1/interactiveplot', form_data, follow=True)
self.assertEqual(response.status_code, 200)
+ response = self.c.get('/rowers/workout/1/histo', form_data, follow=True)
+ self.assertEqual(response.status_code, 200)
+
w = Workout.objects.get(id=1)
diff --git a/rowers/urls.py b/rowers/urls.py
index abfe93ba..04c88fe9 100644
--- a/rowers/urls.py
+++ b/rowers/urls.py
@@ -26,6 +26,7 @@ urlpatterns = [
url(r'^list-workouts/c/(?P
\w+.*)/$',views.workouts_view),
url(r'^list-workouts/s/(?P\w+.*)/$',views.workouts_view),
url(r'^list-workouts/c/(?P\w+.*)/s/(?P\w+.*)$',views.workouts_view),
+ url(r'^list-workouts/(?P\w+.*)/(?P\w+.*)$',views.workouts_view),
url(r'^list-workouts/$',views.workouts_view),
url(r'^list-graphs/$',views.graphs_view),
url(r'^dashboard/c/(?P\w+.*)/$',views.dashboard_view),
@@ -55,6 +56,7 @@ urlpatterns = [
url(r'^graph/(\d+)/delete$',views.graph_delete_view),
url(r'^workout/upload/$',views.workout_upload_view),
url(r'^workout/upload/(.+.*)$',views.workout_upload_view),
+ url(r'^workout/(?P\d+)/histo$',views.workout_histo_view),
url(r'^workout/(?P\d+)/export/c/(?P\w+.*)/s/(?P\w+.*)$',views.workout_export_view),
url(r'^workout/(?P\d+)/export/c/(?P\w+.*)$',views.workout_export_view),
url(r'^workout/(?P\d+)/export/s/(?P\w+.*)$',views.workout_export_view),
@@ -63,6 +65,7 @@ urlpatterns = [
url(r'^workout/(\d+)/emailcsv$',views.workout_csvemail_view),
url(r'^workout/compare/(\d+)/$',views.workout_comparison_list),
url(r'^workout/compare2/(?P\d+)/(?P\d+)/(?P\w+.*)/(?P\w+.*)/$',views.workout_comparison_view),
+ url(r'^workout/compare/(?P\d+)/(?P\d+-\d+-\d+)/(?P\w+.*)$',views.workout_comparison_list),
url(r'^workout/(?P\d+)/export/c/(?P\w+.*)/s/(?P\w+.*)$',views.workout_edit_view),
url(r'^workout/(?P\d+)/edit/c/(?P.+.*)$',views.workout_edit_view),
url(r'^workout/(?P\d+)/edit/s/(?P.+.*)$',views.workout_edit_view),
diff --git a/rowers/views.py b/rowers/views.py
index 96bf21ee..0c940311 100644
--- a/rowers/views.py
+++ b/rowers/views.py
@@ -1,11 +1,14 @@
import time
+import operator
from django.views.generic.base import TemplateView
+from django.db.models import Q
from django.shortcuts import render
from django.http import HttpResponse, HttpResponseRedirect
from django.contrib.auth import authenticate, login, logout
from rowers.forms import LoginForm,DocumentsForm,UploadOptionsForm
from django.core.urlresolvers import reverse
from django.template import RequestContext
+from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.conf import settings
from django.utils.datastructures import MultiValueDictKeyError
from django.utils import timezone,translation
@@ -1339,6 +1342,36 @@ def cum_flex(request,theuser=0,
'promember':promember,
})
+@login_required()
+def workout_histo_view(request,id=0):
+ row = Workout.objects.get(id=id)
+ promember=0
+ mayedit=0
+ if not request.user.is_anonymous():
+ r = Rower.objects.get(user=request.user)
+ result = request.user.is_authenticated() and r.rowerplan=='pro'
+ if result:
+ promember=1
+ if request.user == row.user.user:
+ mayedit=1
+
+ if not promember:
+ return HttpResponseRedirect("/rowers/about/")
+
+
+
+
+ res = interactive_histoall([row])
+ script = res[0]
+ div = res[1]
+
+ return render(request,
+ 'histo_single.html',
+ {'interactiveplot':script,
+ 'the_div':div,
+ 'id':id,
+ 'mayedit':mayedit,
+ })
@login_required()
def histo(request,theuser=0,
@@ -1569,8 +1602,8 @@ def rankings_view(request,theuser=0,
for rankingduration in rankingdurations:
workouts = Workout.objects.filter(user=r,duration=rankingduration,
- workouttype='rower',
- startdatetime__gte=startdate,
+ workouttype='rower',
+ startdatetime__gte=startdate,
startdatetime__lte=enddate).order_by('-distance')
if workouts:
thedistances.append(workouts[0].distance)
@@ -1764,29 +1797,133 @@ def workout_recalcsummary_view(request,id=0):
@login_required()
-def workouts_view(request,message='',successmessage=''):
+def workouts_view(request,message='',successmessage='',
+ startdatestring="",enddatestring="",
+ startdate=timezone.now()-datetime.timedelta(days=365),
+ enddate=timezone.now()):
try:
r = Rower.objects.get(user=request.user)
# res = mailprocessing.safeprocessattachments()
#if len(res)>0 and np.cumsum(np.array(res)).max()>0:
# successmessage = 'New Workouts have been created from email'
- workouts = Workout.objects.filter(user=r).order_by("-date", "-starttime")
-
+ if request.method == 'POST':
+ dateform = DateRangeForm(request.POST)
+ if dateform.is_valid():
+ startdate = dateform.cleaned_data['startdate']
+ enddate = dateform.cleaned_data['enddate']
+ else:
+ dateform = DateRangeForm(initial={
+ 'startdate':startdate,
+ 'enddate':enddate,
+ })
+
+ startdate = datetime.datetime.combine(startdate,datetime.time())
+ enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59))
+
+ if startdatestring:
+ startdate = iso8601.parse_date(startdatestring)
+ if enddatestring:
+ enddate = iso8601.parse_date(enddatestring)
+
+ if enddate < startdate:
+ s = enddate
+ enddate = startdate
+ startdate = s
+
+
+ workouts = Workout.objects.filter(user=r,
+ startdatetime__gte=startdate,
+ startdatetime__lte=enddate).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))
+ )
+
+ paginator = Paginator(workouts,20) # show 25 workouts per page
+ page = request.GET.get('page')
+
+ try:
+ workouts = paginator.page(page)
+ except PageNotAnInteger:
+ workouts = paginator.page(1)
+ except EmptyPage:
+ workouts = paginator.page(paginator.num_pages)
+
return render(request, 'list_workouts.html',
{'workouts': workouts,
'message': message,
'successmessage':successmessage,
+ 'dateform':dateform,
+ 'startdate':startdate,
+ 'enddate':enddate,
})
except Rower.DoesNotExist:
return HttpResponse("Admin has no rower instance")
@user_passes_test(promember,login_url="/login")
-def workout_comparison_list(request,id=0,message='',successmessage=''):
+def workout_comparison_list(request,id=0,message='',successmessage='',
+ startdatestring="",enddatestring="",
+ startdate=timezone.now()-datetime.timedelta(days=365),
+ enddate=timezone.now()):
+
try:
r = Rower.objects.get(user=request.user)
u = User.objects.get(id=r.user.id)
- workouts = Workout.objects.filter(user=r).order_by("-date", "-starttime").exclude(id=id)
+ if request.method == 'POST':
+ dateform = DateRangeForm(request.POST)
+ if dateform.is_valid():
+ startdate = dateform.cleaned_data['startdate']
+ enddate = dateform.cleaned_data['enddate']
+ else:
+ dateform = DateRangeForm(initial={
+ 'startdate':startdate,
+ 'enddate':enddate,
+ })
+
+ if startdatestring:
+ startdate = iso8601.parse_date(startdatestring)
+ if enddatestring:
+ enddate = iso8601.parse_date(enddatestring)
+
+ startdate = datetime.datetime.combine(startdate,datetime.time())
+ enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59))
+
+ if enddate < startdate:
+ s = enddate
+ enddate = startdate
+ startdate = s
+
+ workouts = Workout.objects.filter(user=r,
+ startdatetime__gte=startdate,
+ startdatetime__lte=enddate).order_by("-date", "-starttime").exclude(id=id)
+
+ 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))
+ )
+
+ paginator = Paginator(workouts,15) # show 25 workouts per page
+ page = request.GET.get('page')
+
+ try:
+ workouts = paginator.page(page)
+ except PageNotAnInteger:
+ workouts = paginator.page(1)
+ except EmptyPage:
+ workouts = paginator.page(paginator.num_pages)
+
row = Workout.objects.get(id=id)
return render(request, 'comparison_list.html',
@@ -1797,6 +1934,9 @@ def workout_comparison_list(request,id=0,message='',successmessage=''):
'first_name':u.first_name,
'message': message,
'successmessage':successmessage,
+ 'dateform':dateform,
+ 'startdate':startdate,
+ 'enddate':enddate,
})
except Rower.DoesNotExist:
return HttpResponse("Admin has no rower instance")
@@ -3942,6 +4082,16 @@ def graphs_view(request):
try:
r = Rower.objects.get(user=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))
+ )
+
g = GraphImage.objects.filter(workout__in=workouts).order_by("-creationdatetime")
if (len(g)<=5):
return render(request, 'list_graphs.html',
diff --git a/static/css/rowsandall.css b/static/css/rowsandall.css
index dcfe9580..d163a455 100644
--- a/static/css/rowsandall.css
+++ b/static/css/rowsandall.css
@@ -17,14 +17,19 @@ a {
text-decoration: none;
}
+
a:visited { color:#000; }
a:link { color: #000; }
+
a:hover {
text-decoration: underline;
}
+
+
+
h1 {
/* font-family: Georgia, serif; */
font-weight: normal;
@@ -471,4 +476,16 @@ a.button {
.flexplot {
position: relative;
z-index: 10;
-}
\ No newline at end of file
+}
+
+a.wh:link {
+ color: #e9e9e9;
+}
+
+a.wh:visited {
+ color: #e9e9e9;
+}
+
+a.wh:hover {
+ color: #e9e9e9;
+}