From b2153bc7bc8b1399e07836fa29020b4e532a456e Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Tue, 15 Dec 2020 16:23:09 +0100 Subject: [PATCH] dataviz: add time range fields (#49248) --- combo/apps/dataviz/forms.py | 11 ++++- .../migrations/0016_auto_20201215_1624.py | 30 ++++++++++++ combo/apps/dataviz/models.py | 47 +++++++++++++++++-- .../templates/combo/chartngcell_form.html | 16 +++++++ tests/test_dataviz.py | 18 ++++++- 5 files changed, 115 insertions(+), 7 deletions(-) create mode 100644 combo/apps/dataviz/migrations/0016_auto_20201215_1624.py diff --git a/combo/apps/dataviz/forms.py b/combo/apps/dataviz/forms.py index 9ff2879b..0dbd70e2 100644 --- a/combo/apps/dataviz/forms.py +++ b/combo/apps/dataviz/forms.py @@ -48,8 +48,12 @@ class ChartNgForm(forms.ModelForm): class Meta: model = ChartNgCell - fields = ('title', 'statistic', 'chart_type', 'height', 'sort_order', - 'hide_null_values') + fields = ('title', 'statistic', 'time_range','time_range_start', 'time_range_end', 'chart_type', + 'height', 'sort_order', 'hide_null_values') + widgets = { + 'time_range_start': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'), + 'time_range_end': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'), + } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -80,6 +84,9 @@ class ChartNgForm(forms.ModelForm): # reorder so that filter fields appear after 'statistic' field self.fields = OrderedDict((field_id, self.fields[field_id]) for field_id in field_ids) + if self.instance.statistic.service_slug == 'bijoe': + self.fields.pop('time_range') + def save(self, *args, **kwargs): if 'statistic' in self.changed_data: self.instance.filter_params.clear() diff --git a/combo/apps/dataviz/migrations/0016_auto_20201215_1624.py b/combo/apps/dataviz/migrations/0016_auto_20201215_1624.py new file mode 100644 index 00000000..1dc7f461 --- /dev/null +++ b/combo/apps/dataviz/migrations/0016_auto_20201215_1624.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.29 on 2020-12-15 15:24 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('dataviz', '0015_auto_20201202_1424'), + ] + + operations = [ + migrations.AddField( + model_name='chartngcell', + name='time_range', + field=models.CharField(blank=True, choices=[('current-year', 'Current year'), ('previous-year', 'Previous year'), ('current-month', 'Current month'), ('previous-month', 'Previous month'), ('range', 'Free range')], max_length=20, verbose_name='Filtering (time)'), + ), + migrations.AddField( + model_name='chartngcell', + name='time_range_end', + field=models.DateField(blank=True, null=True, verbose_name='To'), + ), + migrations.AddField( + model_name='chartngcell', + name='time_range_start', + field=models.DateField(blank=True, null=True, verbose_name='From'), + ), + ] diff --git a/combo/apps/dataviz/models.py b/combo/apps/dataviz/models.py index fa727a75..2170b79e 100644 --- a/combo/apps/dataviz/models.py +++ b/combo/apps/dataviz/models.py @@ -16,9 +16,11 @@ import copy import os +from datetime import date from django.urls import reverse from django.db import models +from django.utils import timezone from django.utils.encoding import force_text from django.utils.translation import ugettext_lazy as _, ungettext, gettext from django.conf import settings @@ -137,14 +139,33 @@ class Statistic(models.Model): @register_cell_class class ChartNgCell(CellBase): + TIME_FILTERS = ( + ('current-year', _('Current year')), + ('previous-year', _('Previous year')), + ('current-month', _('Current month')), + ('previous-month', _('Previous month')), + ('range', _('Free range')), + ) + statistic = models.ForeignKey( verbose_name=_('Data'), to=Statistic, blank=False, null=True, on_delete=models.SET_NULL, related_name='cells' ) filter_params = JSONField(default=dict) title = models.CharField(_('Title'), max_length=150, blank=True) - time_filter = models.CharField(_('Filtering (time)'), max_length=20, choices=todo) - time_filter_from = models.DateTimeField(_('From'), null=True) - time_filter_to = models.DateTimeField(_('To'), null=True) + time_range = models.CharField( + _('Filtering (time)'), + max_length=20, + blank=True, + choices=( + ('current-year', _('Current year')), + ('previous-year', _('Previous year')), + ('current-month', _('Current month')), + ('previous-month', _('Previous month')), + ('range', _('Free range')), + ) + ) + time_range_start = models.DateField(_('From'), null=True, blank=True) + time_range_end = models.DateField(_('To'), null=True, blank=True) chart_type = models.CharField(_('Chart Type'), max_length=20, default='bar', choices=( ('bar', _('Bar')), @@ -218,7 +239,7 @@ class ChartNgCell(CellBase): def get_chart(self, width=None, height=None, raise_if_not_cached=False): response = requests.get( self.statistic.url, - params=self.filter_params, + params=self.get_filter_params(), cache_duration=300, remote_service='auto', without_user=True, @@ -270,6 +291,24 @@ class ChartNgCell(CellBase): return chart + def get_filter_params(self): + params = self.filter_params.copy() + now = timezone.now().date() + if self.time_range == 'current-year': + params['start'] = date(year=now.year, month=1, day=1) + elif self.time_range == 'previous-year': + params['start'] = date(year=now.year - 1, month=1, day=1) + params['end'] = date(year=now.year, month=1, day=1) + elif self.time_range == 'current-month': + params['start'] = date(year=now.year, month=now.month, day=1) + elif self.time_range == 'previous-month': + params['start'] = date(year=now.year, month=now.month - 1, day=1) + params['end'] = date(year=now.year, month=now.month, day=1) + elif self.time_range == 'range': + params['start'] = self.time_range_start + params['end'] = self.time_range_end + return params + def parse_response(self, response, chart): # normalize axis to have a fake axis when there are no dimensions and # always a x axis when there is a single dimension. diff --git a/combo/apps/dataviz/templates/combo/chartngcell_form.html b/combo/apps/dataviz/templates/combo/chartngcell_form.html index 33d7b8f0..c883058b 100644 --- a/combo/apps/dataviz/templates/combo/chartngcell_form.html +++ b/combo/apps/dataviz/templates/combo/chartngcell_form.html @@ -6,3 +6,19 @@ {% endif %} + + diff --git a/tests/test_dataviz.py b/tests/test_dataviz.py index 32f8a454..d5bbacbb 100644 --- a/tests/test_dataviz.py +++ b/tests/test_dataviz.py @@ -909,6 +909,7 @@ def test_chartng_cell_manager(app, admin_user, statistics): assert statistics_field.value == str(cell.statistic.pk) assert statistics_field.options[1][2] == 'test: eighth visualization (duration)' assert not 'Unavailable Stat' in resp.text + assert 'time_range' not in resp.form.fields cell.statistic = Statistic.objects.get(slug='unavailable-stat') cell.save() @@ -919,7 +920,7 @@ def test_chartng_cell_manager(app, admin_user, statistics): @with_httmock(new_api_mock) -def test_chartng_cell_manager_new_api(app, admin_user, new_api_statistics): +def test_chartng_cell_manager_new_api(app, admin_user, new_api_statistics, freezer): page = Page.objects.create(title='One', slug='index') cell = ChartNgCell(page=page, order=1, placeholder='content') cell.statistic = Statistic.objects.get(slug='one-serie') @@ -963,6 +964,21 @@ def test_chartng_cell_manager_new_api(app, admin_user, new_api_statistics): cell.refresh_from_db() assert cell.filter_params == {'time_interval': 'month'} + freezer.move_to('2020-03-02 12:01') + resp.form[field_prefix + 'time_range'] = 'previous-year' + resp = resp.form.submit().follow() + cell.refresh_from_db() + cell.get_chart() + assert 'time_interval=month&start=2019-01-01&end=2020-01-01' in new_api_mock.call['requests'][0].url + + resp.form[field_prefix + 'time_range'] = 'range' + resp.form[field_prefix + 'time_range_start'] = '2020-10-01' + resp.form[field_prefix + 'time_range_end'] = '2020-11-03' + resp = resp.form.submit().follow() + cell.refresh_from_db() + cell.get_chart() + assert 'time_interval=month&start=2020-10-01&end=2020-11-03' in new_api_mock.call['requests'][1].url + no_filters_stat = Statistic.objects.get(slug='two-series') resp.form[field_prefix + 'statistic'] = no_filters_stat.pk resp = resp.form.submit().follow() -- 2.20.1