Merge branch 'feature/python3' into develop
This commit is contained in:
+15
-4
@@ -16,6 +16,8 @@ import rowers.mytypes as mytypes
|
|||||||
from rowers.mytypes import otwtypes
|
from rowers.mytypes import otwtypes
|
||||||
from iso8601 import ParseError
|
from iso8601 import ParseError
|
||||||
|
|
||||||
|
import numpy
|
||||||
|
|
||||||
from rowsandall_app.settings import (
|
from rowsandall_app.settings import (
|
||||||
C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET
|
C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET
|
||||||
)
|
)
|
||||||
@@ -424,7 +426,11 @@ def createc2workoutdata(w):
|
|||||||
hr = 0*d
|
hr = 0*d
|
||||||
stroke_data = []
|
stroke_data = []
|
||||||
for i in range(len(t)):
|
for i in range(len(t)):
|
||||||
thisrecord = {"t":t[i],"d":d[i],"p":p[i],"spm":spm[i],"hr":hr[i]}
|
thisrecord = {"t":t[i].astype(int),
|
||||||
|
"d":d[i].astype(int),
|
||||||
|
"p":p[i].astype(int),
|
||||||
|
"spm":spm[i].astype(int),
|
||||||
|
"hr":hr[i].astype(int)}
|
||||||
stroke_data.append(thisrecord)
|
stroke_data.append(thisrecord)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -440,7 +446,7 @@ def createc2workoutdata(w):
|
|||||||
startdatetime = w.startdatetime.isoformat()
|
startdatetime = w.startdatetime.isoformat()
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
startdate = datetime.datetime.combine(w.date,datetime.time())
|
startdate = datetime.datetime.combine(w.date,datetime.time())
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
"type": mytypes.c2mapping[workouttype],
|
"type": mytypes.c2mapping[workouttype],
|
||||||
"date": w.startdatetime.isoformat(),
|
"date": w.startdatetime.isoformat(),
|
||||||
@@ -551,7 +557,7 @@ def make_authorization_url(request):
|
|||||||
params = {"client_id": C2_CLIENT_ID,
|
params = {"client_id": C2_CLIENT_ID,
|
||||||
"response_type": "code",
|
"response_type": "code",
|
||||||
"redirect_uri": C2_REDIRECT_URI}
|
"redirect_uri": C2_REDIRECT_URI}
|
||||||
url = "https://log.concept2.com/oauth/authorize?"+ urllib.urlencode(params)
|
url = "https://log.concept2.com/oauth/authorize?"+ urllib.parse.urlencode(params)
|
||||||
url += "&scope="+scope
|
url += "&scope="+scope
|
||||||
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
@@ -697,6 +703,10 @@ def process_callback(request):
|
|||||||
|
|
||||||
return HttpResponse("got a user name: %s" % username)
|
return HttpResponse("got a user name: %s" % username)
|
||||||
|
|
||||||
|
def default(o):
|
||||||
|
if isinstance(o, numpy.int64): return int(o)
|
||||||
|
raise TypeError
|
||||||
|
|
||||||
# Uploading workout
|
# Uploading workout
|
||||||
def workout_c2_upload(user,w):
|
def workout_c2_upload(user,w):
|
||||||
message = 'trying C2 upload'
|
message = 'trying C2 upload'
|
||||||
@@ -717,6 +727,7 @@ def workout_c2_upload(user,w):
|
|||||||
raise NoTokenError
|
raise NoTokenError
|
||||||
|
|
||||||
data = createc2workoutdata(w)
|
data = createc2workoutdata(w)
|
||||||
|
|
||||||
if data == 0:
|
if data == 0:
|
||||||
return "Error: No data file. Contact info@rowsandall.com if the problem persists",0
|
return "Error: No data file. Contact info@rowsandall.com if the problem persists",0
|
||||||
|
|
||||||
@@ -726,7 +737,7 @@ def workout_c2_upload(user,w):
|
|||||||
'Content-Type': 'application/json'}
|
'Content-Type': 'application/json'}
|
||||||
import urllib
|
import urllib
|
||||||
url = "https://log.concept2.com/api/users/%s/results" % (c2userid)
|
url = "https://log.concept2.com/api/users/%s/results" % (c2userid)
|
||||||
response = requests.post(url,headers=headers,data=json.dumps(data))
|
response = requests.post(url,headers=headers,data=json.dumps(data,default=default))
|
||||||
|
|
||||||
if (response.status_code == 409 ):
|
if (response.status_code == 409 ):
|
||||||
message = "Concept2 Duplicate error"
|
message = "Concept2 Duplicate error"
|
||||||
|
|||||||
+1
-1
@@ -280,7 +280,7 @@ def imports_make_authorization_url(oauth_data):
|
|||||||
|
|
||||||
|
|
||||||
import urllib
|
import urllib
|
||||||
url = oauth_data['authorizaton_uri']+urllib.urlencode(params)
|
url = oauth_data['authorizaton_uri']+urllib.parse.urlencode(params)
|
||||||
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
#!/srv/venv/bin/python
|
#!/srv/venv/bin/python
|
||||||
|
|
||||||
""" Process emails """
|
""" Process emails """
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
PY3K = sys.version_info >= (3, 0)
|
||||||
|
|
||||||
import zipfile
|
import zipfile
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
from time import strftime
|
from time import strftime
|
||||||
|
|
||||||
|
import io
|
||||||
|
|
||||||
from django.core.management.base import BaseCommand
|
from django.core.management.base import BaseCommand
|
||||||
from django_mailbox.models import Message, MessageAttachment,Mailbox
|
from django_mailbox.models import Message, MessageAttachment,Mailbox
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
@@ -62,7 +66,7 @@ def processattachment(rower, fileobj, title, uploadoptions,testing=False):
|
|||||||
|
|
||||||
# test if file exists and is not empty
|
# test if file exists and is not empty
|
||||||
try:
|
try:
|
||||||
with open('media/'+filename,'r') as fop:
|
with io.open('media/'+filename,'rb') as fop:
|
||||||
line = fop.readline()
|
line = fop.readline()
|
||||||
except (IOError, UnicodeEncodeError):
|
except (IOError, UnicodeEncodeError):
|
||||||
if testing:
|
if testing:
|
||||||
@@ -164,6 +168,11 @@ def get_from_address(message):
|
|||||||
except IndexError:
|
except IndexError:
|
||||||
first_line = ''
|
first_line = ''
|
||||||
|
|
||||||
|
try:
|
||||||
|
first_line = first_line.decode('utf-8')
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
if "quiske" in first_line:
|
if "quiske" in first_line:
|
||||||
match = re.search(r'[\w\.-]+@[\w\.-]+', first_line)
|
match = re.search(r'[\w\.-]+@[\w\.-]+', first_line)
|
||||||
return match.group(0)
|
return match.group(0)
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ def make_authorization_url(request):
|
|||||||
|
|
||||||
|
|
||||||
import urllib
|
import urllib
|
||||||
url = "http://localhost:8000/rowers/o/authorize" +urllib.urlencode(params)
|
url = "http://localhost:8000/rowers/o/authorize" +urllib.parse.urlencode(params)
|
||||||
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ def make_authorization_url():
|
|||||||
"redirect_uri": POLAR_REDIRECT_URI,
|
"redirect_uri": POLAR_REDIRECT_URI,
|
||||||
"scope":"write"}
|
"scope":"write"}
|
||||||
import urllib
|
import urllib
|
||||||
url = "https://flow.polar.com/oauth2/authorization" +urllib.urlencode(params)
|
url = "https://flow.polar.com/oauth2/authorization" +urllib.parse.urlencode(params)
|
||||||
|
|
||||||
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ oauth_data = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
import numpy
|
||||||
|
|
||||||
def splitrunkeeperlatlongdata(lijst,tname,latname,lonname):
|
def splitrunkeeperlatlongdata(lijst,tname,latname,lonname):
|
||||||
t = []
|
t = []
|
||||||
lat = []
|
lat = []
|
||||||
@@ -262,6 +264,10 @@ def get_userid(access_token):
|
|||||||
|
|
||||||
return str(res)
|
return str(res)
|
||||||
|
|
||||||
|
def default(o):
|
||||||
|
if isinstance(o, numpy.int64): return int(o)
|
||||||
|
raise TypeError
|
||||||
|
|
||||||
def workout_runkeeper_upload(user,w):
|
def workout_runkeeper_upload(user,w):
|
||||||
message = "Uploading to Runkeeper"
|
message = "Uploading to Runkeeper"
|
||||||
rkid = 0
|
rkid = 0
|
||||||
@@ -287,7 +293,7 @@ def workout_runkeeper_upload(user,w):
|
|||||||
'Content-Length':'nnn'}
|
'Content-Length':'nnn'}
|
||||||
|
|
||||||
url = "https://api.runkeeper.com/fitnessActivities"
|
url = "https://api.runkeeper.com/fitnessActivities"
|
||||||
response = requests.post(url,headers=headers,data=json.dumps(data))
|
response = requests.post(url,headers=headers,data=json.dumps(data,default=default))
|
||||||
|
|
||||||
# check for duplicate error first
|
# check for duplicate error first
|
||||||
if (response.status_code == 409 ):
|
if (response.status_code == 409 ):
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ from __future__ import unicode_literals
|
|||||||
from __future__ import unicode_literals, absolute_import
|
from __future__ import unicode_literals, absolute_import
|
||||||
# All the functionality to connect to SportTracks
|
# All the functionality to connect to SportTracks
|
||||||
|
|
||||||
|
import numpy
|
||||||
|
|
||||||
from rowers.imports import *
|
from rowers.imports import *
|
||||||
import re
|
import re
|
||||||
from rowsandall_app.settings import (
|
from rowsandall_app.settings import (
|
||||||
@@ -235,6 +237,11 @@ def getidfromresponse(response):
|
|||||||
|
|
||||||
return int(id)
|
return int(id)
|
||||||
|
|
||||||
|
def default(o):
|
||||||
|
if isinstance(o, numpy.int64): return int(o)
|
||||||
|
raise TypeError
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def workout_sporttracks_upload(user,w):
|
def workout_sporttracks_upload(user,w):
|
||||||
message = "Uploading to SportTracks"
|
message = "Uploading to SportTracks"
|
||||||
@@ -257,7 +264,7 @@ def workout_sporttracks_upload(user,w):
|
|||||||
'Content-Type': 'application/json'}
|
'Content-Type': 'application/json'}
|
||||||
|
|
||||||
url = "https://api.sporttracks.mobi/api/v2/fitnessActivities.json"
|
url = "https://api.sporttracks.mobi/api/v2/fitnessActivities.json"
|
||||||
response = requests.post(url,headers=headers,data=json.dumps(data))
|
response = requests.post(url,headers=headers,data=json.dumps(data,default=default))
|
||||||
|
|
||||||
# check for duplicate error first
|
# check for duplicate error first
|
||||||
if (response.status_code == 409 ):
|
if (response.status_code == 409 ):
|
||||||
|
|||||||
@@ -1,227 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
{% load staticfiles %}
|
|
||||||
{% load rowerfilters %}
|
|
||||||
|
|
||||||
{% block title %}{{ workout.name }} Advanced {% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<div id="workouts" class="grid_6 alpha">
|
|
||||||
<div class="grid_6 alpha">
|
|
||||||
{% if form.errors %}
|
|
||||||
<p style="color: red;">
|
|
||||||
Please correct the error{{ form.errors|pluralize }} below.
|
|
||||||
</p>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<h1>{{ workout.name }} - Advanced</h1>
|
|
||||||
{% if user.rower.rowerplan == 'basic' %}
|
|
||||||
<p>Functionality marked with an asterisk (*) is limited to the paid plans. See
|
|
||||||
<a href="/rowers/paidplans">the page about Pro membership</a>
|
|
||||||
for more information and to sign up for Pro Membership</a></p>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
<div class="grid_6 alpha">
|
|
||||||
<div class="grid_2 alpha">
|
|
||||||
<p>
|
|
||||||
<a class="button gray small" href="/rowers/workout/{{ workout.id|encode }}/edit">Edit Workout</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2">
|
|
||||||
<p>
|
|
||||||
<a class="button gray small" href="/rowers/workout/{{ workout.id|encode }}/workflow">Workflow View</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2 omega">
|
|
||||||
<p>
|
|
||||||
<a class="button gray small" href="/rowers/workout/{{ workout.id|encode }}/export">Export</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid_6 alpha">
|
|
||||||
|
|
||||||
<table width=100%>
|
|
||||||
<tr>
|
|
||||||
<th>Date:</th><td>{{ workout.date }}</td>
|
|
||||||
</tr><tr>
|
|
||||||
<th>Time:</th><td>{{ workout.starttime }}</td>
|
|
||||||
</tr><tr>
|
|
||||||
<th>Distance:</th><td>{{ workout.distance }}m</td>
|
|
||||||
</tr><tr>
|
|
||||||
<th>Duration:</th><td>{{ workout.duration |durationprint:"%H:%M:%S.%f" }}</td>
|
|
||||||
</tr>
|
|
||||||
<th>Public link to this workout</th>
|
|
||||||
<td>
|
|
||||||
<a href="/rowers/workout/{{ workout.id|encode }}">https://rowsandall.com/rowers/workout/{{ workout.id|encode }}</a>
|
|
||||||
<td>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid_6 alpha">
|
|
||||||
<div class="grid_2 alpha">
|
|
||||||
{% if user|is_promember %}
|
|
||||||
<a class="button blue small" href="/rowers/workout/compare/{{ workout.id|encode }}">Compare Workouts</a>
|
|
||||||
{% else %}
|
|
||||||
<a class="button blue small" href="/rowers/paidplans/">Compare Workouts*</a>
|
|
||||||
{% endif %}
|
|
||||||
<p>
|
|
||||||
Compare this workout to other workouts. Plot HR, SPM, or pace vs time or distance for the two workouts.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2">
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ workout.id|encode }}/flexchart">
|
|
||||||
Flexible Interactive Plot
|
|
||||||
</a>
|
|
||||||
<p>
|
|
||||||
Flexible Interactive plot. Pick your own X and Y axis parameters.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid_2 omega tooltip">
|
|
||||||
<p>
|
|
||||||
{% if user|is_promember %}
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ workout.id|encode }}/editintervals">Edit Intervals</a>
|
|
||||||
{% else %}
|
|
||||||
<a class="button blue small" href="/rowers/paidplans">Edit Intervals*</a>
|
|
||||||
{% endif %}
|
|
||||||
</p>
|
|
||||||
<span class="tooltiptext">Enter or change the interval and summary data for your workout</span>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Enter or change the interval and summary data for your workout
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="grid_6 alpha">
|
|
||||||
<div class="grid_2 alpha">
|
|
||||||
<p>
|
|
||||||
{% if user|is_promember %}
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ workout.id|encode }}/adddistanceplot2">Dist Metrics Plot</a>
|
|
||||||
{% else %}
|
|
||||||
<a class="button blue small" href="/rowers/paidplans">Dist Metrics Plot*</a>
|
|
||||||
{% endif %}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Various advanced stroke metrics plotted versus distance.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2">
|
|
||||||
<p>
|
|
||||||
{% if user|is_promember %}
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ workout.id|encode }}/addtimeplot2">Time Metrics Plot</a>
|
|
||||||
{% else %}
|
|
||||||
<a class="button blue small" href="/rowers/paidplans">Time Metrics Plot*</a>
|
|
||||||
{% endif %}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Various advanced stroke metrics plotted versus time.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2 omega">
|
|
||||||
<p>
|
|
||||||
{% if user|is_promember %}
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ workout.id|encode }}/histo">Power Histogram</a>
|
|
||||||
{% else %}
|
|
||||||
<a class="button blue small" href="/rowers/paidplans">Power Histogram*</a>
|
|
||||||
{% endif %}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Plot the Power Histogram of this workout
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="grid_6 alpha">
|
|
||||||
<div class="grid_2 alpha">
|
|
||||||
<p>
|
|
||||||
{% if user|is_promember %}
|
|
||||||
<a class="button blue small" href="/rowers/workouts-join-select">Glue</a>
|
|
||||||
{% else %}
|
|
||||||
<a class="button blue small" href="/rowers/paidplans">Glue*</a>
|
|
||||||
{% endif %}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Glue multiple workouts together (into one workout). For example, to combine separately recorded intervals.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid_2">
|
|
||||||
<p>
|
|
||||||
{% if user|is_promember %}
|
|
||||||
<a class="button blue small" href="/rowers/workout/fusion/{{ workout.id|encode }}/">Sensor Fusion</a>
|
|
||||||
{% else %}
|
|
||||||
<a class="button blue small" href="/rowers/paidplans">Sensor Fusion*</a>
|
|
||||||
{% endif %}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Merge data from another source into this workout
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2 omega">
|
|
||||||
<p>
|
|
||||||
{% if user|is_promember %}
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ workout.id|encode }}/split">Split Workout</a>
|
|
||||||
{% else %}
|
|
||||||
<a class="button blue small" href="/rowers/paidplans">Split Workout*</a>
|
|
||||||
{% endif %}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Split workout into two seperate workouts
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="grid_6 alpha">
|
|
||||||
<div class="grid_2 alpha">
|
|
||||||
<p>
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ workout.id|encode }}/interactiveplot">Big Interactive Plot</a>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
See (and save) the big interactive plot
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2">
|
|
||||||
<p>
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ workout.id|encode }}/instroke">In-Stroke Metrics</a></p>
|
|
||||||
<p>
|
|
||||||
If your workout has in-stroke metrics (like a stroke power curve or boat acceleration curve), you will find it here.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="advancedplots" class="grid_6 omega">
|
|
||||||
<div class="grid_6 alpha">
|
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
|
||||||
<script async="true" type="text/javascript">
|
|
||||||
Bokeh.set_log_level("info");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{{ interactiveplot |safe }}
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// Set things up to resize the plot on a window resize. You can play with
|
|
||||||
// the arguments of resize_width_height() to change the plot's behavior.
|
|
||||||
var plot_resize_setup = function () {
|
|
||||||
var plotid = Object.keys(Bokeh.index)[0]; // assume we have just one plot
|
|
||||||
var plot = Bokeh.index[plotid];
|
|
||||||
var plotresizer = function() {
|
|
||||||
// arguments: use width, use height, maintain aspect ratio
|
|
||||||
plot.resize_width_height(true, true, true);
|
|
||||||
};
|
|
||||||
window.addEventListener('resize', plotresizer);
|
|
||||||
plotresizer();
|
|
||||||
};
|
|
||||||
window.addEventListener('load', plot_resize_setup);
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
/* Need this to get the page in "desktop mode"; not having an infinite height.*/
|
|
||||||
html, body {height: 100%; margin:5px;}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
||||||
<div id="interactiveplot" class="grid_6 omega">
|
|
||||||
{{ the_div |safe }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
@@ -1,284 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
{% load staticfiles %}
|
|
||||||
{% load rowerfilters %}
|
|
||||||
|
|
||||||
{% block title %}{{ workout.name }} Advanced {% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<div id="workouts" class="grid_6 alpha">
|
|
||||||
|
|
||||||
{% if form.errors %}
|
|
||||||
<p style="color: red;">
|
|
||||||
Please correct the error{{ form.errors|pluralize }} below.
|
|
||||||
</p>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<h1>{{ workout.name }} - Advanced OTW</h1>
|
|
||||||
{% if user.rower.rowerplan == 'basic' %}
|
|
||||||
<p>Functionality marked with an asterisk (*) is limited to the paid plans. See
|
|
||||||
<a href="/rowers/paidplans">the page about Pro membership</a>
|
|
||||||
for more information and to sign up for Pro Membership</a></p>
|
|
||||||
{% endif %}
|
|
||||||
<div class="grid_2 alpha">
|
|
||||||
<p>
|
|
||||||
<a class="button gray small" href="/rowers/workout/{{ workout.id|encode }}/edit">Edit Workout</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2">
|
|
||||||
<p>
|
|
||||||
<a class="button gray small" href="/rowers/workout/{{ workout.id|encode }}/workflow">Workflow View</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2 omega">
|
|
||||||
<p>
|
|
||||||
<a class="button gray small" href="/rowers/workout/{{ workout.id|encode }}/export">Export</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="grid_6 alpha">
|
|
||||||
|
|
||||||
<table width=100%>
|
|
||||||
<tr>
|
|
||||||
<th>Date:</th><td>{{ workout.date }}</td>
|
|
||||||
</tr><tr>
|
|
||||||
<th>Time:</th><td>{{ workout.starttime }}</td>
|
|
||||||
</tr><tr>
|
|
||||||
<th>Distance:</th><td>{{ workout.distance }}m</td>
|
|
||||||
</tr><tr>
|
|
||||||
<th>Duration:</th><td>{{ workout.duration |durationprint:"%H:%M:%S.%f" }}</td>
|
|
||||||
</tr>
|
|
||||||
<th>Public link to this workout</th>
|
|
||||||
<td>
|
|
||||||
<a href="/rowers/workout/{{ workout.id|encode }}">https://rowsandall.com/rowers/workout/{{ workout.id|encode }}</a>
|
|
||||||
<td>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid_6 alpha">
|
|
||||||
<div class="grid_2 alpha">
|
|
||||||
<p>
|
|
||||||
{% if user|is_promember %}
|
|
||||||
<a class="button blue small" href="/rowers/workout/compare/{{ workout.id|encode }}">Compare Workouts</a>
|
|
||||||
{% else %}
|
|
||||||
<a class="button blue small" href="/rowers/paidplans">Compare Workouts*</a>
|
|
||||||
{% endif %}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Compare this workout to other workouts. Plot HR, SPM, or pace vs time or distance for the two workouts.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid_2">
|
|
||||||
<p>
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ workout.id|encode }}/flexchart">Flexible Interactive Plot</a>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Flexible Interactive plot. Pick your own X and Y axis parameters.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid_2 omega tooltip">
|
|
||||||
<p>
|
|
||||||
{% if user|is_promember %}
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ workout.id|encode }}/editintervals">Edit Intervals</a>
|
|
||||||
{% else %}
|
|
||||||
<a class="button blue small" href="/rowers/paidplans">Edit Intervals*</a>
|
|
||||||
{% endif %}
|
|
||||||
</p>
|
|
||||||
<span class="tooltiptext">Enter or change the interval and summary data for your workout</span>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Enter or change the interval and summary data for your workout
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid_6 alpha">
|
|
||||||
<div class="grid_2 alpha">
|
|
||||||
<p>
|
|
||||||
{% if user|is_promember %}
|
|
||||||
<a class="button blue small"href="/rowers/workout/{{ workout.id|encode }}/crewnerdsummary">CrewNerd Summary</a>
|
|
||||||
{% else %}
|
|
||||||
<a class="button blue small" href="/rowers/paidplans">CrewNerd Summary*</a>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Upload a CrewNerd Summary (CSV file) to this workout.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid_2 tooltip">
|
|
||||||
<p>
|
|
||||||
{% if user|is_promember %}
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ workout.id|encode }}/forcecurve">Stroke Profile (Empower)</a>
|
|
||||||
{% else %}
|
|
||||||
<a class="button blue small" href="/rowers/paidplans">Stroke Profile (Empower)*</a>
|
|
||||||
{% endif %}
|
|
||||||
</p>
|
|
||||||
<span class="tooltiptext">Analyze your stroke force profile (need Empower Oarlock data)</span> <p>
|
|
||||||
Interactive plot of Stroke Profile (with Empower Oarlock)
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid_2 omega tooltip">
|
|
||||||
<p>
|
|
||||||
{% if user|is_promember %}
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ workout.id|encode }}/addotwpowerplot">OTW Power Plot</a>
|
|
||||||
{% else %}
|
|
||||||
<a class="button blue small" href="/rowers/paidplans">OTW Power Plot*</a>
|
|
||||||
{% endif %}
|
|
||||||
</p>
|
|
||||||
<span class="tooltiptext">Note: You must run the OTW calculations under Geeky Stuff first. Otherwise the plot will be empty</span>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Pace, wind corrected pace, power, equivalent erg power in a static plot
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid_6 alpha">
|
|
||||||
|
|
||||||
<div class="grid_2 alpha">
|
|
||||||
<p>
|
|
||||||
{% if user|is_promember %}
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ workout.id|encode }}/geeky">Geeky Stuff</a>
|
|
||||||
{% else %}
|
|
||||||
<a class="button blue small" href="/rowers/paidplans">Geeky Stuff*</a>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Add weather and current data and OTW power calculations.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="grid_2 tooltip">
|
|
||||||
<p>
|
|
||||||
{% if user|is_promember %}
|
|
||||||
<a class="button blue small"href="/rowers/workout/{{ workout.id|encode }}/smoothenpace">Smooth out Pace Data</a>
|
|
||||||
{% else %}
|
|
||||||
<a class="button blue small" href="/rowers/paidplans">Smooth out Pace Data*</a>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
</p>
|
|
||||||
<span class="tooltiptext">This will reduce noise on your pace data. The smoothing is irreversible but you can use the reset smoothing button.</span>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Pace data too noisy? Press this button!
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="grid_2 omega">
|
|
||||||
<p>
|
|
||||||
{% if user|is_promember %}
|
|
||||||
<a class="button blue small"href="/rowers/workout/{{ workout.id|encode }}/undosmoothenpace">Raw Data</a>
|
|
||||||
{% else %}
|
|
||||||
<a class="button blue small" href="/rowers/paidplans">Reset Smoothing*</a>
|
|
||||||
{% endif %}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Reset pace data to values before smoothing
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid_6 alpha">
|
|
||||||
<div class="grid_2 alpha">
|
|
||||||
<p>
|
|
||||||
{% if user|is_promember %}
|
|
||||||
<a class="button blue small" href="/rowers/workouts-join-select">Glue</a>
|
|
||||||
{% else %}
|
|
||||||
<a class="button blue small" href="/rowers/paidplans">Glue*</a>
|
|
||||||
{% endif %}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Glue multiple workouts together (into one workout). For example, to combine separately recorded intervals.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2">
|
|
||||||
<p>
|
|
||||||
{% if user|is_promember %}
|
|
||||||
<a class="button blue small" href="/rowers/workout/fusion/{{ workout.id|encode }}/">Sensor Fusion</a>
|
|
||||||
{% else %}
|
|
||||||
<a class="button blue small" href="/rowers/paidplans">Sensor Fusion*</a>
|
|
||||||
{% endif %}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Merge data from another source into this workout
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2 omega">
|
|
||||||
<p>
|
|
||||||
{% if user|is_promember %}
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ workout.id|encode }}/split">Split Workout</a>
|
|
||||||
{% else %}
|
|
||||||
<a class="button blue small" href="/rowers/paidplans">Split Workout*</a>
|
|
||||||
{% endif %}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
Split workout into two seperate workouts
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="grid_6 alpha">
|
|
||||||
<div class="grid_2 alpha">
|
|
||||||
<p>
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ workout.id|encode }}/interactiveplot">Big Interactive Plot</a>
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
See (and save) the big interactive plot
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2">
|
|
||||||
<p>
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ workout.id|encode }}/instroke">In-Stroke Metrics</a></p>
|
|
||||||
<p>
|
|
||||||
If your workout has in-stroke metrics (like a stroke power curve or boat acceleration curve), you will find it here.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="advancedplots" class="grid_6 omega">
|
|
||||||
<div class="grid_6 alpha">
|
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
|
||||||
<script async="true" type="text/javascript">
|
|
||||||
Bokeh.set_log_level("info");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{{ interactiveplot |safe }}
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// Set things up to resize the plot on a window resize. You can play with
|
|
||||||
// the arguments of resize_width_height() to change the plot's behavior.
|
|
||||||
var plot_resize_setup = function () {
|
|
||||||
var plotid = Object.keys(Bokeh.index)[0]; // assume we have just one plot
|
|
||||||
var plot = Bokeh.index[plotid];
|
|
||||||
var plotresizer = function() {
|
|
||||||
// arguments: use width, use height, maintain aspect ratio
|
|
||||||
plot.resize_width_height(true, true, true);
|
|
||||||
};
|
|
||||||
window.addEventListener('resize', plotresizer);
|
|
||||||
plotresizer();
|
|
||||||
};
|
|
||||||
window.addEventListener('load', plot_resize_setup);
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
/* Need this to get the page in "desktop mode"; not having an infinite height.*/
|
|
||||||
html, body {height: 100%; margin:5px;}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
||||||
<div id="interactiveplot" class="grid_6 omega">
|
|
||||||
{{ the_div |safe }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
<script async="true" type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
<script async="true" type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,232 +0,0 @@
|
|||||||
{% load cookielaw_tags %}
|
|
||||||
{% load leaflet_tags %}
|
|
||||||
{% load tz_detect %}
|
|
||||||
{% tz_detect %}
|
|
||||||
{% load analytical %}
|
|
||||||
{% block filters %}
|
|
||||||
{% endblock %}
|
|
||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
{% block headtext %}{% endblock %}
|
|
||||||
<script src="/static/cookielaw/js/cookielaw.js"></script>
|
|
||||||
{% analytical_head_top %}
|
|
||||||
{% if GOOGLE_ANALYTICS_PROPERTY_ID %}
|
|
||||||
{% include "ga.html" %}
|
|
||||||
{% endif %}
|
|
||||||
<link rel="stylesheet" href="/static/css/bokeh-0.12.3.min.css" type="text/css" />
|
|
||||||
<link rel="stylesheet" href="/static/css/bokeh-widgets-0.12.3.min.css" type="text/css" />
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="https://webapiv2.navionics.com/dist/webapi/webapi.min.css" >
|
|
||||||
<script type="text/javascript" src="https://webapiv2.navionics.com/dist/webapi/webapi.min.no-dep.js"></script>
|
|
||||||
|
|
||||||
<link rel="shortcut icon" href="/static/img/favicon.ico" type="image/x-icon" />
|
|
||||||
<link rel="icon" sizes="32x32" href="/static/img/favicon-32x32.png" type="image/png"/>
|
|
||||||
<link rel="icon" sizes="64x64" href="/static/img/favicon-64x64.png" type="image/png"/>
|
|
||||||
<link rel="icon" sizes="192x192" href="/static/img/favicon-192x192.png" type="image/png"/>
|
|
||||||
<link rel="icon" sizes="16x16" href="/static/img/favicon-16x16.png" type="image/png"/>
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta name="viewport" content="initial-scale=0.67">
|
|
||||||
<title>{% block title %}Rowsandall{% endblock %}</title>
|
|
||||||
<link rel="stylesheet" href="/static/css/reset.css" />
|
|
||||||
<link rel="stylesheet" href="/static/css/text.css" />
|
|
||||||
<link rel="stylesheet" href="/static/css/960_12_col.css" />
|
|
||||||
<link rel="stylesheet" href="/static/css/rowsandall.css" />
|
|
||||||
<link rel="stylesheet" href="/static/css/leaflet.css" />
|
|
||||||
<script src="/static/css/leaflet.js" ></script>
|
|
||||||
{% block meta %} {% endblock %}
|
|
||||||
{% analytical_head_bottom %}
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
{% analytical_body_top %}
|
|
||||||
{% block body_top %}{% endblock %}
|
|
||||||
<div class="container_12">
|
|
||||||
<div class="grid_12">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="grid_12">
|
|
||||||
<div id="logo" class="grid_6 alpha">
|
|
||||||
{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
|
|
||||||
<p><a href="/"><img src="/static/img/logo7.png"
|
|
||||||
alt="Rowsandall logo" height="80"></a></p>
|
|
||||||
{% else %}
|
|
||||||
<p><a href="/"><img src="/static/img/logo7.png"
|
|
||||||
alt="Rowsandall logo" height="80"></a></p>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
<div class="grid_6 omega">
|
|
||||||
<div class="grid_4 alpha">
|
|
||||||
<div class="grid_1 alpha">
|
|
||||||
<p id="header">
|
|
||||||
<a class="button gray small" href="/rowers/videos">Videos</a></p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2">
|
|
||||||
<p id="header">
|
|
||||||
<a class="button gray small" href="http://analytics.rowsandall.com/">Rowing Analytics BLOG</a></p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_1 omega">
|
|
||||||
<p id="header">
|
|
||||||
<a class="button gray small" href="/rowers/email">Contact</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_4 alpha">
|
|
||||||
<p>Free Data and Analysis. For Rowers. By Rowers.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid_1">
|
|
||||||
<div class="grid_1 tooltip">
|
|
||||||
{% if user.is_authenticated %}
|
|
||||||
<p>
|
|
||||||
<a class="button gray small" href="/rowers/me/edit">{{ user.first_name }}</a>
|
|
||||||
</p>
|
|
||||||
<span class="tooltiptext">Edit user account, e.g. heart rate zones, power zones, email, teams</span>
|
|
||||||
|
|
||||||
{% else %}
|
|
||||||
<p><a class="button gray small" href="{% url 'login' %}">login</a> </p>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
<div class="grid_1">
|
|
||||||
{% if user.is_authenticated %}
|
|
||||||
<p><a class="button gray small" href="{% url 'logout' %}">logout</a></p>
|
|
||||||
{% else %}
|
|
||||||
<p> </p>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="grid_1 omega">
|
|
||||||
{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
|
|
||||||
<h6 class="graytext">Pro Member</h6>
|
|
||||||
{% else %}
|
|
||||||
<div class="grid_1"><a class="button green small" href="/rowers/paidplans">Upgrade to Pro</a></div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="grid_12">
|
|
||||||
<div class="grid_1 alpha tooltip">
|
|
||||||
{% if user.is_authenticated %}
|
|
||||||
<p><a class="button gray small" href="/rowers/workout/upload/">Upload</a></p>
|
|
||||||
<span class="tooltiptext">Upload CSV, TCX, FIT data files to rowsandall.com</span>
|
|
||||||
{% else %}
|
|
||||||
<p><a class="button green small" href="/rowers/register">Register (free)</a></p>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
<div class="grid_1 tooltip">
|
|
||||||
{% if user.is_authenticated %}
|
|
||||||
<p>
|
|
||||||
<a class="button gray small" href="/rowers/imports/">Import</a>
|
|
||||||
</p>
|
|
||||||
<span class="tooltiptext">Import workouts from Strava, SportTracks, and C2 logbook</span>
|
|
||||||
{% else %}
|
|
||||||
<p> </p>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
<div class="grid_2 tooltip">
|
|
||||||
{% if user.is_authenticated %}
|
|
||||||
<p>
|
|
||||||
<a class="button gray small" href="/rowers/list-workouts/">Workouts</a>
|
|
||||||
</p>
|
|
||||||
<span class="tooltiptext">See your list of workouts</span>
|
|
||||||
{% else %}
|
|
||||||
<p> </p>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
<div class="grid_1 tooltip">
|
|
||||||
{% if user.is_authenticated %}
|
|
||||||
<p>
|
|
||||||
<a class="button gray small" href="/rowers/list-graphs/">Graphs</a>
|
|
||||||
</p>
|
|
||||||
<span class="tooltiptext">See your most recent charts</span>
|
|
||||||
{% else %}
|
|
||||||
<p> </p>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
<div class="grid_2 tooltip">
|
|
||||||
{% if user.is_authenticated %}
|
|
||||||
<p>
|
|
||||||
<a class="button gray small" href="/rowers/analysis">Analysis</a>
|
|
||||||
</p>
|
|
||||||
<span class="tooltiptext">Analysis of workouts over a period of time</span>
|
|
||||||
{% else %}
|
|
||||||
<p> </p>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
<div class="grid_1 tooltip">
|
|
||||||
{% block teams %}
|
|
||||||
{% endblock %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="clear"></div>
|
|
||||||
<div class="grid_12">
|
|
||||||
{% block message %}
|
|
||||||
{% if message %}
|
|
||||||
<p class="message">
|
|
||||||
{{ message }}
|
|
||||||
</p>
|
|
||||||
{% endif %}
|
|
||||||
{% if successmessage %}
|
|
||||||
<p class="successmessage">
|
|
||||||
{{ successmessage }}
|
|
||||||
</p>
|
|
||||||
{% endif %}
|
|
||||||
{% endblock %}
|
|
||||||
</div>
|
|
||||||
<div class="grid_12">
|
|
||||||
{% load tz %}
|
|
||||||
|
|
||||||
{% block content %}{% endblock %}
|
|
||||||
</div>
|
|
||||||
<div class="clear"></div>
|
|
||||||
|
|
||||||
<div class="grid_12 omega" >
|
|
||||||
{% block footer %}
|
|
||||||
<p id="footer">{{ versionstring }}</p>
|
|
||||||
<div class="grid_2 alpha">
|
|
||||||
<p id="footer"><a href="/rowers/email/">© Sander Roosendaal</a></p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_1">
|
|
||||||
<p id="footer">
|
|
||||||
<a href="/rowers/about">About</a></p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_1">
|
|
||||||
<p id="footer">
|
|
||||||
<a href="/rowers/brochure">Brochure</a></p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_1">
|
|
||||||
<p id="footer">
|
|
||||||
<a href="/rowers/developers">Developers</a></p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_1">
|
|
||||||
<p id="footer">
|
|
||||||
<a href="/rowers/legal">Legal</a></p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_1">
|
|
||||||
<p id="footer">
|
|
||||||
<a href="/rowers/partners">Partners</a></p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_1">
|
|
||||||
<p id="footer">
|
|
||||||
<a href="/rowers/physics">Physics</a></p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2">
|
|
||||||
<p id="footer">
|
|
||||||
<a href="http://analytics.rowsandall.com/">Rowing Analytics BLOG</a></p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2 omega">
|
|
||||||
<p id="footer">
|
|
||||||
<a href="https://www.facebook.com/groups/rowsandall/">Facebook group</a></p>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
</div>
|
|
||||||
{% cookielaw_banner %}
|
|
||||||
</div>
|
|
||||||
<!-- end container -->
|
|
||||||
{% analytical_body_bottom %}
|
|
||||||
{% block body_bottom %}{% endblock %}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,194 +0,0 @@
|
|||||||
{% load rowerfilters %}
|
|
||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<script src="/static/cookielaw/js/cookielaw.js"></script>
|
|
||||||
<link rel="stylesheet" href="/static/css/bokeh-0.12.3.min.css" type="text/css" />
|
|
||||||
<link rel="stylesheet" href="/static/css/bokeh-widgets-0.12.3.min.css" type="text/css" />
|
|
||||||
|
|
||||||
<link rel="shortcut icon" href="/static/img/myicon.png" />
|
|
||||||
<link rel="shortcut icon" href="/static/img/favicon.ico" />
|
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta name="viewport" content="initial-scale=0.67">
|
|
||||||
<title>Rowsandall</title>
|
|
||||||
<link rel="stylesheet" href="/static/css/reset.css" />
|
|
||||||
<link rel="stylesheet" href="/static/css/text.css" />
|
|
||||||
<link rel="stylesheet" href="/static/css/960_12_col.css" />
|
|
||||||
<link rel="stylesheet" href="/static/css/rowsandall.css" />
|
|
||||||
{% block meta %} {% endblock %}
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="container_12">
|
|
||||||
<div id="logo" class="grid_2">
|
|
||||||
{% if user|is_promember %}
|
|
||||||
<p><a href="/"><img src="/static/img/logocroppedpro.gif"
|
|
||||||
alt="Rowsandall logo" width="110" heigt="110"></a></p>
|
|
||||||
{% else %}
|
|
||||||
<p><a href="/"><img src="/static/img/logocropped.gif"
|
|
||||||
alt="Rowsandall logo" width="110" heigt="110"></a></p>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
<div class="grid_10 omega">
|
|
||||||
<div class="grid_8 alpha"><p> </p></div>
|
|
||||||
<div class="grid_2 omega">
|
|
||||||
{% if user.is_authenticated %}
|
|
||||||
<p><a class="button gray small" href="/password_change/">Password Change</a></p>
|
|
||||||
{% else %}
|
|
||||||
<p><a class="button gray small" href="/password_reset/">Forgotten Password?</a></p>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="grid_10 omega">
|
|
||||||
<div class="grid_4 suffix_2 alpha">
|
|
||||||
<p>Free Data and Analysis. For Rowers. By Rowers.</p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_3">
|
|
||||||
{% if user|is_promember %}
|
|
||||||
<h6>Pro Member</h6>
|
|
||||||
{% else %}
|
|
||||||
<p> </p>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
<div class="grid_1 omega">
|
|
||||||
{% if user.is_authenticated %}
|
|
||||||
<p><a class="button gray small" href="{% url 'logout' %}">logout</a></p>
|
|
||||||
|
|
||||||
{% else %}
|
|
||||||
<p> </p>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid_10" omega>
|
|
||||||
<div class="grid_1 alpha tooltip">
|
|
||||||
{% if user.is_authenticated %}
|
|
||||||
<p><a class="button gray small" href="/rowers/workout/upload/">Upload</a></p>
|
|
||||||
<span class="tooltiptext">Upload CSV, TCX, FIT data files to rowsandall.com</span>
|
|
||||||
{% else %}
|
|
||||||
<p><a class="button green small" href="/rowers/register">Register (free)</a></p>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
<div class="grid_1 tooltip">
|
|
||||||
{% if user.is_authenticated %}
|
|
||||||
<p>
|
|
||||||
<a class="button gray small" href="/rowers/imports/">Import</a>
|
|
||||||
</p>
|
|
||||||
<span class="tooltiptext">Import workouts from Strava, SportTracks, and C2 logbook</span>
|
|
||||||
{% else %}
|
|
||||||
<p> </p>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
<div class="grid_2 tooltip">
|
|
||||||
{% if user.is_authenticated %}
|
|
||||||
<p>
|
|
||||||
<a class="button gray small" href="/rowers/list-workouts/">Workouts</a>
|
|
||||||
</p>
|
|
||||||
<span class="tooltiptext">See your list of workouts</span>
|
|
||||||
{% else %}
|
|
||||||
<p> </p>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
<div class="grid_2 tooltip">
|
|
||||||
{% if user.is_authenticated %}
|
|
||||||
<p>
|
|
||||||
<a class="button gray small" href="/rowers/list-graphs/">Graphs</a>
|
|
||||||
</p>
|
|
||||||
<span class="tooltiptext">See your most recent charts</span>
|
|
||||||
{% else %}
|
|
||||||
<p> </p>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
<div class="grid_2 suffix_1 tooltip">
|
|
||||||
{% if user.is_authenticated %}
|
|
||||||
<p>
|
|
||||||
<a class="button gray small" href="/rowers/analysis">Analysis</a>
|
|
||||||
</p>
|
|
||||||
<span class="tooltiptext">Analysis of workouts over a period of time</span>
|
|
||||||
{% else %}
|
|
||||||
<p> </p>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
<div class="grid_1 omega tooltip">
|
|
||||||
{% if user.is_authenticated %}
|
|
||||||
<p>
|
|
||||||
<a class="button gray small" href="/rowers/me/edit">{{ user.first_name }}</a>
|
|
||||||
</p>
|
|
||||||
<span class="tooltiptext">Edit user data, e.g. heart rate zones</span>
|
|
||||||
|
|
||||||
{% else %}
|
|
||||||
<p><a class="button gray small" href="{% url 'login' %}">login</a> </p>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="clear"></div>
|
|
||||||
<div class="grid_12">
|
|
||||||
{% block message %}
|
|
||||||
{% if message %}
|
|
||||||
<p class="message">
|
|
||||||
{{ message }}
|
|
||||||
</p>
|
|
||||||
{% endif %}
|
|
||||||
{% if successmessage %}
|
|
||||||
<p class="successmessage">
|
|
||||||
{{ successmessage }}
|
|
||||||
</p>
|
|
||||||
{% endif %}
|
|
||||||
{% endblock %}
|
|
||||||
</div>
|
|
||||||
<div class="grid_12">
|
|
||||||
{% load tz %}
|
|
||||||
|
|
||||||
{% block content %}{% endblock %}
|
|
||||||
</div>
|
|
||||||
<div class="clear"></div>
|
|
||||||
|
|
||||||
<div class="grid_12 omega" >
|
|
||||||
{% block footer %}
|
|
||||||
<p id="footer"
|
|
||||||
>{{ versionstring }}</p>
|
|
||||||
<div class="grid_2 alpha">
|
|
||||||
<p id="footer"><a href="/rowers/email/">© Sander Roosendaal</a></p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_1">
|
|
||||||
<p id="footer">
|
|
||||||
<a href="/rowers/about">About</a></p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_1">
|
|
||||||
<p id="footer">
|
|
||||||
<a href="/rowers/brochure">Brochure</a></p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_1">
|
|
||||||
<p id="footer">
|
|
||||||
<a href="/rowers/developers">Developers</a></p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_1">
|
|
||||||
<p id="footer">
|
|
||||||
<a href="/rowers/legal">Legal</a></p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_1">
|
|
||||||
<p id="footer">
|
|
||||||
<a href="/rowers/physics">Physics</a></p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2">
|
|
||||||
<p id="footer">
|
|
||||||
<a href="/rowers/videos">Videos</a></p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2">
|
|
||||||
<p id="footer">
|
|
||||||
<a href="http://analytics.rowsandall.com/">Rowing Analytics BLOG</a></p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_1 omega">
|
|
||||||
<p id="footer">
|
|
||||||
<a href="/rowers/email">Contact</a></p>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- end container -->
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
{% load staticfiles %}
|
|
||||||
{% load rowerfilters %}
|
|
||||||
|
|
||||||
{% block title %}Rowsandall {% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
|
||||||
<script async="true" type="text/javascript">
|
|
||||||
Bokeh.set_log_level("info");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{{ interactiveplot |safe }}
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// Set things up to resize the plot on a window resize. You can play with
|
|
||||||
// the arguments of resize_width_height() to change the plot's behavior.
|
|
||||||
var plot_resize_setup = function () {
|
|
||||||
var plotid = Object.keys(Bokeh.index)[0]; // assume we have just one plot
|
|
||||||
var plot = Bokeh.index[plotid];
|
|
||||||
var plotresizer = function() {
|
|
||||||
// arguments: use width, use height, maintain aspect ratio
|
|
||||||
plot.resize_width_height(true, false, false);
|
|
||||||
};
|
|
||||||
window.addEventListener('resize', plotresizer);
|
|
||||||
plotresizer();
|
|
||||||
};
|
|
||||||
window.addEventListener('load', plot_resize_setup);
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
/* Need this to get the page in "desktop mode"; not having an infinite height.*/
|
|
||||||
html, body {height: 100%; margin:5px;}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
||||||
<div id="workouts" class="grid_12 alpha">
|
|
||||||
|
|
||||||
|
|
||||||
<h1>Interactive Plot</h1>
|
|
||||||
|
|
||||||
{% if user.is_authenticated and mayedit %}
|
|
||||||
<div class="grid_2 alpha">
|
|
||||||
<p>
|
|
||||||
<a class="button gray small" href="/rowers/workout/{{ workout.id|encode }}/edit">Edit Workout</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2 suffix_2 omega">
|
|
||||||
<p>
|
|
||||||
<a class="button gray small" href="/rowers/workout/{{ workout.id|encode }}/advanced">Advanced Edit</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{{ the_div|safe }}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
<script async="true" type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,77 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
{% load staticfiles %}
|
|
||||||
{% load rowerfilters %}
|
|
||||||
|
|
||||||
{% block title %}Compare Workouts {% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
|
||||||
<script async="true" type="text/javascript">
|
|
||||||
Bokeh.set_log_level("info");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{{ interactiveplot |safe }}
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// Set things up to resize the plot on a window resize. You can play with
|
|
||||||
// the arguments of resize_width_height() to change the plot's behavior.
|
|
||||||
var plot_resize_setup = function () {
|
|
||||||
var plotid = Object.keys(Bokeh.index)[0]; // assume we have just one plot
|
|
||||||
var plot = Bokeh.index[plotid];
|
|
||||||
var plotresizer = function() {
|
|
||||||
// arguments: use width, use height, maintain aspect ratio
|
|
||||||
plot.resize_width_height(true, true, false);
|
|
||||||
};
|
|
||||||
window.addEventListener('resize', plotresizer);
|
|
||||||
plotresizer();
|
|
||||||
};
|
|
||||||
window.addEventListener('load', plot_resize_setup);
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
/* Need this to get the page in "desktop mode"; not having an infinite height.*/
|
|
||||||
html, body {height: 100%; margin:5px;}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
|
|
||||||
<div id="other" class="grid_12 alpha">
|
|
||||||
<div class="grid_2 alpha suffix_10">
|
|
||||||
<a class="button blue small"
|
|
||||||
href="/rowers/workout/compare/{{ id2 }}/{{ id1 }}/{{ xparam }}/{{ yparam }}">Swap Workouts</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p> </p>
|
|
||||||
|
|
||||||
<div id="plotbuttons" class="grid_12 alpha">
|
|
||||||
<div id="x-axis" class="grid_6 alpha">
|
|
||||||
<div class="grid_2 alpha">
|
|
||||||
<a class="button blue small" href="/rowers/workout/compare/{{ id1 }}/{{ id2 }}/time/{{ yparam }}">Time</a>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2 suffix_2 omega">
|
|
||||||
<a class="button blue small" href="/rowers/workout/compare/{{ id1 }}/{{ id2 }}/distance/{{ yparam }}">Distance</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="y-axis" class="grid_6 omega">
|
|
||||||
<div class="grid_2 alpha">
|
|
||||||
<a class="button blue small" href="/rowers/workout/compare/{{ id1 }}/{{ id2 }}/{{ xparam }}/pace">Pace</a>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2">
|
|
||||||
<a class="button blue small" href="/rowers/workout/compare/{{ id1 }}/{{ id2 }}/{{ xparam }}/hr">Heart Rate</a>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2 omega">
|
|
||||||
<a class="button blue small" href="/rowers/workout/compare/{{ id1 }}/{{ id2 }}/{{ xparam }}/spm">SPM</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="theplot" class="grid_12 alpha">
|
|
||||||
|
|
||||||
|
|
||||||
{{ the_div|safe }}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
@@ -1,131 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
{% load staticfiles %}
|
|
||||||
{% load rowerfilters %}
|
|
||||||
|
|
||||||
{% block title %} Comparison Plot {% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
|
||||||
<script async="true" type="text/javascript">
|
|
||||||
Bokeh.set_log_level("info");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{{ interactiveplot |safe }}
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// Set things up to resize the plot on a window resize. You can play with
|
|
||||||
// the arguments of resize_width_height() to change the plot's behavior.
|
|
||||||
var plot_resize_setup = function () {
|
|
||||||
var plotid = Object.keys(Bokeh.index)[0]; // assume we have just one plot
|
|
||||||
var plot = Bokeh.index[plotid];
|
|
||||||
var plotresizer = function() {
|
|
||||||
// arguments: use width, use height, maintain aspect ratio
|
|
||||||
plot.resize_width_height(true, true, false);
|
|
||||||
};
|
|
||||||
window.addEventListener('resize', plotresizer);
|
|
||||||
plotresizer();
|
|
||||||
};
|
|
||||||
window.addEventListener('load', plot_resize_setup);
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
/* Need this to get the page in "desktop mode"; not having an infinite height.*/
|
|
||||||
html, body {height: 100%; margin:5px;}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div id="navigation" class="grid_12 alpha">
|
|
||||||
{% if user.is_authenticated and mayedit %}
|
|
||||||
<div class="grid_2 alpha">
|
|
||||||
<p>
|
|
||||||
<a class="button gray small" href="/rowers/workout/{{ id }}/edit">Edit Workout</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2 suffix_8 omega">
|
|
||||||
<p>
|
|
||||||
<a class="button gray small" href="/rowers/workout/compare/{{ id }}/advanced">Advanced Edit</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="plotbuttons" class="grid_12 alpha">
|
|
||||||
<div id="x-axis" class="grid_6 alpha">
|
|
||||||
<div class="grid_2 alpha">
|
|
||||||
<p>
|
|
||||||
<a class="button blue small"
|
|
||||||
href="/rowers/workout/compare/{{ id2 }}/{{ id1 }}/{{ xparam }}/{{ yparam }}/{{ plottype }}">Swap Workouts</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2 alpha dropdown">
|
|
||||||
<button class="grid_2 alpha button blue small dropbtn">X-axis</button>
|
|
||||||
<div class="dropdown-content">
|
|
||||||
{% for key, value in axchoicesbasic.items %}
|
|
||||||
{% if key != 'None' %}
|
|
||||||
<a class="button blue small alpha" href="/rowers/workout/compare/{{ id1}}/{{ id2 }}/{{ key }}/{{ yparam }}/{{ plottype }}">{{ value }}</a>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{% if promember %}
|
|
||||||
{% for key, value in axchoicespro.items %}
|
|
||||||
<a class="button blue small alpha" href="/rowers/workout/compare/{{ id1 }}/{{ id2 }}/{{ key }}/{{ yparam }}/{{ plottype }}">{{ value }}</a>
|
|
||||||
{% endfor %}
|
|
||||||
{% else %}
|
|
||||||
{% for key, value in axchoicespro.items %}
|
|
||||||
<a class="button rosy small" href="/rowers/paidplans">{{ value }}</a>
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="grid_2 omega dropdown">
|
|
||||||
<button class="grid_2 alpha button blue small dropbtn">Y-axis</button>
|
|
||||||
<div class="dropdown-content">
|
|
||||||
{% for key, value in axchoicesbasic.items %}
|
|
||||||
{% if key not in noylist and key != 'None' %}
|
|
||||||
<a class="button blue small" href="/rowers/workout/compare/{{ id1 }}/{{ id2 }}/{{ xparam }}/{{ key }}/{{ plottype }}">{{ value }}</a>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{% if promember %}
|
|
||||||
{% for key, value in axchoicespro.items %}
|
|
||||||
{% if key not in noylist %}
|
|
||||||
<a class="button blue small" href="/rowers/workout/compare/{{ id1 }}/{{ id2 }}/{{ xparam }}/{{ key }}/{{ plottype }}">{{ value }}</a>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{% else %}
|
|
||||||
{% for key, value in axchoicespro.items %}
|
|
||||||
{% if key not in noylist %}
|
|
||||||
<a class="button rosy small" href="/rowers/paidplans">{{ value }} (Pro)</a>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="y-axis" class="grid_6 omega">
|
|
||||||
<div class="grid_2 prefix_2 alpha">
|
|
||||||
<a class="button blue small" href="/rowers/workout/compare/{{ id1 }}/{{ id2 }}/{{ xparam }}/{{ yparam }}/line">Line Plot</a>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2 omega">
|
|
||||||
<a class="button blue small" href="/rowers/workout/compare/{{ id1 }}/{{ id2 }}/{{ xparam }}/{{ yparam }}/scatter">Scatter Plot</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="theplot" class="grid_12 alpha flexplot">
|
|
||||||
|
|
||||||
|
|
||||||
{{ the_div|safe }}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
@@ -58,18 +58,13 @@
|
|||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<div id="id_css_res">
|
<div id="id_css_res">
|
||||||
<link rel="stylesheet" href="/static/css/bokeh-0.12.3.min.css" type="text/css" />
|
<link rel="stylesheet" href="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.css" type="text/css" />
|
||||||
<link rel="stylesheet" href="/static/css/bokeh-widgets-0.12.3.min.css" type="text/css" />
|
<link rel="stylesheet" href="http://cdn.pydata.org/bokeh/release/bokeh-widgets-1.0.4.min.css" type="text/css" />
|
||||||
</div>
|
</div>
|
||||||
<div id="id_js_res">
|
<div id="id_js_res">
|
||||||
<script
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
|
||||||
type="text/javascript" src="/static/js/bokeh-0.12.3.min.js">
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-widgets-1.0.4.min.js"></script>
|
||||||
</script>
|
|
||||||
<script
|
|
||||||
type="text/javascript" src="/static/js/bokeh-widgets-0.12.3.min.js">
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -60,16 +60,12 @@
|
|||||||
|
|
||||||
|
|
||||||
<div id="id_css_res">
|
<div id="id_css_res">
|
||||||
<link rel="stylesheet" href="/static/css/bokeh-0.12.3.min.css" type="text/css" />
|
<link rel="stylesheet" href="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.css" type="text/css" />
|
||||||
<link rel="stylesheet" href="/static/css/bokeh-widgets-0.12.3.min.css" type="text/css" />
|
<link rel="stylesheet" href="http://cdn.pydata.org/bokeh/release/bokeh-widgets-1.0.4.min.css" type="text/css" />
|
||||||
</div>
|
</div>
|
||||||
<div id="id_js_res">
|
<div id="id_js_res">
|
||||||
<script
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
|
||||||
type="text/javascript" src="/static/js/bokeh-0.12.3.min.js">
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-widgets-1.0.4.min.js"></script>
|
||||||
</script>
|
|
||||||
<script
|
|
||||||
type="text/javascript" src="/static/js/bokeh-widgets-0.12.3.min.js">
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -98,7 +98,7 @@
|
|||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
<script async="true" type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
<script async="true" type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,182 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
{% load staticfiles %}
|
|
||||||
{% load rowerfilters %}
|
|
||||||
{% load tz %}
|
|
||||||
|
|
||||||
{% block title %} Flexible Plot {% endblock %}
|
|
||||||
|
|
||||||
{% localtime on %}
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
|
||||||
<script type="text/javascript" src="/static/js/bokeh-widgets-0.12.3.min.js"></script>
|
|
||||||
<script async="true" type="text/javascript">
|
|
||||||
Bokeh.set_log_level("info");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{{ interactiveplot |safe }}
|
|
||||||
|
|
||||||
{{ widgetscript | safe }}
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// Set things up to resize the plot on a window resize. You can play with
|
|
||||||
// the arguments of resize_width_height() to change the plot's behavior.
|
|
||||||
var plot_resize_setup = function () {
|
|
||||||
var plotid = Object.keys(Bokeh.index)[0]; // assume we have just one plot
|
|
||||||
var plot = Bokeh.index[plotid];
|
|
||||||
var plotresizer = function() {
|
|
||||||
// arguments: use width, use height, maintain aspect ratio
|
|
||||||
plot.resize_width_height(true, true, false);
|
|
||||||
};
|
|
||||||
window.addEventListener('resize', plotresizer);
|
|
||||||
plotresizer();
|
|
||||||
};
|
|
||||||
window.addEventListener('load', plot_resize_setup);
|
|
||||||
</script>
|
|
||||||
<style>
|
|
||||||
/* Need this to get the page in "desktop mode"; not having an infinite height.*/
|
|
||||||
html, body {height: 100%; margin:5px;}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div id="navigation" class="grid_12 alpha">
|
|
||||||
{% if user.is_authenticated and mayedit %}
|
|
||||||
<div class="grid_2 alpha">
|
|
||||||
<p>
|
|
||||||
<a class="button gray small" href="/rowers/workout/{{ id }}/edit">Edit Workout</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2 suffix_8 omega">
|
|
||||||
<p>
|
|
||||||
<a class="button gray small" href="/rowers/workout/{{ id }}/advanced">Advanced Edit</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<p> </p>
|
|
||||||
|
|
||||||
<div id="plotbuttons" class="grid_12 alpha">
|
|
||||||
|
|
||||||
|
|
||||||
<div id="x-axis" class="grid_6 alpha">
|
|
||||||
<div class="grid_2 alpha dropdown">
|
|
||||||
<button class="grid_2 alpha button blue small dropbtn">X-axis</button>
|
|
||||||
<div class="dropdown-content">
|
|
||||||
<a class="button blue small alpha" href="/rowers/workout/{{ id }}/flexchart/time/{{ yparam1 }}/{{ yparam2 }}/{{ plottype }}">Time</a>
|
|
||||||
<a class="button blue small alpha" href="/rowers/workout/{{ id }}/flexchart/distance/{{ yparam1 }}/{{ yparam2 }}/{{ plottype }}">Distance</a>
|
|
||||||
{% if promember %}
|
|
||||||
<a class="button blue small alpha" href="/rowers/workout/{{ id }}/flexchart/power/{{ yparam1 }}/{{ yparam2 }}/scatter">Power</a>
|
|
||||||
<a class="button blue small alpha" href="/rowers/workout/{{ id }}/flexchart/hr/{{ yparam1 }}/{{ yparam2 }}/scatter">HR</a>
|
|
||||||
<a class="button blue small alpha" href="/rowers/workout/{{ id }}/flexchart/spm/{{ yparam1 }}/{{ yparam2 }}/scatter">SPM</a>
|
|
||||||
<a class="button blue small alpha" href="/rowers/workout/{{ id }}/flexchart/peakforce/{{ yparam1 }}/{{ yparam2 }}/scatter">Peak Force</a>
|
|
||||||
<a class="button blue small alpha" href="/rowers/workout/{{ id }}/flexchart/averageforce/{{ yparam1 }}/{{ yparam2 }}/scatter">Average Force</a>
|
|
||||||
<a class="button blue small alpha" href="/rowers/workout/{{ id }}/flexchart/drivelength/{{ yparam1 }}/{{ yparam2 }}/scatter">Drive Length</a>
|
|
||||||
<a class="button blue small alpha" href="/rowers/workout/{{ id }}/flexchart/driveenergy/{{ yparam1 }}/{{ yparam2 }}/scatter">Work per Stroke</a>
|
|
||||||
<a class="button blue small alpha" href="/rowers/workout/{{ id }}/flexchart/drivespeed/{{ yparam1 }}/{{ yparam2 }}/scatter">Drive Speed</a>
|
|
||||||
{% else %}
|
|
||||||
<a class="button rosy small" href="/rowers/paidplans">Power (Pro)</a>
|
|
||||||
<a class="button rosy small" href="/rowers/paidplans">HR (Pro)</a>
|
|
||||||
<a class="button rosy small" href="/rowers/paidplans">SPM (Pro)</a>
|
|
||||||
<a class="button rosy small" href="/rowers/paidplans">Peak Force (Pro)</a>
|
|
||||||
<a class="button rosy small" href="/rowers/paidplans">Average Force (Pro)</a>
|
|
||||||
<a class="button rosy small" href="/rowers/paidplans">Drive Length (Pro)</a>
|
|
||||||
<a class="button rosy small" href="/rowers/paidplans">Work per Stroke (Pro)</a>
|
|
||||||
<a class="button rosy small" href="/rowers/paidplans">Drive Speed (Pro)</a>
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid_2 dropdown">
|
|
||||||
<button class="grid_2 alpha button blue small dropbtn">Left</button>
|
|
||||||
<div class="dropdown-content">
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ id }}/flexchart/{{ xparam }}/pace/{{ yparam2 }}/{{ plottype }}">Pace</a>
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ id }}/flexchart/{{ xparam }}/hr/{{ yparam2 }}/{{ plottype }}">HR</a>
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ id }}/flexchart/{{ xparam }}/spm/{{ yparam2 }}/{{ plottype }}">SPM</a>
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ id }}/flexchart/{{ xparam }}/power/{{ yparam2 }}/{{ plottype }}">Power</a>
|
|
||||||
{% if promember %}
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ id }}/flexchart/{{ xparam }}/peakforce/{{ yparam2 }}/{{ plottype }}">Peak Force</a>
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ id }}/flexchart/{{ xparam }}/averageforce/{{ yparam2 }}/{{ plottype }}">Average Force</a>
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ id }}/flexchart/{{ xparam }}/drivelength/{{ yparam2 }}/{{ plottype }}">Drive Length</a>
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ id }}/flexchart/{{ xparam }}/driveenergy/{{ yparam2 }}/{{ plottype }}">Work per Stroke</a>
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ id }}/flexchart/{{ xparam }}/drivespeed/{{ yparam2 }}/{{ plottype }}">Drive Speed</a>
|
|
||||||
{% else %}
|
|
||||||
<a class="button rosy small" href="/rowers/paidplans">Peak Force (Pro)</a>
|
|
||||||
<a class="button rosy small" href="/rowers/paidplans">Average Force (Pro)</a>
|
|
||||||
<a class="button rosy small" href="/rowers/paidplans">Drive Length (Pro)</a>
|
|
||||||
<a class="button rosy small" href="/rowers/paidplans">Work per Stroke (Pro)</a>
|
|
||||||
<a class="button rosy small" href="/rowers/paidplans">Drive Speed (Pro)</a>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="grid_2 dropdown omega">
|
|
||||||
<button class="grid_2 alpha button blue small dropbtn">Right</button>
|
|
||||||
<div class="dropdown-content">
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ id }}/flexchart/{{ xparam }}/{{ yparam1 }}/hr/{{ plottype }}">HR</a>
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ id }}/flexchart/{{ xparam }}/{{ yparam1 }}/spm/{{ plottype }}">SPM</a>
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ id }}/flexchart/{{ xparam }}/{{ yparam1 }}/power/{{ plottype }}">Power</a>
|
|
||||||
{% if promember %}
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ id }}/flexchart/{{ xparam }}/{{ yparam1 }}/peakforce/{{ plottype }}">Peak Force</a>
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ id }}/flexchart/{{ xparam }}/{{ yparam1 }}/averageforce/{{ plottype }}">Average Force</a>
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ id }}/flexchart/{{ xparam }}/{{ yparam1 }}/drivelength/{{ plottype }}">Drive Length</a>
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ id }}/flexchart/{{ xparam }}/{{ yparam1 }}/driveenergy/{{ plottype }}">Work per Stroke</a>
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ id }}/flexchart/{{ xparam }}/{{ yparam1 }}/drivespeed/{{ plottype }}">Drive Speed</a>
|
|
||||||
{% else %}
|
|
||||||
<a class="button rosy small" href="/rowers/paidplans">Peak Force (Pro)</a>
|
|
||||||
<a class="button rosy small" href="/rowers/paidplans">Average Force (Pro)</a>
|
|
||||||
<a class="button rosy small" href="/rowers/paidplans">Drive Length (Pro)</a>
|
|
||||||
<a class="button rosy small" href="/rowers/paidplans">Work per Stroke (Pro)</a>
|
|
||||||
<a class="button rosy small" href="/rowers/paidplans">Drive Speed (Pro)</a>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ id }}/flexchart/{{ xparam }}/{{ yparam1 }}/None/{{ plottype }}">None</a>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="y-axis" class="grid_6 omega">
|
|
||||||
<div class="grid_2 alpha tooltip">
|
|
||||||
<form enctype="multipart/form-data" action="{{ formloc }}" method="post">
|
|
||||||
{% csrf_token %}
|
|
||||||
{% if workstrokesonly %}
|
|
||||||
<input type="hidden" name="workstrokesonly" value="True">
|
|
||||||
{% else %}
|
|
||||||
<input class="grid_2 alpha button blue small" type="hidden" name="workstrokesonly" value="False">
|
|
||||||
{% endif %}
|
|
||||||
<input class="grid_2 alpha button blue small" value="Toggle Work Strokes" type="Submit">
|
|
||||||
</form>
|
|
||||||
<span class="tooltiptext">If your data source allows, this will show or hide strokes taken during rest intervals.</span>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2">
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ id }}/flexchart/{{ xparam }}/{{ yparam1 }}/{{ yparam2 }}/line">Line Plot</a>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2 omega">
|
|
||||||
<a class="button blue small" href="/rowers/workout/{{ id }}/flexchart/{{ xparam }}/{{ yparam1 }}/{{ yparam2 }}/scatter">Scatter Plot</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="theplot" class="grid_12 alpha flexplot">
|
|
||||||
|
|
||||||
|
|
||||||
{{ the_div|safe }}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="thewidgets" class="grid_12 alpha">
|
|
||||||
|
|
||||||
|
|
||||||
{{ widgetdiv1|safe }}
|
|
||||||
{{ widgetdiv2|safe }}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
{% endlocaltime %}
|
|
||||||
@@ -11,8 +11,8 @@
|
|||||||
{{ js_res | safe }}
|
{{ js_res | safe }}
|
||||||
{{ css_res| safe }}
|
{{ css_res| safe }}
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
|
||||||
<script type="text/javascript" src="/static/js/bokeh-widgets-0.12.3.min.js"></script>
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-widgets-1.0.4.min.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
<script async="true" type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -60,17 +60,12 @@
|
|||||||
|
|
||||||
|
|
||||||
<div id="id_css_res">
|
<div id="id_css_res">
|
||||||
<link rel="stylesheet" href="/static/css/bokeh-0.12.3.min.css" type="text/css" />
|
<link rel="stylesheet" href="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.css" type="text/css" />
|
||||||
<link rel="stylesheet" href="/static/css/bokeh-widgets-0.12.3.min.css" type="text/css" />
|
<link rel="stylesheet" href="http://cdn.pydata.org/bokeh/release/bokeh-widgets-1.0.4.min.css" type="text/css" />
|
||||||
</div>
|
</div>
|
||||||
<div id="id_js_res">
|
<div id="id_js_res">
|
||||||
<script
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
|
||||||
type="text/javascript" src="/static/js/bokeh-0.12.3.min.js">
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-widgets-1.0.4.min.js"></script>
|
||||||
</script>
|
|
||||||
<script
|
|
||||||
type="text/javascript" src="/static/js/bokeh-widgets-0.12.3.min.js">
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
|
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
<script async="true" type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
<script async="true" type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
<script async="true" type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
<script async="true" type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
<script async="true" type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -138,7 +138,7 @@
|
|||||||
<div id="advancedplots" class="grid_6 omega">
|
<div id="advancedplots" class="grid_6 omega">
|
||||||
<div class="grid_6 alpha">
|
<div class="grid_6 alpha">
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
<script async="true" type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
<script async="true" type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
<script async="true" type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
<script async="true" type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
</li>
|
</li>
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
<script async="true" type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
<img src="/static/img/rivercurrent.jpg" width="400">
|
<img src="/static/img/rivercurrent.jpg" width="400">
|
||||||
</li>
|
</li>
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
<script async="true" type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -62,7 +62,7 @@
|
|||||||
</form>
|
</form>
|
||||||
</li>
|
</li>
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
<script async="true" type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,54 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
{% load staticfiles %}
|
|
||||||
{% load rowerfilters %}
|
|
||||||
|
|
||||||
{% block title %} Flexible Plot {% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
{{ js_res | safe }}
|
|
||||||
{{ css_res| safe }}
|
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
|
||||||
<script type="text/javascript" src="/static/js/bokeh-widgets-0.12.3.min.js"></script>
|
|
||||||
<script async="true" type="text/javascript">
|
|
||||||
Bokeh.set_log_level("info");
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{{ the_script |safe }}
|
|
||||||
|
|
||||||
<style>
|
|
||||||
/* Need this to get the page in "desktop mode"; not having an infinite height.*/
|
|
||||||
html, body {height: 100%; margin:5px;}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div id="navigation" class="grid_12 alpha">
|
|
||||||
{% if user.is_authenticated and mayedit %}
|
|
||||||
<div class="grid_2 alpha">
|
|
||||||
<p>
|
|
||||||
<a class="button gray small" href="/rowers/workout/{{ id }}/edit">Edit Workout</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="grid_2 suffix_8 omega">
|
|
||||||
<p>
|
|
||||||
<a class="button gray small" href="/rowers/workout/{{ id }}/advanced">Advanced Edit</a>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<p> </p>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="theplot" class="grid_12 alpha">
|
|
||||||
|
|
||||||
|
|
||||||
{{ the_div|safe }}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
</li>
|
</li>
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
<script async="true" type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
{{ workout.date }} - {{ workout.distance }}m - {{ workout.duration |durationprint:"%H:%M:%S.%f" }}{% endblock %}
|
{{ workout.date }} - {{ workout.distance }}m - {{ workout.duration |durationprint:"%H:%M:%S.%f" }}{% endblock %}
|
||||||
|
|
||||||
{% block meta %}
|
{% block meta %}
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
<script async="true" type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -86,7 +86,7 @@
|
|||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
<script async="true" type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ $('#id_workouttype').change();
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% if mapdiv %}
|
{% if mapdiv %}
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
<script async="true" type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -121,7 +121,7 @@
|
|||||||
</li>
|
</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
<script type="text/javascript" src="/static/js/bokeh-0.12.3.min.js"></script>
|
<script src="http://cdn.pydata.org/bokeh/release/bokeh-1.0.4.min.js"></script>
|
||||||
<script async="true" type="text/javascript">
|
<script async="true" type="text/javascript">
|
||||||
Bokeh.set_log_level("info");
|
Bokeh.set_log_level("info");
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -16,11 +16,12 @@ class TestErrorPages(TestCase):
|
|||||||
factory = RequestFactory()
|
factory = RequestFactory()
|
||||||
request = factory.get('/')
|
request = factory.get('/')
|
||||||
response = error404_view(request)
|
response = error404_view(request)
|
||||||
|
|
||||||
self.assertEqual(response.status_code, 404)
|
self.assertEqual(response.status_code, 404)
|
||||||
self.assertIn('404 Page not found', unicode(response))
|
self.assertIn('404 Page not found', str(response.content))
|
||||||
response = error500_view(request)
|
response = error500_view(request)
|
||||||
self.assertEqual(response.status_code, 500)
|
self.assertEqual(response.status_code, 500)
|
||||||
self.assertIn('500 Internal Server Error', unicode(response))
|
self.assertIn('500 Internal Server Error', str(response.content))
|
||||||
|
|
||||||
response = error400_view(request)
|
response = error400_view(request)
|
||||||
self.assertEqual(response.status_code, 400)
|
self.assertEqual(response.status_code, 400)
|
||||||
|
|||||||
BIN
Binary file not shown.
@@ -5,6 +5,8 @@ from __future__ import unicode_literals
|
|||||||
from __future__ import unicode_literals, absolute_import
|
from __future__ import unicode_literals, absolute_import
|
||||||
from rowers.imports import *
|
from rowers.imports import *
|
||||||
|
|
||||||
|
import numpy
|
||||||
|
|
||||||
import rowers.mytypes as mytypes
|
import rowers.mytypes as mytypes
|
||||||
from rowers.mytypes import otwtypes
|
from rowers.mytypes import otwtypes
|
||||||
|
|
||||||
@@ -305,6 +307,11 @@ def get_userid(access_token):
|
|||||||
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
def default(o):
|
||||||
|
if isinstance(o, numpy.int64): return int(o)
|
||||||
|
raise TypeError
|
||||||
|
|
||||||
|
|
||||||
def workout_ua_upload(user,w):
|
def workout_ua_upload(user,w):
|
||||||
message = "Uploading to MapMyFitness"
|
message = "Uploading to MapMyFitness"
|
||||||
uaid = 0
|
uaid = 0
|
||||||
@@ -331,7 +338,7 @@ def workout_ua_upload(user,w):
|
|||||||
}
|
}
|
||||||
|
|
||||||
url = "https://api.ua.com/v7.1/workout/"
|
url = "https://api.ua.com/v7.1/workout/"
|
||||||
response = requests.post(url,headers=headers,data=json.dumps(data))
|
response = requests.post(url,headers=headers,data=json.dumps(data,default=default))
|
||||||
|
|
||||||
# check for duplicate error first
|
# check for duplicate error first
|
||||||
if (response.status_code == 409 ):
|
if (response.status_code == 409 ):
|
||||||
|
|||||||
@@ -44,6 +44,11 @@ from rowers.utils import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
def cleanbody(body):
|
def cleanbody(body):
|
||||||
|
try:
|
||||||
|
body = body.decode('utf-8')
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
regex = r".*---\n([\s\S]*?)\.\.\..*"
|
regex = r".*---\n([\s\S]*?)\.\.\..*"
|
||||||
matches = re.finditer(regex,body)
|
matches = re.finditer(regex,body)
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,12 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
from rowers.views.statements import *
|
from rowers.views.statements import *
|
||||||
|
|
||||||
|
import numpy
|
||||||
|
|
||||||
|
def default(o):
|
||||||
|
if isinstance(o, numpy.int64): return int(o)
|
||||||
|
raise TypeError
|
||||||
|
|
||||||
|
|
||||||
# Send workout to TP
|
# Send workout to TP
|
||||||
@login_required()
|
@login_required()
|
||||||
@@ -228,7 +234,7 @@ def workout_runkeeper_upload_view(request,id=0):
|
|||||||
'Content-Length':'nnn'}
|
'Content-Length':'nnn'}
|
||||||
|
|
||||||
url = "https://api.runkeeper.com/fitnessActivities"
|
url = "https://api.runkeeper.com/fitnessActivities"
|
||||||
response = requests.post(url,headers=headers,data=json.dumps(data))
|
response = requests.post(url,headers=headers,data=json.dumps(data,default=default))
|
||||||
|
|
||||||
# check for duplicate error first
|
# check for duplicate error first
|
||||||
if (response.status_code == 409 ):
|
if (response.status_code == 409 ):
|
||||||
@@ -293,7 +299,7 @@ def workout_underarmour_upload_view(request,id=0):
|
|||||||
}
|
}
|
||||||
|
|
||||||
url = "https://api.ua.com/v7.1/workout/"
|
url = "https://api.ua.com/v7.1/workout/"
|
||||||
response = requests.post(url,headers=headers,data=json.dumps(data))
|
response = requests.post(url,headers=headers,data=json.dumps(data,default=default))
|
||||||
|
|
||||||
|
|
||||||
# check for duplicate error first
|
# check for duplicate error first
|
||||||
@@ -356,7 +362,7 @@ def workout_sporttracks_upload_view(request,id=0):
|
|||||||
'Content-Type': 'application/json'}
|
'Content-Type': 'application/json'}
|
||||||
|
|
||||||
url = "https://api.sporttracks.mobi/api/v2/fitnessActivities.json"
|
url = "https://api.sporttracks.mobi/api/v2/fitnessActivities.json"
|
||||||
response = requests.post(url,headers=headers,data=json.dumps(data))
|
response = requests.post(url,headers=headers,data=json.dumps(data,default=default))
|
||||||
|
|
||||||
|
|
||||||
# check for duplicate error first
|
# check for duplicate error first
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ import isodate
|
|||||||
import re
|
import re
|
||||||
import cgi
|
import cgi
|
||||||
from icalendar import Calendar, Event
|
from icalendar import Calendar, Event
|
||||||
|
|
||||||
|
from functools import reduce
|
||||||
|
|
||||||
import rowers.braintreestuff as braintreestuff
|
import rowers.braintreestuff as braintreestuff
|
||||||
import rowers.payments as payments
|
import rowers.payments as payments
|
||||||
from rowers.opaque import encoder
|
from rowers.opaque import encoder
|
||||||
@@ -502,7 +505,7 @@ def remove_asynctask(request,id):
|
|||||||
def get_job_result(jobid):
|
def get_job_result(jobid):
|
||||||
if settings.TESTING:
|
if settings.TESTING:
|
||||||
return None
|
return None
|
||||||
elif settings.DEBUG:
|
elif settings.CELERY:
|
||||||
result = celery_result.AsyncResult(jobid).result
|
result = celery_result.AsyncResult(jobid).result
|
||||||
else:
|
else:
|
||||||
running_job_ids = rq_registry.get_job_ids()
|
running_job_ids = rq_registry.get_job_ids()
|
||||||
@@ -541,7 +544,7 @@ def get_job_status(jobid):
|
|||||||
'started_at':None,
|
'started_at':None,
|
||||||
}
|
}
|
||||||
return summary
|
return summary
|
||||||
elif settings.DEBUG:
|
elif settings.CELERY:
|
||||||
job = celery_result.AsyncResult(jobid)
|
job = celery_result.AsyncResult(jobid)
|
||||||
jobresult = job.result
|
jobresult = job.result
|
||||||
|
|
||||||
@@ -592,7 +595,7 @@ def get_job_status(jobid):
|
|||||||
return summary
|
return summary
|
||||||
|
|
||||||
def kill_async_job(request,id='aap'):
|
def kill_async_job(request,id='aap'):
|
||||||
if settings.DEBUG:
|
if settings.CELERY:
|
||||||
job = celery_result.AsyncResult(id)
|
job = celery_result.AsyncResult(id)
|
||||||
job.revoke()
|
job.revoke()
|
||||||
else:
|
else:
|
||||||
@@ -734,7 +737,7 @@ def get_stored_tasks_status(request):
|
|||||||
if finished:
|
if finished:
|
||||||
cache.set(id,100)
|
cache.set(id,100)
|
||||||
progress = 100
|
progress = 100
|
||||||
elif cached_progress>0:
|
elif cached_progress is not None and cached_progress>0:
|
||||||
progress = cached_progress
|
progress = cached_progress
|
||||||
else:
|
else:
|
||||||
progress = 0
|
progress = 0
|
||||||
|
|||||||
@@ -4595,7 +4595,7 @@ def workout_split_view(request,id=0):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
qdict = {'q':rowname}
|
qdict = {'q':rowname}
|
||||||
url+='?'+urllib.urlencode(qdict)
|
url+='?'+urllib.parse.urlencode(qdict)
|
||||||
|
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@
|
|||||||
<link rel="stylesheet" type="text/css" href="/static/admin/css/widgets.css"/>
|
<link rel="stylesheet" type="text/css" href="/static/admin/css/widgets.css"/>
|
||||||
|
|
||||||
<link rel="stylesheet" href="/static/css/resetnew.css" />
|
<link rel="stylesheet" href="/static/css/resetnew.css" />
|
||||||
<link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-9ralMzdK1QYsk4yBY680hmsb4/hJ98xK3w0TIaJ3ll4POWpWUYaA2bRjGGujGT8w" crossorigin="anonymous">
|
<link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-6jHF7Z3XI3fF4XZixAuSu0gGKrXwoX/w3uFPxC56OtjChio7wtTGJWRW53Nhx6Ev" crossorigin="anonymous">
|
||||||
<link rel="stylesheet" href="/static/css/styles2.css">
|
<link rel="stylesheet" href="/static/css/styles2.css">
|
||||||
<link rel="stylesheet" href="/static/css/text2.css" />
|
<link rel="stylesheet" href="/static/css/text2.css" />
|
||||||
<link rel="stylesheet" href="/static/css/rowsandall2.css" />
|
<link rel="stylesheet" href="/static/css/rowsandall2.css" />
|
||||||
|
|||||||
@@ -56,7 +56,7 @@
|
|||||||
<link rel="stylesheet" type="text/css" href="/static/admin/css/widgets.css"/>
|
<link rel="stylesheet" type="text/css" href="/static/admin/css/widgets.css"/>
|
||||||
|
|
||||||
<link rel="stylesheet" href="/static/css/resetnew.css" />
|
<link rel="stylesheet" href="/static/css/resetnew.css" />
|
||||||
<link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.3.1/css/all.css" integrity="sha384-9ralMzdK1QYsk4yBY680hmsb4/hJ98xK3w0TIaJ3ll4POWpWUYaA2bRjGGujGT8w" crossorigin="anonymous">
|
<link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-6jHF7Z3XI3fF4XZixAuSu0gGKrXwoX/w3uFPxC56OtjChio7wtTGJWRW53Nhx6Ev" crossorigin="anonymous">
|
||||||
<link rel="stylesheet" href="/static/css/frontstyles.css">
|
<link rel="stylesheet" href="/static/css/frontstyles.css">
|
||||||
<link rel="stylesheet" href="/static/css/text2.css" />
|
<link rel="stylesheet" href="/static/css/text2.css" />
|
||||||
<link rel="stylesheet" href="/static/css/rowsandall2.css" />
|
<link rel="stylesheet" href="/static/css/rowsandall2.css" />
|
||||||
|
|||||||
Reference in New Issue
Block a user