Private
Public Access
1
0

Merge branch 'release/v4.80'

This commit is contained in:
Sander Roosendaal
2017-11-02 18:32:03 +01:00
10 changed files with 204 additions and 54 deletions

View File

@@ -53,7 +53,7 @@ import sys
import utils
import datautils
from utils import lbstoN
from utils import lbstoN,myqueue
from timezonefinder import TimezoneFinder
@@ -847,52 +847,65 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower',
def handle_nonpainsled(f2, fileformat, summary=''):
oarlength = 2.89
inboard = 0.88
hasrecognized = False
# handle RowPro:
if (fileformat == 'rp'):
row = RowProParser(f2)
hasrecognized = True
# handle TCX
if (fileformat == 'tcx'):
row = TCXParser(f2)
hasrecognized = True
# handle Mystery
if (fileformat == 'mystery'):
row = MysteryParser(f2)
hasrecognized = True
# handle RowPerfect
if (fileformat == 'rowperfect3'):
row = RowPerfectParser(f2)
hasrecognized = True
# handle ErgData
if (fileformat == 'ergdata'):
row = ErgDataParser(f2)
hasrecognized = True
# handle CoxMate
if (fileformat == 'coxmate'):
row = CoxMateParser(f2)
hasrecognized = True
# handle Mike
if (fileformat == 'bcmike'):
row = BoatCoachAdvancedParser(f2)
hasrecognized = True
# handle BoatCoach
if (fileformat == 'boatcoach'):
row = BoatCoachParser(f2)
hasrecognized = True
# handle BoatCoach OTW
if (fileformat == 'boatcoachotw'):
row = BoatCoachOTWParser(f2)
hasrecognized = True
# handle painsled desktop
if (fileformat == 'painsleddesktop'):
row = painsledDesktopParser(f2)
hasrecognized = True
# handle speed coach GPS
if (fileformat == 'speedcoach'):
row = speedcoachParser(f2)
hasrecognized = True
# handle speed coach GPS 2
if (fileformat == 'speedcoach2'):
row = SpeedCoach2Parser(f2)
hasrecognized = True
try:
oarlength, inboard = get_empower_rigging(f2)
summary = row.allstats()
@@ -902,10 +915,12 @@ def handle_nonpainsled(f2, fileformat, summary=''):
# handle ErgStick
if (fileformat == 'ergstick'):
row = ErgStickParser(f2)
hasrecognized = True
# handle FIT
if (fileformat == 'fit'):
row = FITParser(f2)
hasrecognized = True
try:
s = fitsummarydata(f2)
s.setsummary()
@@ -913,6 +928,13 @@ def handle_nonpainsled(f2, fileformat, summary=''):
except:
pass
# Handle c2log
if (fileformat == 'c2log' or fileformat == 'rowprolog'):
return (0,0,0,0)
if not hasrecognized:
return (0,0,0,0)
f_to_be_deleted = f2
# should delete file
f2 = f2[:-4] + 'o.csv'
@@ -953,17 +975,12 @@ def new_workout_from_file(r, f2,
if len(fileformat) == 3 and fileformat[0] == 'zip':
f_to_be_deleted = f2
title = os.path.basename(f2)
if settings.DEBUG:
res = handle_zip_file.delay(
r.user.email, title, f2
)
else:
res = queuelow.enqueue(
handle_zip_file,
r.user.email,
title,
f2
res = myqueue(
queuelow,
handle_zip_file,
r.user.email,
title,
f2
)
return -1, message, f2
@@ -971,7 +988,7 @@ def new_workout_from_file(r, f2,
# Some people try to upload Concept2 logbook summaries
if fileformat == 'c2log':
os.remove(f2)
message = "This C2 logbook summary does not contain stroke data. Please download the Export Stroke Data file from the workout details on the C2 logbook."
message = "This summary does not contain stroke data. Use the files containing stroke by stroke data."
return (0, message, f2)
if fileformat == 'nostrokes':
@@ -1021,14 +1038,16 @@ def new_workout_from_file(r, f2,
return (0, message, '')
dosummary = (fileformat != 'fit')
id, message = save_workout_database(f2, r,
workouttype=workouttype,
makeprivate=makeprivate,
dosummary=dosummary,
workoutsource=fileformat,
summary=summary,
inboard=inboard, oarlength=oarlength,
title=title)
id, message = save_workout_database(
f2, r,
workouttype=workouttype,
makeprivate=makeprivate,
dosummary=dosummary,
workoutsource=fileformat,
summary=summary,
inboard=inboard, oarlength=oarlength,
title=title
)
return (id, message, f2)

View File

@@ -57,8 +57,15 @@ class DocumentsForm(forms.Form):
notes = forms.CharField(required=False,
widget=forms.Textarea)
offline = forms.BooleanField(initial=False,required=False,
label='Process in Background')
class Meta:
fields = ['title','file','workouttype','fileformat']
fields = ['title','file','workouttype','fileformat','offline']
def __init__(self, *args, **kwargs):
from django.forms.widgets import HiddenInput
super(DocumentsForm, self).__init__(*args, **kwargs)
self.fields['offline'].widget = HiddenInput()
from utils import (
workflowleftpanel,workflowmiddlepanel,

View File

@@ -61,7 +61,7 @@ def longtask(aantal,jobid=None,debug=False,
return 1
def longtask2(aantal,jobid=None,debug=False):
def longtask2(aantal,jobid=None,debug=False,secret=''):
counter = 0
channel = 'tasks'
@@ -80,7 +80,8 @@ def longtask2(aantal,jobid=None,debug=False):
url = SITE_URL
url += "/rowers/record-progress/"
url += str(progress)+"/"+jobid
s = requests.get(url)
post_data = {"secret":secret}
s = requests.post(url, data=post_data)
if debug:
print url
print s

View File

@@ -115,6 +115,8 @@ def make_new_workout_from_email(rower, datafile, name, cntr=0):
if fileformat != 'csv':
filename_mediadir, summary, oarlength, inboard = dataprep.handle_nonpainsled(
'media/' + datafilename, fileformat, summary)
if not filename_mediadir:
return 0
else:
filename_mediadir = 'media/' + datafilename
inboard = 0.88

View File

@@ -4,8 +4,35 @@
{% block title %}File loading{% endblock %}
{% block meta %}
<script type='text/javascript'
src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js'>
</script>
<script type='text/javascript'
src='http://ajax.aspnetcdn.com/ajax/jquery.validate/1.14.0/jquery.validate.min.js'>
</script>
<script>
$(document).ready(function() {
$('#id_file').on('change', function(evt) {
var f = this.files[0];
console.log(f);
if (f.size > 4194304) {
alert("File Size must be smaller than 4 MB");
this.value = null;
}
if (f.size > 1048576) {
$('#id_offline').val('True');
console.log("Set offline to True");
$('#extra_message').text('Because of the large size, the file will be processed offline. You will receive email when it is done. The extra actions will not be performed.');
$('#extra_message').addClass('message');
}
});
});
</script>
{% endblock %}
{% block content %}
<form enctype="multipart/form-data" action="{{ formloc }}" method="post">
<form id="file_form" enctype="multipart/form-data" action="{{ formloc }}" method="post">
<div id="left" class="grid_6 alpha">
<h1>Upload Workout File</h1>
{% if user.is_authenticated and user|is_manager %}

View File

@@ -4,6 +4,8 @@
{% block content %}
<div class="grid_12 alpha">
<h1>User Settings</h1>
<p><a href="http://analytics.rowsandall.com/2017/11/02/rowsandall-settings-page-tutorial/">Need help? Click to read the tutorial</a></p>
<div class="grid_6 alpha">
<p>
<h2>Heart Rate Zones</h2>

View File

@@ -3,6 +3,33 @@
{% block title %}File loading{% endblock %}
{% block meta %}
<script type='text/javascript'
src='https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js'>
</script>
<script type='text/javascript'
src='http://ajax.aspnetcdn.com/ajax/jquery.validate/1.14.0/jquery.validate.min.js'>
</script>
<script>
$(document).ready(function() {
$('#id_file').on('change', function(evt) {
var f = this.files[0];
console.log(f);
if (f.size > 4194304) {
alert("File Size must be smaller than 4 MB");
this.value = null;
}
if (f.size > 1048576) {
$('#id_offline').val('True');
console.log("Set offline to True");
$('#extra_message').text('Because of the large size, the file will be processed offline. You will receive email when it is done. The extra actions will not be performed.');
$('#extra_message').addClass('message');
}
});
});
</script>
{% endblock %}
{% block content %}
<form enctype="multipart/form-data" action="{{ formloc }}" method="post">
<div id="left" class="grid_6 alpha">

View File

@@ -14,6 +14,7 @@ from django.views.generic.base import TemplateView
from django.db.models import Q
from django import template
from django.db import IntegrityError, transaction
from django.views.decorators.csrf import csrf_exempt
from django.shortcuts import render
from django.http import (
@@ -100,7 +101,8 @@ from rowers.tasks import handle_makeplot,handle_otwsetpower,handle_sendemailtcx,
from rowers.tasks import (
handle_sendemail_unrecognized,handle_sendemailnewcomment,
handle_sendemailnewresponse, handle_updatedps,
handle_updatecp,long_test_task,long_test_task2
handle_updatecp,long_test_task,long_test_task2,
handle_zip_file
)
from scipy.signal import savgol_filter
@@ -349,7 +351,8 @@ def test_job_view(request,aantal=100):
def test_job_view2(request,aantal=100):
job = myqueue(queuehigh,long_test_task2,int(aantal))
job = myqueue(queuehigh,long_test_task2,int(aantal),
secret=settings.PROGRESS_CACHE_SECRET)
try:
@@ -361,14 +364,22 @@ def test_job_view2(request,aantal=100):
return HttpResponseRedirect(url)
@csrf_exempt
def post_progress(request,id=None,value=0):
if id:
cache.set(id,value,3600)
if request.method == 'POST':
secret = request.POST['secret']
if secret == settings.PROGRESS_CACHE_SECRET:
if id:
cache.set(id,value,3600)
# test
result = cache.get(id)
# test
result = cache.get(id)
return HttpResponse('progress cached '+str(result),status=200)
else:
return HttpResponse('access denied',status=400)
return HttpResponse('progress cached '+str(result),status=200)
else:
return HttpResponse('hi',status=200)
def get_all_queued_jobs(userid=0):
r = StrictRedis()
@@ -701,13 +712,20 @@ def rower_register_view(request):
# Create and send email
fullemail = first_name + " " + last_name + " " + "<" + email + ">"
subject = "Thank you for registering on rowsandall.com"
message = "Thank you for registering on rowsandall.com. You can now login using the credentials you provided.\n"
message += "The first thing you might want to do is check and edit the heart rate band values. After logging in, click the button with your first name.\n"
message += "You can also check our videos page at http://rowsandall.com/rowers/videos for some helpful instruction videos.\n\n"
message += "User name:"+username+"\n"
message += "For all your questions, just reply to this email.\n\n"
message += "Happy rowing!\n\n\n"
message += "Oh, one more thing. The site is currently in beta and is developing fast. Bear with us. Don't hesitate to contact me if anything is broken or doesn't seem to work as advertised."
message = """
Thank you for registering on rowsandall.com. You can now login using the credentials you provided. The first thing you should do is go to the Settings page and make yourself familiar with the various options available to personalize your experience on the website. To get there, click the button with your first name on it in the upper right corner of the opening page.
As a minimum to get you started, enter your data in the Heart Rate Zones and Power Zones sections and your Functional Threshold Power. Then check your Account Information to make sure it is accurate and reflects your preferences.
For additional details on these settings and the buttons at the bottom of the page, read the settings tutorial at http://analytics.rowsandall.com/2017/11/02/rowsandall-settings-page-tutorial/.
Also check out our instructional videos at http://rowsandall.com/rowers/videos.
This website is a labor of love "by rowers, for rowers". If you find it to be useful, please help us cover our hosting costs and gain access to additional functionality by signing on as a Pro member: https://rowsandall.com/rowers/promembership
Oh, one more thing. The site is currently in beta and is developing fast. Bear with us. Don't hesitate to contact me at info@rowsandall.com if anything is broken or doesn't seem to work as advertised.
"""
send_mail(subject, message,
'Sander Roosendaal <info@rowsandall.com>',
[fullemail])
@@ -8234,6 +8252,7 @@ def workout_upload_view(request,
}
notes = form.cleaned_data['notes']
offline = form.cleaned_data['offline']
if optionsform.is_valid():
make_plot = optionsform.cleaned_data['make_plot']
@@ -8266,12 +8285,29 @@ def workout_upload_view(request,
f1 = res[0] # file name
f2 = res[1] # file name incl media directory
id,message,f2 = dataprep.new_workout_from_file(r,f2,
workouttype=workouttype,
makeprivate=makeprivate,
title = t,
notes='')
if not offline:
id,message,f2 = dataprep.new_workout_from_file(
r,f2,
workouttype=workouttype,
makeprivate=makeprivate,
title = t,
notes=''
)
else:
job = myqueue(
queuehigh,
handle_zip_file,
r.user.email,
t,
f2)
messages.info(
request,
"The file was too large to process in real time. It will be processed in a background process. You will receive an email when it is ready")
url = reverse(workout_upload_view)
response = HttpResponseRedirect(url)
return response
if not id:
messages.error(request,message)
url = reverse(workout_upload_view)
@@ -8440,6 +8476,7 @@ def team_workout_upload_view(request,message="",
f = request.FILES['file']
res = handle_uploaded_file(f)
t = form.cleaned_data['title']
offline = form.cleaned_data['offline']
if rowerform.is_valid():
u = rowerform.cleaned_data['user']
if u:
@@ -8480,11 +8517,33 @@ def team_workout_upload_view(request,message="",
f2 = res[1] # file name incl media directory
id,message,f2 = dataprep.new_workout_from_file(r,f2,
workouttype=workouttype,
makeprivate=False,
title = t,
notes='')
if not offline:
id,message,f2 = dataprep.new_workout_from_file(
r,f2,
workouttype=workouttype,
makeprivate=False,
title = t,
notes=''
)
else:
job = myqueue(
queuehigh,
handle_zip_file,
r.user.email,
t,
f2)
messages.info(
request,
"The file was too large to process in real time. It will be processed in a background process. The user will receive an email when it is ready"
)
url = reverse(team_workout_upload_view)
response = HttpResponseRedirect(url)
return response
if not id:
messages.error(request,message)
url = reverse(team_workout_upload_view)
@@ -9508,7 +9567,7 @@ def strokedataform(request,id=0):
# Process the POSTed stroke data according to the API definition
# Return the GET stroke data according to the API definition
from rest_framework_swagger.renderers import OpenAPIRenderer, SwaggerUIRenderer
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
@login_required()
@api_view(['GET','POST'])

View File

@@ -221,6 +221,10 @@ LOGIN_REDIRECT_URL = '/rowers/list-workouts/'
LOGIN_URL = '/login/'
LOGOUT_URL = '/logout/'
# Update Cache with task progress password
PROGRESS_CACHE_SECRET = CFG['progress_cache_secret']
# Concept 2
C2_CLIENT_ID = CFG['c2_client_id']
C2_CLIENT_SECRET = CFG['c2_client_secret']

View File

@@ -226,7 +226,7 @@ var current = null;
<div class="clear"></div>
<div class="grid_12">
<div id="messaging" class="grid_12">
{% if messages %}
{% for message in messages %}
{% if message.level == DEFAULT_MESSAGE_LEVELS.ERROR %}
@@ -241,14 +241,16 @@ var current = null;
{% block message %}
{% if message %}
<p class="message">
{{ message }}
<span>{{ message }}</span>
</p>
{% endif %}
{% if successmessage %}
<p class="successmessage">
{{ successmessage }}
<span>{{ successmessage }}</span>
</p>
{% endif %}
<div id="extra_message">
</div>
{% endblock %}
</div>
<div class="grid_12">