diff --git a/babybuddy/admin.py b/babybuddy/admin.py index 285017cb..5f35f234 100644 --- a/babybuddy/admin.py +++ b/babybuddy/admin.py @@ -14,7 +14,10 @@ class SettingsInline(admin.StackedInline): can_delete = False fieldsets = ( (_('Dashboard'), { - 'fields': ('dashboard_refresh_rate', 'dashboard_hide_empty',) + 'fields': ( + 'dashboard_refresh_rate', + 'dashboard_hide_empty', + 'dashboard_hide_age') }), ) diff --git a/babybuddy/forms.py b/babybuddy/forms.py index 3bb49dfe..c48ce900 100644 --- a/babybuddy/forms.py +++ b/babybuddy/forms.py @@ -44,6 +44,7 @@ class UserSettingsForm(forms.ModelForm): fields = [ 'dashboard_refresh_rate', 'dashboard_hide_empty', + 'dashboard_hide_age', 'language', 'timezone' ] diff --git a/babybuddy/migrations/0017_settings_hide_age.py b/babybuddy/migrations/0017_settings_hide_age.py new file mode 100644 index 00000000..3373cb09 --- /dev/null +++ b/babybuddy/migrations/0017_settings_hide_age.py @@ -0,0 +1,28 @@ +from django.db import migrations, models +from django.utils import timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('babybuddy', '0016_alter_settings_timezone'), + ] + + operations = [ + migrations.AddField( + model_name='settings', + name='dashboard_hide_age', + field=models.DurationField( + choices=[ + (None, 'show all data'), + (timezone.timedelta(days=1), '1 day'), + (timezone.timedelta(days=2), '2 days'), + (timezone.timedelta(days=3), '3 days'), + (timezone.timedelta(weeks=1), '1 week'), + (timezone.timedelta(weeks=4), '4 weeks') + ], + default=None, + null=True, + verbose_name='Hide data older than'), + ), + ] diff --git a/babybuddy/models.py b/babybuddy/models.py index 90b708f3..9db037e4 100644 --- a/babybuddy/models.py +++ b/babybuddy/models.py @@ -39,6 +39,21 @@ class Settings(models.Model): default=False, editable=True ) + dashboard_hide_age = models.DurationField( + verbose_name=_('Hide data older than'), + help_text=_('This setting controls which data will be shown ' + 'in the dashboard.'), + blank=True, + null=True, + default=None, + choices=[ + (None, _('show all data')), + (timezone.timedelta(days=1), _('1 day')), + (timezone.timedelta(days=2), _('2 days')), + (timezone.timedelta(days=3), _('3 days')), + (timezone.timedelta(weeks=1), _('1 week')), + (timezone.timedelta(weeks=4), _('4 weeks')), + ]) language = models.CharField( choices=settings.LANGUAGES, default=settings.LANGUAGE_CODE, diff --git a/babybuddy/templates/babybuddy/user_settings_form.html b/babybuddy/templates/babybuddy/user_settings_form.html index 77f188db..2bb91a7b 100644 --- a/babybuddy/templates/babybuddy/user_settings_form.html +++ b/babybuddy/templates/babybuddy/user_settings_form.html @@ -69,6 +69,11 @@ {% include 'babybuddy/form_field.html' %} {% endwith %} +
+ {% with form_settings.dashboard_hide_age as field %} + {% include 'babybuddy/form_field.html' %} + {% endwith %} +
{% trans "API" %} diff --git a/babybuddy/tests/tests_forms.py b/babybuddy/tests/tests_forms.py index 2a99e76f..fa102d50 100644 --- a/babybuddy/tests/tests_forms.py +++ b/babybuddy/tests/tests_forms.py @@ -157,3 +157,15 @@ class FormsTestCase(TestCase): self.user.refresh_from_db() self.assertEqual(self.user.settings.dashboard_refresh_rate, datetime.timedelta(seconds=300)) + + def test_user_settings_dashboard_hide_age(self): + self.c.login(**self.credentials) + + params = self.settings_template.copy() + params['dashboard_hide_age'] = '1 day, 0:00:00' + + page = self.c.post('/user/settings/', data=params, follow=True) + self.assertEqual(page.status_code, 200) + self.user.refresh_from_db() + self.assertEqual(self.user.settings.dashboard_hide_age, + datetime.timedelta(days=1)) diff --git a/dashboard/templatetags/cards.py b/dashboard/templatetags/cards.py index 8e387ecc..3823c504 100644 --- a/dashboard/templatetags/cards.py +++ b/dashboard/templatetags/cards.py @@ -16,6 +16,15 @@ def _hide_empty(context): return context['request'].user.settings.dashboard_hide_empty +def _filter_data_age(context, keyword="end"): + filter = {} + if context['request'].user.settings.dashboard_hide_age: + now = timezone.localtime() + start_time = now - context['request'].user.settings.dashboard_hide_age + filter[keyword + "__range"] = (start_time, now) + return filter + + @register.inclusion_tag('cards/diaperchange_last.html', takes_context=True) def card_diaperchange_last(context, child): """ @@ -23,8 +32,9 @@ def card_diaperchange_last(context, child): :param child: an instance of the Child model. :returns: a dictionary with the most recent Diaper Change instance. """ - instance = models.DiaperChange.objects.filter( - child=child).order_by('-time').first() + instance = models.DiaperChange.objects.filter(child=child) \ + .filter(**_filter_data_age(context, "time")) \ + .order_by('-time').first() empty = not instance return { @@ -127,6 +137,7 @@ def card_feeding_last(context, child): :returns: a dictionary with the most recent Feeding instance. """ instance = models.Feeding.objects.filter(child=child) \ + .filter(**_filter_data_age(context)) \ .order_by('-end').first() empty = not instance @@ -146,6 +157,7 @@ def card_feeding_last_method(context, child): :returns: a dictionary with the most recent Feeding instances. """ instances = models.Feeding.objects.filter(child=child) \ + .filter(**_filter_data_age(context)) \ .order_by('-end')[:3] empty = len(instances) == 0 @@ -166,6 +178,7 @@ def card_sleep_last(context, child): :returns: a dictionary with the most recent Sleep instance. """ instance = models.Sleep.objects.filter(child=child) \ + .filter(**_filter_data_age(context)) \ .order_by('-end').first() empty = not instance @@ -496,6 +509,7 @@ def card_tummytime_last(context, child): :returns: a dictionary with the most recent Tummy Time instance. """ instance = models.TummyTime.objects.filter(child=child) \ + .filter(**_filter_data_age(context)) \ .order_by('-end').first() empty = not instance diff --git a/dashboard/tests/tests_templatetags.py b/dashboard/tests/tests_templatetags.py index 88584d34..9d085323 100644 --- a/dashboard/tests/tests_templatetags.py +++ b/dashboard/tests/tests_templatetags.py @@ -9,6 +9,8 @@ from babybuddy.models import Settings from core import models from dashboard.templatetags import cards +from unittest import mock + class MockUserRequest: def __init__(self, user): @@ -39,6 +41,31 @@ class TemplateTagsTestCase(TestCase): hide_empty = cards._hide_empty(context) self.assertTrue(hide_empty) + def test_filter_data_age_none(self): + request = MockUserRequest(User.objects.first()) + request.user.settings.dashboard_hide_age = None + context = {'request': request} + filter_data_age = cards._filter_data_age(context) + self.assertFalse(len(filter_data_age)) + + @mock.patch('dashboard.templatetags.cards.timezone') + def test_filter_data_age_one_day(self, mocked_timezone): + request = MockUserRequest(User.objects.first()) + request.user.settings.dashboard_hide_age = timezone.timedelta(days=1) + context = {'request': request} + mocked_timezone.localtime.return_value = \ + timezone.localtime().strptime('2017-11-18', '%Y-%m-%d') + + filter_data_age = cards._filter_data_age(context, keyword="time") + + self.assertIn("time__range", filter_data_age) + self.assertEqual( + filter_data_age["time__range"][0], + timezone.localtime().strptime('2017-11-17', '%Y-%m-%d')) + self.assertEqual( + filter_data_age["time__range"][1], + timezone.localtime().strptime('2017-11-18', '%Y-%m-%d')) + def test_card_diaperchange_last(self): data = cards.card_diaperchange_last(self.context, self.child) self.assertEqual(data['type'], 'diaperchange') @@ -47,6 +74,17 @@ class TemplateTagsTestCase(TestCase): self.assertIsInstance(data['change'], models.DiaperChange) self.assertEqual(data['change'], models.DiaperChange.objects.first()) + @mock.patch('dashboard.templatetags.cards.timezone') + def test_card_diaperchange_last_filter_age(self, mocked_timezone): + request = MockUserRequest(User.objects.first()) + request.user.settings.dashboard_hide_age = timezone.timedelta(days=1) + context = {'request': request} + time = timezone.localtime().strptime('2017-11-10', '%Y-%m-%d') + mocked_timezone.localtime.return_value = timezone.make_aware(time) + + data = cards.card_diaperchange_last(context, self.child) + self.assertTrue(data['empty']) + def test_card_diaperchange_types(self): data = cards.card_diaperchange_types( self.context,