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 %} +
@@ -25,7 +28,7 @@ Upload?

{% endif %} {% if form.errors %} -

+

Please correct the error{{ form.errors|pluralize }} below.

{% endif %} @@ -79,6 +82,10 @@ formdatasetok = false; } + if (!formdatasetok) { + $("#id_dropregion").remove(); + } + if (formdatasetok) { $(document).ready(function() { @@ -99,7 +106,14 @@ console.log("Loading dropper"); jQuery.event.props.push('dataTransfer'); - + $(window).on('dragenter', function() { + $("#id_drop-files").css("background-color","#E9E9E4"); + $("#id_dropregion").addClass("watermark").removeClass("invisible");}) + + $(window).on('dragleave', function() { + $("#id_drop-files").css("background-color","#FFFFFF"); + $("#id_dropregion").removeClass("watermark").addClass("invisible");}) + var frm = $("#file_form"); if( window.FormData === undefined ) { diff --git a/static/css/rowsandall.css b/static/css/rowsandall.css index fe739c64..0362df15 100644 --- a/static/css/rowsandall.css +++ b/static/css/rowsandall.css @@ -26,6 +26,24 @@ background-image: url("/static/img/landing8b.jpg"); } +.watermark { + position: absolute; + float: center; + opacity: 0.25; + font-size: 3em; + width: 100%; + top: 50%; + left: 50%; + transform: translateX(-25%) translateY(-50%); + text-align: center; + vertical-align: middle; + z-index: 1000; +} + +.invisible { + display: none +} + html { font-size: 62.5%; } From cc9a004e92d8acca50aa44d4c1423f4e402b44f8 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Wed, 8 Nov 2017 11:41:30 +0100 Subject: [PATCH 5/5] fix --- rowers/uploads.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rowers/uploads.py b/rowers/uploads.py index 8dab7755..ea29c505 100644 --- a/rowers/uploads.py +++ b/rowers/uploads.py @@ -191,7 +191,7 @@ def upload_options(body): body = cleanbody(body) try: yml = (yaml.load(body)) - if 'fromuploadform' in yml: + if yml and 'fromuploadform' in yml: return yml try: for key, value in yml.iteritems():