Merge branch 'develop' into feature/django2
This commit is contained in:
192
requirements_win.txt
Normal file
192
requirements_win.txt
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
amqp==2.4.2
|
||||||
|
apipkg==1.5
|
||||||
|
appdirs==1.4.3
|
||||||
|
arcgis==1.6.0
|
||||||
|
arrow==0.13.1
|
||||||
|
asn1crypto==0.24.0
|
||||||
|
atomicwrites==1.3.0
|
||||||
|
attrs==19.1.0
|
||||||
|
backcall==0.1.0
|
||||||
|
beautifulsoup4==4.7.1
|
||||||
|
billiard==3.5.0.5
|
||||||
|
bleach==3.1.0
|
||||||
|
bokeh==1.0.4
|
||||||
|
boto==2.49.0
|
||||||
|
braintree==3.51.0
|
||||||
|
cairocffi==1.0.2
|
||||||
|
celery==4.2.2
|
||||||
|
certifi==2019.3.9
|
||||||
|
cffi==1.12.2
|
||||||
|
chardet==3.0.4
|
||||||
|
Click==7.0
|
||||||
|
colorama==0.4.1
|
||||||
|
colorclass==2.2.0
|
||||||
|
cookies==2.2.1
|
||||||
|
coreapi==2.3.3
|
||||||
|
coreschema==0.0.4
|
||||||
|
coverage==4.5.3
|
||||||
|
cryptography==2.6.1
|
||||||
|
cycler==0.10.0
|
||||||
|
dask==1.1.4
|
||||||
|
decorator==4.4.0
|
||||||
|
defusedxml==0.5.0
|
||||||
|
Django==1.9.5
|
||||||
|
django-analytical==2.5.0
|
||||||
|
django-async-messages==0.3.1
|
||||||
|
django-braces==1.13.0
|
||||||
|
django-classy-tags==0.8.0
|
||||||
|
django-cookie-law==2.0.1
|
||||||
|
django-cors-headers==2.4.0
|
||||||
|
django-countries==5.3.3
|
||||||
|
django-datetime-widget==0.9.3
|
||||||
|
django-debug-toolbar==1.4
|
||||||
|
django-extensions==2.1.6
|
||||||
|
django-htmlmin==0.10.0
|
||||||
|
django-leaflet==0.24.0
|
||||||
|
django-mailbox==4.7.1
|
||||||
|
django-oauth-toolkit==0.10.0
|
||||||
|
django-oauth2-provider==0.2.6.1
|
||||||
|
django-rest-framework==0.1.0
|
||||||
|
django-rest-swagger==2.2.0
|
||||||
|
django-rq==1.3.0
|
||||||
|
django-rq-dashboard==0.3.3
|
||||||
|
django-ses==0.8.10
|
||||||
|
django-shell-plus==1.1.7
|
||||||
|
django-social-share==1.3.2
|
||||||
|
django-suit==0.2.26
|
||||||
|
django-suit-rq==1.0.1
|
||||||
|
django-tz-detect==0.2.9
|
||||||
|
djangorestframework==3.5.4
|
||||||
|
docopt==0.6.2
|
||||||
|
docutils==0.14
|
||||||
|
entrypoints==0.3
|
||||||
|
execnet==1.5.0
|
||||||
|
factory-boy==2.11.1
|
||||||
|
Faker==1.0.4
|
||||||
|
fitparse==1.1.0
|
||||||
|
future==0.17.1
|
||||||
|
GDAL==2.3.3
|
||||||
|
geocoder==1.38.1
|
||||||
|
holoviews==1.11.3
|
||||||
|
html5lib==1.0.1
|
||||||
|
htmlmin==0.1.12
|
||||||
|
HTMLParser==0.0.2
|
||||||
|
httplib2==0.12.1
|
||||||
|
icalendar==4.0.3
|
||||||
|
idna==2.8
|
||||||
|
image==1.5.27
|
||||||
|
importlib-resources==1.0.2
|
||||||
|
ipykernel==5.1.0
|
||||||
|
ipython==7.3.0
|
||||||
|
ipython-genutils==0.2.0
|
||||||
|
ipywidgets==7.4.2
|
||||||
|
iso8601==0.1.12
|
||||||
|
isodate==0.6.0
|
||||||
|
itypes==1.1.0
|
||||||
|
jedi==0.13.3
|
||||||
|
jeepney==0.4
|
||||||
|
Jinja2==2.10
|
||||||
|
jsonschema==3.0.1
|
||||||
|
jupyter==1.0.0
|
||||||
|
jupyter-client==5.2.4
|
||||||
|
jupyter-console==6.0.0
|
||||||
|
jupyter-core==4.4.0
|
||||||
|
jupyterlab==0.35.4
|
||||||
|
jupyterlab-server==0.2.0
|
||||||
|
keyring==18.0.0
|
||||||
|
kiwisolver==1.0.1
|
||||||
|
kombu==4.3.0
|
||||||
|
lxml==4.3.2
|
||||||
|
Markdown==3.0.1
|
||||||
|
MarkupSafe==1.1.1
|
||||||
|
matplotlib==3.0.3
|
||||||
|
MiniMockTest==0.5
|
||||||
|
mistune==0.8.4
|
||||||
|
mock==2.0.0
|
||||||
|
more-itertools==6.0.0
|
||||||
|
mpld3==0.3
|
||||||
|
nbconvert==5.4.1
|
||||||
|
nbformat==4.4.0
|
||||||
|
nose==1.3.7
|
||||||
|
nose-parameterized==0.6.0
|
||||||
|
notebook==5.7.6
|
||||||
|
numpy==1.16.2
|
||||||
|
oauth2==1.9.0.post1
|
||||||
|
oauthlib==1.0.3
|
||||||
|
openapi-codec==1.3.2
|
||||||
|
packaging==19.0
|
||||||
|
pandas==0.24.2
|
||||||
|
pandocfilters==1.4.2
|
||||||
|
param==1.8.2
|
||||||
|
parso==0.3.4
|
||||||
|
pathspec==0.5.9
|
||||||
|
pbr==5.1.3
|
||||||
|
pexpect==4.6.0
|
||||||
|
pickleshare==0.7.5
|
||||||
|
Pillow==5.4.1
|
||||||
|
pip-upgrader==1.4.6
|
||||||
|
pluggy==0.9.0
|
||||||
|
prometheus-client==0.6.0
|
||||||
|
prompt-toolkit==2.0.9
|
||||||
|
ptyprocess==0.6.0
|
||||||
|
py==1.8.0
|
||||||
|
pycparser==2.19
|
||||||
|
Pygments==2.3.1
|
||||||
|
pyparsing==2.3.1
|
||||||
|
pyrsistent==0.14.11
|
||||||
|
pyshp==2.1.0
|
||||||
|
pytest==4.3.1
|
||||||
|
pytest-django==3.4.8
|
||||||
|
pytest-forked==1.0.2
|
||||||
|
pytest-runner==4.4
|
||||||
|
pytest-sugar==0.9.2
|
||||||
|
pytest-xdist==1.27.0
|
||||||
|
python-dateutil==2.8.0
|
||||||
|
python-memcached==1.59
|
||||||
|
python-twitter==3.5
|
||||||
|
pytz==2018.9
|
||||||
|
pyviz-comms==0.7.1
|
||||||
|
pywin32-ctypes==0.2.0
|
||||||
|
pywinpty==0.5.5
|
||||||
|
PyYAML==5.1
|
||||||
|
pyzmq==18.0.1
|
||||||
|
qtconsole==4.4.3
|
||||||
|
ratelim==0.1.6
|
||||||
|
redis==3.2.1
|
||||||
|
requests==2.21.0
|
||||||
|
requests-oauthlib==1.2.0
|
||||||
|
rowingdata==2.2.3
|
||||||
|
rowingphysics==0.5.0
|
||||||
|
rq==0.13.0
|
||||||
|
scipy==1.2.1
|
||||||
|
SecretStorage==3.1.1
|
||||||
|
Send2Trash==1.5.0
|
||||||
|
shell==1.0.1
|
||||||
|
shortuuid==0.5.0
|
||||||
|
simplejson==3.16.0
|
||||||
|
six==1.12.0
|
||||||
|
soupsieve==1.8
|
||||||
|
SQLAlchemy==1.3.1
|
||||||
|
sqlparse==0.3.0
|
||||||
|
stravalib==0.10.2
|
||||||
|
termcolor==1.1.0
|
||||||
|
terminado==0.8.1
|
||||||
|
terminaltables==3.1.0
|
||||||
|
testpath==0.4.2
|
||||||
|
text-unidecode==1.2
|
||||||
|
timezonefinder==4.0.1
|
||||||
|
tornado==6.0.1
|
||||||
|
tqdm==4.31.1
|
||||||
|
traitlets==4.3.2
|
||||||
|
units==0.7
|
||||||
|
uritemplate==3.0.0
|
||||||
|
urllib3==1.24.1
|
||||||
|
VerbalExpressions==0.0.2
|
||||||
|
vine==1.3.0
|
||||||
|
wcwidth==0.1.7
|
||||||
|
webencodings==0.5.1
|
||||||
|
widgetsnbextension==3.4.2
|
||||||
|
winkerberos==0.7.0
|
||||||
|
xmltodict==0.12.0
|
||||||
|
yamjam==0.1.7
|
||||||
|
yamllint==1.15.0
|
||||||
@@ -108,9 +108,16 @@ def get_c2_workouts(rower):
|
|||||||
for item in res.json()['data']:
|
for item in res.json()['data']:
|
||||||
alldata[item['id']] = item
|
alldata[item['id']] = item
|
||||||
|
|
||||||
knownc2ids = uniqify([
|
knownc2ids = [
|
||||||
w.uploadedtoc2 for w in Workout.objects.filter(user=rower)
|
w.uploadedtoc2 for w in Workout.objects.filter(user=rower)
|
||||||
])
|
]
|
||||||
|
|
||||||
|
tombstones = [
|
||||||
|
t.uploadedtoc2 for t in TombStone.objects.filter(user=rower)
|
||||||
|
]
|
||||||
|
|
||||||
|
knownc2ids = uniqify(knownc2ids+tombstones)
|
||||||
|
|
||||||
newids = [c2id for c2id in c2ids if not c2id in knownc2ids]
|
newids = [c2id for c2id in c2ids if not c2id in knownc2ids]
|
||||||
|
|
||||||
for c2id in newids:
|
for c2id in newids:
|
||||||
|
|||||||
@@ -1270,6 +1270,7 @@ def new_workout_from_file(r, f2,
|
|||||||
message = None
|
message = None
|
||||||
try:
|
try:
|
||||||
fileformat = get_file_type(f2)
|
fileformat = get_file_type(f2)
|
||||||
|
print(fileformat,'aa')
|
||||||
except IOError:
|
except IOError:
|
||||||
os.remove(f2)
|
os.remove(f2)
|
||||||
message = "Rowsandall could not process this file. The extension is supported but the file seems corrupt. Contact info@rowsandall.com if you think this is incorrect."
|
message = "Rowsandall could not process this file. The extension is supported but the file seems corrupt. Contact info@rowsandall.com if you think this is incorrect."
|
||||||
@@ -1327,7 +1328,13 @@ def new_workout_from_file(r, f2,
|
|||||||
# worth supporting
|
# worth supporting
|
||||||
if fileformat == 'unknown':
|
if fileformat == 'unknown':
|
||||||
message = "We couldn't recognize the file type"
|
message = "We couldn't recognize the file type"
|
||||||
f4 = f2[:-5]+'a'+f2[-5:]
|
extension = os.path.splitext(f2)[1]
|
||||||
|
filename = os.path.splitext(f2)[0]
|
||||||
|
if extension == '.gz':
|
||||||
|
filename = os.path.splitext(filename)[0]
|
||||||
|
extension2 = os.path.splitext(filename)[1]+extension
|
||||||
|
extension = extension2
|
||||||
|
f4 = filename+'a'+extension
|
||||||
copyfile(f2,f4)
|
copyfile(f2,f4)
|
||||||
job = myqueue(queuehigh,
|
job = myqueue(queuehigh,
|
||||||
handle_sendemail_unrecognized,
|
handle_sendemail_unrecognized,
|
||||||
@@ -1335,6 +1342,9 @@ def new_workout_from_file(r, f2,
|
|||||||
r.user.email)
|
r.user.email)
|
||||||
|
|
||||||
return (0, message, f2)
|
return (0, message, f2)
|
||||||
|
if fileformat == 'att':
|
||||||
|
# email attachment which can safely be ignored
|
||||||
|
return (0, '', f2)
|
||||||
|
|
||||||
# handle non-Painsled by converting it to painsled compatible CSV
|
# handle non-Painsled by converting it to painsled compatible CSV
|
||||||
if (fileformat != 'csv'):
|
if (fileformat != 'csv'):
|
||||||
|
|||||||
@@ -63,8 +63,8 @@ class LoginForm(forms.Form):
|
|||||||
class SearchForm(forms.Form):
|
class SearchForm(forms.Form):
|
||||||
q = forms.CharField(max_length=255,required=False,
|
q = forms.CharField(max_length=255,required=False,
|
||||||
widget=forms.TextInput(
|
widget=forms.TextInput(
|
||||||
attrs={'placeholder': 'Search'}),
|
attrs={'placeholder': 'keyword or leave empty'}),
|
||||||
label='Search')
|
label='Filter by Keyword')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3228,6 +3228,13 @@ def interactive_flex_chart2(id=0,promember=0,
|
|||||||
text_color='black',
|
text_color='black',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
sliderlabel = Label(x=10,y=470,x_units='screen',y_units='screen',
|
||||||
|
text='',
|
||||||
|
background_fill_alpha=0.7,
|
||||||
|
background_fill_color='white',
|
||||||
|
text_color='black',text_font_size='10pt',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
if (xparam != 'time') and (xparam != 'distance') and (xparam != 'cumdist'):
|
if (xparam != 'time') and (xparam != 'distance') and (xparam != 'cumdist'):
|
||||||
plot.add_layout(x1means)
|
plot.add_layout(x1means)
|
||||||
@@ -3236,6 +3243,7 @@ def interactive_flex_chart2(id=0,promember=0,
|
|||||||
|
|
||||||
plot.add_layout(y1means)
|
plot.add_layout(y1means)
|
||||||
plot.add_layout(annolabel)
|
plot.add_layout(annolabel)
|
||||||
|
plot.add_layout(sliderlabel)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
yaxlabel = axlabels[yparam1]
|
yaxlabel = axlabels[yparam1]
|
||||||
@@ -3381,6 +3389,7 @@ def interactive_flex_chart2(id=0,promember=0,
|
|||||||
y2label=y2label,
|
y2label=y2label,
|
||||||
xlabel=xlabel,
|
xlabel=xlabel,
|
||||||
annolabel=annolabel,
|
annolabel=annolabel,
|
||||||
|
sliderlabel=sliderlabel,
|
||||||
y2means=y2means,
|
y2means=y2means,
|
||||||
), code="""
|
), code="""
|
||||||
var data = source.data
|
var data = source.data
|
||||||
@@ -3412,6 +3421,11 @@ def interactive_flex_chart2(id=0,promember=0,
|
|||||||
var maxdist = maxdist.value
|
var maxdist = maxdist.value
|
||||||
var minwork = minwork.value
|
var minwork = minwork.value
|
||||||
var maxwork = maxwork.value
|
var maxwork = maxwork.value
|
||||||
|
|
||||||
|
sliderlabel.text = 'SPM: '+minspm.toFixed(0)+'-'+maxspm.toFixed(0)
|
||||||
|
sliderlabel.text += ', Dist: '+mindist.toFixed(0)+'-'+maxdist.toFixed(0)
|
||||||
|
sliderlabel.text += ', WpS: '+minwork.toFixed(0)+'-'+maxwork.toFixed(0)
|
||||||
|
|
||||||
var xm = 0
|
var xm = 0
|
||||||
var ym1 = 0
|
var ym1 = 0
|
||||||
var ym2 = 0
|
var ym2 = 0
|
||||||
|
|||||||
@@ -137,6 +137,8 @@ def make_new_workout_from_email(rower, datafile, name, cntr=0,testing=False):
|
|||||||
|
|
||||||
|
|
||||||
# handle non-Painsled
|
# handle non-Painsled
|
||||||
|
if fileformat == 'att':
|
||||||
|
return 0
|
||||||
if fileformat != 'csv':
|
if fileformat != 'csv':
|
||||||
filename_mediadir, summary, oarlength, inboard,fileformat = dataprep.handle_nonpainsled(
|
filename_mediadir, summary, oarlength, inboard,fileformat = dataprep.handle_nonpainsled(
|
||||||
'media/' + datafilename, fileformat, summary)
|
'media/' + datafilename, fileformat, summary)
|
||||||
|
|||||||
@@ -2506,7 +2506,6 @@ class PlannedSessionFormSmall(ModelForm):
|
|||||||
boattypes = mytypes.boattypes
|
boattypes = mytypes.boattypes
|
||||||
|
|
||||||
# Workout
|
# Workout
|
||||||
@python_2_unicode_compatible
|
|
||||||
class Workout(models.Model):
|
class Workout(models.Model):
|
||||||
workouttypes = mytypes.workouttypes
|
workouttypes = mytypes.workouttypes
|
||||||
workoutsources = mytypes.workoutsources
|
workoutsources = mytypes.workoutsources
|
||||||
@@ -2612,6 +2611,27 @@ class Workout(models.Model):
|
|||||||
|
|
||||||
return stri
|
return stri
|
||||||
|
|
||||||
|
class TombStone(models.Model):
|
||||||
|
user = models.ForeignKey(Rower,on_delete=models.CASCADE)
|
||||||
|
uploadedtoc2 = models.IntegerField(default=0)
|
||||||
|
uploadedtostrava = models.BigIntegerField(default=0)
|
||||||
|
uploadedtosporttracks = models.BigIntegerField(default=0)
|
||||||
|
uploadedtounderarmour = models.BigIntegerField(default=0)
|
||||||
|
uploadedtotp = models.BigIntegerField(default=0)
|
||||||
|
uploadedtorunkeeper = models.BigIntegerField(default=0)
|
||||||
|
|
||||||
|
@receiver(models.signals.pre_delete,sender=Workout)
|
||||||
|
def create_tombstone_on_delete(sender, instance, **kwargs):
|
||||||
|
t = TombStone(
|
||||||
|
user=instance.user,
|
||||||
|
uploadedtoc2 = instance.uploadedtoc2,
|
||||||
|
uploadedtostrava = instance.uploadedtostrava,
|
||||||
|
uploadedtounderarmour = instance.uploadedtounderarmour,
|
||||||
|
uploadedtotp = instance.uploadedtotp,
|
||||||
|
uploadedtorunkeeper = instance.uploadedtorunkeeper,
|
||||||
|
)
|
||||||
|
t.save()
|
||||||
|
|
||||||
# delete files belonging to workout instance
|
# delete files belonging to workout instance
|
||||||
# related GraphImage objects should be deleted automatically
|
# related GraphImage objects should be deleted automatically
|
||||||
@receiver(models.signals.post_delete,sender=Workout)
|
@receiver(models.signals.post_delete,sender=Workout)
|
||||||
|
|||||||
@@ -165,9 +165,15 @@ def get_strava_workouts(rower):
|
|||||||
w.uploadedtostrava = int(stravaid)
|
w.uploadedtostrava = int(stravaid)
|
||||||
w.save()
|
w.save()
|
||||||
|
|
||||||
knownstravaids = uniqify([
|
knownstravaids = [
|
||||||
w.uploadedtostrava for w in Workout.objects.filter(user=rower)
|
w.uploadedtostrava for w in Workout.objects.filter(user=rower)
|
||||||
])
|
]
|
||||||
|
|
||||||
|
tombstones = [
|
||||||
|
t.uploadedtostrava for t in TombStone.objects.filter(user=rower)
|
||||||
|
]
|
||||||
|
|
||||||
|
knownstravaids = uniqify(knownstravaids+tombstones)
|
||||||
|
|
||||||
newids = [stravaid for stravaid in stravaids if not stravaid in knownstravaids]
|
newids = [stravaid for stravaid in stravaids if not stravaid in knownstravaids]
|
||||||
|
|
||||||
|
|||||||
@@ -1026,7 +1026,7 @@ def handle_sendemail_breakthrough(workoutid, useremail,
|
|||||||
d = {
|
d = {
|
||||||
'first_name':userfirstname,
|
'first_name':userfirstname,
|
||||||
'siteurl':siteurl,
|
'siteurl':siteurl,
|
||||||
'workoutid':workoutid,
|
'workoutid':encoder.encode_hex(workoutid),
|
||||||
'btvalues':tablevalues,
|
'btvalues':tablevalues,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1071,7 +1071,7 @@ def handle_sendemail_hard(workoutid, useremail,
|
|||||||
d = {
|
d = {
|
||||||
'first_name':userfirstname,
|
'first_name':userfirstname,
|
||||||
'siteurl':siteurl,
|
'siteurl':siteurl,
|
||||||
'workoutid':workoutid,
|
'workoutid':encoder.encode_hex(workoutid),
|
||||||
'btvalues':tablevalues,
|
'btvalues':tablevalues,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1661,6 +1661,8 @@ def handle_makeplot(f1, f2, t, hrdata, plotnr, imagename,
|
|||||||
haspower = row.df[' Power (watts)'].mean() > 50
|
haspower = row.df[' Power (watts)'].mean() > 50
|
||||||
except TypeError:
|
except TypeError:
|
||||||
haspower = True
|
haspower = True
|
||||||
|
except KeyError:
|
||||||
|
haspower = False
|
||||||
|
|
||||||
nr_rows = len(row.df)
|
nr_rows = len(row.df)
|
||||||
if (plotnr in [1, 2, 4, 5, 8, 11, 9, 12]) and (nr_rows > 1200):
|
if (plotnr in [1, 2, 4, 5, 8, 11, 9, 12]) and (nr_rows > 1200):
|
||||||
|
|||||||
@@ -72,16 +72,13 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{% if rower.user %}
|
{% if rower.user %}
|
||||||
<h1>{{ rower.user.first_name }} Power Estimates</h1>
|
<h1>Power Progress for {{ rower.user.first_name }} </h1>
|
||||||
{% else %}
|
{% else %}
|
||||||
<h1>{{ user.first_name }} Power Estimates</h1>
|
<h1>Power Progress for {{ user.first_name }} </h1>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
<ul class="main-content">
|
<ul class="main-content">
|
||||||
<li class="grid_4">
|
|
||||||
{{ the_div|safe }}
|
|
||||||
</li>
|
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
<form enctype="multipart/form-data" action="/rowers/fitness-progress/user/{{ rower.user.id }}/" method="post">
|
<form enctype="multipart/form-data" action="/rowers/fitness-progress/user/{{ rower.user.id }}/" method="post">
|
||||||
<table>
|
<table>
|
||||||
@@ -92,6 +89,9 @@
|
|||||||
</form>
|
</form>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
|
<li class="grid_4">
|
||||||
|
{{ the_div|safe }}
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
<ul class="main-content">
|
<ul class="main-content">
|
||||||
<li class="grid_4">
|
<li class="grid_4">
|
||||||
<div id="theplot" class="flexplot" style="min-width:300px;">
|
<div id="theplot" class="flexplot">
|
||||||
{{ the_div|safe }}
|
{{ the_div|safe }}
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
@@ -51,8 +51,8 @@
|
|||||||
{{ optionsform.as_table }}
|
{{ optionsform.as_table }}
|
||||||
</table>
|
</table>
|
||||||
<p>
|
<p>
|
||||||
<input name="chartform" class="button green" type="submit"
|
<input name="chartform" type="submit"
|
||||||
value="Submit">
|
value="Update Chart">
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -69,26 +69,19 @@
|
|||||||
{{ the_div |safe }}
|
{{ the_div |safe }}
|
||||||
</li>
|
</li>
|
||||||
<li class="grid_2">
|
<li class="grid_2">
|
||||||
<p>
|
<p>Filter on date
|
||||||
<form enctype="multipart/form-data" method="post">
|
<form enctype="multipart/form-data" method="post">
|
||||||
<table>
|
<table>
|
||||||
{{ dateform.as_table }}
|
{{ dateform.as_table }}
|
||||||
</table>
|
</table>
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<input name='daterange' type="submit" value="Submit">
|
|
||||||
</form>
|
|
||||||
</p>
|
</p>
|
||||||
{% if team %}
|
<p>and keyword</p>
|
||||||
<p>
|
<p>
|
||||||
<form id="searchform" action="/rowers/list-workouts/team/{{ team.id }}/{{ startdate|date:"Y-m-d" }}/{{ enddate|date:"Y-m-d" }}/"
|
|
||||||
method="get" accept-charset="utf-8">
|
|
||||||
{% else %}
|
|
||||||
<form id="searchform" action="/rowers/list-workouts/{{ startdate|date:"Y-m-d" }}/{{ enddate|date:"Y-m-d" }}/"
|
|
||||||
method="get" accept-charset="utf-8">
|
|
||||||
{% endif %}
|
|
||||||
{{ searchform }}
|
{{ searchform }}
|
||||||
<input type="submit" value="GO">
|
</p>
|
||||||
</input>
|
<p>
|
||||||
|
<input name='daterange' type="submit" value="Select workouts">
|
||||||
</form>
|
</form>
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
|
|||||||
@@ -283,7 +283,7 @@ class URLTests(TestCase):
|
|||||||
for u in urls:
|
for u in urls:
|
||||||
if u not in tested and 'rowers' in u and 'http' not in u and 'authorize' not in u and 'import' not in u and 'logout' not in u:
|
if u not in tested and 'rowers' in u and 'http' not in u and 'authorize' not in u and 'import' not in u and 'logout' not in u:
|
||||||
response2 = self.c.get(u)
|
response2 = self.c.get(u)
|
||||||
if response2.status_code not in [200,302]:
|
if response2.status_code not in [200,302,301]:
|
||||||
print(len(tested))
|
print(len(tested))
|
||||||
print(response.templates[0].name)
|
print(response.templates[0].name)
|
||||||
print(url)
|
print(url)
|
||||||
@@ -291,7 +291,7 @@ class URLTests(TestCase):
|
|||||||
print(response2.status_code)
|
print(response2.status_code)
|
||||||
tested.append(u)
|
tested.append(u)
|
||||||
self.assertIn(response2.status_code,
|
self.assertIn(response2.status_code,
|
||||||
[200,302])
|
[200,302,301])
|
||||||
else:
|
else:
|
||||||
tested.append(u)
|
tested.append(u)
|
||||||
|
|
||||||
|
|||||||
3
rowers/tests/testdata/emails/ATT00001.txt
vendored
Normal file
3
rowers/tests/testdata/emails/ATT00001.txt
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
1589
rowers/tests/testdata/emails/RitmoTime_20190321_0805_Full-Workout.csv
vendored
Normal file
1589
rowers/tests/testdata/emails/RitmoTime_20190321_0805_Full-Workout.csv
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -611,11 +611,24 @@ def fitnessmetric_view(request,id=0,mode='rower',
|
|||||||
enddate=enddate,
|
enddate=enddate,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
breadcrumbs = [
|
||||||
|
{
|
||||||
|
'url':'/rowers/analysis',
|
||||||
|
'name':'Analysis'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'url':reverse('fitnessmetric_view'),
|
||||||
|
'name': 'Power Progress'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
return render(request,'fitnessmetric.html',
|
return render(request,'fitnessmetric.html',
|
||||||
{
|
{
|
||||||
'rower':therower,
|
'rower':therower,
|
||||||
'active':'nav-analysis',
|
'active':'nav-analysis',
|
||||||
'chartscript':script,
|
'chartscript':script,
|
||||||
|
'breadcrumbs':breadcrumbs,
|
||||||
'the_div':thediv,
|
'the_div':thediv,
|
||||||
'mode':mode,
|
'mode':mode,
|
||||||
'form':form,
|
'form':form,
|
||||||
|
|||||||
@@ -522,8 +522,10 @@ def rower_register_view(request):
|
|||||||
title='New User Sample Data',
|
title='New User Sample Data',
|
||||||
notes='This is an example workout to get you started')
|
notes='This is an example workout to get you started')
|
||||||
newworkoutid = response[0]
|
newworkoutid = response[0]
|
||||||
|
if newworkoutid:
|
||||||
w = Workout.objects.get(id=newworkoutid)
|
w = Workout.objects.get(id=newworkoutid)
|
||||||
w.startdatetime = timezone.now()
|
w.startdatetime = timezone.now()
|
||||||
|
w.date = timezone.now().date()
|
||||||
w.save()
|
w.save()
|
||||||
|
|
||||||
# Create and send email
|
# Create and send email
|
||||||
|
|||||||
@@ -1178,12 +1178,15 @@ def workouts_view(request,message='',successmessage='',
|
|||||||
startdate = datetime.datetime.combine(startdate,datetime.time())
|
startdate = datetime.datetime.combine(startdate,datetime.time())
|
||||||
enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59))
|
enddate = datetime.datetime.combine(enddate,datetime.time(23,59,59))
|
||||||
|
|
||||||
|
query = None
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
dateform = DateRangeForm(request.POST)
|
dateform = DateRangeForm(request.POST)
|
||||||
|
searchform = SearchForm(request.POST)
|
||||||
if dateform.is_valid():
|
if dateform.is_valid():
|
||||||
startdate = dateform.cleaned_data['startdate']
|
startdate = dateform.cleaned_data['startdate']
|
||||||
enddate = dateform.cleaned_data['enddate']
|
enddate = dateform.cleaned_data['enddate']
|
||||||
|
if searchform.is_valid():
|
||||||
|
query = searchform.cleaned_data['q']
|
||||||
else:
|
else:
|
||||||
dateform = DateRangeForm(initial={
|
dateform = DateRangeForm(initial={
|
||||||
'startdate':startdate,
|
'startdate':startdate,
|
||||||
@@ -1293,7 +1296,6 @@ def workouts_view(request,message='',successmessage='',
|
|||||||
for w in workoutsnohr:
|
for w in workoutsnohr:
|
||||||
res = dataprep.workout_trimp(w)
|
res = dataprep.workout_trimp(w)
|
||||||
|
|
||||||
query = request.GET.get('q')
|
|
||||||
if query:
|
if query:
|
||||||
query_list = query.split()
|
query_list = query.split()
|
||||||
workouts = workouts.filter(
|
workouts = workouts.filter(
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.yellow {
|
.yellow {
|
||||||
color: #cccc00;
|
color: #1c75bc;
|
||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
height: auto;
|
height: auto;
|
||||||
padding: 0px;
|
padding: 0px;
|
||||||
@@ -1005,6 +1005,7 @@ th.rotate > div > span {
|
|||||||
z-index: 10;
|
z-index: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
a.wh:link {
|
a.wh:link {
|
||||||
color: #e9e9e9;
|
color: #e9e9e9;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -564,28 +564,28 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
@media (min-height: 600px) {
|
@media only screen and (min-height: 600px) {
|
||||||
.maxheight {
|
.maxheight {
|
||||||
max-height: 450px;
|
max-height: 450px;
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-height: 600px) {
|
@media only screen and (min-height: 600px) {
|
||||||
.maxheight {
|
.maxheight {
|
||||||
max-height: 450px;
|
max-height: 450px;
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-height: 800px) {
|
@media only screen and (min-height: 800px) {
|
||||||
.maxheight {
|
.maxheight {
|
||||||
max-height: 600px;
|
max-height: 600px;
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-height: 1000px) {
|
@media only screen and (min-height: 1000px) {
|
||||||
.maxheight {
|
.maxheight {
|
||||||
max-height: 800px;
|
max-height: 800px;
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
@@ -593,7 +593,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
@media only screen and (max-width: 600px) {
|
||||||
nav a {
|
nav a {
|
||||||
font-size: 0px;
|
font-size: 0px;
|
||||||
}
|
}
|
||||||
@@ -601,9 +601,22 @@
|
|||||||
nav a i {
|
nav a i {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#theplot .bk-grid-column {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#theplot .bk-plot-layout {
|
||||||
|
position: auto;
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 450px) {
|
|
||||||
|
|
||||||
|
@media only screen and (min-width: 450px) {
|
||||||
.wrapper {
|
.wrapper {
|
||||||
grid-template-columns: 1fr 3fr;
|
grid-template-columns: 1fr 3fr;
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
@@ -648,7 +661,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
@media only screen and (min-width: 768px) {
|
||||||
.wrapper {
|
.wrapper {
|
||||||
grid-template-columns: 1fr 4fr 1fr;
|
grid-template-columns: 1fr 4fr 1fr;
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
@@ -727,7 +740,7 @@
|
|||||||
page-break-after: avoid;
|
page-break-after: avoid;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul, img {
|
ul, img, table {
|
||||||
page-break-inside: avoid;
|
page-break-inside: avoid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user