Replace navigation box by top-level buttons
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Fri, 24 Feb 2017 14:36:49 +0100
changeset 181 12721d10d5bd
parent 180 0802510445f1
child 182 c2b5337dbc99
Replace navigation box by top-level buttons with proper activation detection.
cubicweb_sherpa/views/templates.py
cubicweb_sherpa/views/templates/maintemplate.jinja2.html
test/test_templates.py
--- a/cubicweb_sherpa/views/templates.py	Fri Feb 24 14:00:32 2017 +0100
+++ b/cubicweb_sherpa/views/templates.py	Fri Feb 24 14:36:49 2017 +0100
@@ -18,6 +18,7 @@
 
 from logilab.common.decorators import monkeypatch
 
+from cubicweb import NotAnEntity
 from cubicweb.utils import HTMLHead, UStringIO
 from cubicweb.web.views import basetemplates
 
@@ -45,6 +46,31 @@
     return stream.getvalue()
 
 
+def _compute_active_path(rset):
+    if not rset:
+        return None
+    try:
+        entity = rset.get_entity(0, 0)
+    except NotAnEntity:
+        return None
+    ibreadcrumbs = entity.cw_adapt_to('IBreadCrumbs')
+    # recurs = set([-1]) to avoid some view specific calculation
+    root = ibreadcrumbs.breadcrumbs(recurs=set([-1]))[0]
+    if isinstance(root, tuple):
+        if root[0].endswith('sedalib'):
+            return 'sedalib'
+    elif root.cw_etype in ('ConceptScheme', 'SEDAArchiveTransfer', 'AuthorityRecord'):
+        return root.cw_etype.lower()
+    return None
+
+
+class NavigationLink(object):
+    def __init__(self, url, label, active):
+        self.url = url
+        self.label = label
+        self.active = active
+
+
 class SherpaMainTemplate(basetemplates.TheMainTemplate):
 
     def call(self, view):
@@ -65,6 +91,18 @@
         msgcomp = self._cw.vreg['components'].select_or_none(
             'applmessages', self._cw, rset=self.cw_rset)
         application_message = msgcomp.render() if msgcomp else u''
+        # navigation links
+        navigation_links = []
+        active_path = _compute_active_path(self.cw_rset)
+        for path, label in [
+                ('sedaarchivetransfer', u'Profils SEDA'),
+                ('sedalib', u"Unités d'archive"),
+                ('authorityrecord', u"Notices d'autorité"),
+                ('conceptscheme', u'Vocabulaires'),
+        ]:
+            active = path == active_path
+            link = NavigationLink(self._cw.build_url(path), label, active=active)
+            navigation_links.append(link)
         # contextual components
         contextual_components = self._cw.view('contentheader', rset=self.cw_rset, view=view)
 
@@ -73,22 +111,11 @@
         ctx.update({
             'title': view.page_title(),
             'page_content': view.render(),
+            'navigation_links': navigation_links,
             'application_message': application_message,
             'contextual_components': contextual_components,
             'header_components': header_components,
             'boxes': boxes,
-            'side_box': {
-                'goTo_links': [
-                    {'url': url('SEDAArchiveTransfer'),
-                     'label': 'profils SEDA'},
-                    {'url': url('sedalib'),
-                     'label': u"unités d'archive"},
-                    {'url': url('AuthorityRecord'),
-                     'label': u"notices d'autorité"},
-                    {'url': url('ConceptScheme'),
-                     'label': u"vocabulaires"},
-                ],
-            },
             'footer': {
                 'resources': [
                     {'url': url('shema_seda'),
--- a/cubicweb_sherpa/views/templates/maintemplate.jinja2.html	Fri Feb 24 14:00:32 2017 +0100
+++ b/cubicweb_sherpa/views/templates/maintemplate.jinja2.html	Fri Feb 24 14:36:49 2017 +0100
@@ -26,23 +26,24 @@
       {% endif %}
     </div>
   </nav>
+  <nav role="navigation">
+    <div class="col-md-offset-2">
+      <ul class="nav nav-pills">
+        {% for link in navigation_links %}
+        {% if link.active %}
+        <li class="active"><a href="{{ link.url }}" class="navbar-btn">{{ link.label }}</a></li>
+        {% else %}
+        <li><a href="{{ link.url }}" class="navbar-btn">{{ link.label }}</a></li>
+        {% endif %}
+        {% endfor %}
+      </ul>
+    </div>
+  </nav>
   <div id="{{page_id}}" class="container-fluid" role="main">
     <aside id="aside-main-left" class="col-md-2 cwjs-aside">
       {% for box_html in boxes %}
       {{ box_html|safe}}
       {% endfor %}
-      <div class="panel panel-default contextFreeBox facet_filterbox" id="facet_filterbox">
-        <div class="panel-heading">
-          <div class="panel-title">navigation</div>
-        </div>
-        <div class="panel-body">
-          <ul class="list-unstyled">
-            {% for page in side_box.goTo_links %}
-            <li class="facetvalue"><a href='{{ page.url }}'> {{ page.label }}</a></li>
-            {% endfor %}
-          </ul>
-        </div>
-      </div>
     </aside>
     <div class="col-md-10 page-content" id="pageContent">
       {{ application_message|safe }}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/test_templates.py	Fri Feb 24 14:36:49 2017 +0100
@@ -0,0 +1,85 @@
+# copyright 2017 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr -- mailto:contact@logilab.fr
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the Free
+# Software Foundation, either version 2.1 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 Lesser General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+from cubicweb.devtools.testlib import CubicWebTC
+
+from cubicweb_sherpa.views.templates import _compute_active_path
+
+
+def create_archive_unit(parent, title=None, **kwargs):
+    """Create an archive unit and its mandatory children and return them.
+    """
+    cnx = kwargs.pop('cnx', getattr(parent, '_cw', None))
+    kwargs.setdefault('user_annotation', u'archive unit title')
+    au = cnx.create_entity('SEDAArchiveUnit', seda_archive_unit=parent, **kwargs)
+    alt = cnx.create_entity('SEDAAltArchiveUnitArchiveUnitRefId',
+                            reverse_seda_alt_archive_unit_archive_unit_ref_id=au)
+    last = cnx.create_entity(
+        'SEDASeqAltArchiveUnitArchiveUnitRefIdManagement',
+        reverse_seda_seq_alt_archive_unit_archive_unit_ref_id_management=alt)
+    cnx.create_entity('SEDATitle', seda_title=last, title=title)
+    return au, alt, last
+
+
+class ActivePathTC(CubicWebTC):
+
+    def test_archive_transfer(self):
+        with self.admin_access.cnx() as cnx:
+            at = cnx.create_entity('SEDAArchiveTransfer', title=u'hop')
+            au, alt, last = create_archive_unit(at)
+            cnx.commit()
+
+            for entity in (at, au, alt, last):
+                with self.subTest(entity=entity):
+                    self.assertEqual(_compute_active_path(entity.as_rset()),
+                                     'sedaarchivetransfer')
+
+    def test_archive_unit(self):
+        with self.admin_access.cnx() as cnx:
+            au, alt, last = create_archive_unit(None, cnx=cnx)
+            cnx.commit()
+
+            for entity in (au, alt, last):
+                with self.subTest(entity=entity):
+                    self.assertEqual(_compute_active_path(entity.as_rset()),
+                                     'sedalib')
+
+    def test_authority_record(self):
+        with self.admin_access.cnx() as cnx:
+            org_kind = cnx.find('AgentKind', name=u'authority').one()
+            record = cnx.create_entity('AuthorityRecord', agent_kind=org_kind)
+            cnx.create_entity('NameEntry', parts=u'record', form_variant=u'authorized',
+                              name_entry_for=record)
+            cnx.commit()
+
+            self.assertEqual(_compute_active_path(record.as_rset()),
+                             'authorityrecord')
+
+    def test_concept_scheme(self):
+        with self.admin_access.cnx() as cnx:
+            scheme = cnx.create_entity('ConceptScheme', title=u'vocabulary')
+            concept = scheme.add_concept(u'concept')
+            cnx.commit()
+
+            for entity in (scheme, concept):
+                with self.subTest(entity=entity):
+                    self.assertEqual(_compute_active_path(entity.as_rset()),
+                                     'conceptscheme')
+
+
+if __name__ == '__main__':
+    import unittest
+    unittest.main()