diff --git a/rowers/dataprep.py b/rowers/dataprep.py index 9326cf35..e51e6631 100644 --- a/rowers/dataprep.py +++ b/rowers/dataprep.py @@ -17,6 +17,7 @@ from django.utils import timezone from time import strftime, strptime, mktime, time, daylight import arrow from django.utils.timezone import get_current_timezone + thetimezone = get_current_timezone() from rowingdata import ( TCXParser, RowProParser, ErgDataParser, @@ -25,7 +26,7 @@ from rowingdata import ( MysteryParser, BoatCoachOTWParser, painsledDesktopParser, speedcoachParser, ErgStickParser, SpeedCoach2Parser, FITParser, fitsummarydata, - make_cumvalues, + make_cumvalues,cumcpdata, summarydata, get_file_type, ) @@ -40,7 +41,7 @@ import itertools import math from tasks import ( handle_sendemail_unrecognized, handle_sendemail_breakthrough, - handle_sendemail_hard + handle_sendemail_hard, handle_updatecp,handle_updateergcp ) from django.conf import settings @@ -425,6 +426,106 @@ def paceformatsecs(values): return out +def getcpdata_sql(rower_id,table='cpdata'): + engine = create_engine(database_url, echo=False) + query = sa.text('SELECT * from {table} WHERE user={rower_id};'.format( + rower_id=rower_id, + table=table, + )) + connection = engine.raw_connection() + df = pd.read_sql_query(query, engine) + + return df + +def deletecpdata_sql(rower_id,table='cpdata'): + engine = create_engine(database_url, echo=False) + query = sa.text('DELETE from {table} WHERE user={rower_id};'.format( + rower_id=rower_id, + table=table, + )) + with engine.connect() as conn, conn.begin(): + try: + result = conn.execute(query) + except: + print "Database locked" + conn.close() + engine.dispose() + + + +def updatecpdata_sql(rower_id,delta,cp,table='cpdata',distance=[]): + deletecpdata_sql(rower_id) + df = pd.DataFrame( + { + 'delta':delta, + 'cp':cp, + 'user':rower_id + } + ) + + if not distance.empty: + df['distance'] = distance + + engine = create_engine(database_url, echo=False) + with engine.connect() as conn, conn.begin(): + df.to_sql(table, engine, if_exists='append', index=False) + conn.close() + engine.dispose() + + +def runcpupdate(rower): + startdate = timezone.now()-datetime.timedelta(days=365) + enddate = timezone.now()+datetime.timedelta(days=5) + theworkouts = Workout.objects.filter(user=rower,rankingpiece=True, + workouttype='water', + startdatetime__gte=startdate, + startdatetime__lte=enddate) + + theids = [w.id for w in theworkouts] + + + if settings.DEBUG: + res = handle_updatecp.delay(rower.id,theids,debug=True) + else: + res = queue.enqueue(handle_updatecp,rower.id,theids) + +def fetchcperg(rower,theworkouts): + theids = [int(w.id) for w in theworkouts] + thefilenames = [w.csvfilename for w in theworkouts] + cpdf = getcpdata_sql(rower.id,table='ergcpdata') + + if settings.DEBUG: + res = handle_updateergcp.delay(rower.id,thefilenames,debug=True) + else: + res = queue.enqueue(handle_updateergcp,rower.id,thefilenames) + + return cpdf + + +def fetchcp(rower,theworkouts): + # get all power data from database (plus workoutid) + theids = [int(w.id) for w in theworkouts] + columns = ['power','workoutid','time'] + df = getsmallrowdata_db(columns,ids=theids) + + dfgrouped = df.groupby(['workoutid']) + avgpower2 = dict(dfgrouped.mean()['power'].astype(int)) + + cpdf = getcpdata_sql(rower.id) + + if not cpdf.empty: + return cpdf['delta'],cpdf['cp'],avgpower2 + else: + if settings.DEBUG: + res = handle_updatecp.delay(rower.id,theids,debug=True) + else: + res = queue.enqueue(handle_updatecp,rower.id,theids) + return [],[],avgpower2 + + + return [],[],avgpower2 + + # Processes painsled CSV file to database @@ -567,11 +668,7 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', if dosummary: summary = row.allstats() - #summary = row.summary() - #summary += '\n' - #summary += row.intervalstats() - #workoutstartdatetime = row.rowdatetime timezone_str = 'UTC' try: workoutstartdatetime = timezone.make_aware(row.rowdatetime) @@ -649,24 +746,24 @@ def save_workout_database(f2, r, dosmooth=True, workouttype='rower', ishard = False if workouttype == 'water': df = getsmallrowdata_db(['power', 'workoutid', 'time'], ids=[w.id]) - # delta,cpvalues,avgpower = datautils.getsinglecp(row.df) - thesecs = totaltime - maxt = 1.05 * thesecs - if maxt > 0: - logarr = datautils.getlogarr(maxt) - dfgrouped = df.groupby(['workoutid']) - delta, cpvalues, avgpower = datautils.getcp(dfgrouped, logarr) + if df['power'].mean(): + thesecs = totaltime + maxt = 1.05 * thesecs + if maxt > 0: + logarr = datautils.getlogarr(maxt) + dfgrouped = df.groupby(['workoutid']) + delta, cpvalues, avgpower = datautils.getcp(dfgrouped, logarr) - res, btvalues, res2 = utils.isbreakthrough( - delta, cpvalues, r.p0, r.p1, r.p2, r.p3, r.cpratio) - else: - res = 0 - res2 = 0 - if res: - isbreakthrough = True - res = datautils.updatecp(delta, cpvalues, r) - if res2 and not isbreakthrough: - ishard = True + res, btvalues, res2 = utils.isbreakthrough( + delta, cpvalues, r.p0, r.p1, r.p2, r.p3, r.cpratio) + else: + res = 0 + res2 = 0 + if res: + isbreakthrough = True + res = datautils.updatecp(delta, cpvalues, r) + if res2 and not isbreakthrough: + ishard = True # submit email task to send email about breakthrough workout if isbreakthrough: diff --git a/rowers/dataprepnodjango.py b/rowers/dataprepnodjango.py index c2cd7f9c..767ace9f 100644 --- a/rowers/dataprepnodjango.py +++ b/rowers/dataprepnodjango.py @@ -489,9 +489,9 @@ def testdata(time,distance,pace,spm): return t1 and t2 and t3 and t4 -def getsmallrowdata_db(columns,ids=[]): +def getsmallrowdata_db(columns,ids=[],debug=False): - data = read_cols_df_sql(ids,columns) + data = read_cols_df_sql(ids,columns,debug=debug) return data @@ -548,8 +548,67 @@ def read_df_sql(id,debug=False): engine.dispose() return df +def getcpdata_sql(rower_id,table='cpdata',debug=False): + if debug: + engine = create_engine(database_url_debug, echo=False) + else: + engine = create_engine(database_url, echo=False) + + query = sa.text('SELECT * from {table} WHERE user={rower_id};'.format( + rower_id=rower_id, + table=table, + )) + connection = engine.raw_connection() + df = pd.read_sql_query(query, engine) + + return df + +def deletecpdata_sql(rower_id,table='cpdata',debug=False): + if debug: + engine = create_engine(database_url_debug, echo=False) + else: + engine = create_engine(database_url, echo=False) + + query = sa.text('DELETE from {table} WHERE user={rower_id};'.format( + rower_id=rower_id, + table=table, + )) + with engine.connect() as conn, conn.begin(): + try: + result = conn.execute(query) + except: + print "Database locked" + conn.close() + engine.dispose() + + + +def updatecpdata_sql(rower_id,delta,cp,table='cpdata',distance=pd.Series([]),debug=False): + deletecpdata_sql(rower_id,table=table,debug=debug) + df = pd.DataFrame( + { + 'delta':delta, + 'cp':cp, + 'user':rower_id + } + ) + + if not distance.empty: + df['distance'] = distance + + if debug: + engine = create_engine(database_url_debug, echo=False) + else: + engine = create_engine(database_url, echo=False) + + with engine.connect() as conn, conn.begin(): + df.to_sql(table, engine, if_exists='append', index=False) + conn.close() + engine.dispose() + + def smalldataprep(therows,xparam,yparam1,yparam2): diff --git a/rowers/datautils.py b/rowers/datautils.py index f01aac3b..5d853157 100644 --- a/rowers/datautils.py +++ b/rowers/datautils.py @@ -107,6 +107,7 @@ def getsinglecp(df): return delta,cpvalue,avgpower + def getcp(dfgrouped,logarr): delta = [] cpvalue = [] @@ -206,3 +207,4 @@ def getmaxwattinterval(tt,ww,i): deltat = 0 return deltat,wmax + diff --git a/rowers/forms.py b/rowers/forms.py index 34b14e4d..4923a517 100644 --- a/rowers/forms.py +++ b/rowers/forms.py @@ -152,6 +152,11 @@ class WorkFlowMiddlePanelElement(forms.Form): # The form to indicate additional actions to be performed immediately # after a successful upload + +nextpages = list(landingpages) +nextpages.append(('workout_upload_view','Upload Another File')) +nextpages = tuple(nextpages) + class UploadOptionsForm(forms.Form): plotchoices = ( ('timeplot','Time Plot'), @@ -181,9 +186,9 @@ class UploadOptionsForm(forms.Form): makeprivate = forms.BooleanField(initial=False,required=False, label='Make Workout Private') - landingpage = forms.ChoiceField(choices=landingpages, + landingpage = forms.ChoiceField(choices=nextpages, initial='workout_edit_view', - label='Landing Page') + label='After Upload, go to') class Meta: fields = ['make_plot','plottype','upload_toc2','makeprivate'] diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py index dff5c227..29edb78c 100644 --- a/rowers/interactiveplots.py +++ b/rowers/interactiveplots.py @@ -41,6 +41,7 @@ import pandas as pd from pytz import timezone as tz,utc from django.utils.timezone import get_current_timezone from django.utils.timezone import activate +from django.utils import timezone activate(settings.TIME_ZONE) thetimezone = get_current_timezone() @@ -1065,10 +1066,9 @@ def interactive_otwcpchart(powerdf,promember=0): return [script,div,p1,ratio,message] -def interactive_cpchart(thedistances,thesecs,theavpower, +def interactive_cpchart(rower,thedistances,thesecs,theavpower, theworkouts,promember=0): - message = 0 # plot tools if (promember==1): @@ -1086,7 +1086,7 @@ def interactive_cpchart(thedistances,thesecs,theavpower, p = pd.Series(500./velo) p2 = p.fillna(method='ffill').apply(lambda x: timedeltaconv(x)) - + source = ColumnDataSource( data = dict( dist = thedistances, @@ -1108,6 +1108,7 @@ def interactive_cpchart(thedistances,thesecs,theavpower, paulslope = 5.0/np.log10(2.0) paulintercept = p[0]-paulslope*np.log10(thedistances[0]) + fitx = pd.Series(np.arange(100)*2*max(np.log10(thedistances))/100.) fitp = paulslope*fitx+paulintercept @@ -1198,16 +1199,14 @@ def interactive_cpchart(thedistances,thesecs,theavpower, plot.xaxis.axis_label = "Duration (seconds)" plot.yaxis.axis_label = "Power (W)" - therows = [] - for workout in theworkouts: - f1 = workout.csvfilename - rowdata = rdata(f1) - if rowdata != 0: - therows.append(rowdata) - cpdata = cumcpdata(therows) + cpdata = dataprep.fetchcperg(rower, theworkouts) - velo = cpdata['Distance']/cpdata['Delta'] + if cpdata.empty: + message = 'Calculations are running in the background. Please refresh this page to see updated results' + return ['','',paulslope,paulintercept,p1,message] + + velo = cpdata['distance']/cpdata['delta'] p = 500./velo @@ -1215,12 +1214,12 @@ def interactive_cpchart(thedistances,thesecs,theavpower, source2 = ColumnDataSource( data = dict( - duration = cpdata['Delta'], - power = cpdata['CP'], + duration = cpdata['delta'], + power = cpdata['cp'], tim = niceformat( - cpdata['Delta'].fillna(method='ffill').apply(lambda x: timedeltaconv(x)) + cpdata['delta'].fillna(method='ffill').apply(lambda x: timedeltaconv(x)) ), - dist = cpdata['Distance'], + dist = cpdata['distance'], pace = nicepaceformat(p2), ) ) @@ -1252,6 +1251,7 @@ def interactive_cpchart(thedistances,thesecs,theavpower, script, div = components(plot) + return [script,div,paulslope,paulintercept,p1,message] def interactive_windchart(id=0,promember=0): diff --git a/rowers/metrics.py b/rowers/metrics.py index 4e741b08..9c1fcfa0 100644 --- a/rowers/metrics.py +++ b/rowers/metrics.py @@ -294,7 +294,7 @@ dropping to 8m for race pace in the single.""", 'yparam1':'driveenergy', 'yparam2':'None', 'xparam':'spm', - 'plottype':'line', + 'plottype':'scatter', 'workouttype':'ote', 'reststrokes':True, 'notes':"""This chart shows the Work per Stroke versus Stroke Rate. diff --git a/rowers/models.py b/rowers/models.py index 54002477..1b233404 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -641,7 +641,30 @@ attrs.update(strokedatafields) StrokeData = type(str('StrokeData'), (models.Model,), attrs ) - + +# Storing data for the OTW CP chart +class cpdata(models.Model): + delta = models.IntegerField(default=0) + cp = models.FloatField(default=0) + user = models.IntegerField(default=0) + + class Meta: + db_table = 'cpdata' + index_together = ['user'] + app_label = 'rowers' + +# Storing data for the OTW CP chart +class ergcpdata(models.Model): + delta = models.IntegerField(default=0) + cp = models.FloatField(default=0) + distance = models.FloatField(default=0) + user = models.IntegerField(default=0) + + class Meta: + db_table = 'ergcpdata' + index_together = ['user'] + app_label = 'rowers' + # A wrapper around the png files class GraphImage(models.Model): filename = models.CharField(default='',max_length=150,blank=True,null=True) diff --git a/rowers/tasks.py b/rowers/tasks.py index bea8eddf..372dc1cb 100644 --- a/rowers/tasks.py +++ b/rowers/tasks.py @@ -26,7 +26,7 @@ from utils import deserialize_list from rowers.dataprepnodjango import ( update_strokedata, new_workout_from_file, - getsmallrowdata_db, + getsmallrowdata_db, updatecpdata_sql ) from django.core.mail import send_mail, EmailMessage @@ -400,9 +400,45 @@ def handle_otwsetpower(f1, boattype, weightvalue, return 1 -# This function generates all the static (PNG image) plots + +@app.task +def handle_updateergcp(rower_id,workoutfilenames,debug=False): + therows = [] + for f1 in workoutfilenames: + rowdata = rdata(f1) + if rowdata != 0: + therows.append(rowdata) + + cpdata = rowingdata.cumcpdata(therows) + cpdata.columns = cpdata.columns.str.lower() + + updatecpdata_sql(rower_id,cpdata['delta'],cpdata['cp'], + table='ergcpdata',distance=cpdata['distance'], + debug=debug) + + return 1 +@app.task +def handle_updatecp(rower_id,workoutids,debug=False): + columns = ['power','workoutid','time'] + df = getsmallrowdata_db(columns,ids=workoutids,debug=debug) + dfgrouped = df.groupby(['workoutid']) + + if not df.empty: + maxt = 1.05*df['time'].max()/1000. + else: + maxt = 1000. + + logarr = datautils.getlogarr(maxt) + + + delta,cpvalue,avgpower = datautils.getcp(dfgrouped,logarr) + + updatecpdata_sql(rower_id,delta,cpvalue,debug=debug) + + return 1 + @app.task def handle_makeplot(f1, f2, t, hrdata, plotnr, imagename): diff --git a/rowers/templates/flexchart3otw.html b/rowers/templates/flexchart3otw.html index 02e698d3..c7f2517a 100644 --- a/rowers/templates/flexchart3otw.html +++ b/rowers/templates/flexchart3otw.html @@ -189,7 +189,12 @@ {% else %} > {% endif %} - + + {% if favoritechartnotes %} +
+

Chart {{ favoritenr|add:1 }}:{{ favoritechartnotes }}

+
+ {% endif %} {% endblock %} diff --git a/rowers/templates/flexthumbnails.html b/rowers/templates/flexthumbnails.html index e036ad44..0ff56cc2 100644 --- a/rowers/templates/flexthumbnails.html +++ b/rowers/templates/flexthumbnails.html @@ -8,7 +8,9 @@ {{ chart.div | safe }} + {% if rower.showfavoritechartnotes %} {{ chart.notes }} + {% endif %} {% endfor %} diff --git a/rowers/urls.py b/rowers/urls.py index a218c9b3..d33c32b6 100644 --- a/rowers/urls.py +++ b/rowers/urls.py @@ -177,7 +177,7 @@ urlpatterns = [ url(r'^graph/(?P\d+)/deleteconfirm$',views.graph_delete_confirm_view), url(r'^graph/(?P\d+)/delete$',views.graph_delete_view), url(r'^workout/upload/team/$',views.team_workout_upload_view), - url(r'^workout/upload/$',views.workout_upload_view), + url(r'^workout/upload/$',views.workout_upload_view,name='workout_upload_view'), url(r'^workout/(?P\d+)/histo$',views.workout_histo_view), url(r'^workout/(?P\d+)/task$',views.workout_test_task_view), url(r'^workout/(?P\d+)/forcecurve$',views.workout_forcecurve_view), diff --git a/rowers/views.py b/rowers/views.py index cdaed4ca..0478c968 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -98,7 +98,8 @@ from rowers.rows import handle_uploaded_file from rowers.tasks import handle_makeplot,handle_otwsetpower,handle_sendemailtcx,handle_sendemailcsv from rowers.tasks import ( handle_sendemail_unrecognized,handle_sendemailnewcomment, - handle_sendemailnewresponse, handle_updatedps + handle_sendemailnewresponse, handle_updatedps, + handle_updatecp ) from scipy.signal import savgol_filter @@ -576,32 +577,6 @@ def add_workout_from_strokedata(user,importid,data,strokedata, timestr = strftime("%Y%m%d-%H%M%S") - # # auto smoothing - # pace = df[' Stroke500mPace (sec/500m)'].values - # velo = 500./pace - - # f = df['TimeStamp (sec)'].diff().mean() - # windowsize = 2*(int(10./(f)))+1 - # if windowsize <= 3: - # windowsize = 5 - - # df['originalvelo'] = velo - - # if windowsize > 3 and windowsize < len(velo): - # velo2 = savgol_filter(velo,windowsize,3) - # else: - # velo2=velo - - # velo3 = pd.Series(velo2) - # velo3 = velo3.replace([-np.inf,np.inf],np.nan) - # velo3 = velo3.fillna(method='ffill') - - # pace2 = 500./abs(velo3) - # df[' Stroke500mPace (sec/500m)'] = pace2 - - # df = df.fillna(0) - - # end autosmoothing # Create CSV file name and save data to CSV file csvfilename ='media/Import_'+str(importid)+'.csv' @@ -622,12 +597,15 @@ def add_workout_from_strokedata(user,importid,data,strokedata, totaldist = 0 totaltime = 0 - id,message = dataprep.save_workout_database(csvfilename,r, - workouttype=workouttype, - title=title,notes=comments, - totaldist=totaldist, - totaltime=totaltime, - workoutsource=workoutsource) + id,message = dataprep.save_workout_database( + csvfilename,r, + workouttype=workouttype, + title=title,notes=comments, + totaldist=totaldist, + totaltime=totaltime, + workoutsource=workoutsource, + dosummary=True + ) @@ -2755,6 +2733,7 @@ def rankings_view(request,theuser=0, rankingdurations.append(datetime.time(minute=1)) rankingdurations.append(datetime.time(minute=4)) rankingdurations.append(datetime.time(minute=30)) + rankingdurations.append(datetime.time(hour=1,minute=15)) rankingdurations.append(datetime.time(hour=1)) thedistances = [] @@ -2809,8 +2788,10 @@ def rankings_view(request,theuser=0, # create interactive plot if len(thedistances) !=0 : - res = interactive_cpchart(thedistances,thesecs,theavpower, - theworkouts,promember=promember) + res = interactive_cpchart( + r,thedistances,thesecs,theavpower, + theworkouts,promember=promember + ) script = res[0] div = res[1] paulslope = res[2] @@ -2977,6 +2958,10 @@ def workout_update_cp_view(request,id=0): row.rankingpiece = True row.save() + r = getrower(request.user) + + dataprep.runcpupdate(r) + url = reverse(otwrankings_view) return HttpResponseRedirect(url) @@ -3078,6 +3063,7 @@ def otwrankings_view(request,theuser=0, rankingdurations.append(datetime.time(minute=4)) rankingdurations.append(datetime.time(minute=30)) rankingdurations.append(datetime.time(hour=1)) + rankingdurations.append(datetime.time(hour=1,minute=15)) thedistances = [] theworkouts = [] @@ -3089,39 +3075,15 @@ def otwrankings_view(request,theuser=0, startdatetime__lte=enddate) - # get all power data from database (plus workoutid) - theids = [int(w.id) for w in theworkouts] - columns = ['power','workoutid','time'] - df = dataprep.getsmallrowdata_db(columns,ids=theids) - - thesecs = [] - - for w in theworkouts: - timesecs = 3600*w.duration.hour - timesecs += 60*w.duration.minute - timesecs += w.duration.second - timesecs += 1.e-5*w.duration.microsecond - - thesecs.append(timesecs) - - - if len(thesecs) != 0: - maxt = 1.05*pd.Series(thesecs).max() - else: - maxt = 1000. - - - logarr = datautils.getlogarr(maxt) - - dfgrouped = df.groupby(['workoutid']) - delta,cpvalue,avgpower = datautils.getcp(dfgrouped,logarr) + delta,cpvalue,avgpower = dataprep.fetchcp(r,theworkouts) powerdf = pd.DataFrame({ 'Delta':delta, 'CP':cpvalue, }) - + if powerdf.empty: + messages.info(request,'Your calculations are running in the background. Please reload this page.') powerdf = powerdf[powerdf['CP']>0] powerdf.dropna(axis=0,inplace=True) @@ -3203,7 +3165,7 @@ def otwrankings_view(request,theuser=0, del form.fields["pieceunit"] - + messages.error(request,message) return render(request, 'otwrankings.html', {'rankingworkouts':theworkouts, @@ -6079,6 +6041,7 @@ def workout_workflow_view(request,id): 'mapscript':mapscript, 'mapdiv':mapdiv, 'statcharts':statcharts, + 'rower':r, }) # The famous flex chart @@ -6097,7 +6060,7 @@ def workout_flexchart3_view(request,*args,**kwargs): try: favoritenr = int(request.GET['favoritechart']) except: - favoritenr = 0 + favoritenr = -1 try: @@ -6133,7 +6096,7 @@ def workout_flexchart3_view(request,*args,**kwargs): try: t = favorites[favoritenr].xparam except IndexError: - favoritenr=0 + favoritenr=-1 if 'xparam' in kwargs: xparam = kwargs['xparam'] @@ -6163,6 +6126,13 @@ def workout_flexchart3_view(request,*args,**kwargs): else: yparam2 = 'hr' + print favoritenr + if favoritenr>=0 and r.showfavoritechartnotes: + favoritechartnotes = favorites[favoritenr].notes + else: + favoritechartnotes = '' + favoritenr = 0 + if 'plottype' in kwargs: plottype = kwargs['plottype'] else: @@ -6247,6 +6217,7 @@ def workout_flexchart3_view(request,*args,**kwargs): 'yparam1':yparam1, 'yparam2':yparam2, 'plottype':plottype, + 'favoritechartnotes':favoritechartnotes, 'mayedit':mayedit, 'promember':promember, 'axchoicesbasic':axchoicesbasic, @@ -6275,6 +6246,7 @@ def workout_flexchart3_view(request,*args,**kwargs): 'plottype':plottype, 'axchoicesbasic':axchoicesbasic, 'axchoicespro':axchoicespro, + 'favoritechartnotes':favoritechartnotes, 'noylist':noylist, 'mayedit':mayedit, 'promember':promember, @@ -6655,6 +6627,10 @@ def workout_edit_view(request,id=0,message="",successmessage=""): r.write_csv(row.csvfilename,gzip=True) dataprep.update_strokedata(id,r.df) successmessage = "Changes saved" + + if rankingpiece: + dataprep.runcpupdate(row.user) + messages.info(request,successmessage) url = reverse(workout_edit_view, kwargs = { @@ -7834,10 +7810,14 @@ def workout_upload_view(request, else: messages.error(request,message) - url = reverse(landingpage, - kwargs = { - 'id':w.id, - }) + if landingpage != 'workout_upload_view': + url = reverse(landingpage, + kwargs = { + 'id':w.id, + }) + else: + url = reverse(landingpage) + return HttpResponseRedirect(url) else: response = render(request, @@ -8561,11 +8541,13 @@ def rower_favoritecharts_view(request): plottype = favorites_form.cleaned_data.get('plottype') workouttype = favorites_form.cleaned_data.get('workouttype') reststrokes = favorites_form.cleaned_data.get('reststrokes') + notes = favorites_form.cleaned_data.get('notes') new_instances.append(FavoriteChart(user=r, yparam1=yparam1, yparam2=yparam2, xparam=xparam, plottype=plottype, + notes=notes, workouttype=workouttype, reststrokes=reststrokes)) try: @@ -8802,6 +8784,7 @@ def rower_edit_view(request,message=""): email = ucd['email'] defaultlandingpage = cd['defaultlandingpage'] weightcategory = cd['weightcategory'] + showfavoritechartnotes = cd['showfavoritechartnotes'] getemailnotifications = cd['getemailnotifications'] defaulttimezone=cd['defaulttimezone'] u = request.user @@ -8818,6 +8801,7 @@ def rower_edit_view(request,message=""): r.weightcategory = weightcategory r.getemailnotifications = getemailnotifications r.defaultlandingpage = defaultlandingpage + r.showfavoritechartnotes = showfavoritechartnotes r.save() form = RowerForm(instance=r) powerform = RowerPowerForm(instance=r)