combo/combo/apps/dataviz/views.py

112 lines
4.4 KiB
Python

# combo - content management system
# Copyright (C) 2015-2019 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from django.core import signing
from django.core.exceptions import PermissionDenied
from django.http import Http404, HttpResponse, HttpResponseBadRequest
from django.shortcuts import render
from django.template import TemplateSyntaxError, VariableDoesNotExist
from django.utils.translation import ugettext_lazy as _
from django.views.decorators.clickjacking import xframe_options_sameorigin
from django.views.generic import DetailView
from requests.exceptions import HTTPError
from combo.utils import get_templated_url, requests
from .forms import ChartNgPartialForm
from .models import ChartNgCell, Gauge, MissingVariable, UnsupportedDataSet
def ajax_gauge_count(request, *args, **kwargs):
gauge = Gauge.objects.get(id=kwargs['cell'])
response = requests.get(get_templated_url(gauge.data_source))
return HttpResponse(response.content, content_type='text/json')
class DatavizGraphView(DetailView):
model = ChartNgCell
pk_url_kwarg = 'cell'
def dispatch(self, request, *args, **kwargs):
self.cell = self.get_object()
if not self.cell.page.is_visible(request.user):
raise PermissionDenied()
if not self.cell.is_visible(user=request.user):
raise PermissionDenied()
if not self.cell.statistic or not self.cell.statistic.url:
raise Http404('misconfigured cell')
return super().dispatch(request, *args, **kwargs)
def get(self, request, *args, **kwargs):
form = ChartNgPartialForm(request.GET, instance=self.cell)
if not form.is_valid():
return self.error(_('Wrong parameters.'))
request.extra_context = {}
if request.GET.get('ctx'):
try:
request.extra_context = signing.loads(request.GET['ctx'])
except signing.BadSignature:
return HttpResponseBadRequest('bad signature')
form.instance._request = request
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),
)
except UnsupportedDataSet:
return self.error(_('Unsupported dataset.'))
except MissingVariable:
return self.error(_('Page variable not found.'))
except TemplateSyntaxError:
return self.error(_('Syntax error in page variable.'))
except VariableDoesNotExist:
return self.error(_('Cannot evaluate page variable.'))
except HTTPError as e:
if e.response.status_code == 404:
return self.error(_('Visualization not found.'))
else:
return self.error(_('Unknown HTTP error: %s' % e))
if self.cell.chart_type == 'table':
if not chart.raw_series:
return self.error(_('No data'))
rendered = chart.render_table(
transpose=bool(chart.axis_count == 2),
total=getattr(chart, 'compute_sum', True),
)
rendered = rendered.replace('<table>', '<table class="main">')
return HttpResponse(rendered)
return HttpResponse(chart.render(), content_type='image/svg+xml')
def error(self, error_text):
if self.cell.chart_type == 'table':
return HttpResponse('<p>%s</p>' % error_text)
context = {
'width': self.request.GET.get('width', 200),
'text': error_text,
}
return render(self.request, 'combo/dataviz-error.svg', context=context, content_type='image/svg+xml')
dataviz_graph = xframe_options_sameorigin(DatavizGraphView.as_view())