From a0caedde62d10d6880ca7ed9e4bc057af880eee6 Mon Sep 17 00:00:00 2001
From: Valentin Deniaud <vdeniaud@entrouvert.com>
Date: Tue, 29 Oct 2019 17:46:21 +0100
Subject: [PATCH 3/4] views: grey out unavailable visualizations (#27412)

---
 bijoe/templates/bijoe/homepage.html           |  7 +-----
 bijoe/templates/bijoe/visualizations.html     |  6 +----
 .../templates/bijoe/visualizations_list.html  | 10 ++++++++
 bijoe/views.py                                |  1 +
 bijoe/visualization/models.py                 | 11 +++++++++
 bijoe/visualization/utils.py                  | 10 +++++---
 bijoe/visualization/views.py                  |  1 +
 tests/test_views.py                           | 23 ++++++++++++++++---
 8 files changed, 52 insertions(+), 17 deletions(-)
 create mode 100644 bijoe/templates/bijoe/visualizations_list.html

diff --git a/bijoe/templates/bijoe/homepage.html b/bijoe/templates/bijoe/homepage.html
index 22c850b..0eecec2 100644
--- a/bijoe/templates/bijoe/homepage.html
+++ b/bijoe/templates/bijoe/homepage.html
@@ -9,12 +9,7 @@
 {% block content %}
   {% if visualizations %}
     <h2>{% trans "Visualizations" %}</h2>
-    <ul class="objects-list single-links bijoe-visualizations">
-    {% for visualization in visualizations %}
-         {% url 'visualization' pk=visualization.pk as visualization_url %}
-         <li><a href="{{ visualization_url }}">{{ visualization.name }}</a></li>
-    {% endfor %}
-    </ul>
+    {% include "bijoe/visualizations_list.html" %}
   {% endif %}
   {% if warehouses %}
     <h2>{% trans "Data sources" %}</h2>
diff --git a/bijoe/templates/bijoe/visualizations.html b/bijoe/templates/bijoe/visualizations.html
index eecacaf..bd3f1c4 100644
--- a/bijoe/templates/bijoe/visualizations.html
+++ b/bijoe/templates/bijoe/visualizations.html
@@ -11,9 +11,5 @@
 {% endblock %}
 
 {% block content %}
-  <ul class="objects-list single-links bijoe-visualizations">
-  {% for visualization in object_list %}
-    <li><a href="{% url "visualization" pk=visualization.pk %}">{{ visualization.name }}</a></li>
-  {% endfor %}
-  </ul>
+{% include "bijoe/visualizations_list.html" %}
 {% endblock %}
diff --git a/bijoe/templates/bijoe/visualizations_list.html b/bijoe/templates/bijoe/visualizations_list.html
new file mode 100644
index 0000000..28983c0
--- /dev/null
+++ b/bijoe/templates/bijoe/visualizations_list.html
@@ -0,0 +1,10 @@
+{% load i18n %}
+
+<ul class="objects-list single-links bijoe-visualizations">
+  {% for visualization in visualizations %}
+    {% url 'visualization' pk=visualization.pk as visualization_url %}
+    <li>
+      <a {% if visualization.exists %}href="{{ visualization_url }}"{% else %}class="disabled" title="{% trans "Form data not found" %}"{% endif %}>{{ visualization.name }}</a>
+    </li>
+  {% endfor %}
+</ul>
diff --git a/bijoe/views.py b/bijoe/views.py
index 548af1e..d78e21c 100644
--- a/bijoe/views.py
+++ b/bijoe/views.py
@@ -35,6 +35,7 @@ except ImportError:
 from .utils import get_warehouses
 from .engine import Engine
 from .visualization.models import Visualization
+from .visualization.utils import Visualization as VisuUtil
 
 
 class AuthorizationMixin(object):
diff --git a/bijoe/visualization/models.py b/bijoe/visualization/models.py
index e6f4e43..33ed13e 100644
--- a/bijoe/visualization/models.py
+++ b/bijoe/visualization/models.py
@@ -18,10 +18,13 @@ import json
 import datetime
 
 from django.db import models
+from django.http import Http404
 from django.utils.text import slugify
 from django.utils.translation import ugettext_lazy as _
 from jsonfield import JSONField
 
+from .utils import Visualization as VisuUtils
+
 
 class JSONEncoder(json.JSONEncoder):
     def default(self, obj):
@@ -62,3 +65,11 @@ class Visualization(models.Model):
                 slug = '%s-%s' % (base_slug, i)
             self.slug = slug
         return super(Visualization, self).save(*args, **kwargs)
+
+    @property
+    def exists(self):
+        try:
+            VisuUtils.get_cube(self.parameters)
+            return True
+        except Http404:
+            return False
diff --git a/bijoe/visualization/utils.py b/bijoe/visualization/utils.py
index 89b8418..26b0204 100644
--- a/bijoe/visualization/utils.py
+++ b/bijoe/visualization/utils.py
@@ -74,8 +74,8 @@ class Visualization(object):
                              drilldown_x=self.drilldown_x, drilldown_y=self.drilldown_y,
                              filters=copy.deepcopy(self.filters), loop=self.loop)
 
-    @classmethod
-    def from_json(cls, d):
+    @staticmethod
+    def get_cube(d):
         for warehouse in get_warehouses():
             if d['warehouse'] == warehouse.name:
                 break
@@ -83,9 +83,13 @@ class Visualization(object):
             raise Http404('warehouse %s not found' % d['warehouse'])
         engine = Engine(warehouse)
         try:
-            cube = engine[d['cube']]
+            return engine[d['cube']]
         except KeyError:
             raise Http404('cube %s not found' % d['cube'])
+
+    @classmethod
+    def from_json(cls, d):
+        cube = cls.get_cube(d)
         representation = d['representation']
         measure = cube.measures[d['measure']]
         drilldown_x = cube.dimensions[d['drilldown_x']] if 'drilldown_x' in d else None
diff --git a/bijoe/visualization/views.py b/bijoe/visualization/views.py
index 8d5f91f..5a655e0 100644
--- a/bijoe/visualization/views.py
+++ b/bijoe/visualization/views.py
@@ -185,6 +185,7 @@ class DeleteVisualizationView(views.AuthorizationMixin, DeleteView):
 class VisualizationsView(views.AuthorizationMixin, ListView):
     template_name = 'bijoe/visualizations.html'
     model = models.Visualization
+    context_object_name = 'visualizations'
 
 
 class RenameVisualization(views.AuthorizationMixin, UpdateView):
diff --git a/tests/test_views.py b/tests/test_views.py
index 89ee37f..0d88fcd 100644
--- a/tests/test_views.py
+++ b/tests/test_views.py
@@ -36,9 +36,9 @@ def test_superuser(app, admin):
 
 
 def test_visualizations_json_api(schema1, app, admin):
-    Visualization(name='test', parameters={}).save()
-    Visualization(name='test', parameters={}).save()
-    Visualization(name='test', parameters={}).save()
+    Visualization(name='test', parameters={'warehouse': 'schema1', 'cube': 'test'}).save()
+    Visualization(name='test', parameters={'warehouse': 'schema1', 'cube': 'test'}).save()
+    Visualization(name='test', parameters={'warehouse': 'schema1', 'cube': 'test'}).save()
     login(app, admin)
     resp = app.get(reverse('visualizations-json'))
     assert set([x['slug'] for x in resp.json]) == set(['test', 'test-2', 'test-3'])
@@ -90,3 +90,20 @@ def test_visualization_json_api_duration(schema1, app, admin):
         'format': '1',
         'unit': 'seconds',
     }
+
+
+def test_missing_data(schema1, app, admin):
+    visualization = Visualization(
+        name='test',
+        parameters={
+            'cube': 'missing_cube',
+            'warehouse': 'schema1',
+            'measure': 'duration',
+            'representation': 'table',
+            'loop': '',
+            'filters': {}})
+    visualization.save()
+    login(app, admin)
+
+    response = app.get('/')
+    assert response.pyquery('ul li a.disabled').text() == visualization.name
-- 
2.20.1

