Projet

Général

Profil

0001-dataviz-add-support-for-loop-warn-if-there-are-three.patch

Frédéric Péters, 01 septembre 2019 10:42

Télécharger (10 ko)

Voir les différences:

Subject: [PATCH] dataviz: add support for loop, warn if there are three
 dimensions (#35698)

 combo/apps/dataviz/models.py |  29 ++++++++--
 combo/apps/dataviz/views.py  |  26 +++++++--
 tests/test_dataviz.py        | 104 ++++++++++++++++++++++++++++++++++-
 3 files changed, 146 insertions(+), 13 deletions(-)
combo/apps/dataviz/models.py
30 30
from combo.utils import get_templated_url, requests
31 31

  
32 32

  
33
class UnsupportedDataSet(Exception):
34
    pass
35

  
36

  
33 37
@register_cell_class
34 38
class Gauge(CellBase):
35 39
    title = models.CharField(_('Title'), max_length=150, blank=True, null=True)
......
157 161
    def get_cell_extra_context(self, context):
158 162
        ctx = super(ChartNgCell, self).get_cell_extra_context(context)
159 163
        if self.chart_type == 'table':
160
            chart = self.get_chart(raise_if_not_cached=not(context.get('synchronous')))
161
            ctx['table'] = chart.render_table(
162
                transpose=bool(chart.axis_count == 2),
163
            )
164
            ctx['table'] = ctx['table'].replace('<table>', '<table class="main">')
164
            try:
165
                chart = self.get_chart(raise_if_not_cached=not(context.get('synchronous')))
166
            except UnsupportedDataSet:
167
                ctx['table'] = '<p>%s</p>' % _('Unsupported dataset.')
168
            else:
169
                ctx['table'] = chart.render_table(
170
                    transpose=bool(chart.axis_count == 2),
171
                )
172
                ctx['table'] = ctx['table'].replace('<table>', '<table class="main">')
165 173
        return ctx
166 174

  
167 175
    def get_chart(self, width=None, height=None, raise_if_not_cached=False):
......
186 194

  
187 195
        # normalize axis to have a fake axis when there are no dimensions and
188 196
        # always a x axis when there is a single dimension.
197
        data = response['data']
198
        loop_labels = response['axis'].get('loop') or []
189 199
        x_labels = response['axis'].get('x_labels') or []
190 200
        y_labels = response['axis'].get('y_labels') or []
191
        data = response['data']
201
        if loop_labels:
202
            if x_labels and y_labels:
203
                # no support for three dimensions
204
                raise UnsupportedDataSet()
205
            if not y_labels:
206
                y_labels = loop_labels
207
            else:
208
                x_labels, y_labels = y_labels, loop_labels
192 209
        if not x_labels and not y_labels:  # unidata
193 210
            x_labels = ['']
194 211
            y_labels = ['']
combo/apps/dataviz/views.py
16 16

  
17 17
from django.core.exceptions import PermissionDenied
18 18
from django.http import HttpResponse
19
from django.utils.translation import ugettext_lazy as _
19 20

  
20 21
from combo.utils import get_templated_url, requests
21
from .models import Gauge, ChartNgCell
22
from .models import Gauge, ChartNgCell, UnsupportedDataSet
22 23

  
23 24

  
24 25
def ajax_gauge_count(request, *args, **kwargs):
......
33 34
        raise PermissionDenied()
34 35
    if not cell.is_visible(request.user):
35 36
        raise PermissionDenied()
36
    chart = cell.get_chart(
37
            width=int(request.GET.get('width', 0)) or None,
38
            height=int(request.GET.get('height', 0)) or int(cell.height)
39
    )
40
    return HttpResponse(chart.render(), content_type='image/svg+xml')
37
    try:
38
        chart = cell.get_chart(
39
                width=int(request.GET.get('width', 0)) or None,
40
                height=int(request.GET.get('height', 0)) or int(cell.height)
41
        )
42
    except UnsupportedDataSet:
43
        svg = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
44
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
45
  viewBox="0 0 %(width)s 30" width="%(width)s" height="30">
46
  <text
47
       y="20"
48
       x="10"
49
       style="font-family: sans-serif; font-size: 16px; fill:#000000;">%(text)s</text>
50
</svg>""" % {'width': request.GET.get('width', 200),
51
             'text': _('Unsupported dataset.')}
52
    else:
53
        svg = chart.render()
54
    return HttpResponse(svg, content_type='image/svg+xml')
tests/test_dataviz.py
8 8
from django.test import override_settings
9 9

  
10 10
from combo.data.models import Page
11
from combo.apps.dataviz.models import Gauge, ChartNgCell
11
from combo.apps.dataviz.models import Gauge, ChartNgCell, UnsupportedDataSet
12 12

  
13 13
from .test_public import login, normal_user
14 14

  
......
70 70
        'name': 'fourth visualization (no axis)',
71 71
        'slug': 'fourth',
72 72
    },
73
    {
74
        'data-url': 'https://bijoe.example.com/visualization/5/json/',
75
        'path': 'https://bijoe.example.com/visualization/5/iframe/?signature=123',
76
        'name': 'fifth visualization (loop/X)',
77
        'slug': 'fifth',
78
    },
79
    {
80
        'data-url': 'https://bijoe.example.com/visualization/6/json/',
81
        'path': 'https://bijoe.example.com/visualization/6/iframe/?signature=123',
82
        'name': 'sixth visualization (loop/Y)',
83
        'slug': 'sixth',
84
    },
85
    {
86
        'data-url': 'https://bijoe.example.com/visualization/7/json/',
87
        'path': 'https://bijoe.example.com/visualization/7/iframe/?signature=123',
88
        'name': 'seventh visualization (loop/X/Y)',
89
        'slug': 'seventh',
90
    },
91

  
73 92
]
74 93

  
75 94

  
......
114 133
            'axis': {}
115 134
        }
116 135
        return {'content': json.dumps(response), 'request': request, 'status_code': 200}
136
    if url.path == '/visualization/5/json/':
137
        response = {
138
            'format': '1',
139
            'data': [
140
                [222, 134, 53],
141
                [122, 114, 33],
142
            ],
143
            'axis': {
144
                'x_labels': ['web', 'mail', 'email'],
145
                'loop': ['foo', 'bar'],
146
            }
147
        }
148
        return {'content': json.dumps(response), 'request': request, 'status_code': 200}
149
    if url.path == '/visualization/6/json/':
150
        response = {
151
            'format': '1',
152
            'data': [
153
                [222, 134, 53],
154
                [122, 114, 33],
155
            ],
156
            'axis': {
157
                'y_labels': ['web', 'mail', 'email'],
158
                'loop': ['foo', 'bar'],
159
            }
160
        }
161
        return {'content': json.dumps(response), 'request': request, 'status_code': 200}
162
    if url.path == '/visualization/7/json/':
163
        response = {
164
            'format': '1',
165
            'data': [
166
                [[222, 134, 53], [122, 114, 33]],
167
                [[222, 134, 53], [122, 114, 33]],
168
                [[222, 134, 53], [122, 114, 33]],
169
                [[222, 134, 53], [122, 114, 33]],
170
            ],
171
            'axis': {
172
                'x_labels': ['foo', 'bar'],
173
                'y_labels': ['web', 'mail', 'email'],
174
                'loop': ['a', 'b', 'c', 'd'],
175
            }
176
        }
177
        return {'content': json.dumps(response), 'request': request, 'status_code': 200}
117 178

  
118 179

  
119 180
def test_chartng_cell(app):
......
186 247
            assert chart.x_labels == ['']
187 248
            assert chart.raw_series == [([222], {'title': ''})]
188 249

  
250
            # loop/X
251
            cell.data_reference = 'plop:fifth'
252
            cell.save()
253
            chart = cell.get_chart()
254
            assert chart.x_labels == ['web', 'mail', 'email']
255
            assert chart.raw_series == [
256
                ([222, 134, 53], {'title': u'foo'}),
257
                ([122, 114, 33], {'title': u'bar'}),
258
            ]
259

  
260
            # loop/Y
261
            cell.data_reference = 'plop:sixth'
262
            cell.save()
263
            chart = cell.get_chart()
264
            assert chart.x_labels == ['web', 'mail', 'email']
265
            assert chart.raw_series == [
266
                ([222, 134, 53], {'title': u'foo'}),
267
                ([122, 114, 33], {'title': u'bar'}),
268
            ]
269

  
270
            # loop/X/Y
271
            cell.data_reference = 'plop:seventh'
272
            cell.save()
273
            with pytest.raises(UnsupportedDataSet):
274
                chart = cell.get_chart()
275

  
276

  
189 277
def test_chartng_cell_view(app, normal_user):
190 278
    page = Page(title='One', slug='index')
191 279
    page.save()
......
230 318
            resp = app.get('/')
231 319
            assert '<td>222</td>' in resp.text
232 320

  
321
            # unsupported dataset
322
            cell.data_reference = 'plop:seventh'
323
            cell.save()
324
            resp = app.get('/')
325
            assert 'Unsupported dataset' in resp.text
326

  
327
            cell.chart_type = 'bar'
328
            cell.save()
329
            resp = app.get('/api/dataviz/graph/1/?width=400', status=200)
330
            assert 'Unsupported dataset' in resp.text
331

  
233 332

  
234 333
def test_chartng_cell_manager(app, admin_user):
235 334
    page = Page(title='One', slug='index')
......
247 346
            resp = app.get('/manage/pages/%s/' % page.id)
248 347
            assert resp.form['cdataviz_chartngcell-%s-data_reference' % cell.id].options == [
249 348
                (u'plop:example', True, u'example visualization (X)'),
349
                (u'plop:fifth', False, u'fifth visualization (loop/X)'),
250 350
                (u'plop:fourth', False, u'fourth visualization (no axis)'),
251 351
                (u'plop:second', False, u'second visualization (Y)'),
352
                (u'plop:seventh', False, u'seventh visualization (loop/X/Y)'),
353
                (u'plop:sixth', False, u'sixth visualization (loop/Y)'),
252 354
                (u'plop:third', False, u'third visualization (X/Y)'),
253 355
            ]
254
-