[PATCH 5 of 5 sherpa] Replace navigation box by top-level buttons

Sylvain Thenault sylvain.thenault at logilab.fr
Fri Feb 24 16:11:06 CET 2017


# HG changeset patch
# User Sylvain Thénault <sylvain.thenault at logilab.fr>
# Date 1487943409 -3600
#      Fri Feb 24 14:36:49 2017 +0100
# Node ID 6747b7ddc393e9f67421228b594690c110c509b9
# Parent  9403b62e12aee1cc104cf4cc05af2c0aa745377d
Replace navigation box by top-level buttons

with proper activation detection.

diff --git a/cubicweb_sherpa/views/management.py b/cubicweb_sherpa/views/management.py
--- a/cubicweb_sherpa/views/management.py
+++ b/cubicweb_sherpa/views/management.py
@@ -26,11 +26,11 @@ from cubes.relationwidget.views import R
 
 class SherpaSecurityManagementView(management.SecurityManagementView):
     """Security view overriden to hide permissions definitions and using a
     RelationFacetWidget to edit owner"""
     __select__ = (management.SecurityManagementView.__select__ &
-                  relation_possible('owned_by', action='add'))
+                  relation_possible('owned_by', action='add', strict=True))
 
     def entity_call(self, entity):
         w = self.w
         w(u'<h1><span class="etype">%s</span> <a href="%s">%s</a></h1>'
           % (entity.dc_type().capitalize(),
@@ -54,11 +54,11 @@ class SherpaSecurityManagementView(manag
         form.render(w=w, display_progress_div=False)
 
 
 actions.ManagePermissionsAction.__select__ = (
     action.Action.__select__ & one_line_rset() & non_final_entity()
-    & relation_possible('owned_by', action='add'))
+    & relation_possible('owned_by', action='add', strict=True))
 
 
 def registration_callback(vreg):
     vreg.register_all(globals().values(), __name__)
     vreg.unregister(management.SecurityManagementView)
diff --git a/cubicweb_sherpa/views/templates.py b/cubicweb_sherpa/views/templates.py
--- a/cubicweb_sherpa/views/templates.py
+++ b/cubicweb_sherpa/views/templates.py
@@ -16,10 +16,11 @@
 # along with this program. If not, see <http://www.gnu.org/licenses/>.
 """sherpa views/templates"""
 
 from logilab.common.decorators import monkeypatch
 
+from cubicweb import NotAnEntity
 from cubicweb.utils import HTMLHead, UStringIO
 from cubicweb.web.views import basetemplates
 
 from . import jinja_render
 
@@ -43,10 +44,35 @@ def render_component(comp):
     w = stream.write
     comp.render(w)
     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):
         self.set_request_content_type()
         self.write_doctype()
@@ -63,34 +89,35 @@ class SherpaMainTemplate(basetemplates.T
                              for comp in self.get_components(view, context='header-right')]
         # application message
         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)
 
         ctx = self.base_context()
         url = self._cw.build_url
         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'),
                      'label': u'Schéma du SEDA 2.0'},
                     {'url': url('dictionnaire'),
diff --git a/cubicweb_sherpa/views/templates/maintemplate.jinja2.html b/cubicweb_sherpa/views/templates/maintemplate.jinja2.html
--- a/cubicweb_sherpa/views/templates/maintemplate.jinja2.html
+++ b/cubicweb_sherpa/views/templates/maintemplate.jinja2.html
@@ -24,27 +24,28 @@
 
       </div>
       {% 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 }}
       {{ contextual_components|safe }}
       {{ page_content|safe }}
diff --git a/test/test_templates.py b/test/test_templates.py
new file mode 100644
--- /dev/null
+++ b/test/test_templates.py
@@ -0,0 +1,85 @@
+# copyright 2017 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
+# contact http://www.logilab.fr -- mailto:contact at 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()


More information about the saem-devel mailing list