From 3b6c2cf84b618b47dfca091370fae8b0d0ae4e6b Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Mon, 8 Feb 2021 08:23:46 +0100 Subject: [PATCH 1/6] hr pie chart label now with new hR zones --- rowers/interactiveplots.py | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py index 9374b4eb..3887e29d 100644 --- a/rowers/interactiveplots.py +++ b/rowers/interactiveplots.py @@ -230,7 +230,7 @@ def interactive_hr_piechart(df,rower,title,totalseconds=0): if totalseconds == 0: totalseconds = sumtimehr - + hrzones = rower.hrzones qry = 'hr < {ut2}'.format(ut2=rower.ut2) qrydata = df.query(qry) @@ -253,12 +253,12 @@ def interactive_hr_piechart(df,rower,title,totalseconds=0): frac_an = totalseconds*df.query(qry)['deltat'].sum()/sumtimehr datadict = { - ' Date: Tue, 9 Feb 2021 08:28:00 +0100 Subject: [PATCH 2/6] fix #607 --- rowers/templates/flexchartstacked.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rowers/templates/flexchartstacked.html b/rowers/templates/flexchartstacked.html index 11a54331..665453ac 100644 --- a/rowers/templates/flexchartstacked.html +++ b/rowers/templates/flexchartstacked.html @@ -21,11 +21,11 @@

{% if workout|previousworkout:rower.user %} - Previous  {% endif %} {% if workout|nextworkout:rower.user %} - Next {% endif %}

From 4b463f472ab46bd5844f0dfb0d6c82a7946c9eee Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Tue, 9 Feb 2021 08:32:40 +0100 Subject: [PATCH 3/6] fix #605 --- rowers/dataprep.py | 3 +++ rowers/templates/splitworkout.html | 12 ++++++------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/rowers/dataprep.py b/rowers/dataprep.py index 5aa8720d..8a13960f 100644 --- a/rowers/dataprep.py +++ b/rowers/dataprep.py @@ -2255,6 +2255,7 @@ def new_workout_from_df(r, df, boattype = parent.boattype notes = parent.notes summary = parent.summary + rpe = parent.rpe if parent.privacy == 'hidden': makeprivate = True else: @@ -2267,6 +2268,7 @@ def new_workout_from_df(r, df, notes = '' summary = '' makeprivate = False + rpe = 0 if startdatetime == '': startdatetime = timezone.now() @@ -2305,6 +2307,7 @@ def new_workout_from_df(r, df, inboard=inboard, makeprivate=makeprivate, dosmooth=False, + rpe=rpe, consistencychecks=False) job = myqueue(queuehigh,handle_calctrimp,id,csvfilename,r.ftp,r.sex,r.hrftp,r.max,r.rest) diff --git a/rowers/templates/splitworkout.html b/rowers/templates/splitworkout.html index b07c1a54..5c93f159 100644 --- a/rowers/templates/splitworkout.html +++ b/rowers/templates/splitworkout.html @@ -7,7 +7,7 @@ {% block main %}

Split Workout

- + {% localtime on %}
  • @@ -17,19 +17,19 @@ {{ form.as_table }} {% csrf_token %} - +

  • - + - + {{ thescript |safe }} - + {{ thediv |safe }} @@ -67,7 +67,7 @@

    - + {% endblock %} From 7295e0e70d31360d56f852511c0ba3ac05f1413d Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Tue, 9 Feb 2021 08:39:52 +0100 Subject: [PATCH 4/6] implemented subscription_cancel --- rowers/braintreestuff.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/rowers/braintreestuff.py b/rowers/braintreestuff.py index 3c7020f2..3bc7546b 100644 --- a/rowers/braintreestuff.py +++ b/rowers/braintreestuff.py @@ -64,6 +64,20 @@ def process_webhook(notification): f.write(timestamp+' '+notification.kind+'\n') if notification.kind == 'subscription_charged_successfully': return send_invoice(notification.subscription) + if notification.kind == 'subscription_canceled': + subscription = notification.subscription + rs = Rower.objects.filter(subscription_id=subscription.id) + if rs.count() == 0: + return 0 + r = rs[0] + result,mesg,errormsg = cancel_subscription(r,subscription.id) + if result: + with open('braintreewebhooks.log','a') as f: + f.write('Subscription canceled: '+subscription.id+'\n') + return subscription.id + with open('braintreewebhooks.log','a') as f: + f.write('Could not cancel Subscription: '+subscription.id+'\n') + return 0 return 0 def send_invoice(subscription): From d0ecd7ceead8047cff142504ff4d7bd7ce35a67e Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Tue, 9 Feb 2021 17:32:55 +0100 Subject: [PATCH 5/6] first version erase column --- rowers/templates/workout_data.html | 20 +++- rowers/templates/workout_erase_column.html | 44 ++++++++ rowers/templatetags/rowerfilters.py | 11 ++ rowers/urls.py | 2 + rowers/views/workoutviews.py | 120 +++++++++++++++++++++ 5 files changed, 195 insertions(+), 2 deletions(-) create mode 100644 rowers/templates/workout_erase_column.html diff --git a/rowers/templates/workout_data.html b/rowers/templates/workout_data.html index a259bb35..a5ce5581 100644 --- a/rowers/templates/workout_data.html +++ b/rowers/templates/workout_data.html @@ -17,8 +17,24 @@

    -
  • - {{ htmltable|safe }} +
  • +
  • + + {% endfor %} + + {% for row in data.values.tolist %} + + + {% for value in row %} + + {% endfor %} + + {% endfor %} +
    + {% for i in cols %} + {{i}} erase
    + {{ forloop.counter0 }} + {{ value }}
diff --git a/rowers/templates/workout_erase_column.html b/rowers/templates/workout_erase_column.html new file mode 100644 index 00000000..12d13549 --- /dev/null +++ b/rowers/templates/workout_erase_column.html @@ -0,0 +1,44 @@ +{% extends "newbase.html" %} +{% load staticfiles %} +{% load rowerfilters %} + +{% block title %}Workout Data{% endblock %} + +{% block main %} +

Erase {{ column }} for {{ workout.name }}

+ +
    +
  • +

    + This will erase column {{ column }} from the following workout: +

    + + + + + + + + + + + + +
    Name:{{ workout.name }}
    Date:{{ workout.date }}
    Time:{{ workout.starttime }}
    Distance:{{ workout.distance }}m
    Duration:{{ workout.duration |durationprint:"%H:%M:%S.%f" }}
    +

    + The data cannot be recovered. If you are sure, please confirm. +

    +
  • +
  • +
    + {% csrf_token %} + +
    +
  • +
+ +{% endblock %} + +{% block sidebar %} +{% include 'menu_workout.html' %} +{% endblock %} diff --git a/rowers/templatetags/rowerfilters.py b/rowers/templatetags/rowerfilters.py index dd33bcf1..7cc4d99c 100644 --- a/rowers/templatetags/rowerfilters.py +++ b/rowers/templatetags/rowerfilters.py @@ -85,6 +85,10 @@ def icon(s): except KeyError: return 'fa-chart-line' +@register.filter +def datarows(data): + return range(len(data)) + @register.filter def adaptive(s): u = s @@ -519,11 +523,18 @@ def mayeditplan(obj,request): return mayedit +@register.filter +def iterrows(df): + return df.iterrows() @register.filter(name='times') def times(number): return range(number) +@register.simple_tag +def get_df_iloc(data,i,j): + return data.iloc(i,j) + @register.simple_tag def get_field_id(id,s,form): field_name = s+str(id) diff --git a/rowers/urls.py b/rowers/urls.py index de7a0fb2..c3bda9e1 100644 --- a/rowers/urls.py +++ b/rowers/urls.py @@ -463,6 +463,8 @@ urlpatterns = [ re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/stats/$',views.workout_stats_view,name='workout_stats_view'), re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/data/$',views.workout_data_view, name='workout_data_view'), + re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/(?P\w+)/erase/$',views.workout_erase_column_view, + name='workout_erase_column_view'), re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/zeropower-confirm/$',views.remove_power_confirm_view, name='remove_power_confirm_view'), re_path(r'^workout/(?P\b[0-9A-Fa-f]+\b)/zeropower/$',views.remove_power_view, diff --git a/rowers/views/workoutviews.py b/rowers/views/workoutviews.py index 867c5a20..bdc0a05c 100644 --- a/rowers/views/workoutviews.py +++ b/rowers/views/workoutviews.py @@ -3166,6 +3166,124 @@ def instroke_chart(request,id=0,metric=''): return HttpResponseRedirect(url) +# erase column +@permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True) +def workout_erase_column_view(request, id=0,column=''): + r = getrower(request.user) + w = get_workoutuser(id,request) + + protected = ['time','pace','velo','cumdist','ftime','fpace',] + if column in protected: + messages.error(request,'You cannot erase this protected column') + url = reverse('workout_data_view',kwargs={ + 'id':encoder.encode_hex(w.id) + }) + + return HttpResponseRedirect(url) + + try: + data = dataprep.getsmallrowdata_db([column],ids=[w.id]) + except: + messages.error(request,'Invalid column') + url = reverse('workout_data_view',kwargs={ + 'id':encoder.encode_hex(w.id) + }) + + return HttpResponseRedirect(url) + + try: + cdata = data[column] + except KeyError: + url = reverse('workout_data_view',kwargs={ + 'id':encoder.encode_hex(w.id) + }) + + return HttpResponseRedirect(url) + + + if not column: + url = reverse('workout_data_view',kwargs={ + 'id':encoder.encode_hex(w.id) + }) + + return HttpResponseRedirect(url) + + if request.method == 'POST': + + mms = {} + for m in rowingmetrics: + mms[m[0]] = m[1] + + try: + defaultvalue = mms[column]['default'] + except KeyError: + if not mms[column]['null']: + messages.error(request,'You cannot erase this protected column') + url = reverse('workout_data_view',kwargs={ + 'id':encoder.encode_hex(w.id) + }) + + return HttpResponseRedirect(url) + defaultvalue = 0 + + try: + columnl = dataprep.columndict[column] + except KeyError: + messages.error(request,'You cannot erase this column') + url = reverse('workout_data_view',kwargs={ + 'id':encoder.encode_hex(w.id) + }) + + return HttpResponseRedirect(url) + + row,workout = dataprep.getrowdata(id=w.id) + row.df[columnl] = defaultvalue + print(row.df[columnl]) + row.write_csv(w.csvfilename,gzip=True) + + datadf = dataprep.dataprep(row.df,id=w.id) + + + messages.info(request,'Data for column '+column+' have been erased') + url = reverse('workout_data_view',kwargs={ + 'id':encoder.encode_hex(w.id) + }) + + return HttpResponseRedirect(url) + + + breadcrumbs = [ + { + 'url':'/rowers/list-workouts/', + 'name':'Workouts' + }, + { + 'url':get_workout_default_page(request,id), + 'name': w.name + }, + { + 'url':reverse('workout_data_view',kwargs={'id':id}), + 'name': 'Data Explorer' + } + + ] + + return render(request, + 'workout_erase_column.html', + { + 'column':column, + 'teams':get_my_teams(request.user), + 'workout': w, + 'breadcrumbs': breadcrumbs, + + } + ) + + + + + + # data explorer @permission_required('workout.change_workout',fn=get_workout_by_opaqueid,raise_exception=True) @@ -3268,6 +3386,8 @@ def workout_data_view(request, id=0): 'workout_data.html', { 'htmltable': htmltable, + 'data':datadf, + 'cols':datadf.columns, 'form':form, 'teams':get_my_teams(request.user), 'workout': w, From f1fb46d0e14411cc31ef8f5316bbf33f0ce9db30 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Tue, 9 Feb 2021 18:35:19 +0100 Subject: [PATCH 6/6] fix some bugs --- rowers/dataprep.py | 12 ++++++------ rowers/views/workoutviews.py | 25 +++++++++++++++++++++++-- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/rowers/dataprep.py b/rowers/dataprep.py index 8a13960f..b8ed1b36 100644 --- a/rowers/dataprep.py +++ b/rowers/dataprep.py @@ -1061,8 +1061,8 @@ def get_workoutsummaries(userid,startdate): return df -def workout_goldmedalstandard(workout): - if workout.goldmedalstandard > 0: +def workout_goldmedalstandard(workout,reset=False): + if workout.goldmedalstandard > 0 and not reset: return workout.goldmedalstandard,workout.goldmedalseconds if workout.workouttype in rowtypes: goldmedalstandard,goldmedalseconds = calculate_goldmedalstandard(workout.user,workout) @@ -3018,10 +3018,10 @@ def dataprep(rowdatadf, id=0, bands=True, barchart=True, otwpower=True, -def workout_trimp(w): +def workout_trimp(w,reset=False): r = w.user - if w.trimp > 0: + if w.trimp > 0 and not reset: return w.trimp,w.hrtss r = w.user @@ -3062,8 +3062,8 @@ def workout_trimp(w): return 0,0 -def workout_rscore(w): - if w.rscore > 0: +def workout_rscore(w,reset=False): + if w.rscore > 0 and not reset: return w.rscore,w.normp r = w.user diff --git a/rowers/views/workoutviews.py b/rowers/views/workoutviews.py index bdc0a05c..d9a2b063 100644 --- a/rowers/views/workoutviews.py +++ b/rowers/views/workoutviews.py @@ -3236,13 +3236,34 @@ def workout_erase_column_view(request, id=0,column=''): return HttpResponseRedirect(url) + row,workout = dataprep.getrowdata(id=w.id) row.df[columnl] = defaultvalue - print(row.df[columnl]) - row.write_csv(w.csvfilename,gzip=True) + os.remove(w.csvfilename+'.gz') + + row.write_csv(w.csvfilename,gzip=True) + + + row,workout = dataprep.getrowdata(id=w.id) datadf = dataprep.dataprep(row.df,id=w.id) + if column == 'hr': + w.hrtss = 0 + w.trimp = 0 + w.save() + + if column == 'power': + w.rscore = 0 + w.normp = 0 + w.goldmedalstandard = -1 + w.goldmedalseconds = 0 + w.save() + + trimp,hrtss = dataprep.workout_trimp(w,reset=True) + rscore,normp = dataprep.workout_rscore(w,reset=True) + goldstandard,goldstandardduration = dataprep.workout_goldmedalstandard(w,reset=True) + messages.info(request,'Data for column '+column+' have been erased') url = reverse('workout_data_view',kwargs={