diff --git a/rowers/forms.py b/rowers/forms.py index 1e9974e2..efc6ac85 100644 --- a/rowers/forms.py +++ b/rowers/forms.py @@ -57,7 +57,41 @@ class DocumentsForm(forms.Form): class Meta: fields = ['title','file','workouttype','fileformat'] +from utils import workflowleftpanel,workflowmiddlepanel +# Form to change Workflow page layout +class WorkFlowLeftPanelForm(forms.Form): + panels = ['panel_editbuttons.html','panel_stats.html','panel_staticchart.html'] + leftpanel = forms.MultipleChoiceField(label='Left Panel', + choices=workflowleftpanel, + initial=panels) + def __init__(self, *args, **kwargs): + if 'instance' in kwargs: + r = kwargs.pop('instance') + panels = r.workflowleftpanel + else: + panels = ['panel_editbuttons.html','panel_stats.html','panel_staticchart.html'] + + super(WorkFlowLeftPanelForm,self).__init__(*args, **kwargs) + + +class WorkFlowMiddlePanelForm(forms.Form): + panels = ['panel_statcharts.html', + 'flexthumbnails.html', + 'panel_summary.html'] + + middlepanel = forms.MultipleChoiceField(label='Middle Panel', + choices=workflowmiddlepanel, + initial=panels) + def __init__(self, *args, **kwargs): + if 'instance' in kwargs: + r = kwargs.pop('instance') + panels = r.workflowleftpanel + else: + panels = ['panel_editbuttons.html','panel_stats.html','panel_staticchart.html'] + + super(WorkFlowMiddlePanelForm,self).__init__(*args, **kwargs) + # The form to indicate additional actions to be performed immediately # after a successful upload class UploadOptionsForm(forms.Form): diff --git a/rowers/models.py b/rowers/models.py index 83e699e3..02f50de6 100644 --- a/rowers/models.py +++ b/rowers/models.py @@ -61,6 +61,47 @@ timezones = ( class UserFullnameChoiceField(forms.ModelChoiceField): def label_from_instance(self,obj): return obj.get_full_name() + +# model for configurable template field +class TemplateListField(models.TextField): + def __init__(self, *args, **kwargs): + self.token = kwargs.pop('token',',') + super(TemplateListField, self).__init__(*args, **kwargs) + + def to_python(self, value): + if not value: return + if isinstance(value, list): + return value + # remove double quotes and brackets + value = re.sub(r'u\"','',value) + value = re.sub(r'u\'','',value) + value = re.sub(r'\\','',value) + value = re.sub(r'\"','',value) + value = re.sub(r'\'','',value) + value = re.sub(r'\[','',value) + value = re.sub(r'\]','',value) + value = re.sub(r'\[\[','[',value) + value = re.sub(r'\]\]',']',value) + value = re.sub(r'\ \ ',' ',value) + value = re.sub(r', ',',',value) + + return value.split(self.token) + + def from_db_value(self,value, expression, connection, context): + if value is None: + return value + if isinstance(value, list): + return value + return value.split(self.token) + + def get_db_prep_value(self, value, connection, prepared=False): + if not value: return + assert(isinstance(value, list) or isinstance(value, tuple)) + return self.token.join([unicode(s) for s in value]) + + def value_to_string(self, obj): + value = self._get_val_from_obj(obj) + return self.get_deb_prep_value(value) # model for Power Zone names class PowerZonesField(models.TextField): @@ -234,6 +275,18 @@ class Rower(models.Model): 'Pwr TR', 'Pwr AN']) + # Site Settings + workflowleftpanel = TemplateListField(default=[ + 'panel_statcharts.html', + 'flexthumbnails.html', + 'panel_summary.html']) + + workflowmiddlepanel = TemplateListField(default=[ + 'panel_editbuttons.html', + 'panel_stats.html', + 'panel_staticchart.html', + ]) + # Access tokens c2token = models.CharField(default='',max_length=200,blank=True,null=True) tokenexpirydate = models.DateTimeField(blank=True,null=True) diff --git a/rowers/templates/workflowconfig.html b/rowers/templates/workflowconfig.html new file mode 100644 index 00000000..de43183a --- /dev/null +++ b/rowers/templates/workflowconfig.html @@ -0,0 +1,58 @@ +{% extends "base.html" %} + +{% block title %}Change Rower Export Settings{% endblock %} + +{% block content %} + + +
+

Workflow Page Configuration

+

+ Here, you can configure which elements, and in which order, are visible on the Workflow page. +

+

+ Select the elements you want to have in each panel. You can select multiple by holding down Control while clicking on an item. Similarly, you can unselect one item by holding down Control while clicking. Use the arrows to change the order by moving selected items up, resp down. Press the Save button to store your configuration. +

+
+
+

+ {% if formleft.errors %} +

+ Please correct the error{{ formleft.errors|pluralize }} below. +

+ {% endif %} + + + {{ formleft.as_table }} +
+ {% csrf_token %} +

+
+
+ Move Up
+ Move Down +
+
+

+ {% if formmiddle.errors %} +

+ Please correct the error{{ formmiddle.errors|pluralize }} below. +

+ {% endif %} + + + {{ formmiddle.as_table }} +
+
+
+ Move Up
+ Move Down +
+
+ + +
+ + + +{% endblock %} diff --git a/rowers/urls.py b/rowers/urls.py index 7e6b9fee..2331bc34 100644 --- a/rowers/urls.py +++ b/rowers/urls.py @@ -312,6 +312,7 @@ urlpatterns = [ url(r'^me/tprefresh/$',views.rower_tp_token_refresh), url(r'^me/c2refresh/$',views.rower_c2_token_refresh), url(r'^me/favoritecharts/$',views.rower_favoritecharts_view), + url(r'^me/workflowconfig$',views.workout_workflow_config_view), url(r'^email/send/$', views.sendmail), url(r'^email/thankyou/$', TemplateView.as_view(template_name='thankyou.html'), name='thankyou'), url(r'^email/$', TemplateView.as_view(template_name='email.html'), name='email'), diff --git a/rowers/utils.py b/rowers/utils.py index d0b1732a..ef460420 100644 --- a/rowers/utils.py +++ b/rowers/utils.py @@ -5,6 +5,18 @@ import colorsys lbstoN = 4.44822 +workflowmiddlepanel = ( + ('panel_statcharts.html','Static Charts'), + ('flexthumbnails.html','Flex Charts'), + ('panel_summary.html','Summary'), + ) + +workflowleftpanel = ( + ('panel_editbuttons.html','Edit Links'), + ('panel_stats.html','Stats'), + ('panel_staticchart.html','Create Static Charts') + ) + def absolute(request): urls = { 'ABSOLUTE_ROOT': request.build_absolute_uri('/')[:-1].strip("/"), diff --git a/rowers/views.py b/rowers/views.py index 141307f1..f5fd6bd6 100644 --- a/rowers/views.py +++ b/rowers/views.py @@ -22,7 +22,7 @@ from django.http import ( from django.contrib.auth import authenticate, login, logout from rowers.forms import ( LoginForm,DocumentsForm,UploadOptionsForm, - TeamUploadOptionsForm, + TeamUploadOptionsForm,WorkFlowLeftPanelForm,WorkFlowMiddlePanelForm, ) from django.core.urlresolvers import reverse from django.core.exceptions import PermissionDenied @@ -5852,8 +5852,25 @@ def workout_comparison_view2(request,id1=0,id2=0,xparam='distance', 'promember':promember, }) +# Workflow Configuration +@login_required() +def workout_workflow_config_view(request): + request.session['referer'] = absolute(request)['PATH'] + request.session[translation.LANGUAGE_SESSION_KEY] = USER_LANGUAGE + r = getrower(request.user) + formleft = WorkFlowLeftPanelForm(instance=r) + formmiddle = WorkFlowMiddlePanelForm() -# Flex thumbnails + # Add processing of POST data + + return render(request,'workflowconfig.html', + { + 'rower':r, + 'formleft':formleft, + 'formmiddle':formmiddle, + }) + +# Workflow View @login_required() def workout_workflow_view(request,id): request.session['referer'] = absolute(request)['PATH'] @@ -5892,13 +5909,9 @@ def workout_workflow_view(request,id): 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_stats.html', - 'panel_staticchart.html', - ] + middleTemplates = r.workflowleftpanel + + leftTemplates = r.workflowmiddlepanel return render(request, 'workflow.html', diff --git a/static/img/movedn.gif b/static/img/movedn.gif new file mode 100644 index 00000000..a9cbca3a Binary files /dev/null and b/static/img/movedn.gif differ diff --git a/static/img/moveup.gif b/static/img/moveup.gif new file mode 100644 index 00000000..78fb28fe Binary files /dev/null and b/static/img/moveup.gif differ diff --git a/static/js/reorderSelect.js b/static/js/reorderSelect.js new file mode 100644 index 00000000..d3a75878 --- /dev/null +++ b/static/js/reorderSelect.js @@ -0,0 +1,27 @@ + +function moveUp(selectId) { + var selectList = document.getElementById(selectId); + var selectOptions = selectList.getElementsByTagName('option'); + for (var i = 1; i < selectOptions.length; i++) { + var opt = selectOptions[i]; + if (opt.selected) { + selectList.removeChild(opt); + selectList.insertBefore(opt, selectOptions[i - 1]); + } + } +} + +function moveDown(selectId) { + var selectList = document.getElementById(selectId); + var selectOptions = selectList.getElementsByTagName('option'); + for (var i = selectOptions.length - 2; i >= 0; i--) { + var opt = selectOptions[i]; + if (opt.selected) { + var nextOpt = selectOptions[i + 1]; + opt = selectList.removeChild(opt); + nextOpt = selectList.replaceChild(opt, nextOpt); + selectList.insertBefore(nextOpt, opt); + } + } +} +