diff -r 000000000000 -r b97547f5f1fa web/views/basetemplates.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/views/basetemplates.py Wed Nov 05 15:52:50 2008 +0100 @@ -0,0 +1,516 @@ +# -*- coding: utf-8 -*- +"""default templates for CubicWeb web client + +:organization: Logilab +:copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved. +:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr +""" +__docformat__ = "restructuredtext en" + +from logilab.mtconverter import html_escape + +from cubicweb import NoSelectableObject, ObjectNotFound +from cubicweb.common.view import Template, MainTemplate, NOINDEX, NOFOLLOW +from cubicweb.common.selectors import nfentity_selector +from cubicweb.common.utils import make_uid + +from cubicweb.web.views.baseviews import vid_from_rset + +# main templates ############################################################## + + +class LogInOutTemplate(MainTemplate): + + def call(self): + self.set_request_content_type() + w = self.w + self.write_doctype() + lang = self.req.lang + self.template_header('text/html', self.req._('login_action')) + w(u'
\n') + self.content(w) + w(u'') + + def template_header(self, content_type, view=None, page_title='', additional_headers=()): + w = self.whead + # explictly close the' % ( + html_escape(indexurl), + self.req._('go back to the index page'))) + + +class TheMainTemplate(MainTemplate): + """default main template : + + - call header / footer templates + - build result set + - guess and call an appropriate view through the view manager + """ + id = 'main' + + def _select_view_and_rset(self): + req = self.req + if self.rset is None and not hasattr(req, '_rql_processed'): + req._rql_processed = True + rset = self.process_rql(req.form.get('rql')) + else: + rset = self.rset + # handle special "method" param when necessary + # XXX this should probably not be in the template (controller ?), however: + # * we need to have the displayed rset + # * we don't want to handle it in each view + if rset and rset.rowcount == 1 and '__method' in req.form: + entity = rset.get_entity(0, 0) + try: + method = getattr(entity, req.form.pop('__method')) + method() + except Exception, ex: + self.exception('while handling __method') + req.set_message(req._("error while handling __method: %s") % req._(ex)) + vid = req.form.get('vid') or vid_from_rset(req, rset, self.schema) + try: + view = self.vreg.select_view(vid, req, rset) + except ObjectNotFound: + self.warning("the view %s could not be found", vid) + req.set_message(req._("The view %s could not be found") % vid) + vid = vid_from_rset(req, rset, self.schema) + view = self.vreg.select_view(vid, req, rset) + except NoSelectableObject: + if rset: + req.set_message(req._("The view %s can not be applied to this query") % vid) + else: + req.set_message(req._("You have no access to this view or it's not applyable to current data")) + self.warning("the view %s can not be applied to this query", vid) + vid = vid_from_rset(req, rset, self.schema) + view = self.vreg.select_view(vid, req, rset) + return view, rset + + def call(self): + view, rset = self._select_view_and_rset() + req = self.req + # update breadcrumps **before** validating cache, unless the view + # specifies explicitly it should not be added to breadcrumb or the + # view is a binary view + if view.add_to_breadcrumbs and not view.binary: + req.update_breadcrumbs() + view.set_http_cache_headers() + req.validate_cache() + with_templates = not view.binary and view.templatable and \ + not req.form.has_key('__notemplate') + if not with_templates: + view.set_request_content_type() + self.set_stream(templatable=False) + else: + self.set_request_content_type() + content_type = self.content_type + self.template_header(content_type, view) + if view.binary: + # have to replace our unicode stream using view's binary stream + view.dispatch() + assert self._stream, 'duh, template used as a sub-view ?? (%s)' % self._stream + self._stream = view._stream + else: + view.dispatch(w=self.w) + if with_templates: + self.template_footer(view) + + + def process_rql(self, rql): + """execute rql if specified""" + if rql: + self.ensure_ro_rql(rql) + if not isinstance(rql, unicode): + rql = unicode(rql, self.req.encoding) + pp = self.vreg.select_component('magicsearch', self.req) + self.rset = pp.process_query(rql, self.req) + return self.rset + return None + + def template_header(self, content_type, view=None, page_title='', additional_headers=()): + page_title = page_title or view.page_title() + additional_headers = additional_headers or view.html_headers() + self.template_html_header(content_type, page_title, additional_headers) + self.template_body_header(view) + # display entity type restriction component + etypefilter = self.vreg.select_component('etypenavigation', + self.req, self.rset) + if etypefilter and etypefilter.propval('visible'): + etypefilter.dispatch(w=self.w) + self.pagination(self.req, self.rset, self.w, not view.need_navigation) + self.w(u'
\n')
+ rqlcomp = self.vreg.select_component('rqlinput', self.req, self.rset)
+ if rqlcomp:
+ rqlcomp.dispatch(w=self.w, view=view)
+ msgcomp = self.vreg.select_component('applmessages', self.req, self.rset)
+ if msgcomp:
+ msgcomp.dispatch(w=self.w)
+ self.content_header(view)
+ w(u' \n')
+ vtitle = self.req.form.get('vtitle')
+ if vtitle:
+ w(u' \n') # close id=contentmain
+ self.w(u'\n') # closes id=pageContent
+ self.content_footer(view)
+ self.w(u'%s\n' % vtitle) + + def template_footer(self, view=None): + self.w(u' | \n')
+ self.nav_column(view, 'right')
+ self.w(u'
\n') + self.topleft_header() + boxes = list(self.vreg.possible_vobjects('boxes', self.req, self.rset, + view=view, context='left')) + if boxes: + w(u' | ') + w(u' \n') + w(u'')
+ w(u' \n')
+ vtitle = self.req.form.get('vtitle')
+ if vtitle:
+ w(u' %s' % (vtitle)) + + def topleft_header(self): + self.w(u'
''')
+ self.state_header()
+ self.w(u'''
+
+ ''')
+
+ def main_header(self, view):
+ """build the top menu with authentification info and the rql box"""
+ self.w(u'
%s ' % msg)
+
+
+
+class HTMLPageFooter(Template):
+ """default html page footer: include logo if any, and close the HTML body
+ """
+ id = 'footer'
+
+ def call(self, **kwargs):
+ req = self.req
+ self.w(u' ')
+
+
+class HTMLContentHeader(Template):
+ """default html page content header:
+ * include message component if selectable for this request
+ * include selectable content navigation components
+ """
+ id = 'contentheader'
+
+ def call(self, view, **kwargs):
+ """by default, display informal messages in content header"""
+ components = self.vreg.possible_vobjects('contentnavigation',
+ self.req, self.rset,
+ view=view, context='navtop')
+ if components:
+ self.w(u'')
+ for comp in components:
+ comp.dispatch(w=self.w, view=view)
+ self.w(u' ')
+
+
+class HTMLContentFooter(Template):
+ """default html page content footer: include selectable content navigation
+ components
+ """
+ id = 'contentfooter'
+
+ def call(self, view, **kwargs):
+ components = self.vreg.possible_vobjects('contentnavigation',
+ self.req, self.rset,
+ view=view, context='navbottom')
+ if components:
+ self.w(u' ')
+
+
+class LogFormTemplate(Template):
+ id = 'logform'
+ title = 'log in'
+
+ def call(self, id, klass, title=True, message=True):
+ self.req.add_css('cubicweb.login.css')
+ self.w(u'' % (id, klass))
+ if title:
+ self.w(u' \n')
+
+ def display_message(self):
+ message = self.req.message
+ if message:
+ self.w(u'%s '
+ % self.req.property_value('ui.site-title'))
+ self.w(u'\n')
+
+ if message:
+ self.display_message()
+ if self.config['auth-mode'] == 'http':
+ # HTTP authentication
+ pass
+ else:
+ # Cookie authentication
+ self.login_form(id)
+ self.w(u' %s \n' % message)
+
+ def login_form(self, id):
+ _ = self.req._
+ self.w(u'\n')
+ # XXX doesn't seem to work, rewrite this
+ self.w(u'''''' % id)
+
+
+def login_form_url(config, req):
+ if req.https:
+ return req.url()
+ if config.get('https-url'):
+ return req.url().replace(req.base_url(), config['https-url'])
+ return req.url()
+
|