[hooks/notification] Fix indentation
Follow-up for changeset 1b8552265f3b "[hooks/notification] use a cnx not a
session"
# copyright 2003-2012 LOGILAB S.A. (Paris, FRANCE), all rights reserved.# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr## This file is part of CubicWeb.## CubicWeb 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.## CubicWeb 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 CubicWeb. If not, see <http://www.gnu.org/licenses/>."""default templates for CubicWeb web client"""__docformat__="restructuredtext en"_=unicodefromlogilab.mtconverterimportxml_escapefromlogilab.common.deprecationimportclass_renamedfromlogilab.common.registryimportobjectify_predicatefromlogilab.common.decoratorsimportclasspropertyfromcubicweb.predicatesimportmatch_kwargs,no_cnx,anonymous_userfromcubicweb.viewimportView,MainTemplate,NOINDEX,NOFOLLOW,StartupViewfromcubicweb.utilsimportUStringIOfromcubicweb.schemaimportdisplay_namefromcubicweb.webimportcomponent,formfieldsasff,formwidgetsasfwfromcubicweb.web.viewsimportforms# main templates ##############################################################classLogInOutTemplate(MainTemplate):defcall(self):self.set_request_content_type()w=self.wself.write_doctype()self.template_header('text/html',self._cw._('login_action'))w(u'<body>\n')self.content(w)w(u'</body>')deftemplate_header(self,content_type,view=None,page_title='',additional_headers=()):w=self.whead# explictly close the <base> tag to avoid IE 6 bugs while browsing DOMw(u'<base href="%s"></base>'%xml_escape(self._cw.base_url()))w(u'<meta http-equiv="content-type" content="%s; charset=%s"/>\n'%(content_type,self._cw.encoding))w(NOINDEX)w(NOFOLLOW)w(u'\n'.join(additional_headers)+u'\n')self.wview('htmlheader',rset=self.cw_rset)w(u'<title>%s</title>\n'%xml_escape(page_title))defcontent(self):raiseNotImplementedError()classLogInTemplate(LogInOutTemplate):__regid__='login'__select__=anonymous_user()title='log in'defcontent(self,w):self.wview('logform',rset=self.cw_rset,id='loginBox',klass='')classLoggedOutTemplate(StartupView):__regid__='loggedout'__select__=anonymous_user()title='logged out'defcall(self):msg=self._cw._('you have been logged out')ifself._cw.cnx:comp=self._cw.vreg['components'].select('applmessages',self._cw)comp.render(w=self.w,msg=msg)self.wview('index')else:self.w(u'<h2>%s</h2>'%msg)@objectify_predicatedefmodal_view(cls,req,rset,*args,**kwargs):ifreq.form.get('__modal',None):return1@objectify_predicatedeftemplatable_view(cls,req,rset,*args,**kwargs):view=kwargs.pop('view',None)ifviewisNone:return1ifview.binary:return0if'__notemplate'inreq.form:return0returnview.templatableclassNonTemplatableViewTemplate(MainTemplate):"""main template for any non templatable views (xml, binaries, etc.)"""__regid__='main-template'__select__=~templatable_view()defcall(self,view):view.set_request_content_type()view.set_stream()if(('__notemplate'inself._cw.form)andview.templatableandview.content_type==self._cw.html_content_type()):view.w(u'<div>')view.render()view.w(u'</div>')else:view.render()# have to replace our stream by view's stream (which may be a binary# stream)self._stream=view._streamclassModalMainTemplate(MainTemplate):""" a no-decoration main template for standard views that typically live in a modal context """__regid__='main-template'__select__=templatable_view()&modal_view()defcall(self,view):view.set_request_content_type()view.render(w=self.w)classTheMainTemplate(MainTemplate):"""default main template : - call header / footer templates """__regid__='main-template'__select__=templatable_view()defcall(self,view):self.set_request_content_type()self.template_header(self.content_type,view)w=self.ww(u'<div id="pageContent">\n')vtitle=self._cw.form.get('vtitle')ifvtitle:w(u'<div class="vtitle">%s</div>\n'%xml_escape(vtitle))# display entity type restriction componentetypefilter=self._cw.vreg['components'].select_or_none('etypenavigation',self._cw,rset=self.cw_rset)ifetypefilterandetypefilter.cw_propval('visible'):etypefilter.render(w=w)nav_html=UStringIO()ifviewandnotview.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')# close id=contentmainw(nav_html.getvalue())w(u'</div>\n')# closes id=pageContentself.template_footer(view)deftemplate_header(self,content_type,view=None,page_title='',additional_headers=()):page_title=page_titleorview.page_title()additional_headers=additional_headersorview.html_headers()self.template_html_header(content_type,page_title,additional_headers)self.template_body_header(view)deftemplate_html_header(self,content_type,page_title,additional_headers=()):w=self.wheadlang=self._cw.langself.write_doctype()# explictly close the <base> tag to avoid IE 6 bugs while browsing DOMself._cw.html_headers.define_var('BASE_URL',self._cw.base_url())self._cw.html_headers.define_var('DATA_URL',self._cw.datadir_url)w(u'<meta http-equiv="content-type" content="%s; charset=%s"/>\n'%(content_type,self._cw.encoding))w(u'\n'.join(additional_headers)+u'\n')self.wview('htmlheader',rset=self.cw_rset)ifpage_title:w(u'<title>%s</title>\n'%xml_escape(page_title))deftemplate_body_header(self,view):w=self.ww(u'<body>\n')self.wview('header',rset=self.cw_rset,view=view)w(u'<div id="page"><table width="100%" border="0" id="mainLayout"><tr>\n')self.nav_column(view,'left')w(u'<td id="contentColumn">\n')components=self._cw.vreg['components']rqlcomp=components.select_or_none('rqlinput',self._cw,rset=self.cw_rset)ifrqlcomp:rqlcomp.render(w=self.w,view=view)msgcomp=components.select_or_none('applmessages',self._cw,rset=self.cw_rset)ifmsgcomp:msgcomp.render(w=self.w)self.content_header(view)deftemplate_footer(self,view=None):self.content_footer(view)self.w(u'</td>\n')self.nav_column(view,'right')self.w(u'</tr></table></div>\n')self.wview('footer',rset=self.cw_rset)self.w(u'</body>')defnav_column(self,view,context):boxes=list(self._cw.vreg['ctxcomponents'].poss_visible_objects(self._cw,rset=self.cw_rset,view=view,context=context))ifboxes:getlayout=self._cw.vreg['components'].selectself.w(u'<td id="navColumn%s"><div class="navboxes">\n'%context.capitalize())forboxinboxes:box.render(w=self.w,view=view)self.w(u'</div></td>\n')defcontent_header(self,view=None):"""by default, display informal messages in content header"""self.wview('contentheader',rset=self.cw_rset,view=view)defcontent_footer(self,view=None):self.wview('contentfooter',rset=self.cw_rset,view=view)classErrorTemplate(TheMainTemplate):"""fallback template if an internal error occurred during displaying the main template. This template may be called for authentication error, which means that req.cnx and req.user may not be set. """__regid__='error-template'defcall(self):"""display an unexpected error"""self.set_request_content_type()self._cw.reset_headers()view=self._cw.vreg['views'].select('error',self._cw,rset=self.cw_rset)self.template_header(self.content_type,view,self._cw._('an error occurred'),[NOINDEX,NOFOLLOW])view.render(w=self.w)self.template_footer(view)deftemplate_header(self,content_type,view=None,page_title='',additional_headers=()):w=self.wheadlang=self._cw.langself.write_doctype()w(u'<meta http-equiv="content-type" content="%s; charset=%s"/>\n'%(content_type,self._cw.encoding))w(u'\n'.join(additional_headers))self.wview('htmlheader',rset=self.cw_rset)w(u'<title>%s</title>\n'%xml_escape(page_title))self.w(u'<body>\n')deftemplate_footer(self,view=None):self.w(u'</body>')classSimpleMainTemplate(TheMainTemplate):__regid__='main-no-top'deftemplate_header(self,content_type,view=None,page_title='',additional_headers=()):page_title=page_titleorview.page_title()additional_headers=additional_headersorview.html_headers()whead=self.wheadlang=self._cw.langself.write_doctype()whead(u'<meta http-equiv="content-type" content="%s; charset=%s"/>\n'%(content_type,self._cw.encoding))whead(u'\n'.join(additional_headers)+u'\n')self.wview('htmlheader',rset=self.cw_rset)w=self.wwhead(u'<title>%s</title>\n'%xml_escape(page_title))w(u'<body>\n')w(u'<div id="page">')w(u'<table width="100%" border="0" id="mainLayout"><tr>\n')w(u'<td id="navColumnLeft">\n')self.topleft_header()boxes=list(self._cw.vreg['ctxcomponents'].poss_visible_objects(self._cw,rset=self.cw_rset,view=view,context='left'))ifboxes:w(u'<div class="navboxes">\n')forboxinboxes:box.render(w=w)self.w(u'</div>\n')w(u'</td>')w(u'<td id="contentColumn" rowspan="2">')deftopleft_header(self):logo=self._cw.vreg['components'].select_or_none('logo',self._cw,rset=self.cw_rset)iflogoandlogo.cw_propval('visible'):w=self.ww(u'<table id="header"><tr>\n')w(u'<td>')logo.render(w=w)w(u'</td>\n')w(u'</tr></table>\n')# page parts templates ########################################################classHTMLHeader(View):"""default html headers"""__regid__='htmlheader'defcall(self,**kwargs):self.favicon()self.stylesheets()self.javascripts()self.alternates()deffavicon(self):favicon=self._cw.uiprops.get('FAVICON',None)iffavicon:self.whead(u'<link rel="shortcut icon" href="%s"/>\n'%favicon)defstylesheets(self):req=self._cwadd_css=req.add_cssforcssinreq.uiprops['STYLESHEETS']:add_css(css,localfile=False)forcssinreq.uiprops['STYLESHEETS_PRINT']:add_css(css,u'print',localfile=False)forcssinreq.uiprops['STYLESHEETS_IE']:add_css(css,localfile=False,ieonly=True)defjavascripts(self):forjscriptinself._cw.uiprops['JAVASCRIPTS']:self._cw.add_js(jscript,localfile=False)defalternates(self):urlgetter=self._cw.vreg['components'].select_or_none('rss_feed_url',self._cw,rset=self.cw_rset)ifurlgetterisnotNone:self.whead(u'<link rel="alternate" type="application/rss+xml" title="RSS feed" href="%s"/>\n'%xml_escape(urlgetter.feed_url()))classHTMLPageHeader(View):"""default html page header"""__regid__='header'main_cell_components=('appliname','breadcrumbs')headers=(('headtext','header-left'),('header-center','header-center'),('header-right','header-right'))defcall(self,view,**kwargs):self.main_header(view)self.w(u'<div id="stateheader">')self.state_header()self.w(u'</div>')defmain_header(self,view):"""build the top menu with authentification info and the rql box"""w=self.ww(u'<table id="header"><tr>\n')forcolid,contextinself.headers:w(u'<td id="%s">'%colid)components=self._cw.vreg['ctxcomponents'].poss_visible_objects(self._cw,rset=self.cw_rset,view=view,context=context)forcompincomponents:comp.render(w=w)w(u' ')w(u'</td>')w(u'</tr></table>\n')defstate_header(self):state=self._cw.search_stateifstate[0]=='normal':return_=self._cw._value=self._cw.view('oneline',self._cw.eid_rset(state[1][1]))msg=' '.join((_("searching for"),display_name(self._cw,state[1][3]),_("to associate with"),value,_("by relation"),'"',display_name(self._cw,state[1][2],state[1][0]),'"'))returnself.w(u'<div class="stateMessage">%s</div>'%msg)classHTMLPageFooter(View):"""default html page footer: include footer actions"""__regid__='footer'defcall(self,**kwargs):self.w(u'<div id="footer">')self.footer_content()self.w(u'</div>')deffooter_content(self):actions=self._cw.vreg['actions'].possible_actions(self._cw,rset=self.cw_rset)footeractions=actions.get('footer',())fori,actioninenumerate(footeractions):self.w(u'<a href="%s">%s</a>'%(action.url(),self._cw._(action.title)))ifi<(len(footeractions)-1):self.w(u' | ')classHTMLContentHeader(View):"""default html page content header: * include message component if selectable for this request * include selectable content navigation components """__regid__='contentheader'defcall(self,view,**kwargs):"""by default, display informal messages in content header"""components=self._cw.vreg['ctxcomponents'].poss_visible_objects(self._cw,rset=self.cw_rset,view=view,context='navtop')ifcomponents:self.w(u'<div id="contentheader">')forcompincomponents:comp.render(w=self.w,view=view)self.w(u'</div><div class="clear"></div>')classHTMLContentFooter(View):"""default html page content footer: include selectable content navigation components """__regid__='contentfooter'defcall(self,view,**kwargs):components=self._cw.vreg['ctxcomponents'].poss_visible_objects(self._cw,rset=self.cw_rset,view=view,context='navbottom')ifcomponents:self.w(u'<div id="contentfooter">')forcompincomponents:comp.render(w=self.w,view=view)self.w(u'</div>')classBaseLogForm(forms.FieldsForm):"""Abstract Base login form to be used by any login form """__abstract__=True__regid__='logform'domid='loginForm'needs_css=('cubicweb.login.css',)onclick_base="javascript: cw.htmlhelpers.popupLoginBox('%s', '%s');"onclick_args=(None,None)@classpropertydefform_buttons(cls):# we use a property because sub class will need to define their own onclick_args.# Therefor we can't juste make the string formating when instanciating this classonclick=cls.onclick_base%cls.onclick_argsform_buttons=[fw.SubmitButton(label=_('log in'),attrs={'class':'loginButton'}),fw.ResetButton(label=_('cancel'),attrs={'class':'loginButton','onclick':onclick}),]## Can't shortcut next access because __dict__ is a "dictproxy" which ## does not support items assignement.# cls.__dict__['form_buttons'] = form_buttonsreturnform_buttonsdefform_action(self):ifself.actionisNone:# reuse existing redirection if it existstarget=self._cw.form.get('postlogin_path',self._cw.relative_path())url_args={}iftargetandtarget!='/':url_args['postlogin_path']=targetreturnself._cw.build_url('login',__secure__=True,**url_args)returnsuper(LogForm,self).form_action()classLogForm(BaseLogForm):"""Simple login form that send username and password """__regid__='logform'domid='loginForm'needs_css=('cubicweb.login.css',)# XXX have to recall fields name since python is mangling __login/__password__login=ff.StringField('__login',widget=fw.TextInput({'class':'data'}))__password=ff.StringField('__password',label=_('password'),widget=fw.PasswordSingleInput({'class':'data'}))onclick_args=('popupLoginBox','__login')classLogFormView(View):# XXX an awfull lot of hardcoded assumptions there# makes it unobvious to reuse/specialize__regid__='logform'__select__=match_kwargs('id','klass')title='log in'defcall(self,id,klass,title=True,showmessage=True):w=self.ww(u'<div id="%s" class="%s">'%(id,klass))iftitle:stitle=self._cw.property_value('ui.site-title')ifstitle:stitle=xml_escape(stitle)else:stitle=u' 'w(u'<div class="loginTitle">%s</div>'%stitle)w(u'<div class="loginContent">\n')ifshowmessageandself._cw.message:w(u'<div class="loginMessage">%s</div>\n'%self._cw.message)config=self._cw.vreg.configifconfig['auth-mode']!='http':self.login_form(id)# Cookie authenticationw(u'</div>')ifself._cw.httpsandconfig.anonymous_user()[0]andconfig['https-deny-anonymous']:path=xml_escape(config['base-url']+self._cw.relative_path())w(u'<div class="loginMessage"><a href="%s">%s</a></div>\n'%(path,self._cw._('No account? Try public access at %s')%path))w(u'</div>\n')deflogin_form(self,id):cw=self._cwform=cw.vreg['forms'].select('logform',cw)ifcw.vreg.config['allow-email-login']:label=cw._('login or email')else:label=cw.pgettext('CWUser','login')form.field_by_name('__login').label=labelform.render(w=self.w,table_class='',display_progress_div=False)cw.html_headers.add_onload('jQuery("#__login:visible").focus()')LogFormTemplate=class_renamed('LogFormTemplate',LogFormView)