diff --git a/bijoe/visualization/urls.py b/bijoe/visualization/urls.py index 3bc5ee5..d55313b 100644 --- a/bijoe/visualization/urls.py +++ b/bijoe/visualization/urls.py @@ -30,6 +30,7 @@ urlpatterns = [ url(r'warehouse/(?P[^/]*)/(?P[^/]*)/save/$', views.create_visualization, name='create-visualization'), url(r'(?P\d+)/$', views.visualization, name='visualization'), + url(r'(?P\d+)/json/$', views.visualization_json, name='visualization-json'), url(r'(?P\d+)/geojson/$', views.visualization_geojson, name='visualization-geojson'), url(r'(?P\d+)/iframe/$', views.visualization_iframe, name='visualization-iframe'), url(r'(?P\d+)/ods/$', views.visualization_ods, name='visualization-ods'), diff --git a/bijoe/visualization/views.py b/bijoe/visualization/views.py index b96b3a5..1c67c1c 100644 --- a/bijoe/visualization/views.py +++ b/bijoe/visualization/views.py @@ -14,6 +14,7 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +from collections import OrderedDict import hashlib import json @@ -212,9 +213,11 @@ class VisualizationsJSONView(MultipleObjectMixin, View): path = reverse('visualization-iframe', kwargs={'pk': visualization.pk}) sig = hashlib.sha1(path + settings.SECRET_KEY).hexdigest() path += '?signature=' + sig + data_uri = reverse('visualization-json', kwargs={'pk': visualization.pk}) data.append({ 'name': visualization.name, 'path': request.build_absolute_uri(path), + 'data-url': request.build_absolute_uri(data_uri), }) response = HttpResponse(content_type='application/json') response.write(json.dumps(data)) @@ -263,6 +266,66 @@ class VisualizationGeoJSONView(generics.GenericAPIView): return Response(geojson) +class VisualizationJSONView(generics.GenericAPIView): + permission_classes = () + queryset = models.Visualization.objects.all() + + def get(self, request, pk, format=None): + instance = self.get_object() + loop = [] + all_visualizations = Visualization.from_json(instance.parameters, request=request) + for visualization in all_visualizations: + drilldowns = visualization.drilldown + if len(drilldowns) == 2: + x_labels = [x.label for x in visualization.drilldown_x.members] + y_labels = [y.label for y in visualization.drilldown_y.members] + used_x_labels = OrderedDict() + used_y_labels = OrderedDict() + default = 0 + grid = {(x, y): default for x in x_labels for y in y_labels} + + for row in visualization.data(): + x_label = unicode(row[0]['value']) + y_label = unicode(row[1]['value']) + used_x_labels[x_label] = True + used_y_labels[y_label] = True + grid[(x_label, y_label)] = row[2]['value'] + + data = [] + for y in used_y_labels.keys(): + data.append([grid[(x, y)] for x in used_x_labels.keys()]) + axis = { + 'x_labels': [x.strip() for x in used_x_labels.keys()], + 'y_labels': [x.strip() for x in used_y_labels.keys()] + } + elif len(drilldowns) == 1: + table = list(visualization.data()) + axis_data = [x[0]['value'].strip() for x in table] + data = [x[1]['value'] for x in table] + if visualization.drilldown_x: + axis = {'x_labels': axis_data} + else: + axis = {'y_labels': axis_data} + elif len(drilldowns) == 0: + data = list(list(visualization.data())[0])[0]['value'] + axis = {} + loop.append({'data': data, 'axis': axis}) + + if not all_visualizations.loop: + data = loop[0]['data'] + axis = loop[0]['axis'] + else: + axis = loop[0]['axis'] + axis['loop'] = [x.label for x in all_visualizations.loop.members] + data = [x['data'] for x in loop] + + return Response({ + 'data': data, + 'axis': axis, + 'format': '1', + }) + + warehouse = WarehouseView.as_view() cube = CubeView.as_view() cube_iframe = xframe_options_exempt(CubeIframeView.as_view()) @@ -275,6 +338,7 @@ visualization = VisualizationView.as_view() visualization_iframe = xframe_options_exempt(VisualizationIframeView.as_view()) visualization_geojson = VisualizationGeoJSONView.as_view() visualization_ods = VisualizationODSView.as_view() +visualization_json = VisualizationJSONView.as_view() cube_iframe.mellon_no_passive = True visualization_iframe.mellon_no_passive = True diff --git a/tests/test_views.py b/tests/test_views.py index 1275f44..054347e 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -14,6 +14,10 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +from django.core.urlresolvers import reverse + +from bijoe.visualization.models import Visualization + from utils import login @@ -29,3 +33,26 @@ def test_superuser(app, admin): assert len(resp.json) == 1 assert resp.json[0]['slug'] == 'statistics' app.get('/', status=200) + + +def test_visualization_json_api(schema1, app, admin): + visualization = Visualization( + name='test', + parameters={ + 'cube': 'facts1', + 'warehouse': 'schema1', + 'measure': 'simple_count', + 'representation': 'table', + 'loop': '', + 'filters': {}, + 'drilldown_x': 'date__yearmonth'}) + visualization.save() + + login(app, admin) + resp = app.get(reverse('visualization-json', kwargs={'pk': visualization.id})) + # values from test_schem1/test_yearmonth_drilldown + assert resp.json == { + 'axis': {'x_labels': ['01/2017', '02/2017', '03/2017', '04/2017', '05/2017', '06/2017', '07/2017', '08/2017']}, + 'data': [10, 1, 1, 1, 1, 1, 1, 1], + 'format': '1' + }