[templates] Add a Brainomics UI base template
authorVincent Michel <vincent.michel@logilab.fr>
Wed, 17 Jul 2013 11:25:47 +0200
changeset 268 2e0c4fb017ba
parent 267 8cb3dc963355
child 269 3dfafb4debd5
[templates] Add a Brainomics UI base template
views/basetemplates.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/views/basetemplates.py	Wed Jul 17 11:25:47 2013 +0200
@@ -0,0 +1,164 @@
+"""bootstrap implementation of base templates
+
+:organization: Logilab
+:copyright: 2013 LOGILAB S.A. (Paris, FRANCE), license is LGPL.
+:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
+"""
+
+__docformat__ = "restructuredtext en"
+
+from logilab.common.decorators import monkeypatch
+
+from logilab.mtconverter import xml_escape
+
+from cubicweb.utils import UStringIO
+from cubicweb.web.views import basetemplates
+
+
+HTML5 = u'<!DOCTYPE html>'
+
+basetemplates.TheMainTemplate.doctype = HTML5
+
+
+### XXX / TODOs
+###
+### <footer> is set by ContentFooter class. In orbui, it's set by
+###          the main template
+
+@monkeypatch(basetemplates.TheMainTemplate)
+def call(self, view):
+    self.set_request_content_type()
+    self.template_header(self.content_type, view)
+    w = self.w
+    w(u'<div class="row-fluid">')
+    w(u'<div class="span12" id="pageContent">')
+    vtitle = self._cw.form.get('vtitle')
+    if vtitle:
+        w(u'<div class="vtitle">%s</div>\n' % xml_escape(vtitle))
+    # display entity type restriction component
+    etypefilter = self._cw.vreg['components'].select_or_none(
+        'etypenavigation', self._cw, rset=self.cw_rset)
+    if etypefilter and etypefilter.cw_propval('visible'):
+        etypefilter.render(w=w)
+    nav_html = UStringIO()
+    if view and not view.handle_pagination:
+        view.paginate(w=nav_html.write)
+    w(nav_html.getvalue())
+    w(u'<div id="contentmain">\n')
+    view.render(w=w)
+    w(u'</div>\n') # closes id=contentmain
+    w(nav_html.getvalue())
+    w(u'</div>\n' # closes id=pageContent
+      u'</div>\n') # closes row-fluid
+    self.template_footer(view)
+
+
+@monkeypatch(basetemplates.TheMainTemplate)
+def template_html_header(self, content_type, page_title,
+                         additional_headers=()):
+    w = self.whead
+    lang = self._cw.lang
+    self.write_doctype()
+    # explicitly close the <base> tag to avoid IE 6 bugs while browsing the DOM
+    self._cw.html_headers.define_var('BASE_URL', self._cw.base_url())
+    w(u'<meta http-equiv="content-type" content="%s; charset=%s"/>\n'
+      % (content_type, self._cw.encoding))
+    w(u'<meta name="viewport" content="initial-scale=1.0; '
+      u'maximum-scale=1.0; width=device-width; "/>')
+    w(u'\n'.join(additional_headers) + u'\n')
+    # FIXME this is a quick option to make cw work in IE9
+    # you'll lose all IE9 functionality, the browser will act as IE8.
+    w(u'<meta http-equiv="X-UA-Compatible" content="IE=8" />\n')
+    w(u'<!-- Le HTML5 shim, for IE6-8 support of HTML elements -->\n'
+      u'  <!--[if lt IE 9]>\n'
+      u'        <script src="%s"></script>\n'
+      u'  <![endif]-->\n' % self._cw.data_url('js/html5.js'))
+    self.wview('htmlheader', rset=self.cw_rset)
+    if page_title:
+        w(u'<title>%s</title>\n' % xml_escape(page_title))
+
+
+@monkeypatch(basetemplates.TheMainTemplate)
+def template_body_header(self, view):
+    w = self.w
+    w(u'<body>\n')
+    self.wview('header', rset=self.cw_rset, view=view)
+    w(u'<div id="page" class="container-fluid">\n'
+      u'<div class="row-fluid">\n')
+    #w(u'<div class="span3">')
+    nb_boxes = self.nav_column(view, 'left')
+    #w(u'</div>')
+    if nb_boxes is not None and nb_boxes:
+        content_span = 9
+    else:
+        content_span = 12
+    w(u'<div id="contentColumn" class="span%s">' % content_span)
+    components = self._cw.vreg['components']
+    rqlcomp = components.select_or_none('rqlinput', self._cw, rset=self.cw_rset)
+    if rqlcomp:
+        rqlcomp.render(w=self.w, view=view)
+    msgcomp = components.select_or_none('applmessages', self._cw, rset=self.cw_rset)
+    if msgcomp:
+        msgcomp.render(w=self.w)
+    self.content_header(view)
+
+@monkeypatch(basetemplates.TheMainTemplate)
+def template_footer(self, view=None):
+    self.w(u'<div class="row">')
+    self.content_footer(view)
+    self.w(u'</div>')
+    self.w(u'</div>\n') # XXX closes div#contentColumn span9 in template_body_header
+    self.nav_column(view, 'right')
+    self.w(u'</div>\n') # XXX closes div#page in template_body_header
+    self.wview('footer', rset=self.cw_rset)
+    self.w(u'</div>'    # closes class="row-fluid"
+           u'</div>')   # closes class="container-fluid"
+    self.w(u'</body>')
+
+@monkeypatch(basetemplates.TheMainTemplate)
+def nav_column(self, view, context):
+    boxes = list(self._cw.vreg['ctxcomponents'].poss_visible_objects(
+        self._cw, rset=self.cw_rset, view=view, context=context))
+    if boxes:
+        getlayout = self._cw.vreg['components'].select
+        self.w(u'<div id="aside-main-%s" class="span3">\n'
+               u'<div class="well">\n' %
+               context) # XXX Should arrange Facets soon
+        self.w(u'<div class="navboxes" id="navColumn%s">\n' % context.capitalize())
+        for box in boxes:
+            box.render(w=self.w, view=view)
+        self.w(u'</div>'
+               u'</div>'
+               u'</div>')
+    return len(boxes)
+
+
+@monkeypatch(basetemplates.HTMLPageHeader)
+def main_header(self, view):
+    """build the top menu with authentification info and the rql box"""
+    spans = {'headtext': 'span2',
+             'header-center': 'span9',
+             'header-right': 'span1',
+             }
+    w = self.w
+    w(u'<div id="header" class="navbar">'
+      u'<div class="navbar-inner">'
+      u'<div class="container">')
+    for colid, context in self.headers:
+        w(u'<div id="%s" class="%s">' % (colid, spans.get(colid, 'span2')))
+        components = self._cw.vreg['ctxcomponents'].poss_visible_objects(
+            self._cw, rset=self.cw_rset, view=view, context=context)
+        for comp in components:
+            comp.render(w=w)
+            w(u'&#160;')
+        w(u'</div>')
+    w(u'</div></div></div>\n')
+
+
+@monkeypatch(basetemplates.HTMLPageFooter)
+def call(self, **kwargs):
+    self.w(u'<footer id="pagefooter">')
+    self.w(u'<div id="footer" class"container">')
+    self.footer_content()
+    self.w(u'</div>')
+    self.w(u'</footer>')