From 5061cbcd1cd4335a606f41532a4792fbc023edb4 Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Tue, 7 Nov 2017 17:00:18 +0100
Subject: [PATCH 1/5] work in progress: now has alternative way to find chart
settings
---
rowers/uploads.py | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/rowers/uploads.py b/rowers/uploads.py
index a6fab4a1..e05eca04 100644
--- a/rowers/uploads.py
+++ b/rowers/uploads.py
@@ -19,6 +19,9 @@ import yamllint
from subprocess import call
import re
+from verbal_expressions import VerEx
+
+
import django_rq
queue = django_rq.get_queue('default')
queuelow = django_rq.get_queue('low')
@@ -45,6 +48,29 @@ def cleanbody(body):
return body
+def matchchart(line):
+ results = []
+ tester = VerEx().start_of_line().find('chart')
+ tester2 = VerEx().start_of_line().find('chart').anything().find('distance')
+ tester3 = VerEx().start_of_line().find('chart').anything().find('time')
+ tester4 = VerEx().start_of_line().find('chart').anything().find('pie')
+ if tester.match(line):
+ if tester2.match(line):
+ return 'distanceplot'
+ if tester3.match(line):
+ return 'timeplot'
+ if tester3.match(line):
+ return 'pieplot'
+
+def get_plotoptions_body2(uploadoptions,body):
+ for line in body.splitlines():
+ chart = matchchart(line)
+ if chart:
+ uploadoptions['make_plot'] = True
+ uploadoptions['plottype'] = chart
+
+
+
def getsyncoptions(uploadoptions,values):
try:
value = values.lower()
From 70b55290290940debd63c9e1102abc77ab705c30 Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Tue, 7 Nov 2017 22:21:01 +0100
Subject: [PATCH 2/5] alternative natural language for plot,sync,privacy
---
rowers/uploads.py | 97 ++++++++++++++++++++++++++++++++++++++---------
1 file changed, 79 insertions(+), 18 deletions(-)
diff --git a/rowers/uploads.py b/rowers/uploads.py
index e05eca04..a7bd5622 100644
--- a/rowers/uploads.py
+++ b/rowers/uploads.py
@@ -19,8 +19,8 @@ import yamllint
from subprocess import call
import re
-from verbal_expressions import VerEx
-
+from verbalexpressions import VerEx
+import re
import django_rq
queue = django_rq.get_queue('default')
@@ -48,29 +48,85 @@ def cleanbody(body):
return body
+# currently only matches one chart
def matchchart(line):
results = []
- tester = VerEx().start_of_line().find('chart')
- tester2 = VerEx().start_of_line().find('chart').anything().find('distance')
- tester3 = VerEx().start_of_line().find('chart').anything().find('time')
- tester4 = VerEx().start_of_line().find('chart').anything().find('pie')
- if tester.match(line):
- if tester2.match(line):
+ tester = VerEx().start_of_line().find('chart').OR().find('plot')
+ tester2 = VerEx().start_of_line().find('chart').OR().find('plot').anything().find('distance')
+ tester3 = VerEx().start_of_line().find('chart').OR().find('plot').anything().find('time')
+ tester4 = VerEx().start_of_line().find('chart').OR().find('plot').anything().find('pie')
+ if tester.match(line.lower()):
+ if tester2.match(line.lower()):
return 'distanceplot'
- if tester3.match(line):
+ if tester3.match(line.lower()):
return 'timeplot'
- if tester3.match(line):
+ if tester3.match(line.lower()):
return 'pieplot'
-def get_plotoptions_body2(uploadoptions,body):
+def matchsync(line):
+ results = []
+ tester = '((sync)|(synchronization)|(export))'
+ tester2 = tester+'(.*)((c2)|(concept2)|(logbook))'
+ tester3 = tester+'(.*)((tp)|(trainingpeaks))'
+ tester4 = tester+'(.*)(strava)'
+ tester5 = tester+'(.*)((st)|(sporttracks))'
+ tester6 = tester+'(.*)((rk)|(runkeeper))'
+ tester7 = tester+'(.*)((mapmyfitness)|(underarmour)|(ua))'
+
+ tester = re.compile(tester)
+
+ if tester.match(line.lower()):
+ testers = [
+ ('upload_to_C2',re.compile(tester2)),
+ ('upload_totp',re.compile(tester3)),
+ ('upload_to_Strava',re.compile(tester4)),
+ ('upload_to_SportTracks',re.compile(tester5)),
+ ('upload_to_RunKeeper',re.compile(tester6)),
+ ('upload_to_MapMyFitness',re.compile(tester7)),
+ ]
+ for t in testers:
+ if t[1].match(line.lower()):
+ results.append(t[0])
+
+ return results
+
+def getprivateoptions_body2(uploadoptions,body):
+ tester = re.compile('^(priva)')
+ for line in body.splitlines():
+ if tester.match(line.lower()):
+ v = True
+ negs = ['false','False','None','no']
+ for neg in negs:
+ tstr = re.compile('^(.*)'+neg)
+
+ if tstr.match(line.lower()):
+ v = False
+
+ uploadoptions['makeprivate'] = v
+
+ return uploadoptions
+
+def getplotoptions_body2(uploadoptions,body):
for line in body.splitlines():
chart = matchchart(line)
if chart:
uploadoptions['make_plot'] = True
uploadoptions['plottype'] = chart
-
+ return uploadoptions
+def getsyncoptions_body2(uploadoptions,body):
+ result = []
+ for line in body.splitlines():
+ result = result+matchsync(line)
+
+ result = list(set(result))
+
+ for r in result:
+ uploadoptions[r] = True
+
+ return uploadoptions
+
def getsyncoptions(uploadoptions,values):
try:
value = values.lower()
@@ -147,13 +203,18 @@ def upload_options(body):
except AttributeError:
pass
except yaml.YAMLError as exc:
- pm = exc.problem_mark
- strpm = str(pm)
- pbm = "Your email has an issue on line {} at position {}. The error is: ".format(
- pm.line+1,
- pm.column+1,
+ try:
+ uploadoptions = getplotoptions_body2(uploadoptions,body)
+ uploadoptions = getsyncoptions_body2(uploadoptions,body)
+ uploadoptions = getprivateoptions_body2(uploadoptions,body)
+ except IOError:
+ pm = exc.problem_mark
+ strpm = str(pm)
+ pbm = "Your email has an issue on line {} at position {}. The error is: ".format(
+ pm.line+1,
+ pm.column+1,
)+strpm
- return {'error':pbm}
+ return {'error':pbm}
if uploadoptions == {}:
uploadoptions['message'] = 'No parsing issue. No valid commands detected'
From a8eae5911dcbc16297d5cfda82e0b097c6657d2b Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Wed, 8 Nov 2017 09:22:15 +0100
Subject: [PATCH 3/5] upload options work in background upload
---
rowers/management/commands/processemail.py | 6 +++++-
rowers/templates/document_form.html | 6 +++---
rowers/uploads.py | 2 ++
rowers/views.py | 8 +++++++-
4 files changed, 17 insertions(+), 5 deletions(-)
diff --git a/rowers/management/commands/processemail.py b/rowers/management/commands/processemail.py
index 4719bee3..5adffab1 100644
--- a/rowers/management/commands/processemail.py
+++ b/rowers/management/commands/processemail.py
@@ -114,7 +114,11 @@ class Command(BaseCommand):
extension = attachment.document.name[-3:].lower()
try:
message = Message.objects.get(id=attachment.message_id)
- body = "\n".join(message.text.splitlines())
+ if message.text:
+ body = "\n".join(message.text.splitlines())
+ else:
+ body = message.body
+
uploadoptions = uploads.upload_options(body)
from_address = message.from_address[0].lower()
name = message.subject
diff --git a/rowers/templates/document_form.html b/rowers/templates/document_form.html
index 7ad85c58..c7d2cda2 100644
--- a/rowers/templates/document_form.html
+++ b/rowers/templates/document_form.html
@@ -53,7 +53,7 @@
If you check "make private", this workout will not be visible to your followers and will not show up in your teams' workouts list. With the Landing Page option, you can select to which (workout related) page you will be
taken after a successfull upload.
- Select Files with the File button or drag them on the marked area
+ Select Files with the File button or drag them on the marked area
@@ -141,7 +141,7 @@
$('#id_offline').prop('checked','True');
data.set($('#id_offline').attr('name'),$('#id_offline').prop('checked'));
console.log("Set offline to True");
- $('#extra_message').text('Because of the large size, we recommend to use background processing. You will receive email when it is done. The extra actions will not be performed.');
+ $('#extra_message').text('Because of the large size, we recommend to use background processing. You will receive email when it is done.');
$('#extra_message').addClass('message');
}
}
@@ -240,7 +240,7 @@
$('#id_offline').prop('checked','True');
data.set($('#id_offline').attr('name'),$('#id_offline').prop('checked'));
console.log("Set offline to True");
- $('#extra_message').text('Because of the large size, we recommend to use background processing. You will receive email when it is done. The extra actions will not be performed.');
+ $('#extra_message').text('Because of the large size, we recommend to use background processing. You will receive email when it is done.');
$('#extra_message').addClass('message');
}
data.set("file",f);
diff --git a/rowers/uploads.py b/rowers/uploads.py
index a7bd5622..8dab7755 100644
--- a/rowers/uploads.py
+++ b/rowers/uploads.py
@@ -191,6 +191,8 @@ def upload_options(body):
body = cleanbody(body)
try:
yml = (yaml.load(body))
+ if 'fromuploadform' in yml:
+ return yml
try:
for key, value in yml.iteritems():
lowkey = key.lower()
diff --git a/rowers/views.py b/rowers/views.py
index bfa49541..619a99db 100644
--- a/rowers/views.py
+++ b/rowers/views.py
@@ -8,6 +8,7 @@ import pytz
import operator
import warnings
import urllib
+import yaml
from PIL import Image
from numbers import Number
from django.views.generic.base import TemplateView
@@ -8551,9 +8552,14 @@ def workout_upload_view(request,
)
else:
workoutsbox = Mailbox.objects.filter(name='workouts')[0]
+ uploadoptions['fromuploadform'] = True
+ bodyyaml = yaml.safe_dump(
+ uploadoptions,
+ default_flow_style=False
+ )
msg = Message(mailbox=workoutsbox,
from_header=r.user.email,
- subject = t)
+ subject = t,body=bodyyaml)
msg.save()
f3 = 'media/mailbox_attachments/'+f2[6:]
copyfile(f2,f3)
From 7e0e8dcfea9ec9432b150923c3386e98e9f75a3b Mon Sep 17 00:00:00 2001
From: Sander Roosendaal
Date: Wed, 8 Nov 2017 10:20:45 +0100
Subject: [PATCH 4/5] added watermark to drag area
---
rowers/templates/document_form.html | 20 +++++++++++++++++---
static/css/rowsandall.css | 18 ++++++++++++++++++
2 files changed, 35 insertions(+), 3 deletions(-)
diff --git a/rowers/templates/document_form.html b/rowers/templates/document_form.html
index c7d2cda2..23888508 100644
--- a/rowers/templates/document_form.html
+++ b/rowers/templates/document_form.html
@@ -15,7 +15,10 @@
{% endblock %}
- {% block content %}
+{% block content %}
+
+
Drag and drop files here
+