diff --git a/combo/apps/dataviz/__init__.py b/combo/apps/dataviz/__init__.py
index 0740f934..8fe74c4c 100644
--- a/combo/apps/dataviz/__init__.py
+++ b/combo/apps/dataviz/__init__.py
@@ -30,13 +30,4 @@ class AppConfig(django.apps.AppConfig):
from . import urls
return urls.urlpatterns
- def ready(self):
- @checks.register('settings')
- def check_settings(**kwargs):
- # Check if CUBES_URL is a proper URL string
- if (getattr(settings, 'CUBES_URL', None) is not None
- and (not isinstance(settings.CUBES_URL, str)
- or not re.match(r'https?://', settings.CUBES_URL))):
- yield checks.Error('settings.CUBES_URL must be an HTTP URL')
-
default_app_config = 'combo.apps.dataviz.AppConfig'
diff --git a/combo/apps/dataviz/forms.py b/combo/apps/dataviz/forms.py
index 0063afce..a137929f 100644
--- a/combo/apps/dataviz/forms.py
+++ b/combo/apps/dataviz/forms.py
@@ -14,17 +14,12 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-import json
-
-from django.utils.translation import ugettext_lazy as _
from django import forms
from django.conf import settings
-from django.core.exceptions import ValidationError
from combo.utils import requests
-from .models import BaseCubesChart, ChartCell
-from .utils import get_cubes, get_cube, get_drilldown
+from .models import ChartCell
class ChartForm(forms.ModelForm):
@@ -42,78 +37,3 @@ class ChartForm(forms.ModelForm):
available_charts.extend([(x['path'], x['name']) for x in result])
available_charts.sort(key=lambda x: x[1])
self.fields['url'].widget = forms.Select(choices=available_charts)
-
-
-class CubesBarChartForm(forms.ModelForm):
- EMPTY = [(u'', _('None'))]
-
- class Meta:
- model = BaseCubesChart
- fields = ('title', 'url', 'cube', 'aggregate1', 'drilldown1', 'drilldown2',
- 'other_parameters')
-
- def __init__(self, *args, **kwargs):
- super(CubesBarChartForm, self).__init__(*args, **kwargs)
- for field in ('cube', 'aggregate1', 'drilldown1', 'drilldown2'):
- self.fields[field] = forms.ChoiceField(
- label=self.fields[field].label,
- initial=self.fields[field].initial,
- required=False,
- choices=self.EMPTY)
- if getattr(settings, 'CUBES_URL', None):
- cube_choices = self.get_cubes_choices()
- if cube_choices:
- self.fields['cube'].choices = cube_choices
- aggregate1_choices = self.get_aggregate_choices()
- # If there is no choice, hide the selector
- if not aggregate1_choices or len(aggregate1_choices) < 3:
- self.fields['aggregate1'].widget = forms.HiddenInput()
- if aggregate1_choices:
- self.fields['aggregate1'].choices = aggregate1_choices
- drilldown_choices = self.get_drilldown_choices()
- if drilldown_choices:
- self.fields['drilldown1'].choices = drilldown_choices
- self.fields['drilldown2'].choices = drilldown_choices
-
- def clean(self):
- cleaned_data = self.cleaned_data
- if getattr(settings, 'CUBES_URL', None):
- aggregate1_choices = self.get_aggregate_choices()
- # If there is no choice, autoselect
- if aggregate1_choices and len(aggregate1_choices) == 2:
- cleaned_data['aggregate1'] = aggregate1_choices[1][0]
- return cleaned_data
-
- def clean_other_parameters(self):
- other_parameters = self.cleaned_data['other_parameters']
- if other_parameters:
- try:
- decoded = json.loads(other_parameters)
- assert isinstance(decoded, dict)
- for key, value in decoded.iteritems():
- assert isinstance(key, unicode)
- assert isinstance(value, unicode)
- except (ValueError, AssertionError):
- raise ValidationError(_('Other parameter must be a JSON object containing only '
- 'strings'))
- return other_parameters
-
- def get_cubes_choices(self):
- cubes = get_cubes()
- return self.EMPTY + [(cube['name'], cube.get('label')) for cube in cubes]
-
- def get_aggregate_choices(self):
- cube = self.data.get(self.add_prefix('cube')) if self.data else self.instance.cube
- if cube:
- cube = get_cube(cube)
- if cube:
- return self.EMPTY + [(ag['name'], ag['label']) for ag in cube.get('aggregates', [])]
- return []
-
- def get_drilldown_choices(self):
- cube = self.data.get(self.add_prefix('cube')) if self.data else self.instance.cube
- if cube:
- choices = get_drilldown(cube)
- if choices:
- return self.EMPTY + choices
- return []
diff --git a/combo/apps/dataviz/models.py b/combo/apps/dataviz/models.py
index 779fdcef..828708b0 100644
--- a/combo/apps/dataviz/models.py
+++ b/combo/apps/dataviz/models.py
@@ -14,9 +14,6 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-import json
-from collections import OrderedDict
-
from django.core.urlresolvers import reverse
from django.db import models
from django.utils.translation import ugettext_lazy as _
@@ -24,9 +21,8 @@ from django.conf import settings
from combo.data.models import CellBase
from combo.data.library import register_cell_class
-from combo.utils import NothingInCacheException, get_templated_url
+from combo.utils import get_templated_url
-from . import utils
@register_cell_class
class Gauge(CellBase):
@@ -92,159 +88,3 @@ class ChartCell(CellBase):
context['title'] = self.title
context['url'] = self.url
return context
-
-class BaseCubesChart(CellBase):
- title = models.CharField(_('Title'), max_length=150, blank=True, null=True)
- url = models.URLField(_('URL'), max_length=150, blank=True, null=True)
- cube = models.CharField(verbose_name=_('Form'), max_length=256, blank=True, null=True)
- aggregate1 = models.CharField(verbose_name=_('Aggregate'), max_length=64, blank=True, null=True)
- drilldown1 = models.CharField(verbose_name=_('Criterion 1'), max_length=64, blank=True,
- null=True)
- drilldown2 = models.CharField(verbose_name=_('Criterion 2'), max_length=64, blank=True,
- null=True)
- other_parameters = models.TextField(verbose_name=_('Other parameters'), blank=True, null=True)
-
- class Meta:
- abstract = True
-
- @classmethod
- def is_enabled(self):
- return bool(getattr(settings, 'CUBES_URL', None))
-
- def get_additional_label(self):
- return self.title
-
- def get_default_form_class(self):
- from .forms import CubesBarChartForm
- return CubesBarChartForm
-
- def get_cell_extra_context(self, context):
- ctx = {
- 'cell': self,
- 'title': self.title,
- 'url': self.url,
- 'aggregate': self.get_aggregate(context=context),
- }
- cube = utils.get_cube(self.cube)
- aggregates = dict((ag['name'], ag['label']) for ag in cube.get('aggregates', []))
- drilldowns = utils.get_drilldown(self.cube)
- if self.aggregate1 and aggregates:
- ctx['aggregate1_label'] = aggregates.get(self.aggregate1)
- if self.drilldown1 and drilldowns:
- ctx['drilldown1_label'] = dict(drilldowns).get(self.drilldown1)
- if self.drilldown2 and drilldowns:
- ctx['drilldown2_label'] = dict(drilldowns).get(self.drilldown2)
- return ctx
-
- def get_aggregate(self, context={}):
- '''Get aggregate defined by chosen cube and the two drildown paths, request ordering of the
- data by natural order of each axis.'''
- from .utils import get_aggregate, get_cube, compute_levels
- def simplify_integers(l):
- for x in l:
- if isinstance(x, float):
- if x - round(x) < 0.001:
- x = int(x)
- yield x
-
- other_parameters = json.loads(self.other_parameters) if self.other_parameters else {}
- if context and 'parameters' in context:
- parameters = context['parameters']
- for key in parameters:
- if not key.startswith('cubes-cut-'):
- continue
- name = key.split(u'cubes-cut-', 1)[1]
- value = parameters[key]
- new_cut = u'%s:%s' % (name, value)
- if other_parameters.get('cut'):
- other_parameters['cut'] = other_parameters['cut'] + u'|' + new_cut
- else:
- other_parameters['cut'] = new_cut
-
- aggregate = get_aggregate(name=self.cube,
- aggregate1=self.aggregate1,
- drilldown1=self.drilldown1,
- drilldown2=self.drilldown2,
- other_parameters=other_parameters)
-
- cube = get_cube(self.cube)
- if not aggregate or not cube:
- return
-
- label_refs1 = []
- key_refs1 = []
- if self.drilldown1:
- compute_levels(cube, self.drilldown1, label_refs=label_refs1, key_refs=key_refs1)
- key_refs2 = []
- label_refs2 = []
- if self.drilldown2:
- compute_levels(cube, self.drilldown2, label_refs=label_refs2, key_refs=key_refs2)
- for ag in cube['aggregates']:
- if ag['name'] != self.aggregate1:
- continue
- break
-
- def cell_ref(cell, refs):
- return tuple(cell[ref] for ref in refs)
-
- keys1 = OrderedDict()
- labels = OrderedDict()
- datasets = OrderedDict()
-
- for cell in aggregate['cells']:
- label1 = u' / '.join(map(unicode, simplify_integers(cell_ref(cell, label_refs1))))
- key1 = cell_ref(cell, key_refs1)
- labels[key1] = label1
- keys1[key1] = 1
- if key_refs2:
- label2 = u' / '.join(map(unicode, simplify_integers(cell_ref(cell, label_refs2))))
- key2 = cell_ref(cell, key_refs2)
- else:
- label2 = ''
- key2 = 1
- dataset = datasets.setdefault(key2, {'label': label2,
- 'data': OrderedDict()})
- value = cell[self.aggregate1]
- dataset['data'][key1] = value
- for dataset in datasets.itervalues():
- dataset['data'] = [dataset['data'].get(key, 0) for key in keys1]
-
- return {
- 'labels': labels.values(),
- 'datasets': [{
- 'label': dataset['label'],
- 'data': dataset['data'],
- } for dataset in datasets.itervalues()]
- }
-
- def render(self, context):
- if not context.get('synchronous'):
- raise NothingInCacheException()
- return super(BaseCubesChart, self).render(context)
-
- def render_for_search(self):
- return ''
-
-
-@register_cell_class
-class CubesBarChart(BaseCubesChart):
- template_name = 'combo/cubes-barchart.html'
-
- class Media:
- js = ('xstatic/ChartNew.js', 'js/combo.cubes-barchart.js')
-
- class Meta:
- verbose_name = _('Cubes Barchart')
-
- def get_cell_extra_context(self, context):
- ctx = super(CubesBarChart, self).get_cell_extra_context(context)
- # Need JSON serialization to pass data to Chart.js
- ctx['json_aggregate'] = json.dumps(ctx['aggregate'])
- return ctx
-
-@register_cell_class
-class CubesTable(BaseCubesChart):
- template_name = 'combo/cubes-table.html'
-
- class Meta:
- verbose_name = _('Cubes Table')
diff --git a/combo/apps/dataviz/templates/combo/cubes-barchart.html b/combo/apps/dataviz/templates/combo/cubes-barchart.html
deleted file mode 100644
index 1e20ef1e..00000000
--- a/combo/apps/dataviz/templates/combo/cubes-barchart.html
+++ /dev/null
@@ -1,15 +0,0 @@
-{% if title %}
-
-{% endif %}
-
-
-
-
diff --git a/combo/apps/dataviz/templates/combo/cubes-table.html b/combo/apps/dataviz/templates/combo/cubes-table.html
deleted file mode 100644
index 59784da7..00000000
--- a/combo/apps/dataviz/templates/combo/cubes-table.html
+++ /dev/null
@@ -1,23 +0,0 @@
-{% if title %}
-
-{% endif %}
-
-
- |
- {% for label in aggregate.labels %}
- {{ label }} |
- {% endfor %}
-
-
- {% for dataset in aggregate.datasets %}
-
- {{ dataset.label }} |
- {% for value in dataset.data %}
- {{ value }} |
- {% endfor %}
-
- {% endfor %}
-
-
diff --git a/combo/apps/dataviz/utils.py b/combo/apps/dataviz/utils.py
deleted file mode 100644
index cb4fd874..00000000
--- a/combo/apps/dataviz/utils.py
+++ /dev/null
@@ -1,152 +0,0 @@
-# combo - content management system
-# Copyright (C) 2015 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 .
-
-import requests
-from requests.exceptions import RequestException
-import urlparse
-
-from django.utils.translation import ugettext as _
-from django.conf import settings
-
-
-def get_requests_params():
- return getattr(settings, 'CUBES_REQUESTS_PARAMS', {})
-
-
-def get_cubes():
- try:
- r = requests.get(urlparse.urljoin(settings.CUBES_URL, 'cubes'), **get_requests_params())
- except RequestException:
- return []
- try:
- return r.json()
- except ValueError:
- return []
-
-
-def get_cube(name):
- model_url = urlparse.urljoin(settings.CUBES_URL, 'cube/%s/model' % name)
- try:
- r = requests.get(model_url, **get_requests_params())
- except RequestException:
- return None
- try:
- return r.json()
- except ValueError:
- return None
-
-
-def get_drilldown(name):
- cube = get_cube(name)
- if not cube:
- return []
- l = []
- seen = set()
- for dimension in cube.get('dimensions', []):
- dim_name = dimension['name']
- dim_label = dimension.get('label') or dim_name
- if dimension.get('levels'):
- levels = {}
- for level in dimension['levels']:
- levels[level['name']] = level.get('label') or level['name']
- if dimension.get('hierarchies'):
- for hierarchy in dimension['hierarchies']:
- h_name = hierarchy['name']
- h_label = hierarchy.get('label') or h_name
- if h_name == 'default':
- h_label = ''
- for i in range(1, len(hierarchy['levels'])+1):
- level = hierarchy['levels'][i-1]
- label = _(u'by ') + _(u' and ').join(
- levels[level] for level in hierarchy['levels'][:i]
- )
- name = '%s@%s:%s' % (dim_name, h_name, level)
- if label not in seen:
- l.append((name, label))
- seen.add(label)
- else:
- raise NotImplementedError
- else:
- l.append((dim_name, _(u'by %s') % dim_label))
- return l
-
-
-def compute_levels(cube, drilldown, key_refs=None, label_refs=None):
- from .utils import get_attribute_ref
- dim = drilldown.split('@')[0]
- hier = drilldown.split('@')[1].split(':')[0]
- lev = drilldown.split(':')[1]
-
- for dimension in cube['dimensions']:
- if dimension['name'] != dim:
- continue
- level_label_refs = {}
- level_key_refs = {}
- for level in dimension['levels']:
- level_key_refs[level['name']] = get_attribute_ref(level, level['key'])
- level_label_refs[level['name']] = get_attribute_ref(level, level['label_attribute'])
- for hierarchy in dimension['hierarchies']:
- if hierarchy['name'] != hier:
- continue
- for level in hierarchy['levels']:
- if key_refs is not None:
- key_refs.append(level_key_refs[level])
- if label_refs is not None:
- label_refs.append(level_label_refs[level])
- if level == lev:
- break
- break
- break
-
-
-def get_aggregate(name, aggregate1, drilldown1, drilldown2, other_parameters=None):
- if not name:
- return None
- cube = get_cube(name)
- aggregate_url = urlparse.urljoin(settings.CUBES_URL, 'cube/%s/aggregate' % name)
- if not aggregate1:
- return None
- try:
- params = {'aggregate': aggregate1}
- drilldowns = []
- key_refs = []
- if drilldown1:
- compute_levels(cube, drilldown1, key_refs=key_refs)
- drilldowns.append(drilldown1)
- if drilldown2:
- compute_levels(cube, drilldown2, key_refs=key_refs)
- drilldowns.append(drilldown2)
- if drilldowns:
- params['drilldown'] = drilldowns
-
- if key_refs:
- params['order'] = key_refs
- if other_parameters:
- params.update(other_parameters)
-
- r = requests.get(aggregate_url, params=params, **get_requests_params())
- except RequestException:
- return None
- try:
- return r.json()
- except ValueError:
- return None
-
-
-def get_attribute_ref(level, name):
- for attribute in level['attributes']:
- if attribute['name'] == name:
- return attribute['ref']
diff --git a/combo/settings.py b/combo/settings.py
index 22d064c4..e3a3bac6 100644
--- a/combo/settings.py
+++ b/combo/settings.py
@@ -77,7 +77,6 @@ INSTALLED_APPS = (
'combo.apps.maps',
'combo.apps.calendar',
'haystack',
- 'xstatic.pkg.chartnew_js',
'xstatic.pkg.josefinsans',
'xstatic.pkg.leaflet',
'xstatic.pkg.opensans',
diff --git a/debian/control b/debian/control
index 32bbc9f5..0f8e7aa9 100644
--- a/debian/control
+++ b/debian/control
@@ -14,7 +14,6 @@ Depends: ${misc:Depends}, ${python:Depends},
python-gadjo,
python-requests,
python-feedparser,
- python-xstatic-chartnew-js,
python-xstatic-josefinsans,
python-xstatic-leaflet,
python-xstatic-leaflet-markercluster,
diff --git a/debian/pydist-overrides b/debian/pydist-overrides
index 703e56fa..0c6fbc3e 100644
--- a/debian/pydist-overrides
+++ b/debian/pydist-overrides
@@ -1,2 +1 @@
django_ckeditor python-django-ckeditor
-XStatic-ChartNew.js python-xstatic-chartnew-js
diff --git a/requirements.txt b/requirements.txt
index ea18253e..e5c11803 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -4,7 +4,6 @@ gadjo
feedparser
django-jsonfield
requests
-XStatic-ChartNew.js
XStatic-Leaflet
XStatic_JosefinSans
XStatic_OpenSans
diff --git a/setup.py b/setup.py
index fede8d8c..20049306 100644
--- a/setup.py
+++ b/setup.py
@@ -140,7 +140,6 @@ setup(
'feedparser',
'django-jsonfield',
'requests',
- 'XStatic-ChartNew.js',
'XStatic-Leaflet',
'XStatic-Leaflet-MarkerCluster',
'XStatic_JosefinSans',