Compare commits
10 Commits
c3531638c6
...
732c79d022
Author | SHA1 | Date |
---|---|---|
Valentin Deniaud | 732c79d022 | |
Valentin Deniaud | 79e0ef7ff6 | |
Valentin Deniaud | 6c203dcd7e | |
Valentin Deniaud | f1ed047e6b | |
Valentin Deniaud | 358138125e | |
Valentin Deniaud | 7a8d872e16 | |
Serghei Mihai | 5f63dbbd3d | |
Serghei Mihai | 78bbd7718b | |
Serghei Mihai | a6a6b8c54c | |
Serghei Mihai | b312c2fd11 |
|
@ -360,7 +360,6 @@ class ChartNgCell(CellBase):
|
|||
if self.statistic.service_slug == 'bijoe':
|
||||
x_labels, y_labels, data = self.parse_response(response, chart)
|
||||
chart.x_labels = x_labels
|
||||
self.prepare_chart(chart, width, height)
|
||||
|
||||
if chart.axis_count == 1:
|
||||
data = self.process_one_dimensional_data(chart, data)
|
||||
|
@ -379,7 +378,6 @@ class ChartNgCell(CellBase):
|
|||
|
||||
chart.x_labels = data['x_labels']
|
||||
chart.axis_count = min(len(data['series']), 2)
|
||||
self.prepare_chart(chart, width, height)
|
||||
|
||||
if self.statistic.data_type:
|
||||
chart.config.value_formatter = self.get_value_formatter(self.statistic.data_type)
|
||||
|
@ -401,7 +399,7 @@ class ChartNgCell(CellBase):
|
|||
|
||||
for serie in data['series']:
|
||||
chart.add(serie['label'], serie['data'])
|
||||
|
||||
self.configure_chart(chart, width, height)
|
||||
return chart
|
||||
|
||||
def get_filter_params(self):
|
||||
|
@ -531,14 +529,37 @@ class ChartNgCell(CellBase):
|
|||
|
||||
return x_labels, y_labels, data
|
||||
|
||||
def prepare_chart(self, chart, width, height):
|
||||
def configure_dot_chart(self, chart, width, height):
|
||||
chart.show_legend = False
|
||||
# use a single colour for dots
|
||||
chart.config.style.colors = ('#1f77b4',) * max(len(chart.x_labels), 1)
|
||||
|
||||
def configure_horizontal_bar_chart(self, chart, width, height):
|
||||
if width and width < 500:
|
||||
# truncate labels
|
||||
chart.x_labels = [pygal.util.truncate(x, 15) for x in chart.x_labels]
|
||||
|
||||
def configure_pie_chart(self, chart, width, height):
|
||||
chart.show_legend = True
|
||||
if width and height:
|
||||
# pies are as tall as wide, reserve the appropriate space and distribute
|
||||
# the rest for the legend.
|
||||
chart.truncate_legend = (width - height) // 10
|
||||
elif width:
|
||||
chart.truncate_legend = width // 20
|
||||
|
||||
def configure_chart(self, chart, width, height):
|
||||
auto_height_scale = pygal.style.DefaultStyle.legend_font_size * 1.75
|
||||
chart.config.margin = 0
|
||||
if width:
|
||||
chart.config.width = width
|
||||
if height:
|
||||
chart.config.height = height
|
||||
height = height or int(self.height)
|
||||
# adapt chart's height to legend length
|
||||
chart.config.height = max(height, auto_height_scale * len(chart.raw_series))
|
||||
|
||||
if width or height:
|
||||
chart.config.explicit_size = True
|
||||
|
||||
chart.config.js = [os.path.join(settings.STATIC_URL, 'js/pygal-tooltips.js')]
|
||||
|
||||
chart.show_legend = bool(chart.axis_count > 1)
|
||||
|
@ -557,25 +578,15 @@ class ChartNgCell(CellBase):
|
|||
'#17becf',
|
||||
)
|
||||
|
||||
if self.chart_type == 'dot':
|
||||
chart.show_legend = False
|
||||
# use a single colour for dots
|
||||
chart.config.style.colors = ('#1f77b4',) * max(len(chart.x_labels), 1)
|
||||
custom_configure_method_name = 'configure_%s_chart' % self.chart_type.replace('-', '_')
|
||||
if hasattr(self, custom_configure_method_name):
|
||||
getattr(self, custom_configure_method_name)(chart, width, height)
|
||||
|
||||
if self.chart_type != 'pie':
|
||||
if width and width < 500:
|
||||
chart.legend_at_bottom = True
|
||||
if self.chart_type == 'horizontal-bar':
|
||||
# truncate labels
|
||||
chart.x_labels = [pygal.util.truncate(x, 15) for x in chart.x_labels]
|
||||
else:
|
||||
chart.show_legend = True
|
||||
if width and height:
|
||||
# pies are as tall as wide, reserve the appropriate space and distribute
|
||||
# the rest for the legend.
|
||||
chart.truncate_legend = (width - height) // 10
|
||||
elif width:
|
||||
chart.truncate_legend = width // 20
|
||||
# restore demanded chart's height
|
||||
chart.config.height = height
|
||||
|
||||
def process_one_dimensional_data(self, chart, data):
|
||||
if self.hide_null_values:
|
||||
|
|
|
@ -73,7 +73,7 @@ class DatavizGraphView(DetailView):
|
|||
try:
|
||||
chart = form.instance.get_chart(
|
||||
width=int(request.GET['width']) if request.GET.get('width') else None,
|
||||
height=int(request.GET['height']) if request.GET.get('height') else int(self.cell.height),
|
||||
height=int(request.GET['height']) if request.GET.get('height') else None,
|
||||
)
|
||||
except UnsupportedDataSet:
|
||||
return self.error(_('Unsupported dataset.'))
|
||||
|
|
|
@ -4,6 +4,7 @@ import json
|
|||
import urllib.parse
|
||||
from unittest import mock
|
||||
|
||||
import lxml
|
||||
import pytest
|
||||
from django.apps import apps
|
||||
from django.contrib.auth.models import Group
|
||||
|
@ -149,6 +150,12 @@ VISUALIZATION_JSON = [
|
|||
'name': 'sixteenth visualization (numerical labels)',
|
||||
'slug': 'sixteenth',
|
||||
},
|
||||
{
|
||||
'data-url': 'https://bijoe.example.com/visualization/17/json/',
|
||||
'path': 'https://bijoe.example.com/visualization/17/iframe/?signature=123',
|
||||
'name': 'seventeenth visualization (string labels)',
|
||||
'slug': 'seventeenth',
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
|
@ -324,6 +331,83 @@ def bijoe_mock(url, request):
|
|||
'measure': 'integer',
|
||||
}
|
||||
return {'content': json.dumps(response), 'request': request, 'status_code': 200}
|
||||
if url.path == '/visualization/17/json/':
|
||||
response = {
|
||||
'data': [
|
||||
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
|
||||
],
|
||||
'axis': {
|
||||
'x_labels': [
|
||||
'Mois de %s' % m
|
||||
for m in [
|
||||
'janvier',
|
||||
'février',
|
||||
'mars',
|
||||
'avril',
|
||||
'mai',
|
||||
'juin',
|
||||
'juillet',
|
||||
'août',
|
||||
'septembre',
|
||||
'octobre',
|
||||
'novembre',
|
||||
'décembre',
|
||||
]
|
||||
],
|
||||
'y_labels': ['Label %s' % i for i in range(0, 9)],
|
||||
},
|
||||
'format': '1',
|
||||
'unit': None,
|
||||
'measure': 'integer',
|
||||
}
|
||||
return {'content': json.dumps(response), 'request': request, 'status_code': 200}
|
||||
|
||||
if url.path == '/visualization/17/json/':
|
||||
response = {
|
||||
'data': [
|
||||
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
|
||||
],
|
||||
'axis': {
|
||||
'x_labels': [
|
||||
'Mois de %s' % m
|
||||
for m in [
|
||||
'janvier',
|
||||
'février',
|
||||
'mars',
|
||||
'avril',
|
||||
'mai',
|
||||
'juin',
|
||||
'juillet',
|
||||
'août',
|
||||
'septembre',
|
||||
'octobre',
|
||||
'novembre',
|
||||
'décembre',
|
||||
]
|
||||
],
|
||||
'y_labels': ['Label %s' % i for i in range(0, 9)],
|
||||
},
|
||||
'format': '1',
|
||||
'unit': None,
|
||||
'measure': 'integer',
|
||||
}
|
||||
return {'content': json.dumps(response), 'request': request, 'status_code': 200}
|
||||
|
||||
|
||||
STATISTICS_LIST = {
|
||||
|
@ -1345,6 +1429,69 @@ def test_chartng_cell_view(app, normal_user, statistics):
|
|||
assert 'not found' in resp.text
|
||||
|
||||
|
||||
@with_httmock(bijoe_mock)
|
||||
def test_chartng_cell_with_truncated_labels(app, normal_user, statistics):
|
||||
page = Page(title='One', slug='index')
|
||||
page.save()
|
||||
|
||||
cell = ChartNgCell(page=page, order=1, placeholder='content', chart_type='horizontal-bar')
|
||||
cell.statistic = Statistic.objects.get(slug='seventeenth')
|
||||
cell.save()
|
||||
location = '/api/dataviz/graph/%s/' % cell.id
|
||||
resp = app.get(location + '?width=499')
|
||||
svg = lxml.etree.fromstring(resp.text.encode())
|
||||
for label in svg.xpath(
|
||||
"//ns:g[@class='legends']//ns:text", namespaces={'ns': 'http://www.w3.org/2000/svg'}
|
||||
):
|
||||
assert len(label) <= 15
|
||||
|
||||
|
||||
@with_httmock(bijoe_mock)
|
||||
def test_chartng_cell_viewbox(app, normal_user, statistics):
|
||||
page = Page(title='One', slug='index')
|
||||
page.save()
|
||||
|
||||
cell = ChartNgCell(page=page, order=1, placeholder='content')
|
||||
cell.statistic = Statistic.objects.get(slug='eighth')
|
||||
cell.save()
|
||||
location = '/api/dataviz/graph/%s/' % cell.id
|
||||
resp = app.get(location + '?width=600')
|
||||
svg = lxml.etree.fromstring(resp.text.encode())
|
||||
assert svg.attrib['width'] == '600'
|
||||
assert svg.attrib['height'] == '250'
|
||||
|
||||
cell.statistic = Statistic.objects.get(slug='seventeenth')
|
||||
cell.save()
|
||||
|
||||
resp = app.get(location + '?width=800&height=600')
|
||||
svg = lxml.etree.fromstring(resp.text.encode())
|
||||
assert svg.attrib['width'] == '800'
|
||||
assert svg.attrib['height'] == '600'
|
||||
|
||||
# simulate chart preview from backoffice
|
||||
resp = app.get(location + '?width=300&height=150')
|
||||
svg = lxml.etree.fromstring(resp.text.encode())
|
||||
assert svg.attrib['width'] == '300'
|
||||
assert svg.attrib['height'] == '150'
|
||||
|
||||
# reduce cell's height
|
||||
cell.height = '150'
|
||||
cell.save()
|
||||
|
||||
resp = app.get(location + '?width=600&height=200')
|
||||
svg = lxml.etree.fromstring(resp.text.encode())
|
||||
# rendered cell should be higher than defined height
|
||||
assert svg.attrib['height'] == '220.5'
|
||||
|
||||
# test pie chart rendering
|
||||
cell.chart_type = 'pie'
|
||||
cell.save()
|
||||
resp = app.get(location + '?width=600&height=200')
|
||||
svg = lxml.etree.fromstring(resp.text.encode())
|
||||
# rendered cell should be higher than defined height
|
||||
assert svg.attrib['height'] == '220.5'
|
||||
|
||||
|
||||
@with_httmock(new_api_mock)
|
||||
def test_chartng_cell_view_new_api(app, normal_user, new_api_statistics):
|
||||
page = Page.objects.create(title='One', slug='index')
|
||||
|
|
Loading…
Reference in New Issue