cubicweb/web/views/basetemplates.py
changeset 11870 3a84a79c4ed5
parent 11767 432f87a63057
child 11874 ea1d92b677b5
equal deleted inserted replaced
11869:d8b66e3fd335 11870:3a84a79c4ed5
    16 # You should have received a copy of the GNU Lesser General Public License along
    16 # You should have received a copy of the GNU Lesser General Public License along
    17 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
    17 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
    18 """default templates for CubicWeb web client"""
    18 """default templates for CubicWeb web client"""
    19 
    19 
    20 
    20 
    21 from cubicweb import _
       
    22 
       
    23 from logilab.mtconverter import xml_escape
    21 from logilab.mtconverter import xml_escape
    24 from logilab.common.deprecation import class_renamed
    22 from logilab.common.deprecation import class_renamed
    25 from logilab.common.registry import objectify_predicate
    23 from logilab.common.registry import objectify_predicate
    26 from logilab.common.decorators import classproperty
    24 from logilab.common.decorators import classproperty
    27 
    25 
    28 from cubicweb.predicates import match_kwargs, no_cnx, anonymous_user
    26 from cubicweb import _
       
    27 from cubicweb.predicates import match_kwargs, anonymous_user
    29 from cubicweb.view import View, MainTemplate, NOINDEX, NOFOLLOW, StartupView
    28 from cubicweb.view import View, MainTemplate, NOINDEX, NOFOLLOW, StartupView
    30 from cubicweb.utils import UStringIO
    29 from cubicweb.utils import UStringIO
    31 from cubicweb.schema import display_name
    30 from cubicweb.schema import display_name
    32 from cubicweb.web import component, formfields as ff, formwidgets as fw
    31 from cubicweb.web import formfields as ff, formwidgets as fw
    33 from cubicweb.web.views import forms
    32 from cubicweb.web.views import forms
       
    33 
    34 
    34 
    35 # main templates ##############################################################
    35 # main templates ##############################################################
    36 
    36 
    37 class LogInOutTemplate(MainTemplate):
    37 class LogInOutTemplate(MainTemplate):
    38 
    38 
    89 
    89 
    90 @objectify_predicate
    90 @objectify_predicate
    91 def modal_view(cls, req, rset, *args, **kwargs):
    91 def modal_view(cls, req, rset, *args, **kwargs):
    92     if req.form.get('__modal', None):
    92     if req.form.get('__modal', None):
    93         return 1
    93         return 1
       
    94 
    94 
    95 
    95 @objectify_predicate
    96 @objectify_predicate
    96 def templatable_view(cls, req, rset, *args, **kwargs):
    97 def templatable_view(cls, req, rset, *args, **kwargs):
    97     view = kwargs.pop('view', None)
    98     view = kwargs.pop('view', None)
    98     if view is None:
    99     if view is None:
   174         self.template_html_header(content_type, page_title, additional_headers)
   175         self.template_html_header(content_type, page_title, additional_headers)
   175         self.template_body_header(view)
   176         self.template_body_header(view)
   176 
   177 
   177     def template_html_header(self, content_type, page_title, additional_headers=()):
   178     def template_html_header(self, content_type, page_title, additional_headers=()):
   178         w = self.whead
   179         w = self.whead
   179         lang = self._cw.lang
       
   180         self.write_doctype()
   180         self.write_doctype()
   181         self._cw.html_headers.define_var('BASE_URL', self._cw.base_url())
   181         self._cw.html_headers.define_var('BASE_URL', self._cw.base_url())
   182         self._cw.html_headers.define_var('DATA_URL', self._cw.datadir_url)
   182         self._cw.html_headers.define_var('DATA_URL', self._cw.datadir_url)
   183         w(u'<meta http-equiv="content-type" content="%s; charset=%s"/>\n'
   183         w(u'<meta http-equiv="content-type" content="%s; charset=%s"/>\n'
   184           % (content_type, self._cw.encoding))
   184           % (content_type, self._cw.encoding))
   213 
   213 
   214     def nav_column(self, view, context):
   214     def nav_column(self, view, context):
   215         boxes = list(self._cw.vreg['ctxcomponents'].poss_visible_objects(
   215         boxes = list(self._cw.vreg['ctxcomponents'].poss_visible_objects(
   216             self._cw, rset=self.cw_rset, view=view, context=context))
   216             self._cw, rset=self.cw_rset, view=view, context=context))
   217         if boxes:
   217         if boxes:
   218             getlayout = self._cw.vreg['components'].select
       
   219             self.w(u'<td id="navColumn%s"><div class="navboxes">\n' % context.capitalize())
   218             self.w(u'<td id="navColumn%s"><div class="navboxes">\n' % context.capitalize())
   220             for box in boxes:
   219             for box in boxes:
   221                 box.render(w=self.w, view=view)
   220                 box.render(w=self.w, view=view)
   222             self.w(u'</div></td>\n')
   221             self.w(u'</div></td>\n')
   223 
   222 
   246         view.render(w=self.w)
   245         view.render(w=self.w)
   247         self.template_footer(view)
   246         self.template_footer(view)
   248 
   247 
   249     def template_header(self, content_type, view=None, page_title='', additional_headers=()):
   248     def template_header(self, content_type, view=None, page_title='', additional_headers=()):
   250         w = self.whead
   249         w = self.whead
   251         lang = self._cw.lang
       
   252         self.write_doctype()
   250         self.write_doctype()
   253         w(u'<meta http-equiv="content-type" content="%s; charset=%s"/>\n'
   251         w(u'<meta http-equiv="content-type" content="%s; charset=%s"/>\n'
   254           % (content_type, self._cw.encoding))
   252           % (content_type, self._cw.encoding))
   255         w(u'\n'.join(additional_headers))
   253         w(u'\n'.join(additional_headers))
   256         self.wview('htmlheader', rset=self.cw_rset)
   254         self.wview('htmlheader', rset=self.cw_rset)
   267 
   265 
   268     def template_header(self, content_type, view=None, page_title='', additional_headers=()):
   266     def template_header(self, content_type, view=None, page_title='', additional_headers=()):
   269         page_title = page_title or view.page_title()
   267         page_title = page_title or view.page_title()
   270         additional_headers = additional_headers or view.html_headers()
   268         additional_headers = additional_headers or view.html_headers()
   271         whead = self.whead
   269         whead = self.whead
   272         lang = self._cw.lang
       
   273         self.write_doctype()
   270         self.write_doctype()
   274         whead(u'<meta http-equiv="content-type" content="%s; charset=%s"/>\n'
   271         whead(u'<meta http-equiv="content-type" content="%s; charset=%s"/>\n'
   275               % (content_type, self._cw.encoding))
   272               % (content_type, self._cw.encoding))
   276         whead(u'\n'.join(additional_headers) + u'\n')
   273         whead(u'\n'.join(additional_headers) + u'\n')
   277         self.wview('htmlheader', rset=self.cw_rset)
   274         self.wview('htmlheader', rset=self.cw_rset)
   335         for jscript in self._cw.uiprops['JAVASCRIPTS']:
   332         for jscript in self._cw.uiprops['JAVASCRIPTS']:
   336             self._cw.add_js(jscript, localfile=False)
   333             self._cw.add_js(jscript, localfile=False)
   337 
   334 
   338     def alternates(self):
   335     def alternates(self):
   339         urlgetter = self._cw.vreg['components'].select_or_none('rss_feed_url',
   336         urlgetter = self._cw.vreg['components'].select_or_none('rss_feed_url',
   340                                                            self._cw, rset=self.cw_rset)
   337                                                                self._cw, rset=self.cw_rset)
   341         if urlgetter is not None:
   338         if urlgetter is not None:
   342             self.whead(u'<link rel="alternate" type="application/rss+xml" title="RSS feed" href="%s"/>\n'
   339             self.whead(u'<link rel="alternate" type="application/rss+xml" title="RSS feed" href="%s"/>\n'
   343                        %  xml_escape(urlgetter.feed_url()))
   340                        % xml_escape(urlgetter.feed_url()))
   344 
   341 
   345 
   342 
   346 class HTMLPageHeader(View):
   343 class HTMLPageHeader(View):
   347     """default html page header"""
   344     """default html page header"""
   348     __regid__ = 'header'
   345     __regid__ = 'header'
   404             self.w(u'<a href="%s">%s</a>' % (action.url(),
   401             self.w(u'<a href="%s">%s</a>' % (action.url(),
   405                                              self._cw._(action.title)))
   402                                              self._cw._(action.title)))
   406             if i < (len(footeractions) - 1):
   403             if i < (len(footeractions) - 1):
   407                 self.w(u' | ')
   404                 self.w(u' | ')
   408 
   405 
       
   406 
   409 class HTMLContentHeader(View):
   407 class HTMLContentHeader(View):
   410     """default html page content header:
   408     """default html page content header:
   411     * include message component if selectable for this request
   409     * include message component if selectable for this request
   412     * include selectable content navigation components
   410     * include selectable content navigation components
   413     """
   411     """
   436         if components:
   434         if components:
   437             self.w(u'<div id="contentfooter">')
   435             self.w(u'<div id="contentfooter">')
   438             for comp in components:
   436             for comp in components:
   439                 comp.render(w=self.w, view=view)
   437                 comp.render(w=self.w, view=view)
   440             self.w(u'</div>')
   438             self.w(u'</div>')
       
   439 
   441 
   440 
   442 class BaseLogForm(forms.FieldsForm):
   441 class BaseLogForm(forms.FieldsForm):
   443     """Abstract Base login form to be used by any login form
   442     """Abstract Base login form to be used by any login form
   444     """
   443     """
   445     __abstract__ = True
   444     __abstract__ = True
   459         form_buttons = [fw.SubmitButton(label=_('log in'),
   458         form_buttons = [fw.SubmitButton(label=_('log in'),
   460                                     attrs={'class': 'loginButton'}),
   459                                     attrs={'class': 'loginButton'}),
   461                         fw.ResetButton(label=_('cancel'),
   460                         fw.ResetButton(label=_('cancel'),
   462                                        attrs={'class': 'loginButton',
   461                                        attrs={'class': 'loginButton',
   463                                               'onclick': onclick}),]
   462                                               'onclick': onclick}),]
   464         ## Can't shortcut next access because __dict__ is a "dictproxy" which 
   463         ## Can't shortcut next access because __dict__ is a "dictproxy" which
   465         ## does not support items assignement.
   464         ## does not support items assignement.
   466         # cls.__dict__['form_buttons'] = form_buttons
   465         # cls.__dict__['form_buttons'] = form_buttons
   467         return form_buttons
   466         return form_buttons
   468 
   467 
   469     def form_action(self):
   468     def form_action(self):
   475             if target and target != '/':
   474             if target and target != '/':
   476                 url_args['postlogin_path'] = target
   475                 url_args['postlogin_path'] = target
   477             return self._cw.build_url('login', __secure__=True, **url_args)
   476             return self._cw.build_url('login', __secure__=True, **url_args)
   478         return super(BaseLogForm, self).form_action()
   477         return super(BaseLogForm, self).form_action()
   479 
   478 
       
   479 
   480 class LogForm(BaseLogForm):
   480 class LogForm(BaseLogForm):
   481     """Simple login form that send username and password
   481     """Simple login form that send username and password
   482     """
   482     """
   483     __regid__ = 'logform'
   483     __regid__ = 'logform'
   484     domid = 'loginForm'
   484     domid = 'loginForm'
   486     # XXX have to recall fields name since python is mangling __login/__password
   486     # XXX have to recall fields name since python is mangling __login/__password
   487     __login = ff.StringField('__login', widget=fw.TextInput({'class': 'data'}))
   487     __login = ff.StringField('__login', widget=fw.TextInput({'class': 'data'}))
   488     __password = ff.StringField('__password', label=_('password'),
   488     __password = ff.StringField('__password', label=_('password'),
   489                                 widget=fw.PasswordSingleInput({'class': 'data'}))
   489                                 widget=fw.PasswordSingleInput({'class': 'data'}))
   490 
   490 
   491     onclick_args =  ('popupLoginBox', '__login')
   491     onclick_args = ('popupLoginBox', '__login')
   492 
   492 
   493 
   493 
   494 class LogFormView(View):
   494 class LogFormView(View):
   495     # XXX an awful lot of hardcoded assumptions there
   495     # XXX an awful lot of hardcoded assumptions there
   496     #     makes it unobvious to reuse/specialize
   496     #     makes it unobvious to reuse/specialize
   529             label = cw.pgettext('CWUser', 'login')
   529             label = cw.pgettext('CWUser', 'login')
   530         form.field_by_name('__login').label = label
   530         form.field_by_name('__login').label = label
   531         form.render(w=self.w, table_class='', display_progress_div=False)
   531         form.render(w=self.w, table_class='', display_progress_div=False)
   532         cw.html_headers.add_onload('jQuery("#__login:visible").focus()')
   532         cw.html_headers.add_onload('jQuery("#__login:visible").focus()')
   533 
   533 
       
   534 
   534 LogFormTemplate = class_renamed('LogFormTemplate', LogFormView)
   535 LogFormTemplate = class_renamed('LogFormTemplate', LogFormView)