diff --git a/init.sh b/init.sh deleted file mode 100644 index c93635f0..00000000 --- a/init.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -source /srv/venv/bin/activate -cd /srv/app -python manage.py migrate -python manage.py collectstatic --noinput -python manage.py runserver diff --git a/rowers/c2stuff.py b/rowers/c2stuff.py index 87895291..4a082f35 100644 --- a/rowers/c2stuff.py +++ b/rowers/c2stuff.py @@ -18,6 +18,7 @@ from iso8601 import ParseError import numpy import json +from json.decoder import JSONDecodeError from rowsandall_app.settings import ( C2_CLIENT_ID, C2_REDIRECT_URI, C2_CLIENT_SECRET diff --git a/rowers/dataprep.py b/rowers/dataprep.py index bbfd6ffb..33f961be 100644 --- a/rowers/dataprep.py +++ b/rowers/dataprep.py @@ -1782,6 +1782,11 @@ def delete_strokedata(id): dirname = 'media/strokedata_{id}.parquet.gz'.format(id=id) try: shutil.rmtree(dirname) + except OSError: + try: + os.remove(dirname) + except FileNotFoundError: + pass except FileNotFoundError: pass diff --git a/rowers/management/commands/processalerts.py b/rowers/management/commands/processalerts.py index febfe20f..12937fcd 100644 --- a/rowers/management/commands/processalerts.py +++ b/rowers/management/commands/processalerts.py @@ -45,7 +45,7 @@ class Command(BaseCommand): # explanatorytexts othertexts = [alert.description()] - + # send email job = myqueue(queue,handle_send_email_alert, alert.manager.email, @@ -58,11 +58,11 @@ class Command(BaseCommand): # advance next_run if not testing: - alert.next_run = datetime.date.today() + datetime.timedelta(days=alert.period) + alert.next_run = datetime.date.today() + datetime.timedelta(days=alert.period-1) alert.save() if testing: print('{nr} alerts found'.format(nr = len(todaysalerts))) - + self.stdout.write(self.style.SUCCESS( 'Successfully processed alerts')) diff --git a/rowers/plannedsessions.py b/rowers/plannedsessions.py index ce71c7c8..1064db19 100644 --- a/rowers/plannedsessions.py +++ b/rowers/plannedsessions.py @@ -706,6 +706,7 @@ def get_team(request): def get_dates_timeperiod(request,startdatestring='',enddatestring='', defaulttimeperiod='thisweek'): # set start end date according timeperiod + # should always return datetime.date timeperiod = request.GET.get('when') @@ -720,8 +721,8 @@ def get_dates_timeperiod(request,startdatestring='',enddatestring='', startdate = dt.datetime.strptime(startdatestring,'%Y-%m-%d').date() enddate = dt.datetime.strptime(enddatestring,'%Y-%m-%d').date() except ValueError: - startdate = parser.parse(startdatestring,fuzzy=True) - enddate = parser.parse(enddatestring, fuzzy=True) + startdate = parser.parse(startdatestring,fuzzy=True).date() + enddate = parser.parse(enddatestring, fuzzy=True).date() return startdate,enddate diff --git a/rowers/templates/embedded_video_mini.html b/rowers/templates/embedded_video_mini.html index 466cb5e9..20288285 100644 --- a/rowers/templates/embedded_video_mini.html +++ b/rowers/templates/embedded_video_mini.html @@ -47,7 +47,7 @@ function copyText() { var tempInput = document.createElement("input"); tempInput.style = "position: absolute; left: -1000px; top: -1000px"; - tempInput.value = "{{ siteurl }}/rowers/video/{{ analysis.id|encode }}/"; + tempInput.value = "{{ siteurl }}/rowers/video/{{ analysis.id|encode }}/m/"; document.body.appendChild(tempInput); tempInput.select(); document.execCommand("copy"); @@ -108,19 +108,22 @@ function copyText() {
  • Playing the video will advance the data in synchronization. Use the regular YouTube controls to move around in the video and play it.

    +

    In this reduced view, you cannot edit the video analysis. There is a separate + view for that here. +

  • + href="https://www.facebook.com/sharer/sharer.php?u=https://rowsandall.com/rowers/video/{{ analysis.id|encode }}/m/"> Share diff --git a/rowers/templates/paymentconfirmationemail.html b/rowers/templates/paymentconfirmationemail.html index 0bc62f45..1d97167c 100644 --- a/rowers/templates/paymentconfirmationemail.html +++ b/rowers/templates/paymentconfirmationemail.html @@ -7,6 +7,17 @@ Thank you. We have received the payment of € {{ amount }} for Rowsandall related services.

    +

    + With your contribution, you are helping to keep this service to the rowing community + running. As the founder and developer of the Rowsandall.com site I am very interested + to know what you think of Rowsandall.com, as well as suggestions for improvements. +

    + +

    + So don't hesitate to respond to this email and let me know. I will read and respond to each + email. +

    +

    Please contact our customer service by replying to this email if you have any further questions regarding the payment. @@ -16,4 +27,3 @@ Best Regards, the Rowsandall Team

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

    Dear {{ first_name }},

    + +

    + Welcome on the trial for the Self-Coach plan. +

    +

    +As the developer of the Rowsandall.com site I am very interested to know what you think of Rowsandall.com. Especially, I'd like to understand how you started using the site, what you are looking for, and what you think could be improved. +

    +

    +The Self-Coach functionality allows you to create training plans and sessions for you and your training group. Feel free to contact me any time you need help. +

    +

    +I'd also love to hear a bit about your rowing background. +

    + +

    + So don't hesitate to respond to this email and let me know. I will read and respond to each + email. +

    +

    +Thank you very much for your help and for supporting rowsandall.com. +

    + + +

    + Best Regards, the Rowsandall Team +

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

    Dear {{ first_name }},

    + +

    + Welcome on the trial for the Pro plan. +

    +

    +As the developer of the Rowsandall.com site I am very interested to know +what you think of Rowsandall.com. +Especially, I'd like to understand how you started using the site, +what you are looking for, and what you think could be improved. +

    + +

    +I'd also love to hear a bit about your rowing background. +

    + +

    + So don't hesitate to respond to this email and let me know. I will read and respond to each + email. +

    + +

    +Thank you very much for your help and for supporting rowsandall.com. +

    + + +

    + Best Regards, the Rowsandall Team +

    +{% endblock %} diff --git a/rowers/templates/subscription_update_email.html b/rowers/templates/subscription_update_email.html index d805d0d5..6f0cee59 100644 --- a/rowers/templates/subscription_update_email.html +++ b/rowers/templates/subscription_update_email.html @@ -5,22 +5,34 @@

    Thank you. We have received the payment of € {{ amount }} for - your updated Rowsandall subscription. - You are now on the Rowsandall paid plan "{{ planname }}". + your updated Rowsandall subscription. + You are now on the Rowsandall paid plan "{{ planname }}".

    +

    + With your contribution, you are helping to keep this service to the rowing community + running. As the founder and developer of the Rowsandall.com site I am very interested + to know what you think of Rowsandall.com, as well as suggestions for improvements. +

    + +

    + So don't hesitate to respond to this email and let me know. I will read and respond to each + email. +

    + {% if recurring=='recurring' %}

    + Some more information about the subscription. The subscription cost is €{{ price }} per year. Your next charge is due on {{ end_of_billing_period }}. We will charge you automatically - on that date. + on that date.

    The subscription will keep running until you change or stop it. At any point in time you can change the automatically renewing subscription to a "one year only" subscription through the upgrade page. On this page, you can also - upgrade your subscription. + upgrade your subscription.

    {% else %} @@ -28,7 +40,7 @@ The price of the subscription is €{{ price }}. You have paid €{{ amount }} as a prorated cost of your upgrade. This one year subscription will automatically end on {{ end_of_billing_period }}. You can - renew your subscription after that. + renew your subscription after that.

    @@ -60,4 +72,3 @@ Best Regards, the Rowsandall Team

    {% endblock %} - diff --git a/rowers/tests/test_simplefunctions.py b/rowers/tests/test_simplefunctions.py index 22cc3140..fcc8743d 100644 --- a/rowers/tests/test_simplefunctions.py +++ b/rowers/tests/test_simplefunctions.py @@ -11,11 +11,29 @@ from django.http import Http404 from rowers.views import get_workout +class TestDateTime(TestCase): + def setUp(self): + self.factory = RequestFactory() + + def tearDown(self): + pass + + def test_get_dates(self): + request = self.factory.get('/rowers/sessions/create/user/230/?startdate=13.01.2020&enddate=19.01.2020') + startdate,enddate = get_dates_timeperiod(request) + + teststart = datetime.date(2020,1,1) + self.assertTrue(teststartenddate) + + # tests simple functions from views.py class SimpleViewTest(TestCase): def setUp(self): self.u = UserFactory() - + self.r = Rower.objects.create(user=self.u, birthdate=faker.profile()['birthdate'], gdproptin=True, @@ -36,11 +54,11 @@ class SimpleViewTest(TestCase): except (IOError, FileNotFoundError,OSError): pass - + def test_getrequestrower(self): user_no_rower = UserFactory(username='norower') user_no_rower.set_password(faker.word()) - + login = self.c.login(username=self.u.username, password=self.password) self.assertTrue(login) @@ -75,7 +93,7 @@ class SimpleViewTest(TestCase): self.assertRedirects(response, expected_url='/rowers/email/', status_code=302,target_status_code=200) - + def test_getworkout(self): with assert_raises(Http404): @@ -108,7 +126,3 @@ class SimpleViewTest(TestCase): login = self.c.login(username=self.u.username, password=self.password) self.assertEqual(login,False) - - - - diff --git a/rowers/views/planviews.py b/rowers/views/planviews.py index c820b2ae..05910fbc 100644 --- a/rowers/views/planviews.py +++ b/rowers/views/planviews.py @@ -445,8 +445,9 @@ def plannedsession_create_view(request, sps = get_sessions(r,startdate=startdate,enddate=enddate).exclude( sessiontype='race') - - sessiontemplates = PlannedSession.objects.filter(manager=request.user,is_template=True) + sessiontemplates = PlannedSession.objects.filter( + manager=request.user, + is_template=True).order_by("name") try: trainingplan = TrainingPlan.objects.filter( @@ -1511,11 +1512,11 @@ def plannedsession_teamclone_view(request,id=0): ps.name += ' (copy)' ps.is_template = False - deltadays = ps.enddate-ps.startdate + deltadays = ps.preferreddate-ps.startdate - ps.startdate = timezone.now().date() - ps.enddate = (timezone.now()+deltadays).date() - ps.preferreddate = ps.preferreddate+deltadays + ps.startdate = startdate + ps.enddate = enddate + ps.preferreddate = startdate+deltadays ps.save() diff --git a/rowers/views/userviews.py b/rowers/views/userviews.py index a8aea814..710fd771 100644 --- a/rowers/views/userviews.py +++ b/rowers/views/userviews.py @@ -13,23 +13,30 @@ def start_trial_view(request): messages.error(request,'You do not qualify for a trial') url = '/rowers/paidplans' return HttpResponseRedirect(url) - + r.protrialexpires = datetime.date.today()+datetime.timedelta(13) r.save() url = reverse('workouts_view') messages.info(request,'We have started your 14 day trial period') - + subject2 = "User started Pro Trial" message2 = "User Started Pro Trial.\n" message2 += request.user.email + "\n" message2 += "User name: "+request.user.username - + send_mail(subject2, message2, 'Rowsandall Server ', ['roosendaalsander@gmail.com']) - + + send_template_email('Rowsandall ', + [r.user.email], + 'Welcome to the Rowsandall Pro Trial', + 'protrialewelcome.html', + {'first_name':r.user.first_name, + 'last_name':r.user.last_name}) + return HttpResponseRedirect(url) @login_required() @@ -40,7 +47,7 @@ def start_plantrial_view(request): messages.error(request,'You do not qualify for a trial') url = '/rowers/paidplans' return HttpResponseRedirect(url) - + r.plantrialexpires = datetime.date.today()+datetime.timedelta(13) r.protrialexpires = datetime.date.today()+datetime.timedelta(13) r.save() @@ -48,16 +55,23 @@ def start_plantrial_view(request): url = reverse('workouts_view') messages.info(request,'We have started your 14 day trial period') - + subject2 = "User started Plan Trial" message2 = "User Started Plan Trial.\n" message2 += request.user.email + "\n" message2 += "User name: "+request.user.username - + send_mail(subject2, message2, 'Rowsandall Server ', ['roosendaalsander@gmail.com']) - + + send_template_email('Rowsandall ', + [r.user.email], + 'Welcome to the Rowsandall Self-Coach Trial', + 'plantrialwelcome.html', + {'first_name':r.user.first_name, + 'last_name':r.user.last_name}) + return HttpResponseRedirect(url) # Page where user can manage his favorite charts @@ -79,7 +93,7 @@ def rower_favoritecharts_view(request,userid=0): FavoriteChartFormSet = formset_factory(FavoriteForm,formset=BaseFavoriteFormSet,extra=0) if aantal==0: FavoriteChartFormSet = formset_factory(FavoriteForm,formset=BaseFavoriteFormSet,extra=1) - + if request.method == 'POST': favorites_formset = FavoriteChartFormSet(request.POST) @@ -115,7 +129,7 @@ def rower_favoritecharts_view(request,userid=0): messages.error(request,message) else: favorites_formset = FavoriteChartFormSet(initial=favorites_data) - + context = { 'favorites_formset':favorites_formset, @@ -123,8 +137,8 @@ def rower_favoritecharts_view(request,userid=0): 'rower':r, } - - + + return render(request,'favoritecharts.html',context) # page where user sets his export settings @@ -154,7 +168,7 @@ def rower_exportsettings_view(request,userid=0): 'name': 'Export Settings' } ] - + return render(request, 'rower_exportsettings.html', {'form':form, 'rower':r, @@ -367,7 +381,7 @@ def rower_prefs_view(request,userid=0,message=""): 'rower':r, }) - + # Revoke an app that you granted access through the API. # this views is called when you press a button on the User edit page # the button is only there when you have granted access to an app @@ -401,7 +415,7 @@ def rower_update_empower_view( r = getrower(request.user) except Rower.DoesNotExist: raise Http404("Rower doesn't exist") - + if request.method == 'POST' and 'daterange' in request.POST: dateform = DateRangeForm(request.POST) if dateform.is_valid(): @@ -416,7 +430,7 @@ def rower_update_empower_view( 'startdate':startdate, 'enddate':enddate, }) - + if request.method == 'POST' and 'workouts' in request.POST: form = WorkoutMultipleCompareForm(request.POST) @@ -424,7 +438,7 @@ def rower_update_empower_view( cd = form.cleaned_data workouts = cd['workouts'] workoutdicts = [] - + for w in workouts: if w.user != r: message = "You can only alter your own workouts" @@ -440,7 +454,7 @@ def rower_update_empower_view( messages.error(request,message) else: - + workoutdict = { 'id':w.id, 'boattype':w.boattype, @@ -454,7 +468,7 @@ def rower_update_empower_view( w.workoutsource = 'speedcoach2corrected' w.save() - + job = myqueue(queuelow,handle_update_empower, request.user.email,workoutdicts, debug=False, @@ -479,7 +493,7 @@ def rower_update_empower_view( workoutsource='speedcoach2', user=r, ).order_by("-date","-starttime") - + form = WorkoutMultipleCompareForm() form.fields["workouts"].queryset = workouts # GET request = prepare form @@ -491,5 +505,3 @@ def rower_update_empower_view( 'form':form, 'rower':r }) - - diff --git a/rowers/views/workoutviews.py b/rowers/views/workoutviews.py index b72db049..592cbc14 100644 --- a/rowers/views/workoutviews.py +++ b/rowers/views/workoutviews.py @@ -131,7 +131,7 @@ def workout_video_view_mini(request,id=''): 'name': w.name }, { - 'url':reverse('workout_video_view',kwargs={'id':encoder.encode_hex(analysis.id)}), + 'url':reverse('workout_video_view_mini',kwargs={'id':encoder.encode_hex(analysis.id)}), 'name': 'Video Analysis' }