From a226a957c8f2cd3b71fa3366c08f95d05433f64a Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Thu, 12 Oct 2017 10:02:50 +0200 Subject: [PATCH 1/6] implemented default set of flex favs on user registration --- rowers/metrics.py | 59 ++++++++++++++++++++++++++++- rowers/models.py | 2 + rowers/templates/flexchart3.html | 2 - rowers/templates/flexchart3otw.html | 2 - rowers/views.py | 23 ++++++++++- 5 files changed, 81 insertions(+), 7 deletions(-) diff --git a/rowers/metrics.py b/rowers/metrics.py index b4140f1c..27694003 100644 --- a/rowers/metrics.py +++ b/rowers/metrics.py @@ -219,7 +219,7 @@ rowingmetrics = ( 'ax_max': 15, 'default': 0, 'mode':'both', - 'type': 'pro'}), + 'type': 'basic'}), ) @@ -236,3 +236,60 @@ axlabels = {ax[0]:ax[1] for ax in axes} yaxminima = {ax[0]:ax[2] for ax in axes} yaxmaxima = {ax[0]:ax[3] for ax in axes} + +defaultfavoritecharts = ( + { + 'yparam1':'pace', + 'yparam2':'spm', + 'xparam':'time', + 'plottype':'line', + 'workouttype':'both', + 'reststrokes':True, + 'notes':'Some Notes 1', + }, + { + 'yparam1':'pace', + 'yparam2':'hr', + 'xparam':'time', + 'plottype':'line', + 'workouttype':'both', + 'reststrokes':True, + 'notes':'Some Notes 2', + }, + { + 'yparam1':'distanceperstroke', + 'yparam2':'hr', + 'xparam':'time', + 'plottype':'line', + 'workouttype':'otw', + 'reststrokes':True, + 'notes':'Some Notes 3', + }, + { + 'yparam1':'strokeenergy', + 'yparam2':'hr', + 'xparam':'time', + 'plottype':'line', + 'workouttype':'ote', + 'reststrokes':True, + 'notes':'Some Notes 3', + }, + { + 'yparam1':'distanceperstroke', + 'yparam2':'None', + 'xparam':'spm', + 'plottype':'line', + 'workouttype':'otw', + 'reststrokes':True, + 'notes':'Some Notes 4', + }, + { + 'yparam1':'strokeenergy', + 'yparam2':'None', + 'xparam':'spm', + 'plottype':'line', + 'workouttype':'ote', + 'reststrokes':True, + 'notes':'Some Notes 4', + }, + ) diff --git a/rowers/models.py b/rowers/models.py index 6bb2c91e..2913c6be 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -344,6 +344,8 @@ class FavoriteChart(models.Model): default='both', verbose_name='Workout Type') reststrokes = models.BooleanField(default=True,verbose_name="Incl. Rest") + notes = models.CharField(max_length=300,verbose_name='Chart Notes', + default='Flex Chart Notes',blank=True) user = models.ForeignKey(Rower) diff --git a/rowers/templates/flexchart3.html b/rowers/templates/flexchart3.html index aa49ff65..37aaac5c 100644 --- a/rowers/templates/flexchart3.html +++ b/rowers/templates/flexchart3.html @@ -168,7 +168,6 @@ -{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
{% if maxfav >= 0 %} @@ -204,7 +203,6 @@ {% endif %}
-{% endif %} {% endblock %} {% endlocaltime %} diff --git a/rowers/templates/flexchart3otw.html b/rowers/templates/flexchart3otw.html index 52a8eeaa..5da6e48c 100644 --- a/rowers/templates/flexchart3otw.html +++ b/rowers/templates/flexchart3otw.html @@ -151,7 +151,6 @@ -{% if user.rower.rowerplan == 'pro' or user.rower.rowerplan == 'coach' %}
{% if maxfav >= 0 %} @@ -187,7 +186,6 @@ {% endif %}
-{% endif %} {% endblock %} {% endlocaltime %} diff --git a/rowers/views.py b/rowers/views.py index 074b5b65..03f119a3 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -49,7 +49,7 @@ from rowers.models import ( WorkoutComment,WorkoutCommentForm,RowerExportForm, ) from rowers.models import FavoriteForm,BaseFavoriteFormSet,SiteAnnouncement -from rowers.metrics import rowingmetrics +from rowers.metrics import rowingmetrics,defaultfavoritecharts import rowers.uploads as uploads from django.forms.formsets import formset_factory import StringIO @@ -324,6 +324,22 @@ def ispromember(user): result = False return result +# More User/Rower utils +def add_defaultfavorites(r): + for c in defaultfavoritecharts: + f = FavoriteChart(user=r, + yparam1=c['yparam1'], + yparam2=c['yparam2'], + xparam=c['xparam'], + plottype=c['plottype'], + workouttype=c['workouttype'], + reststrokes=c['reststrokes'], + notes=c['notes']) + + f.save() + return 1 + + # User registration def rower_register_view(request): if request.method == 'POST': @@ -344,6 +360,9 @@ def rower_register_view(request): therower.save() + # create default favorite charts + add_defaultfavorites(therower) + # Create Sample workout f = 'media/testdata.csv.gz' timestr = strftime("%Y%m%d-%H%M%S") @@ -8258,7 +8277,7 @@ def workout_summary_edit_view(request,id,message="",successmessage="" }) # Page where user can manage his favorite charts -@user_passes_test(ispromember,login_url="/rowers/me/edit",redirect_field_name=None) +@login_required() def rower_favoritecharts_view(request): message = '' successmessage = '' From 08b49b32bbd8bb6ea4a8b0ea3a1ecbbfb1b41318 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Thu, 12 Oct 2017 12:37:33 +0200 Subject: [PATCH 2/6] more around default fav charts --- rowers/metrics.py | 22 +++++++++++++++------- rowers/models.py | 13 +++++++++++-- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/rowers/metrics.py b/rowers/metrics.py index 27694003..b2986565 100644 --- a/rowers/metrics.py +++ b/rowers/metrics.py @@ -245,7 +245,7 @@ defaultfavoritecharts = ( 'plottype':'line', 'workouttype':'both', 'reststrokes':True, - 'notes':'Some Notes 1', + 'notes':"""This chart shows your pace and stroke rate versus time. """, }, { 'yparam1':'pace', @@ -254,7 +254,9 @@ defaultfavoritecharts = ( 'plottype':'line', 'workouttype':'both', 'reststrokes':True, - 'notes':'Some Notes 2', + 'notes':"""This chart shows your pace and heart rate versus time. +Heart rate values will be shown only when it is in your data, i.e. +in case you recorded your heart rate during your workout""", }, { 'yparam1':'distanceperstroke', @@ -263,7 +265,8 @@ defaultfavoritecharts = ( 'plottype':'line', 'workouttype':'otw', 'reststrokes':True, - 'notes':'Some Notes 3', + 'notes':"""This chart shows the Distance covered per stroke, and your +heart rate versus time. """, }, { 'yparam1':'strokeenergy', @@ -272,16 +275,20 @@ defaultfavoritecharts = ( 'plottype':'line', 'workouttype':'ote', 'reststrokes':True, - 'notes':'Some Notes 3', + 'notes':"""This chart shows the Work per Stroke and your heart rate +plotted versus time. """, }, { 'yparam1':'distanceperstroke', 'yparam2':'None', 'xparam':'spm', - 'plottype':'line', + 'plottype':'scatter', 'workouttype':'otw', 'reststrokes':True, - 'notes':'Some Notes 4', + 'notes':"""This chart shows the Distance per Stroke versus stroke +stroke rate. You should see a steady decline of the Distance per Stroke +as you increase stroke rate. Typical values are > 10m for steady state +dropping to 8m for race pace in the single.""", }, { 'yparam1':'strokeenergy', @@ -290,6 +297,7 @@ defaultfavoritecharts = ( 'plottype':'line', 'workouttype':'ote', 'reststrokes':True, - 'notes':'Some Notes 4', + 'notes':"""This chart shows the Work per Stroke versus Stroke Rate. +This value should be fairly constant across all stroke rates.""", }, ) diff --git a/rowers/models.py b/rowers/models.py index 2913c6be..af0b3374 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -298,6 +298,10 @@ class Rower(models.Model): defaulttimezone = models.CharField(default='UTC',max_length=100, choices=timezones, verbose_name='Default Time Zone') + + # Show flex chart notes + showfavoritechartnotes = models.BooleanField(default=True, + verbose_name='Show Notes for Favorite Charts') def __str__(self): return self.user.username @@ -353,7 +357,11 @@ class FavoriteForm(ModelForm): class Meta: model = FavoriteChart fields = ['xparam','yparam1','yparam2', - 'plottype','workouttype','reststrokes'] + 'plottype','workouttype','reststrokes','notes'] + widgets = { + 'notes': forms.Textarea, + } + # To generate favorite chart forms on the fly class BaseFavoriteFormSet(BaseFormSet): @@ -830,7 +838,8 @@ class RowerPowerZonesForm(ModelForm): class AccountRowerForm(ModelForm): class Meta: model = Rower - fields = ['weightcategory','getemailnotifications','defaulttimezone'] + fields = ['weightcategory','getemailnotifications', + 'defaulttimezone','showfavoritechartnotes'] class UserForm(ModelForm): class Meta: From 3028809d24a1948983773d4b001063a78197b059 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Thu, 12 Oct 2017 13:04:18 +0200 Subject: [PATCH 3/6] removed obsolete flexchart template files --- rowers/models.py | 6 +- rowers/templates/favoritecharts.html | 11 +- rowers/templates/flexchart.html | 95 ------------ rowers/templates/flexchart3.html | 208 --------------------------- 4 files changed, 9 insertions(+), 311 deletions(-) delete mode 100644 rowers/templates/flexchart.html delete mode 100644 rowers/templates/flexchart3.html diff --git a/rowers/models.py b/rowers/models.py index af0b3374..83e699e3 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -358,9 +358,9 @@ class FavoriteForm(ModelForm): model = FavoriteChart fields = ['xparam','yparam1','yparam2', 'plottype','workouttype','reststrokes','notes'] - widgets = { - 'notes': forms.Textarea, - } +# widgets = { +# 'notes': forms.Textarea, +# } # To generate favorite chart forms on the fly diff --git a/rowers/templates/favoritecharts.html b/rowers/templates/favoritecharts.html index 0ce6512d..efe81047 100644 --- a/rowers/templates/favoritecharts.html +++ b/rowers/templates/favoritecharts.html @@ -5,6 +5,11 @@ {% block content %}
{% csrf_token %} +
+
+

+
+
{{ favorites_formset.management_form }} {% for favorites_form in favorites_formset %} @@ -18,11 +23,6 @@

 

-
-
-

-
-
@@ -37,4 +37,5 @@ }); + {% endblock %} diff --git a/rowers/templates/flexchart.html b/rowers/templates/flexchart.html deleted file mode 100644 index 479cc35b..00000000 --- a/rowers/templates/flexchart.html +++ /dev/null @@ -1,95 +0,0 @@ -{% extends "base.html" %} -{% load staticfiles %} -{% load rowerfilters %} - -{% block title %} Flexible Plot {% endblock %} - -{% block content %} - - - - - {{ interactiveplot |safe }} - - - - - - - -

 

- -
- - -
-
- Time -
-
- Distance -
- -
- -
-
- Pace -
-
- HR -
-
- SPM -
-
- Power -
-
- -
- -
- - - {{ the_div|safe }} - -
- -{% endblock %} \ No newline at end of file diff --git a/rowers/templates/flexchart3.html b/rowers/templates/flexchart3.html deleted file mode 100644 index 37aaac5c..00000000 --- a/rowers/templates/flexchart3.html +++ /dev/null @@ -1,208 +0,0 @@ -{% extends "base.html" %} -{% load staticfiles %} -{% load rowerfilters %} -{% load tz %} - -{% block title %} Flexible Plot {% endblock %} - -{% localtime on %} -{% block content %} - -{{ js_res | safe }} -{{ css_res| safe }} - - - - - -{{ the_script |safe }} - - - - - - - -

 

- -
- - - - -
-
-
- {% csrf_token %} - {% if workstrokesonly %} - - - {% else %} - - - {% endif %} -
- If your data source allows, this will show or hide strokes taken during rest intervals. -
-
- Line Plot -
- -
- -
- -
- - - {{ the_div|safe }} - -
- -
-
- {% if maxfav >= 0 %} - Manage Favorites - {% else %} -   - {% endif %} -
-
- {% if favoritenr > 0 %} - < - {% else %} - < - {% endif %} -
-
-
- {% csrf_token %} - - {% if workstrokesonly %} - - {% else %} - - {% endif %} - -
-
-
- {% if favoritenr < maxfav %} - > - {% else %} - > - {% endif %} -
-
- -{% endblock %} -{% endlocaltime %} From e806089ef7f95ded6d5450630ee1ccaaa9867e57 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Thu, 12 Oct 2017 22:20:07 +0200 Subject: [PATCH 4/6] v1 of workflow.html - need speed up chart generation --- rowers/interactiveplots.py | 195 ++++++++++++++++++++++++++++++++- rowers/templates/workflow.html | 41 +++++++ rowers/urls.py | 1 + rowers/views.py | 60 ++++++++-- 4 files changed, 288 insertions(+), 9 deletions(-) create mode 100644 rowers/templates/workflow.html diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py index 7e828b40..9732440c 100644 --- a/rowers/interactiveplots.py +++ b/rowers/interactiveplots.py @@ -2482,13 +2482,13 @@ def interactive_flex_chart2(id=0,promember=0, title="Max Distance",callback=callback) callback.args["maxdist"] = slider_dist_max - layout = layoutrow([layoutcolumn([slider_spm_min, + layout = layoutrow([layoutcolumn([annotation, + slider_spm_min, slider_spm_max, slider_dist_min, slider_dist_max, slider_work_min, slider_work_max, - annotation, ], ), plot]) @@ -2499,6 +2499,197 @@ def interactive_flex_chart2(id=0,promember=0, return [script,div,js_resources,css_resources,workstrokesonly] +def thumbnail_flex_chart(id=0,promember=0, + xparam='time', + yparam1='pace', + yparam2='hr', + plottype='line', + workstrokesonly=False): + + + #rowdata,row = dataprep.getrowdata_db(id=id) + columns = [xparam,yparam1,yparam2,'time'] + + rowdata = dataprep.getsmallrowdata_db(columns,ids=[id],doclean=True, + workstrokesonly=workstrokesonly) + + if rowdata.empty: + rowdata = dataprep.getsmallrowdata_db(columns,ids=[id],doclean=True, + workstrokesonly=False) + workstrokesonly=False + + try: + tests = rowdata[yparam2] + except KeyError: + yparam2 = 'None' + + try: + tests = rowdata[yparam1] + except KeyError: + yparam1 = 'None' + + rowdata.dropna(axis=1,how='all',inplace=True) + + if rowdata.empty: + return "","No valid data" + else: + try: + rowdata.sort_values(by='time',ascending=True,inplace=True) + except KeyError: + pass + + workoutstateswork = [1,4,5,8,9,6,7] + workoutstatesrest = [3] + workoutstatetransition = [0,2,10,11,12,13] + + if workstrokesonly: + try: + rowdata = rowdata[~rowdata['workoutstate'].isin(workoutstatesrest)] + except KeyError: + pass + + try: + tseconds = rowdata.ix[:,'time'] + except KeyError: + return '','No time data - cannot make flex plot','','' + + + try: + rowdata['x1'] = rowdata.ix[:,xparam] + except KeyError: + rowdata['x1'] = 0*rowdata.ix[:,'time'] + + try: + rowdata['y1'] = rowdata.ix[:,yparam1] + except KeyError: + rowdata['y1'] = 0*rowdata.ix[:,'time'] + + if yparam2 != 'None': + try: + rowdata['y2'] = rowdata.ix[:,yparam2] + except KeyError: + rowdata['y2'] = 0*rowdata.ix[:,'time'] + else: + rowdata['y2'] = rowdata['y1'] + + if xparam=='time': + xaxmax = tseconds.max() + xaxmin = tseconds.min() + elif xparam=='distance' or xparam=='cumdist': + xaxmax = rowdata['x1'].max() + xaxmin = rowdata['x1'].min() + else: + xaxmax = yaxmaxima[xparam] + xaxmin = yaxminima[xparam] + + x_axis_type = 'linear' + y_axis_type = 'linear' + if xparam == 'time': + x_axis_type = 'datetime' + + if yparam1 == 'pace': + y_axis_type = 'datetime' + y1mean = rowdata.ix[:,'pace'].mean() + + + rowdata['xname'] = axlabels[xparam] + rowdata['yname1'] = axlabels[yparam1] + if yparam2 != 'None': + rowdata['yname2'] = axlabels[yparam2] + else: + rowdata['yname2'] = axlabels[yparam1] + + + # prepare data + source = ColumnDataSource( + rowdata + ) + + + sizing_mode = 'fixed' # 'scale_width' also looks nice with this example + plot = Figure(x_axis_type=x_axis_type,y_axis_type=y_axis_type, + plot_width=200,plot_height=150, + ) + + + + plot.toolbar.logo = None + plot.toolbar_location = None + #plot.yaxis.visible = False + plot.xaxis.axis_label_text_font_size = "7pt" + plot.yaxis.axis_label_text_font_size = "7pt" + plot.xaxis.major_label_text_font_size = "7pt" + plot.yaxis.major_label_text_font_size = "7pt" + # add watermark + plot.extra_y_ranges = {"watermark": watermarkrange} + plot.extra_x_ranges = {"watermark": watermarkrange} + + + + if plottype=='line': + plot.line('x1','y1',source=source) + elif plottype=='scatter': + plot.scatter('x1','y1',source=source,fill_alpha=0.4, + line_color=None) + + plot.xaxis.axis_label = axlabels[xparam] + plot.yaxis.axis_label = axlabels[yparam1] + + + + yrange1 = Range1d(start=yaxminima[yparam1],end=yaxmaxima[yparam1]) + plot.y_range = yrange1 + + if (xparam != 'time') and (xparam != 'distance') and (xparam != 'cumdist'): + xrange1 = Range1d(start=yaxminima[xparam],end=yaxmaxima[xparam]) + plot.x_range = xrange1 + + if xparam == 'time': + xrange1 = Range1d(start=xaxmin,end=xaxmax) + plot.x_range = xrange1 + plot.xaxis[0].formatter = DatetimeTickFormatter( + hours = ["%H"], + minutes = ["%M"], + seconds = ["%S"], + days = ["0"], + months = [""], + years = [""] + ) + + + if yparam1 == 'pace': + plot.yaxis[0].formatter = DatetimeTickFormatter( + seconds = ["%S"], + minutes = ["%M"] + ) + + + if yparam2 != 'None': + yrange2 = Range1d(start=yaxminima[yparam2],end=yaxmaxima[yparam2]) + plot.extra_y_ranges["yax2"] = yrange2 + #= {"yax2": yrange2} + + if plottype=='line': + plot.line('x1','y2',color="red",y_range_name="yax2", + source=source) + + elif plottype=='scatter': + plot.scatter('x1','y2',source=source, + fill_alpha=0.4, + line_color=None,color="red",y_range_name="yax2") + + plot.add_layout(LinearAxis(y_range_name="yax2", + axis_label=axlabels[yparam2], + major_label_text_font_size="7pt", + axis_label_text_font_size="7pt", + ),'right', + ) + + + script, div = components(plot) + + return [script,div] + def interactive_bar_chart(id=0,promember=0): # check if valid ID exists (workout exists) diff --git a/rowers/templates/workflow.html b/rowers/templates/workflow.html new file mode 100644 index 00000000..2a454179 --- /dev/null +++ b/rowers/templates/workflow.html @@ -0,0 +1,41 @@ +{% extends "base.html" %} +{% load staticfiles %} +{% load rowerfilters %} +{% load tz %} + + +{% get_current_timezone as TIME_ZONE %} + +{% block title %}{{ workout.name }}{% endblock %} +{% block og_title %}{{ workout.name }}{% endblock %} +{% block description %}{{ workout.name }} +{{ workout.date }} - {{ workout.distance }}m - {{ workout.duration |durationprint:"%H:%M:%S.%f" }}{% endblock %} +{% block og_description %}{{ workout.name }} +{{ workout.date }} - {{ workout.distance }}m - {{ workout.duration |durationprint:"%H:%M:%S.%f" }}{% endblock %} + +{% block meta %} + + + +{% for chart in charts %} +{{ chart.script |safe }} +{% endfor %} +{% endblock %} + +{% block content %} +
+ {% for chart in charts %} +
+

{{ forloop.counter }}

+
+ + {{ chart.div | safe }} + + {{ chart.notes }} +
+
+ {% endfor %} +
+{% endblock %} diff --git a/rowers/urls.py b/rowers/urls.py index 96199525..7e6b9fee 100644 --- a/rowers/urls.py +++ b/rowers/urls.py @@ -327,6 +327,7 @@ urlpatterns = [ url(r'^legal', TemplateView.as_view(template_name='legal.html'),name='legal'), url(r'^register$',views.rower_register_view), url(r'^register/thankyou/$', TemplateView.as_view(template_name='registerthankyou.html'), name='registerthankyou'), + url(r'^workout/(?P\d+)/workflow$',views.workout_workflow_view), url(r'^workout/(?P\d+)/flexchart/(?P\w+.*)/(?P\w+.*)/(?P\w+.*)/(?P\w+)/$',views.workout_flexchart3_view), url(r'^workout/(?P\d+)/flexchart/(?P\w+.*)/(?P\w+.*)/(?P\w+.*)/(?P\w+.*)$',views.workout_flexchart3_view), url(r'^workout/(?P\d+)/flexchart/(?P\w+.*)/(?P\w+.*)/(?P\w+.*)$',views.workout_flexchart3_view), diff --git a/rowers/views.py b/rowers/views.py index 03f119a3..630970c4 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -5846,7 +5846,59 @@ def workout_comparison_view2(request,id1=0,id2=0,xparam='distance', 'promember':promember, }) - + +# Flex thumbnails +@login_required() +def workout_workflow_view(request,id): + try: + row = Workout.objects.get(id=id) + except Workout.DoesNotExist: + raise Http404("Workout doesn't exist") + + r = getrower(request.user) + result = request.user.is_authenticated() and ispromember(request.user) + if result: + promember=1 + if request.user == row.user.user: + mayedit=1 + + workouttype = 'ote' + if row.workouttype in ('water','coastal'): + workouttype = 'otw' + + try: + favorites = FavoriteChart.objects.filter(user=r, + workouttype__in=[workouttype,'both']).order_by("id") + maxfav = len(favorites)-1 + except: + favorites = None + maxfav = 0 + + charts = [] + + if favorites: + for f in favorites: + workstrokesonly = not f.reststrokes + script,div = thumbnail_flex_chart(id=id,promember=promember, + xparam=f.xparam, + yparam1=f.yparam1, + yparam2=f.yparam2, + plottype=f.plottype, + workstrokesonly=workstrokesonly) + + charts.append({ + 'script':script, + 'div':div, + 'notes':f.notes}) + + + return render(request, + 'workflow.html', + { + 'charts':charts, + 'workout':row, + }) + # The famous flex chart def workout_flexchart3_view(request,*args,**kwargs): @@ -5978,12 +6030,6 @@ def workout_flexchart3_view(request,*args,**kwargs): css_resources = "" - # script = res[0] - # div = res[1] - # js_resources = res[2] - # css_resources = res[3] - - axchoicesbasic = {ax[0]:ax[1] for ax in axes if ax[4]=='basic'} axchoicespro = {ax[0]:ax[1] for ax in axes if ax[4]=='pro'} noylist = ["time","distance"] From 5ab1152825d8ec2c83f1911d2e07d4e4937d50d7 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Fri, 13 Oct 2017 14:10:53 +0200 Subject: [PATCH 5/6] added workflow view --- rowers/interactiveplots.py | 90 +++++++++++++++---------- rowers/templates/flexthumbnails.html | 11 +++ rowers/templates/panel_editbuttons.html | 15 +++++ rowers/templates/panel_statcharts.html | 8 +++ rowers/templates/panel_staticchart.html | 20 ++++++ rowers/templates/panel_stats.html | 5 ++ rowers/templates/panel_summary.html | 5 ++ rowers/templates/workflow.html | 34 +++++++--- rowers/views.py | 37 +++++----- 9 files changed, 161 insertions(+), 64 deletions(-) create mode 100644 rowers/templates/flexthumbnails.html create mode 100644 rowers/templates/panel_editbuttons.html create mode 100644 rowers/templates/panel_statcharts.html create mode 100644 rowers/templates/panel_staticchart.html create mode 100644 rowers/templates/panel_stats.html create mode 100644 rowers/templates/panel_summary.html diff --git a/rowers/interactiveplots.py b/rowers/interactiveplots.py index 9732440c..2cc207c0 100644 --- a/rowers/interactiveplots.py +++ b/rowers/interactiveplots.py @@ -2499,25 +2499,64 @@ def interactive_flex_chart2(id=0,promember=0, return [script,div,js_resources,css_resources,workstrokesonly] -def thumbnail_flex_chart(id=0,promember=0, - xparam='time', - yparam1='pace', - yparam2='hr', - plottype='line', - workstrokesonly=False): +def thumbnails_set(r,id,favorites): + charts = [] + columns = [f.xparam for f in favorites] + columns += [f.yparam1 for f in favorites] + columns += [f.yparam2 for f in favorites] - #rowdata,row = dataprep.getrowdata_db(id=id) - columns = [xparam,yparam1,yparam2,'time'] - - rowdata = dataprep.getsmallrowdata_db(columns,ids=[id],doclean=True, - workstrokesonly=workstrokesonly) + columns += ['time'] + rowdata = dataprep.getsmallrowdata_db(columns,ids=[id],doclean=True) + rowdata.dropna(axis=1,how='all',inplace=True) if rowdata.empty: - rowdata = dataprep.getsmallrowdata_db(columns,ids=[id],doclean=True, - workstrokesonly=False) - workstrokesonly=False + return [ + {'script':"", + 'div':"", + 'notes':"" + }] + else: + try: + rowdata.sort_values(by='time',ascending=True,inplace=True) + except KeyError: + pass + + l = len(rowdata) + maxlength = 50 + if l > maxlength: + bins = np.linspace(rowdata['time'].min(),rowdata['time'].max(),maxlength) + groups = rowdata.groupby(np.digitize(rowdata['time'],bins)) + rowdata = groups.mean() + for f in favorites: + workstrokesonly = not f.reststrokes + script,div = thumbnail_flex_chart( + rowdata, + id=id, + xparam=f.xparam, + yparam1=f.yparam1, + yparam2=f.yparam2, + plottype=f.plottype, + ) + + + charts.append({ + 'script':script, + 'div':div, + 'notes':f.notes}) + + return charts + + +def thumbnail_flex_chart(rowdata,id=0,promember=0, + xparam='time', + yparam1='pace', + yparam2='hr', + plottype='line', + workstrokesonly=False): + + try: tests = rowdata[yparam2] except KeyError: @@ -2528,25 +2567,7 @@ def thumbnail_flex_chart(id=0,promember=0, except KeyError: yparam1 = 'None' - rowdata.dropna(axis=1,how='all',inplace=True) - if rowdata.empty: - return "","No valid data" - else: - try: - rowdata.sort_values(by='time',ascending=True,inplace=True) - except KeyError: - pass - - workoutstateswork = [1,4,5,8,9,6,7] - workoutstatesrest = [3] - workoutstatetransition = [0,2,10,11,12,13] - - if workstrokesonly: - try: - rowdata = rowdata[~rowdata['workoutstate'].isin(workoutstatesrest)] - except KeyError: - pass try: tseconds = rowdata.ix[:,'time'] @@ -2620,11 +2641,6 @@ def thumbnail_flex_chart(id=0,promember=0, plot.yaxis.axis_label_text_font_size = "7pt" plot.xaxis.major_label_text_font_size = "7pt" plot.yaxis.major_label_text_font_size = "7pt" - # add watermark - plot.extra_y_ranges = {"watermark": watermarkrange} - plot.extra_x_ranges = {"watermark": watermarkrange} - - if plottype=='line': plot.line('x1','y1',source=source) diff --git a/rowers/templates/flexthumbnails.html b/rowers/templates/flexthumbnails.html new file mode 100644 index 00000000..d6a5016a --- /dev/null +++ b/rowers/templates/flexthumbnails.html @@ -0,0 +1,11 @@ + {% for chart in charts %} +
+

{{ forloop.counter }}

+
+ + {{ chart.div | safe }} + + {{ chart.notes }} +
+
+ {% endfor %} diff --git a/rowers/templates/panel_editbuttons.html b/rowers/templates/panel_editbuttons.html new file mode 100644 index 00000000..e2c836ea --- /dev/null +++ b/rowers/templates/panel_editbuttons.html @@ -0,0 +1,15 @@ +
+

+ Edit Workout +

+
+
+

+ Advanced +

+
+ diff --git a/rowers/templates/panel_statcharts.html b/rowers/templates/panel_statcharts.html new file mode 100644 index 00000000..141fd15e --- /dev/null +++ b/rowers/templates/panel_statcharts.html @@ -0,0 +1,8 @@ +{% for graph in statcharts %} +
+ + {{ graph.filename }} +
+{% endfor %} diff --git a/rowers/templates/panel_staticchart.html b/rowers/templates/panel_staticchart.html new file mode 100644 index 00000000..90095d8d --- /dev/null +++ b/rowers/templates/panel_staticchart.html @@ -0,0 +1,20 @@ +
+

+ Add Time Plot +

+
+ +
+

+ Add Pie Chart +

+
+ diff --git a/rowers/templates/panel_stats.html b/rowers/templates/panel_stats.html new file mode 100644 index 00000000..248127f8 --- /dev/null +++ b/rowers/templates/panel_stats.html @@ -0,0 +1,5 @@ +
+

+ Workout Stats +

+
diff --git a/rowers/templates/panel_summary.html b/rowers/templates/panel_summary.html new file mode 100644 index 00000000..759fd39b --- /dev/null +++ b/rowers/templates/panel_summary.html @@ -0,0 +1,5 @@ +

+

+    {{ workout.summary }}
+  
+

diff --git a/rowers/templates/workflow.html b/rowers/templates/workflow.html index 2a454179..a4fe822f 100644 --- a/rowers/templates/workflow.html +++ b/rowers/templates/workflow.html @@ -25,17 +25,29 @@ {% endblock %} {% block content %} -
- {% for chart in charts %} -
-

{{ forloop.counter }}

-
- - {{ chart.div | safe }} - - {{ chart.notes }} -
+
+
+

{{ workout.name }}

- {% endfor %} +
+ {% block left_panel %} + {% for templateName in leftTemplates %} + {% include templateName %} + {% endfor %} + {% endblock %} +
+
+ {% block middle_panel %} + {% for templateName in middleTemplates %} +
+ {% include templateName %} +
+ {% endfor %} + {% endblock %} +
+
+ {% block right_panel %} +

 

+ {% endblock %}
{% endblock %} diff --git a/rowers/views.py b/rowers/views.py index 630970c4..88ed6029 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -5850,6 +5850,8 @@ def workout_comparison_view2(request,id1=0,id2=0,xparam='distance', # Flex thumbnails @login_required() def workout_workflow_view(request,id): + request.session['referer'] = absolute(request)['PATH'] + request.session[translation.LANGUAGE_SESSION_KEY] = USER_LANGUAGE try: row = Workout.objects.get(id=id) except Workout.DoesNotExist: @@ -5876,28 +5878,28 @@ def workout_workflow_view(request,id): charts = [] - if favorites: - for f in favorites: - workstrokesonly = not f.reststrokes - script,div = thumbnail_flex_chart(id=id,promember=promember, - xparam=f.xparam, - yparam1=f.yparam1, - yparam2=f.yparam2, - plottype=f.plottype, - workstrokesonly=workstrokesonly) - - charts.append({ - 'script':script, - 'div':div, - 'notes':f.notes}) + if favorites: + charts = thumbnails_set(r,id,favorites) + statcharts = GraphImage.objects.filter(workout=row) + + # This will be user configurable in the future + middleTemplates = ['panel_statcharts.html','flexthumbnails.html', + 'panel_summary.html'] + leftTemplates = [ + 'panel_editbuttons.html','panel_staticchart.html', + 'panel_stats.html' + ] return render(request, 'workflow.html', { + 'middleTemplates':middleTemplates, + 'leftTemplates':leftTemplates, 'charts':charts, 'workout':row, - }) + 'statcharts':statcharts, + }) # The famous flex chart def workout_flexchart3_view(request,*args,**kwargs): @@ -6810,7 +6812,10 @@ def workout_add_chart_view(request,id,plotnr=1): imagename=imagename) - url = "/rowers/workout/"+str(w.id)+"/edit" + try: + url = request.session['referer'] + except KeyError: + url = "/rowers/workout/"+str(w.id)+"/edit" return HttpResponseRedirect(url) From 80cdd24913914d85a26fd76a668d02341d75c0c0 Mon Sep 17 00:00:00 2001 From: Sander Roosendaal Date: Fri, 13 Oct 2017 14:30:16 +0200 Subject: [PATCH 6/6] fine tuning headers --- rowers/templates/flexthumbnails.html | 7 +++++-- rowers/templates/panel_editbuttons.html | 3 +++ rowers/templates/panel_statcharts.html | 3 +++ rowers/templates/panel_staticchart.html | 3 +++ rowers/templates/panel_summary.html | 1 + rowers/templates/workflow.html | 5 ++++- rowers/views.py | 5 +++-- static/css/rowsandall.css | 19 ++++++++++++++++++- 8 files changed, 40 insertions(+), 6 deletions(-) diff --git a/rowers/templates/flexthumbnails.html b/rowers/templates/flexthumbnails.html index d6a5016a..24d88ffc 100644 --- a/rowers/templates/flexthumbnails.html +++ b/rowers/templates/flexthumbnails.html @@ -1,6 +1,8 @@ - {% for chart in charts %} +{% if charts %} +

Flex Charts

+{% for chart in charts %}
-

{{ forloop.counter }}

+ {{ forloop.counter }}
{% endfor %} +{% endif %} diff --git a/rowers/templates/panel_editbuttons.html b/rowers/templates/panel_editbuttons.html index e2c836ea..a79cb80a 100644 --- a/rowers/templates/panel_editbuttons.html +++ b/rowers/templates/panel_editbuttons.html @@ -1,3 +1,6 @@ +
+

Navigation

+

Edit Workout diff --git a/rowers/templates/panel_statcharts.html b/rowers/templates/panel_statcharts.html index 141fd15e..e1e44ea9 100644 --- a/rowers/templates/panel_statcharts.html +++ b/rowers/templates/panel_statcharts.html @@ -1,3 +1,5 @@ +{% if statcharts %} +

Static Charts

{% for graph in statcharts %} {% endfor %} +{% endif %} diff --git a/rowers/templates/panel_staticchart.html b/rowers/templates/panel_staticchart.html index 90095d8d..60da93a4 100644 --- a/rowers/templates/panel_staticchart.html +++ b/rowers/templates/panel_staticchart.html @@ -1,3 +1,6 @@ +
+

Create Charts

+

Add Time Plot diff --git a/rowers/templates/panel_summary.html b/rowers/templates/panel_summary.html index 759fd39b..47ad211e 100644 --- a/rowers/templates/panel_summary.html +++ b/rowers/templates/panel_summary.html @@ -1,3 +1,4 @@ +

Summary

     {{ workout.summary }}
diff --git a/rowers/templates/workflow.html b/rowers/templates/workflow.html
index a4fe822f..a7de9675 100644
--- a/rowers/templates/workflow.html
+++ b/rowers/templates/workflow.html
@@ -33,8 +33,11 @@
     {% block left_panel %}
      {% for templateName in leftTemplates %}
       {% include templateName %}
-     {% endfor %}
+    {% endfor %}
     {% endblock %}
+    
+

Click on the thumbnails to view the full chart

+
{% block middle_panel %} diff --git a/rowers/views.py b/rowers/views.py index 88ed6029..efc20124 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -5887,8 +5887,9 @@ def workout_workflow_view(request,id): middleTemplates = ['panel_statcharts.html','flexthumbnails.html', 'panel_summary.html'] leftTemplates = [ - 'panel_editbuttons.html','panel_staticchart.html', - 'panel_stats.html' + 'panel_editbuttons.html', + 'panel_stats.html', + 'panel_staticchart.html', ] return render(request, diff --git a/static/css/rowsandall.css b/static/css/rowsandall.css index 7dfd9851..7be4294f 100644 --- a/static/css/rowsandall.css +++ b/static/css/rowsandall.css @@ -62,11 +62,28 @@ h1 { font-weight: normal; /* padding-top: 20px; */ text-align: left; + font-size: 2em; } h2 { -/* padding-top: 20px; */ + /* padding-top: 20px; */ + font-weight: normal; text-align: left; + font-size: 1.5em; +} + +h3 { + /* padding-top: 20px; */ + font-weight: normal; + text-align: left; + font-size: 1em; +} + +h3 { + /* padding-top: 20px; */ + font-weight: normal; + text-align: left; + font-size: 1em; } p {