From 73b89418253144cf59307c95ace03ad1fcdc0b24 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Fri, 30 Nov 2018 17:15:50 +0100 Subject: [PATCH 1/7] initial implementation. To Do: Add unsubscribe/subscribe functionality for participants --- rowers/models.py | 4 ++ rowers/plannedsessions.py | 3 +- rowers/tasks.py | 58 +++++++++++++++++++++++ rowers/templates/raceregisteredemail.html | 19 ++++++++ rowers/templates/racesubmissionemail.html | 19 ++++++++ rowers/templates/virtualevent.html | 8 +++- rowers/views.py | 54 +++++++++++++++++++++ 7 files changed, 162 insertions(+), 3 deletions(-) create mode 100644 rowers/templates/raceregisteredemail.html create mode 100644 rowers/templates/racesubmissionemail.html diff --git a/rowers/models.py b/rowers/models.py index 10b84581..ce91d5c2 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -2422,6 +2422,8 @@ class VirtualRaceResult(models.Model): verbose_name='Gender') age = models.IntegerField(null=True) + emailnotifications = models.BooleanField(default=True, + verbose_name = 'Receive race notifications by email') def __unicode__(self): rr = Rower.objects.get(id=self.userid) @@ -2472,6 +2474,8 @@ class IndoorVirtualRaceResult(models.Model): verbose_name='Gender') age = models.IntegerField(null=True) + emailnotifications = models.BooleanField(default=True, + verbose_name = 'Receive race notifications by email') def __unicode__(self): rr = Rower.objects.get(id=self.userid) diff --git a/rowers/plannedsessions.py b/rowers/plannedsessions.py index c9b9232f..fdef9f08 100644 --- a/rowers/plannedsessions.py +++ b/rowers/plannedsessions.py @@ -729,10 +729,11 @@ def race_can_submit(r,race): if is_complete == False: return True else: - return False + return True else: return False + print 'pop' return False def race_can_resubmit(r,race): diff --git a/rowers/tasks.py b/rowers/tasks.py index 374cd509..c319b1e4 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -740,6 +740,64 @@ def handle_updatedps(useremail, workoutids, debug=False,**kwargs): # send email when a breakthrough workout is uploaded +@app.task +def handle_sendemail_raceregistration( + useremail, username, registeredname, racename, raceid, **kwargs): + + if 'debug' in kwargs: + debug = kwargs['debug'] + else: + debug = True + + subject = "A new competitor has registered for virtual race {n}".format( + n = racename + ) + + from_email = 'Rowsandall ' + + d = { + 'username':username, + 'registeredname':registeredname, + 'racename':racename, + 'raceid':raceid, + } + + res = send_template_email(from_email,[useremail], + subject, + 'raceregisteredemail.html', + d,**kwargs) + + return 1 + +@app.task +def handle_sendemail_racesubmission( + useremail, username, registeredname, racename, raceid, **kwargs): + + if 'debug' in kwargs: + debug = kwargs['debug'] + else: + debug = True + + subject = "A new result has been submitted for virtual race {n}".format( + n = racename + ) + + from_email = 'Rowsandall ' + + d = { + 'username':username, + 'registeredname':registeredname, + 'racename':racename, + 'raceid':raceid, + } + + res = send_template_email(from_email,[useremail], + subject, + 'racesubmissionemail.html', + d,**kwargs) + + return 1 + @app.task def handle_send_disqualification_email( useremail,username,reason,message, racename, **kwargs): diff --git a/rowers/templates/raceregisteredemail.html b/rowers/templates/raceregisteredemail.html new file mode 100644 index 00000000..f16d120e --- /dev/null +++ b/rowers/templates/raceregisteredemail.html @@ -0,0 +1,19 @@ +{% extends "emailbase.html" %} +{% block body %} +

Dear {{ username }},

+ +

+ A new competitor has registered for the race {{ racename }}: {{ registeredname }} +

+ + +

+ You can check race participants and results on the race page on Rowsandall: + {{ racename }} +

+ +

+ Best Regards, the Rowsandall Team +

+{% endblock %} + diff --git a/rowers/templates/racesubmissionemail.html b/rowers/templates/racesubmissionemail.html new file mode 100644 index 00000000..263fd867 --- /dev/null +++ b/rowers/templates/racesubmissionemail.html @@ -0,0 +1,19 @@ +{% extends "emailbase.html" %} +{% block body %} +

Dear {{ username }},

+ +

+ One of your competitors, {{ registeredname }}, has submitted a result for {{ racename }} +

+ + +

+ Check out the results on the race page! + {{ racename }} +

+ +

+ Best Regards, the Rowsandall Team +

+{% endblock %} + diff --git a/rowers/templates/virtualevent.html b/rowers/templates/virtualevent.html index 97e94b79..7271460e 100644 --- a/rowers/templates/virtualevent.html +++ b/rowers/templates/virtualevent.html @@ -39,8 +39,12 @@

+ data-url="{{ request.build_absolute_uri }}" + {% if race.sessiontype == 'race' %} + data-text="@rowsandall #rowingdata Participate in virtual race '{{ race.name }}'">Tweet +{% else %} +data-text="@rowsandall #rowingdata Participate in Indoor Rowing virtual race '{{ race.name }}'">Tweet +{% endif %}

diff --git a/rowers/views.py b/rowers/views.py index 8088b67d..f8576213 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -168,6 +168,8 @@ from rowers.tasks import ( handle_update_empower, handle_sendemailics, handle_sendemail_userdeleted, + handle_sendemail_raceregistration, + handle_sendemail_racesubmission, ) from scipy.signal import savgol_filter @@ -16526,6 +16528,22 @@ def virtualevent_register_view(request,id=0): add_rower_race(r,race) + otherrecords = IndoorVirtualRaceResult.objects.filter( + race = race).exclude(userid = r.id) + + for otherrecord in otherrecords: + otheruser = Rower.objects.get(id=otherrecord.userid) + othername = otheruser.user.first_name+' '+otheruser.user.last_name + registeredname = r.user.first_name+' '+r.user.last_name + if otherrecord.emailnotifications: + job = myqueue( + queue, + handle_sendemail_raceregistration, + otheruser.user.email, othername, + registeredname, + race.name, + race.id + ) messages.info( @@ -16633,6 +16651,22 @@ def indoorvirtualevent_register_view(request,id=0): add_rower_race(r,race) + otherrecords = IndoorVirtualRaceResult.objects.filter( + race = race).exclude(userid = r.id) + + for otherrecord in otherrecords: + otheruser = Rower.objects.get(id=otherrecord.userid) + othername = otheruser.user.first_name+' '+otheruser.user.last_name + registeredname = r.user.first_name+' '+r.user.last_name + if otherrecord.emailnotifications: + job = myqueue( + queue, + handle_sendemail_raceregistration, + otheruser.user.email, othername, + registeredname, + race.name, + race.id + ) messages.info( @@ -17142,6 +17176,7 @@ def virtualevent_submit_result_view(request,id=0): race=race ) + entrychoices = [] for record in records: @@ -17234,6 +17269,25 @@ def virtualevent_submit_result_view(request,id=0): request.session['async_tasks'] = [(jobid,'submit_race')] messages.info(request,"We are evaluating your result. The page will reload when we're done. Your result will show up if you adhered to the course") + + if result: + otherrecords = resultobj.objects.filter( + race = race).exclude(userid = r.id) + + for otherrecord in otherrecords: + otheruser = Rower.objects.get(id=otherrecord.userid) + othername = otheruser.user.first_name+' '+otheruser.user.last_name + registeredname = r.user.first_name+' '+r.user.last_name + if otherrecord.emailnotifications: + job = myqueue( + queue, + handle_sendemail_racesubmission, + otheruser.user.email, othername, + registeredname, + race.name, + race.id + ) + # redirect to race page url = reverse(virtualevent_view, From 2178a25db35b2b4aa8b4ca2dee578cb2bdfa7c99 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Sun, 2 Dec 2018 12:26:21 +0100 Subject: [PATCH 2/7] added manual and upload links to race page --- rowers/models.py | 2 +- rowers/plannedsessions.py | 37 +++++++++++++++++++++++++++++- rowers/templates/virtualevent.html | 32 +++++++++++++++++++++++++- rowers/templates/workout_form.html | 10 ++++++++ rowers/views.py | 9 ++++++++ 5 files changed, 87 insertions(+), 3 deletions(-) diff --git a/rowers/models.py b/rowers/models.py index ce91d5c2..09a61c8b 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -2690,7 +2690,7 @@ class WorkoutForm(ModelForm): startdate__lte=workout.date, enddate__gte=workout.date, ).order_by("preferreddate","startdate","enddate").exclude( - sessiontype='race') + sessiontype__in=['race','indoorrace']) if not sps: del self.fields['plannedsession'] diff --git a/rowers/plannedsessions.py b/rowers/plannedsessions.py index fdef9f08..09c657b4 100644 --- a/rowers/plannedsessions.py +++ b/rowers/plannedsessions.py @@ -20,7 +20,7 @@ from rowers.models import ( Rower, Workout,Team, GeoCourse, TrainingMicroCycle,TrainingMesoCycle,TrainingMacroCycle, TrainingPlan,PlannedSession,VirtualRaceResult,CourseTestResult, - get_course_timezone, IndoorVirtualRaceResult + get_course_timezone, IndoorVirtualRaceResult,VirtualRace ) from rowers.courses import get_time_course @@ -33,6 +33,41 @@ import iso8601 from iso8601 import ParseError from rowers.tasks import handle_check_race_course +def get_indoorraces(workout): + races1 = VirtualRace.objects.filter( + registration_closure__gt=timezone.now(), + sessiontype='indoorrace', + startdate__lte=workout.date, + enddate__gte=workout.date, + sessionmode='distance', + sessionvalue=workout.distance) + + + if workout.duration.second != 0 and workout.duration.microsecond != 0: + duration = 60*workout.duration.hour+workout.duration.minute + + + races2 = VirtualRace.objects.filter( + registration_closure__gt=timezone.now(), + sessiontype='indoorrace', + startdate__lte=workout.date, + enddate__gte=workout.date, + sessionmode='time', + sessionvalue=duration) + + races = races1 | races2 + else: + races = races1 + + registrations = IndoorVirtualRaceResult.objects.filter( + race__in = races, + userid=workout.user.id) + + races = [r.race for r in registrations] + + + return races + def get_todays_micro(plan,thedate=date.today()): thismicro = None diff --git a/rowers/templates/virtualevent.html b/rowers/templates/virtualevent.html index 7271460e..cf192349 100644 --- a/rowers/templates/virtualevent.html +++ b/rowers/templates/virtualevent.html @@ -155,7 +155,37 @@ data-text="@rowsandall #rowingdata Participate in Indoor Rowing virtual race '{{

{% endif %} {% if button == 'submitbutton' %} - Submit Result + + + + + + + + + + {% if race.sessiontype == 'indoorrace' %} + + + + + {% endif %} +
+ Submit Workout + + Submit a workout that is already on the site as your race result +
+ Upload your race result + + Upload a new workout to the site and submit it as a result. You + need a workout data file. +
+ Enter your race result manually + + If you don't have a data file, enter the results + manually. If you have a photo of the monitor with the + result, it is recommended to add this to the workout. +
{% endif %} {% if button == 'resubmitbutton' %}

diff --git a/rowers/templates/workout_form.html b/rowers/templates/workout_form.html index ce0e29e6..986878ec 100644 --- a/rowers/templates/workout_form.html +++ b/rowers/templates/workout_form.html @@ -118,6 +118,16 @@ $('#id_workouttype').change();

+ {% if indoorraces %} +
  • +

    Racing

    + {% for race in indoorraces %} +

    + Submit this to Indoor Race {{ race.name }} +

    + {% endfor %} +
  • + {% endif %} {% if mapdiv %}
  • diff --git a/rowers/views.py b/rowers/views.py index f8576213..825c1015 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -3460,6 +3460,12 @@ def addmanual_view(request): add_workouts_plannedsession([w],ps,w.user) messages.info(request,'New workout created') + + url = reverse( + workout_edit_view, + kwargs={'id':id} + ) + return HttpResponseRedirect(url) else: return render(request,'manualadd.html', {'form':form, @@ -9979,6 +9985,8 @@ def workout_edit_view(request,id=0,message="",successmessage=""): row = get_workout(id) + indoorraces = get_indoorraces(row) + if (checkworkoutuser(request.user,row)==False): raise PermissionDenied("Access denied") @@ -10171,6 +10179,7 @@ def workout_edit_view(request,id=0,message="",successmessage=""): 'graphs':g, 'breadcrumbs':breadcrumbs, 'rower':r, + 'indoorraces':indoorraces, 'active':'nav-workouts', 'mapscript':mapscript, 'mapdiv':mapdiv, From a746052fbfc7b2dc240c74151427913b3ad6f373 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Sun, 2 Dec 2018 13:14:19 +0100 Subject: [PATCH 3/7] adding race buttons to left racing menu not ready yet --- rowers/templates/menu_racing.html | 71 +++++++++++++++++++++++++++++- rowers/templates/virtualevent.html | 2 +- rowers/views.py | 24 ++++++++++ 3 files changed, 94 insertions(+), 3 deletions(-) diff --git a/rowers/templates/menu_racing.html b/rowers/templates/menu_racing.html index 4a06ef2d..3add6467 100644 --- a/rowers/templates/menu_racing.html +++ b/rowers/templates/menu_racing.html @@ -15,15 +15,82 @@  New Indoor Race
  • + {% if race %} + {% if reguest.user.is_anonymous %} +
  • + {% if race.sessiontype == 'race' %} + +  Register + {% else %} + +  Register + {% endif %} +
  • + {% endif %} + {% for button in buttons %} + {% if button == 'registerbutton' %} +
  • + {% if race.sessiontype == 'race' %} + +  Register + {% else %} + +  Register + {% endif %} +
  • + {% endif %} + {% if button == 'submitbutton' %} +
  • + +  Submit Workout +
  • +
  • + +  Upload your race result + +
  • +
  • + +  Enter Result + +
  • + {% endif %} + {% if button == 'resubmitbutton' %} +
  • + Submit New Result +
  • + {% endif %} + {% if button == 'withdrawbutton' %} + +  Withdraw + {% endif %} + {% if button == 'adddisciplinebutton' %} + +  Register New Boat + + {% endif %} + {% if button == 'editbutton' %} +
  • + {% if race.sessiontype == 'race' %} +  Edit Race + + {% else %} +  Edit Race + + {% endif %} +
  • + {% endif %} + {% endfor %} + {% endif %}
  • -  Courses +  Courses
  • {% if course %}
  • - +