0001-dataviz-add-time-range-fields-49248.patch
combo/apps/dataviz/forms.py | ||
---|---|---|
48 | 48 | |
49 | 49 |
class Meta: |
50 | 50 |
model = ChartNgCell |
51 |
fields = ('title', 'statistic', 'chart_type', 'height', 'sort_order', |
|
52 |
'hide_null_values') |
|
51 |
fields = ('title', 'statistic', 'time_range','time_range_start', 'time_range_end', 'chart_type', |
|
52 |
'height', 'sort_order', 'hide_null_values') |
|
53 |
widgets = { |
|
54 |
'time_range_start': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'), |
|
55 |
'time_range_end': forms.DateInput(attrs={'type': 'date'}, format='%Y-%m-%d'), |
|
56 |
} |
|
53 | 57 | |
54 | 58 |
def __init__(self, *args, **kwargs): |
55 | 59 |
super().__init__(*args, **kwargs) |
... | ... | |
80 | 84 |
# reorder so that filter fields appear after 'statistic' field |
81 | 85 |
self.fields = OrderedDict((field_id, self.fields[field_id]) for field_id in field_ids) |
82 | 86 | |
87 |
if self.instance.statistic.service_slug == 'bijoe': |
|
88 |
self.fields.pop('time_range') |
|
89 | ||
83 | 90 |
def save(self, *args, **kwargs): |
84 | 91 |
if 'statistic' in self.changed_data: |
85 | 92 |
self.instance.filter_params.clear() |
combo/apps/dataviz/migrations/0016_auto_20201215_1624.py | ||
---|---|---|
1 |
# -*- coding: utf-8 -*- |
|
2 |
# Generated by Django 1.11.29 on 2020-12-15 15:24 |
|
3 |
from __future__ import unicode_literals |
|
4 | ||
5 |
from django.db import migrations, models |
|
6 | ||
7 | ||
8 |
class Migration(migrations.Migration): |
|
9 | ||
10 |
dependencies = [ |
|
11 |
('dataviz', '0015_auto_20201202_1424'), |
|
12 |
] |
|
13 | ||
14 |
operations = [ |
|
15 |
migrations.AddField( |
|
16 |
model_name='chartngcell', |
|
17 |
name='time_range', |
|
18 |
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)'), |
|
19 |
), |
|
20 |
migrations.AddField( |
|
21 |
model_name='chartngcell', |
|
22 |
name='time_range_end', |
|
23 |
field=models.DateField(blank=True, null=True, verbose_name='To'), |
|
24 |
), |
|
25 |
migrations.AddField( |
|
26 |
model_name='chartngcell', |
|
27 |
name='time_range_start', |
|
28 |
field=models.DateField(blank=True, null=True, verbose_name='From'), |
|
29 |
), |
|
30 |
] |
combo/apps/dataviz/models.py | ||
---|---|---|
16 | 16 | |
17 | 17 |
import copy |
18 | 18 |
import os |
19 |
from datetime import date |
|
19 | 20 | |
20 | 21 |
from django.urls import reverse |
21 | 22 |
from django.db import models |
23 |
from django.utils import timezone |
|
22 | 24 |
from django.utils.encoding import force_text |
23 | 25 |
from django.utils.translation import ugettext_lazy as _, ungettext, gettext |
24 | 26 |
from django.conf import settings |
... | ... | |
137 | 139 | |
138 | 140 |
@register_cell_class |
139 | 141 |
class ChartNgCell(CellBase): |
142 |
TIME_FILTERS = ( |
|
143 |
('current-year', _('Current year')), |
|
144 |
('previous-year', _('Previous year')), |
|
145 |
('current-month', _('Current month')), |
|
146 |
('previous-month', _('Previous month')), |
|
147 |
('range', _('Free range')), |
|
148 |
) |
|
149 | ||
140 | 150 |
statistic = models.ForeignKey( |
141 | 151 |
verbose_name=_('Data'), to=Statistic, blank=False, null=True, on_delete=models.SET_NULL, related_name='cells' |
142 | 152 |
) |
143 | 153 |
filter_params = JSONField(default=dict) |
144 | 154 |
title = models.CharField(_('Title'), max_length=150, blank=True) |
155 |
time_range = models.CharField( |
|
156 |
_('Filtering (time)'), |
|
157 |
max_length=20, |
|
158 |
blank=True, |
|
159 |
choices=( |
|
160 |
('current-year', _('Current year')), |
|
161 |
('previous-year', _('Previous year')), |
|
162 |
('current-month', _('Current month')), |
|
163 |
('previous-month', _('Previous month')), |
|
164 |
('range', _('Free range')), |
|
165 |
) |
|
166 |
) |
|
167 |
time_range_start = models.DateField(_('From'), null=True, blank=True) |
|
168 |
time_range_end = models.DateField(_('To'), null=True, blank=True) |
|
145 | 169 |
chart_type = models.CharField(_('Chart Type'), max_length=20, default='bar', |
146 | 170 |
choices=( |
147 | 171 |
('bar', _('Bar')), |
... | ... | |
215 | 239 |
def get_chart(self, width=None, height=None, raise_if_not_cached=False): |
216 | 240 |
response = requests.get( |
217 | 241 |
self.statistic.url, |
218 |
params=self.filter_params,
|
|
242 |
params=self.get_filter_params(),
|
|
219 | 243 |
cache_duration=300, |
220 | 244 |
remote_service='auto', |
221 | 245 |
without_user=True, |
... | ... | |
267 | 291 | |
268 | 292 |
return chart |
269 | 293 | |
294 |
def get_filter_params(self): |
|
295 |
params = self.filter_params.copy() |
|
296 |
now = timezone.now().date() |
|
297 |
if self.time_range == 'current-year': |
|
298 |
params['start'] = date(year=now.year, month=1, day=1) |
|
299 |
elif self.time_range == 'previous-year': |
|
300 |
params['start'] = date(year=now.year - 1, month=1, day=1) |
|
301 |
params['end'] = date(year=now.year, month=1, day=1) |
|
302 |
elif self.time_range == 'current-month': |
|
303 |
params['start'] = date(year=now.year, month=now.month, day=1) |
|
304 |
elif self.time_range == 'previous-month': |
|
305 |
params['start'] = date(year=now.year, month=now.month - 1, day=1) |
|
306 |
params['end'] = date(year=now.year, month=now.month, day=1) |
|
307 |
elif self.time_range == 'range': |
|
308 |
params['start'] = self.time_range_start |
|
309 |
params['end'] = self.time_range_end |
|
310 |
return params |
|
311 | ||
270 | 312 |
def parse_response(self, response, chart): |
271 | 313 |
# normalize axis to have a fake axis when there are no dimensions and |
272 | 314 |
# always a x axis when there is a single dimension. |
combo/apps/dataviz/templates/combo/chartngcell_form.html | ||
---|---|---|
6 | 6 |
</div> |
7 | 7 |
{% endif %} |
8 | 8 |
</div> |
9 | ||
10 |
<script> |
|
11 |
$(function () { |
|
12 |
start_field = $('#id_cdataviz_chartngcell-{{ cell.pk }}-time_range_start'); |
|
13 |
end_field = $('#id_cdataviz_chartngcell-{{ cell.pk }}-time_range_end'); |
|
14 |
$('#id_cdataviz_chartngcell-{{ cell.pk }}-time_range').change(function() { |
|
15 |
if(this.value == 'range') { |
|
16 |
start_field.parent().show(); |
|
17 |
end_field.parent().show(); |
|
18 |
} else { |
|
19 |
start_field.parent().hide(); |
|
20 |
end_field.parent().hide(); |
|
21 |
} |
|
22 |
}).change(); |
|
23 |
}); |
|
24 |
</script> |
tests/test_dataviz.py | ||
---|---|---|
2 | 2 | |
3 | 3 |
import mock |
4 | 4 |
import pytest |
5 |
from datetime import timedelta |
|
5 |
from datetime import timedelta, date
|
|
6 | 6 |
from httmock import HTTMock, with_httmock, remember_called, urlmatch |
7 | 7 |
from requests.exceptions import HTTPError |
8 | 8 | |
... | ... | |
909 | 909 |
assert statistics_field.value == str(cell.statistic.pk) |
910 | 910 |
assert statistics_field.options[1][2] == 'test: eighth visualization (duration)' |
911 | 911 |
assert not 'Unavailable Stat' in resp.text |
912 |
assert 'time_range' not in resp.form.fields |
|
912 | 913 | |
913 | 914 |
cell.statistic = Statistic.objects.get(slug='unavailable-stat') |
914 | 915 |
cell.save() |
... | ... | |
963 | 964 |
cell.refresh_from_db() |
964 | 965 |
assert cell.filter_params == {'time_interval': 'month'} |
965 | 966 | |
967 |
resp.form[field_prefix + 'time_range'] = 'previous-year' |
|
968 |
resp = resp.form.submit().follow() |
|
969 |
cell.refresh_from_db() |
|
970 |
assert cell.time_range == 'previous-year' |
|
971 | ||
972 |
resp.form[field_prefix + 'time_range'] = 'range' |
|
973 |
resp.form[field_prefix + 'time_range_start'] = '2020-10-01' |
|
974 |
resp.form[field_prefix + 'time_range_end'] = '2020-11-03' |
|
975 |
resp = resp.form.submit().follow() |
|
976 |
cell.refresh_from_db() |
|
977 |
assert cell.time_range == 'range' |
|
978 |
assert cell.time_range_start == date(year=2020, month=10, day=1) |
|
979 |
assert cell.time_range_end == date(year=2020, month=11, day=3) |
|
980 | ||
966 | 981 |
no_filters_stat = Statistic.objects.get(slug='two-series') |
967 | 982 |
resp.form[field_prefix + 'statistic'] = no_filters_stat.pk |
968 | 983 |
resp = resp.form.submit().follow() |
... | ... | |
1175 | 1190 | |
1176 | 1191 | |
1177 | 1192 |
@with_httmock(new_api_mock) |
1178 |
def test_chartng_cell_new_api_filter_params(new_api_statistics, nocache): |
|
1193 |
def test_chartng_cell_new_api_filter_params(new_api_statistics, nocache, freezer):
|
|
1179 | 1194 |
page = Page.objects.create(title='One', slug='index') |
1180 | 1195 |
cell = ChartNgCell(page=page, order=1, placeholder='content') |
1181 | 1196 |
cell.statistic = Statistic.objects.get(slug='one-serie') |
... | ... | |
1192 | 1207 |
request = new_api_mock.call['requests'][1] |
1193 | 1208 |
assert 'time_interval=day' in request.url |
1194 | 1209 |
assert 'ou=default' in request.url |
1210 | ||
1211 |
freezer.move_to('2020-03-02 12:01') |
|
1212 |
cell.time_range = 'previous-year' |
|
1213 |
cell.save() |
|
1214 |
chart = cell.get_chart() |
|
1215 |
request = new_api_mock.call['requests'][2] |
|
1216 |
assert 'time_interval=day' in request.url |
|
1217 |
assert 'ou=default' in request.url |
|
1218 |
assert 'start=2019-01-01' in request.url and '2020-01-01' in request.url |
|
1219 | ||
1220 |
cell.time_range = 'range' |
|
1221 |
cell.time_range_start = '2020-10-01' |
|
1222 |
cell.time_range_end = '2020-11-03' |
|
1223 |
cell.save() |
|
1224 |
chart = cell.get_chart() |
|
1225 |
request = new_api_mock.call['requests'][3] |
|
1226 |
assert 'start=2020-10-01' in request.url and '2020-11-03' in request.url |
|
1195 |
- |