dataviz: add sort and hide empty data options on chart cell (#45503)
This commit is contained in:
parent
05f16b523a
commit
ee8c7b2306
|
@ -43,7 +43,8 @@ class ChartForm(forms.ModelForm):
|
|||
class ChartNgForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = ChartNgCell
|
||||
fields = ('title', 'data_reference', 'chart_type', 'height')
|
||||
fields = ('title', 'data_reference', 'chart_type', 'height', 'sort_order',
|
||||
'hide_null_values')
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ChartNgForm, self).__init__(*args, **kwargs)
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.18 on 2020-08-13 09:00
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('dataviz', '0010_auto_20190328_1111'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='chartngcell',
|
||||
name='hide_null_values',
|
||||
field=models.BooleanField(default=False, help_text='This setting only applies for one-dimensional charts.', verbose_name='Hide null values'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='chartngcell',
|
||||
name='sort_order',
|
||||
field=models.CharField(choices=[('none', 'None'), ('alpha', 'Alphabetically'), ('asc', 'Increasing values'), ('desc', 'Decreasing values')], default='none', help_text='This setting only applies for one-dimensional charts.', max_length=5, verbose_name='Sort data'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='chartngcell',
|
||||
name='chart_type',
|
||||
field=models.CharField(choices=[('bar', 'Bar'), ('horizontal-bar', 'Horizontal Bar'), ('stacked-bar', 'Stacked Bar'), ('line', 'Line'), ('pie', 'Pie'), ('dot', 'Dot'), ('table', 'Table')], default='bar', max_length=20, verbose_name='Chart Type'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='chartngcell',
|
||||
name='height',
|
||||
field=models.CharField(choices=[('150', 'Short (150px)'), ('250', 'Average (250px)'), ('350', 'Tall (350px)')], default='250', max_length=20, verbose_name='Height'),
|
||||
),
|
||||
]
|
|
@ -126,6 +126,18 @@ class ChartNgCell(CellBase):
|
|||
('350', _('Tall (350px)')),
|
||||
))
|
||||
|
||||
sort_order = models.CharField(_('Sort data'), max_length=5, default='none',
|
||||
help_text=_('This setting only applies for one-dimensional charts.'),
|
||||
choices=(
|
||||
('none', _('None')),
|
||||
('alpha', _('Alphabetically')),
|
||||
('asc', _('Increasing values')),
|
||||
('desc', _('Decreasing values')),
|
||||
))
|
||||
|
||||
hide_null_values = models.BooleanField(default=False, verbose_name=_('Hide null values'),
|
||||
help_text=_('This setting only applies for one-dimensional charts.'))
|
||||
|
||||
manager_form_template = 'combo/chartngcell_form.html'
|
||||
|
||||
class Meta:
|
||||
|
@ -233,6 +245,26 @@ class ChartNgCell(CellBase):
|
|||
else:
|
||||
chart.axis_count = 2
|
||||
|
||||
# hide/sort values
|
||||
if chart.axis_count == 1 and (self.sort_order != 'none' or self.hide_null_values):
|
||||
if self.sort_order == 'alpha':
|
||||
tmp_items = sorted(zip(x_labels, data), key=lambda x: x[0])
|
||||
elif self.sort_order == 'asc':
|
||||
tmp_items = sorted(zip(x_labels, data), key=lambda x: x[1])
|
||||
elif self.sort_order == 'desc':
|
||||
tmp_items = sorted(zip(x_labels, data), key=lambda x: x[1], reverse=True)
|
||||
else:
|
||||
tmp_items = zip(x_labels, data)
|
||||
tmp_x_labels = []
|
||||
tmp_data = []
|
||||
for label, value in tmp_items:
|
||||
if self.hide_null_values and not value:
|
||||
continue
|
||||
tmp_x_labels.append(label)
|
||||
tmp_data.append(value)
|
||||
x_labels = tmp_x_labels
|
||||
data = tmp_data
|
||||
|
||||
chart.config.margin = 0
|
||||
if width:
|
||||
chart.config.width = width
|
||||
|
|
|
@ -361,6 +361,282 @@ def test_chartng_cell(app):
|
|||
chart = cell.get_chart()
|
||||
|
||||
|
||||
def test_chartng_cell_hide_null_values(app):
|
||||
page = Page(title='One', slug='index')
|
||||
page.save()
|
||||
|
||||
with override_settings(KNOWN_SERVICES={
|
||||
'bijoe': {'plop': {'title': 'test', 'url': 'https://bijoe.example.com',
|
||||
'secret': 'combo', 'orig': 'combo'}}}):
|
||||
with HTTMock(bijoe_mock):
|
||||
cell = ChartNgCell(page=page, order=1)
|
||||
cell.data_reference = 'plop:example'
|
||||
cell.hide_null_values = True
|
||||
cell.save()
|
||||
assert cell.cached_json == VISUALIZATION_JSON[0]
|
||||
|
||||
# bar
|
||||
chart = cell.get_chart()
|
||||
assert chart.__class__.__name__ == 'Bar'
|
||||
assert chart.x_labels == ['web', 'mail', 'email']
|
||||
assert chart.raw_series == [([222, 134, 53], {'title': ''})]
|
||||
|
||||
# horizontal bar
|
||||
cell.chart_type = 'horizontal-bar'
|
||||
chart = cell.get_chart()
|
||||
assert chart.__class__.__name__ == 'HorizontalBar'
|
||||
assert chart.x_labels == ['web', 'mail', 'email']
|
||||
assert chart.raw_series == [([222, 134, 53], {'title': ''})]
|
||||
|
||||
# pie
|
||||
cell.chart_type = 'pie'
|
||||
chart = cell.get_chart()
|
||||
assert chart.__class__.__name__ == 'Pie'
|
||||
assert chart.x_labels == ['web', 'mail', 'email']
|
||||
assert chart.raw_series == [
|
||||
([222], {'title': u'web'}),
|
||||
([134], {'title': u'mail'}),
|
||||
([53], {'title': u'email'})
|
||||
]
|
||||
|
||||
# data in Y
|
||||
cell.chart_type = 'bar'
|
||||
cell.data_reference = 'plop:second'
|
||||
cell.save()
|
||||
assert cell.cached_json == VISUALIZATION_JSON[1]
|
||||
|
||||
chart = cell.get_chart()
|
||||
assert chart.x_labels == ['web', 'mail', 'email']
|
||||
assert chart.raw_series == [([222, 134, 53], {'title': ''})]
|
||||
|
||||
# data in X/Y
|
||||
cell.chart_type = 'bar'
|
||||
cell.data_reference = 'plop:third'
|
||||
cell.save()
|
||||
assert cell.cached_json == VISUALIZATION_JSON[2]
|
||||
|
||||
chart = cell.get_chart()
|
||||
assert chart.x_labels == ['web', 'mail', 'phone', 'email']
|
||||
assert chart.raw_series == [
|
||||
([222, 134, 0, 53], {'title': u'foo'}),
|
||||
([122, 114, 2, 33], {'title': u'bar'}),
|
||||
]
|
||||
|
||||
# single data point
|
||||
cell.chart_type = 'bar'
|
||||
cell.data_reference = 'plop:fourth'
|
||||
cell.save()
|
||||
assert cell.cached_json == VISUALIZATION_JSON[3]
|
||||
|
||||
chart = cell.get_chart()
|
||||
assert chart.x_labels == ['']
|
||||
assert chart.raw_series == [([222], {'title': ''})]
|
||||
|
||||
# loop/X
|
||||
cell.data_reference = 'plop:fifth'
|
||||
cell.save()
|
||||
chart = cell.get_chart()
|
||||
assert chart.x_labels == ['web', 'mail', 'phone', 'email']
|
||||
assert chart.raw_series == [
|
||||
([222, 134, 0, 53], {'title': u'foo'}),
|
||||
([122, 114, 2, 33], {'title': u'bar'}),
|
||||
]
|
||||
|
||||
# loop/Y
|
||||
cell.data_reference = 'plop:sixth'
|
||||
cell.save()
|
||||
chart = cell.get_chart()
|
||||
assert chart.x_labels == ['web', 'mail', 'phone', 'email']
|
||||
assert chart.raw_series == [
|
||||
([222, 134, 0, 53], {'title': u'foo'}),
|
||||
([122, 114, 2, 33], {'title': u'bar'}),
|
||||
]
|
||||
|
||||
|
||||
def test_chartng_cell_sort_order_alpha(app):
|
||||
page = Page(title='One', slug='index')
|
||||
page.save()
|
||||
|
||||
with override_settings(KNOWN_SERVICES={
|
||||
'bijoe': {'plop': {'title': 'test', 'url': 'https://bijoe.example.com',
|
||||
'secret': 'combo', 'orig': 'combo'}}}):
|
||||
with HTTMock(bijoe_mock):
|
||||
cell = ChartNgCell(page=page, order=1)
|
||||
cell.data_reference = 'plop:example'
|
||||
cell.sort_order = 'alpha'
|
||||
cell.save()
|
||||
assert cell.cached_json == VISUALIZATION_JSON[0]
|
||||
|
||||
# bar
|
||||
chart = cell.get_chart()
|
||||
assert chart.__class__.__name__ == 'Bar'
|
||||
assert chart.x_labels == ['email', 'mail', 'phone', 'web']
|
||||
assert chart.raw_series == [([53, 134, 0, 222], {'title': ''})]
|
||||
|
||||
# horizontal bar
|
||||
cell.chart_type = 'horizontal-bar'
|
||||
chart = cell.get_chart()
|
||||
assert chart.__class__.__name__ == 'HorizontalBar'
|
||||
assert chart.x_labels == ['email', 'mail', 'phone', 'web']
|
||||
assert chart.raw_series == [([53, 134, 0, 222], {'title': ''})]
|
||||
|
||||
# pie
|
||||
cell.chart_type = 'pie'
|
||||
chart = cell.get_chart()
|
||||
assert chart.__class__.__name__ == 'Pie'
|
||||
assert chart.x_labels == ['email', 'mail', 'phone', 'web']
|
||||
assert chart.raw_series == [
|
||||
([53], {'title': u'email'}),
|
||||
([134], {'title': u'mail'}),
|
||||
([222], {'title': u'web'})
|
||||
]
|
||||
|
||||
# data in Y
|
||||
cell.chart_type = 'bar'
|
||||
cell.data_reference = 'plop:second'
|
||||
cell.save()
|
||||
assert cell.cached_json == VISUALIZATION_JSON[1]
|
||||
|
||||
chart = cell.get_chart()
|
||||
assert chart.x_labels == ['email', 'mail', 'phone', 'web']
|
||||
assert chart.raw_series == [([53, 134, 0, 222], {'title': ''})]
|
||||
|
||||
# data in X/Y
|
||||
cell.chart_type = 'bar'
|
||||
cell.data_reference = 'plop:third'
|
||||
cell.save()
|
||||
assert cell.cached_json == VISUALIZATION_JSON[2]
|
||||
|
||||
chart = cell.get_chart()
|
||||
assert chart.x_labels == ['web', 'mail', 'phone', 'email']
|
||||
assert chart.raw_series == [
|
||||
([222, 134, 0, 53], {'title': u'foo'}),
|
||||
([122, 114, 2, 33], {'title': u'bar'}),
|
||||
]
|
||||
|
||||
# single data point
|
||||
cell.chart_type = 'bar'
|
||||
cell.data_reference = 'plop:fourth'
|
||||
cell.save()
|
||||
assert cell.cached_json == VISUALIZATION_JSON[3]
|
||||
|
||||
chart = cell.get_chart()
|
||||
assert chart.x_labels == ['']
|
||||
assert chart.raw_series == [([222], {'title': ''})]
|
||||
|
||||
# loop/X
|
||||
cell.data_reference = 'plop:fifth'
|
||||
cell.save()
|
||||
chart = cell.get_chart()
|
||||
assert chart.x_labels == ['web', 'mail', 'phone', 'email']
|
||||
assert chart.raw_series == [
|
||||
([222, 134, 0, 53], {'title': u'foo'}),
|
||||
([122, 114, 2, 33], {'title': u'bar'}),
|
||||
]
|
||||
|
||||
# loop/Y
|
||||
cell.data_reference = 'plop:sixth'
|
||||
cell.save()
|
||||
chart = cell.get_chart()
|
||||
assert chart.x_labels == ['web', 'mail', 'phone', 'email']
|
||||
assert chart.raw_series == [
|
||||
([222, 134, 0, 53], {'title': u'foo'}),
|
||||
([122, 114, 2, 33], {'title': u'bar'}),
|
||||
]
|
||||
|
||||
|
||||
def test_chartng_cell_sort_order_desc(app):
|
||||
page = Page(title='One', slug='index')
|
||||
page.save()
|
||||
|
||||
with override_settings(KNOWN_SERVICES={
|
||||
'bijoe': {'plop': {'title': 'test', 'url': 'https://bijoe.example.com',
|
||||
'secret': 'combo', 'orig': 'combo'}}}):
|
||||
with HTTMock(bijoe_mock):
|
||||
cell = ChartNgCell(page=page, order=1)
|
||||
cell.data_reference = 'plop:example'
|
||||
cell.sort_order = 'desc'
|
||||
cell.save()
|
||||
assert cell.cached_json == VISUALIZATION_JSON[0]
|
||||
|
||||
# bar
|
||||
chart = cell.get_chart()
|
||||
assert chart.__class__.__name__ == 'Bar'
|
||||
assert chart.x_labels == ['web', 'mail', 'email', 'phone']
|
||||
assert chart.raw_series == [([222, 134, 53, 0], {'title': ''})]
|
||||
|
||||
# horizontal bar
|
||||
cell.chart_type = 'horizontal-bar'
|
||||
chart = cell.get_chart()
|
||||
assert chart.__class__.__name__ == 'HorizontalBar'
|
||||
assert chart.x_labels == ['web', 'mail', 'email', 'phone']
|
||||
assert chart.raw_series == [([222, 134, 53, 0], {'title': ''})]
|
||||
|
||||
# pie
|
||||
cell.chart_type = 'pie'
|
||||
chart = cell.get_chart()
|
||||
assert chart.__class__.__name__ == 'Pie'
|
||||
assert chart.x_labels == ['web', 'mail', 'email', 'phone']
|
||||
assert chart.raw_series == [
|
||||
([222], {'title': u'web'}),
|
||||
([134], {'title': u'mail'}),
|
||||
([53], {'title': u'email'})
|
||||
]
|
||||
|
||||
# data in Y
|
||||
cell.chart_type = 'bar'
|
||||
cell.data_reference = 'plop:second'
|
||||
cell.save()
|
||||
assert cell.cached_json == VISUALIZATION_JSON[1]
|
||||
|
||||
chart = cell.get_chart()
|
||||
assert chart.x_labels == ['web', 'mail', 'email', 'phone']
|
||||
assert chart.raw_series == [([222, 134, 53, 0], {'title': ''})]
|
||||
|
||||
# data in X/Y
|
||||
cell.chart_type = 'bar'
|
||||
cell.data_reference = 'plop:third'
|
||||
cell.save()
|
||||
assert cell.cached_json == VISUALIZATION_JSON[2]
|
||||
|
||||
chart = cell.get_chart()
|
||||
assert chart.x_labels == ['web', 'mail', 'phone', 'email']
|
||||
assert chart.raw_series == [
|
||||
([222, 134, 0, 53], {'title': u'foo'}),
|
||||
([122, 114, 2, 33], {'title': u'bar'}),
|
||||
]
|
||||
|
||||
# single data point
|
||||
cell.chart_type = 'bar'
|
||||
cell.data_reference = 'plop:fourth'
|
||||
cell.save()
|
||||
assert cell.cached_json == VISUALIZATION_JSON[3]
|
||||
|
||||
chart = cell.get_chart()
|
||||
assert chart.x_labels == ['']
|
||||
assert chart.raw_series == [([222], {'title': ''})]
|
||||
|
||||
# loop/X
|
||||
cell.data_reference = 'plop:fifth'
|
||||
cell.save()
|
||||
chart = cell.get_chart()
|
||||
assert chart.x_labels == ['web', 'mail', 'phone', 'email']
|
||||
assert chart.raw_series == [
|
||||
([222, 134, 0, 53], {'title': u'foo'}),
|
||||
([122, 114, 2, 33], {'title': u'bar'}),
|
||||
]
|
||||
|
||||
# loop/Y
|
||||
cell.data_reference = 'plop:sixth'
|
||||
cell.save()
|
||||
chart = cell.get_chart()
|
||||
assert chart.x_labels == ['web', 'mail', 'phone', 'email']
|
||||
assert chart.raw_series == [
|
||||
([222, 134, 0, 53], {'title': u'foo'}),
|
||||
([122, 114, 2, 33], {'title': u'bar'}),
|
||||
]
|
||||
|
||||
|
||||
def test_chartng_cell_view(app, normal_user):
|
||||
page = Page(title='One', slug='index')
|
||||
page.save()
|
||||
|
|
Loading…
Reference in New Issue