From def8fef77d4a2d0b10ac250cb43f9d83c359ec5a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpeters@entrouvert.com>
Date: Wed, 31 Jul 2019 12:23:03 +0200
Subject: [PATCH 1/2] backoffice: use a django template to render data source
 view page (#33693)

---
 wcs/admin/data_sources.py                     | 105 ++++++------------
 wcs/data_sources.py                           |  13 +++
 .../wcs/backoffice/data-sources.html          |  34 ++++++
 3 files changed, 80 insertions(+), 72 deletions(-)
 create mode 100644 wcs/templates/wcs/backoffice/data-sources.html

diff --git a/wcs/admin/data_sources.py b/wcs/admin/data_sources.py
index 3fc476962..71f93fc00 100644
--- a/wcs/admin/data_sources.py
+++ b/wcs/admin/data_sources.py
@@ -19,8 +19,8 @@ from quixote.directory import Directory
 from quixote.html import TemplateIO, htmltext
 
 from qommon import _
+from qommon import template
 from qommon.form import *
-from qommon.humantime import seconds2humanduration
 from qommon.backoffice.menu import html_top
 from wcs.data_sources import (NamedDataSource, DataSourceSelectionWidget,
         get_structured_items)
@@ -117,6 +117,7 @@ class NamedDataSourceUI(object):
 
 class NamedDataSourcePage(Directory):
     _q_exports = ['', 'edit', 'delete']
+    do_not_call_in_templates = True
 
     def __init__(self, component):
         self.datasource = NamedDataSource.get(component)
@@ -125,79 +126,39 @@ class NamedDataSourcePage(Directory):
 
     def _q_index(self):
         html_top('datasources', title=self.datasource.name)
+        return template.QommonTemplateResponse(
+                templates=['wcs/backoffice/data-sources.html'],
+                context={'view': self, 'datasource': self.datasource})
+
+    def preview_block(self):
+        if self.datasource.data_source.get('type') not in ('json', 'formula'):
+            return ''
+        items = get_structured_items(self.datasource.data_source)
+        if not items:
+            return ''
         r = TemplateIO(html=True)
-
-        r += htmltext('<div id="appbar">')
-        r += htmltext('<h2>%s - ') % _('Data Source')
-        r += self.datasource.name
-        r += htmltext('</h2>')
-        r += htmltext('<span class="actions">')
-        r += htmltext('<a href="delete" rel="popup">%s</a>') % _('Delete')
-        r += htmltext('<a href="edit">%s</a>') % _('Edit')
-        r += htmltext('</span>')
+        r += htmltext('<h3>%s</h3>') % _('Preview (first items only)')
+        r += htmltext('<div class="bo-block data-source-preview">')
+        r += htmltext('<ul>')
+        additional_keys = set()
+        for item in items[:10]:
+            if not isinstance(item.get('text'), str):
+                r += htmltext('<li><tt>%s</tt>: <i>%s (%r)</i></li>') % (
+                        item.get('id'),
+                        _('error: not a string'),
+                        item.get('text'))
+            else:
+                r += htmltext('<li><tt>%s</tt>: %s</li>') % (
+                        item.get('id'), item.get('text'))
+                additional_keys |= set(item.keys())
+        if len(items) > 10:
+            r += htmltext('<li>...</li>')
+        r += htmltext('</ul>')
+        additional_keys -= set(['id', 'text'])
+        if additional_keys:
+            r += htmltext('<p>%s %s</p>') % (_('Additional keys are available:'),
+                    ', '.join(sorted(additional_keys)))
         r += htmltext('</div>')
-
-        if self.datasource.description:
-            r += htmltext('<div class="bo-block">')
-            r += self.datasource.description
-            r += htmltext('</div>')
-
-        data_source_labels = {
-            'json': _('JSON'),
-            'jsonp': _('JSONP'),
-            'formula': _('Python Expression'),
-        }
-
-        if self.datasource.data_source and self.datasource.data_source.get('type') in data_source_labels:
-            data_source_type = self.datasource.data_source.get('type')
-            r += htmltext('<h3>%s</h3>') % _('Configuration')
-            r += htmltext('<ul>')
-            r += htmltext('<li>%s</li>') % _(
-                    'Type of source: %s') % data_source_labels.get(data_source_type)
-            if data_source_type in ('json', 'jsonp'):
-                r += htmltext('<li>%s<a href="%s">%s</a></li>') % (
-                        _('URL: '),
-                        self.datasource.data_source.get('value'),
-                        self.datasource.data_source.get('value'))
-            elif data_source_type == 'formula':
-                r += htmltext('<li>%s<tt>%s</tt></li>') % (
-                        _('Python Expression: '),
-                    self.datasource.data_source.get('value'))
-            if self.datasource.cache_duration:
-                r += htmltext('<li>%s %s</li>') % (
-                        _('Cache Duration:'),
-                        seconds2humanduration(int(self.datasource.cache_duration)))
-            r += htmltext('</ul>')
-
-            if data_source_type in ('json', 'formula'):
-                items = get_structured_items(self.datasource.data_source)
-                if items:
-                    r += htmltext('<h3>%s</h3>') % _('Preview (first items only)')
-                    r += htmltext('<div class="bo-block data-source-preview"><ul>')
-                    r += htmltext('<ul>')
-                    additional_keys = set()
-                    for item in items[:10]:
-                        if not isinstance(item.get('text'), str):
-                            r += htmltext('<li><tt>%s</tt>: <i>%s (%r)</i></li>') % (
-                                    item.get('id'),
-                                    _('error: not a string'),
-                                    item.get('text'))
-                        else:
-                            r += htmltext('<li><tt>%s</tt>: %s</li>') % (
-                                    item.get('id'), item.get('text'))
-                            additional_keys |= set(item.keys())
-                    if len(items) > 10:
-                        r += htmltext('<li>...</li>')
-                    r += htmltext('</ul>')
-                    additional_keys -= set(['id', 'text'])
-                    if additional_keys:
-                        r += htmltext('<p>%s %s</p>') % (_('Additional keys are available:'),
-                                ', '.join(sorted(additional_keys)))
-                    r += htmltext('</div>')
-        else:
-            # the data source field is required so this should never happen
-            r += htmltext('<p class="infonotice">%s</p>') % _('Not configured')
-
         return r.getvalue()
 
     def edit(self):
diff --git a/wcs/data_sources.py b/wcs/data_sources.py
index 5c318ee05..56432d46e 100644
--- a/wcs/data_sources.py
+++ b/wcs/data_sources.py
@@ -26,6 +26,7 @@ from quixote.html import TemplateIO
 
 from qommon import _
 from qommon.form import *
+from qommon.humantime import seconds2humanduration
 from qommon.misc import get_variadic_url
 import qommon.misc
 from qommon import get_logger
@@ -385,6 +386,18 @@ class NamedDataSource(XmlStorableObject):
     def get_substitution_variables(cls):
         return {'data_source': DataSourcesSubstitutionProxy()}
 
+    def type_label(self):
+        data_source_labels = {
+            'json': _('JSON'),
+            'jsonp': _('JSONP'),
+            'formula': _('Python Expression'),
+        }
+        data_source_type = self.data_source.get('type')
+        return data_source_labels.get(data_source_type)
+
+    def humanized_cache_duration(self):
+        return seconds2humanduration(int(self.cache_duration))
+
 
 class DataSourcesSubstitutionProxy(object):
     def __getattr__(self, attr):
diff --git a/wcs/templates/wcs/backoffice/data-sources.html b/wcs/templates/wcs/backoffice/data-sources.html
new file mode 100644
index 000000000..d6376a54d
--- /dev/null
+++ b/wcs/templates/wcs/backoffice/data-sources.html
@@ -0,0 +1,34 @@
+{% load i18n %}
+
+{% block body %}
+<div id="appbar">
+<h2>{% trans "Data Source" %} - {{ datasource.name }}</h2>
+<span class="actions">
+  <a href="delete" rel="popup">{% trans "Delete" %}</a>
+  <a href="edit">{% trans "Edit" %}</a>
+</span>
+</div>
+
+{% if datasource.description %}
+<div class="bo-block">{{ datasource.description }}</div>
+{% endif %}
+
+{% if datasource.data_source %}
+<h3>{% trans "Configuration" %}</h3>
+<ul>
+  <li>{% trans "Type of source:" %} {{ datasource.type_label }}</li>
+  {% if datasource.data_source.type == 'json' or datasource.data_source.type == 'jsonp' %}
+  <li>{% trans "URL:" %} <a href="{{ datasource.data_source.value }}">{{ datasource.data_source.value }}</a></li>
+  {% elif datasource.data_source.type == 'formula' %}
+  <li>{% trans "Python Expression:" %} {{ datasource.data_source.value }}</li>
+  {% endif %}
+  {% if datasource.cache_duration %}
+  <li>{% trans "Cache Duration:" %} {{ datasource.humanized_cache_duration }}
+  {% endif %}
+</ul>
+{{ view.preview_block|safe }}
+{% else %}
+<p class="infonotice">{% trans "Not configured" %}</p>
+{% endif %}
+
+{% endblock %}
-- 
2.23.0.rc0

