Skip to content

Commit

Permalink
Merge pull request #7 from andela/ft-set-up-support-for-drop-sets-140…
Browse files Browse the repository at this point in the history
…649403

Ft set up support for drop sets 140649403
  • Loading branch information
sirjmkitavi committed Mar 29, 2017
2 parents 0ea5436 + d034118 commit 26fffae
Show file tree
Hide file tree
Showing 11 changed files with 307 additions and 5 deletions.
5 changes: 4 additions & 1 deletion wger/core/templates/tags/render_day.html
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,11 @@ <h4 class="media-heading">
<td colspan="2">
<a href="{% url 'manager:set:add' day.obj.id %}"
class="wger-modal-dialog">{% trans "Add exercises to this workout day" %}</a>
|
<a href="{% url 'manager:set:add_dropset' day.obj.id %}"
class="wger-modal-dialog">{% trans "Add drop set exercise to this work out day" %}</a>
</td>
</tr>
{% endif %}
</tbody>
</table>
</table>
20 changes: 20 additions & 0 deletions wger/exercises/migrations/0005_equipment_weight_choice.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.12 on 2017-03-20 07:51
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('exercises', '0004_auto_20170301_1156'),
]

operations = [
migrations.AddField(
model_name='equipment',
name='weight_choice',
field=models.CharField(choices=[('5', '5 Kgs'), ('10', '10 Kgs'), ('15', '15 Kgs'), ('20', '20 Kgs')], max_length=10, null=True),
),
]
19 changes: 19 additions & 0 deletions wger/exercises/migrations/0006_remove_equipment_weight_choice.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.12 on 2017-03-21 07:33
from __future__ import unicode_literals

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('exercises', '0005_equipment_weight_choice'),
]

operations = [
migrations.RemoveField(
model_name='equipment',
name='weight_choice',
),
]
4 changes: 2 additions & 2 deletions wger/exercises/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ def get_owner_object(self):

@python_2_unicode_compatible
class Equipment(models.Model):
'''
"""
Equipment used or needed by an exercise
'''
"""

name = models.CharField(max_length=50,
verbose_name=_('Name'))
Expand Down
20 changes: 20 additions & 0 deletions wger/gym/migrations/0008_auto_20170320_1051.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.12 on 2017-03-20 07:51
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('gym', '0007_auto_20170301_1156'),
]

operations = [
migrations.AlterField(
model_name='gymconfig',
name='weeks_inactive',
field=models.PositiveIntegerField(default=4, help_text='Number of weeks since the last time a user logged his presence to be considered inactive', verbose_name='Reminder of inactive members'),
),
]
43 changes: 43 additions & 0 deletions wger/manager/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,29 @@ def __init__(self, *args, **kwargs):
'they will be grouped together for a superset.')


class DropSetFormMobile(ModelForm):
class Meta:
model = Set
exclude = ('order', 'exerciseday')
widgets = {'exercises': MultipleHiddenInput(), }

categories_list = ModelChoiceField(ExerciseCategory.objects.all(),
empty_label=_('All categories'),
label=_('Categories'),
widget=TranslatedSelect(),
required=False)

exercise_list = ModelChoiceField(Exercise.objects.filter(equipment__name__in=['Kettlebell', 'Barbell', 'Dumbbell']))

# We need to overwrite the init method here because otherwise Django
# will output a default help text, regardless of the widget used
# https://code.djangoproject.com/ticket/9321
def __init__(self, *args, **kwargs):
super(SetFormMobile, self).__init__(*args, **kwargs)
self.fields['exercise_list'].help_text = _('You can search for more than one exercise, '
'they will be grouped together for a superset.')


class SetFormMobile(ModelForm):
'''
Don't use the auto completer when accessing the mobile version
Expand All @@ -115,6 +138,7 @@ class Meta:
label=_('Categories'),
widget=TranslatedSelect(),
required=False)

exercise_list = ModelChoiceField(Exercise.objects)

# We need to overwrite the init method here because otherwise Django
Expand All @@ -126,6 +150,25 @@ def __init__(self, *args, **kwargs):
'they will be grouped together for a superset.')


class DropSetForm(ModelForm):
"""Form for adding drop sets """
class Meta:
model = Set
exclude = ('order', 'exerciseday')
widgets = {'exercises': ExerciseAjaxSelect(), }

# We need to overwrite the init method here because otherwise Django
# will output a default help text, regardless of the widget used
# https://code.djangoproject.com/ticket/9321
def __init__(self, *args, **kwargs):
super(DropSetForm, self).__init__(*args, **kwargs)

self.fields['exercises'].help_text = _('You can search for more than one exercise, '
'they will be grouped together for a superset.')
self.fields['exercises'].queryset = Exercise.objects.filter(equipment__name__in=['Kettlebell', 'Barbell',
'Dumbbell']).select_related()


class SettingForm(ModelForm):

class Meta:
Expand Down
78 changes: 78 additions & 0 deletions wger/manager/templates/set/drop_sets.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
{% extends extend_template %}
{% load i18n %}
{% load staticfiles %}
{% load wger_extras %}


<!--
Title
-->

{% block title %}{% with day_name=day.description %}{% blocktrans %}Add drop set exercises to day "{{day_name}}"{% endblocktrans %}{% endwith %}{% endblock %}


<!--
Header
-->
{% block header %}
<script>
function wgerCustomPageInit()
{
wgerInitEditSet();
}
</script>
{% endblock %}

<!--
Main Content
-->
{% block content %}


<form action="{{form_action}}"
method="post"
class="form-horizontal">

{% csrf_token %}
{% render_form_field form.exercises %}
<div class="form-group">
<label for="id_sets" class="control-label col-md-3">
{{form.sets.label}}:
<span id="id_sets_value">{{ form.sets.value }}</span>
</label>
<div class="col-md-9">
<input name="sets"
id="id_sets"
min="1"
max="10"
value="{{ form.sets.value }}"
type="range"
class="form-control">
</div>
</div>


<div class="form-group">
<label class="col-md-3 control-label">
{% trans "Repetitions" %}
</label>
<div class=" col-md-9">
<span class="help-block">{% blocktrans %}If you do the same repetitions for all sets,
you can just enter one value: e.g. for 4 sets just enter one "10" for the repetitions, this
automatically becomes "4 x 10".{% endblocktrans %}</span>
</div>
</div>
<div class="form-group">
<div class="col-md-12">
<div id="formsets">
{% for formset in formsets %}
{% include 'set/formset.html' with exercise=formset.exercise formset=formset.formset %}
{% endfor %}
</div>
</div>
</div>


{% render_form_submit %}
</form>
{% endblock %}
42 changes: 42 additions & 0 deletions wger/manager/tests/test_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,48 @@ def test_add_set(self, fail=False):
else:
self.assertIn(setting.reps, (8, 10))

def test_add_drop_sets(self, fail=False):
# POST the data
self.user_login('test')
exercises_id = [1, 2]
post_data = {'exercises': exercises_id,
'exercise_list': 1, # Only for mobile version
'sets': 4,

'exercise1-TOTAL_FORMS': 4,
'exercise1-INITIAL_FORMS': 0,
'exercise1-MAX_NUM_FORMS': 1000,
'exercise1-0-reps': 113,
'exercise1-0-repetition_unit': 1,
'exercise1-0-weight_unit': 1,
'exercise1-1-reps': 113,
'exercise1-1-repetition_unit': 1,
'exercise1-1-weight_unit': 1,
'exercise1-2-reps': 113,
'exercise1-2-repetition_unit': 1,
'exercise1-2-weight_unit': 1,
'exercise1-3-reps': 113,
'exercise1-3-repetition_unit': 1,
'exercise1-3-weight_unit': 1,

'exercise2-TOTAL_FORMS': 4,
'exercise2-INITIAL_FORMS': 0,
'exercise2-MAX_NUM_FORMS': 1000,
'exercise2-0-reps': 113,
'exercise2-0-repetition_unit': 1,
'exercise2-0-weight_unit': 1,
'exercise2-1-reps': 113,
'exercise2-1-repetition_unit': 2,
'exercise2-1-weight_unit': 2,
'exercise2-2-reps': 113,
'exercise2-2-repetition_unit': 1,
'exercise2-2-weight_unit': 1,
'exercise2-3-reps': 113,
'exercise2-3-repetition_unit': 2,
'exercise2-3-weight_unit': 2}
response = self.client.post(reverse('manager:set:add_dropset', kwargs={'day_pk': 5}), post_data)
self.assertEqual(response.status_code, 200)


class SetDeleteTestCase(WorkoutManagerTestCase):
'''
Expand Down
3 changes: 3 additions & 0 deletions wger/manager/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@
url(r'^day/(?P<day_pk>\d+)/set/add/$',
set.create,
name='add'),
url(r'^day/(?P<day_pk>\d+)/set/add_dropset/$',
set.create_drop_set,
name='add_dropset'),
url(r'^get-formset/(?P<exercise_pk>\d+)/(?P<reps>\d+)/',
set.get_formset,
name='get-formset'), # Used by JS
Expand Down
2 changes: 1 addition & 1 deletion wger/manager/views/day.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def get_success_url(self):

def get_form(self, form_class=DayForm):
'''
Filter the days of the week that are alreeady used by other days
Filter the days of the week that are already used by other days
'''

# Get the form
Expand Down
76 changes: 75 additions & 1 deletion wger/manager/views/set.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@
from wger.manager.forms import (
SetForm,
SetFormMobile,
SettingForm
SettingForm,
DropSetForm,
DropSetFormMobile,
)
from wger.utils.language import load_item_languages
from wger.config.models import LanguageConfig
Expand All @@ -54,6 +56,78 @@
extra=1)


@login_required
def create_drop_set(request, day_pk):
""" Creates a new drop set """
day = get_object_or_404(Day, pk=day_pk)
if day.get_owner_object().user != request.user:
return HttpResponseForbidden()

# Select the correct form depending on the flavour of the request.
# The difference is that the mobile form doesn't use the autocompleter for
# exercises, but 2 dropdowns, one to filter by category and one to select
# the exercises themselves.
if request.flavour == 'mobile':
form_class = DropSetFormMobile
else:
form_class = DropSetForm

context = {}
formsets = []
form = form_class(initial={'sets': Set.DEFAULT_SETS})

# For the mobile dropdown list we need to manually filter the exercises
# by language and status
if request.flavour == 'mobile':
languages = load_item_languages(LanguageConfig.SHOW_ITEM_EXERCISES)
form.fields['exercise_list'].queryset = Exercise.objects.accepted() \
.filter(language__in=languages)

# If the form and all formsets validate, save them
if request.method == "POST":
form = form_class(request.POST)
if form.is_valid():
for exercise in form.cleaned_data['exercises']:
formset = SettingFormset(request.POST,
queryset=Setting.objects.none(),
prefix='exercise{0}'.format(exercise.id))
formsets.append({'exercise': exercise, 'formset': formset})
all_valid = True

for formset in formsets:
if not formset['formset'].is_valid():
all_valid = False

if form.is_valid() and all_valid:
# Manually take care of the order, TODO: better move this to the model
max_order = day.set_set.select_related().aggregate(models.Max('order'))
form.instance.order = (max_order['order__max'] or 0) + 1
form.instance.exerciseday = day
set_obj = form.save()

for formset in formsets:
instances = formset['formset'].save(commit=False)
for instance in instances:
instance.set = set_obj
instance.order = 1
instance.exercise = formset['exercise']
instance.save()

return HttpResponseRedirect(reverse('manager:workout:view',
kwargs={'pk': day.get_owner_object().id}))
else:
logger.debug(form.errors)

# Other context we need
context['form'] = form
context['day'] = day
context['max_sets'] = Set.MAX_SETS
context['formsets'] = formsets
context['form_action'] = reverse('manager:set:add_dropset', kwargs={'day_pk': day_pk})
context['extend_template'] = 'base_empty.html' if request.is_ajax() else 'base.html'
return render(request, 'set/drop_sets.html', context)


@login_required
def create(request, day_pk):
'''
Expand Down

0 comments on commit 26fffae

Please sign in to comment.