# copyright 2003-2010 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/>."""Bases HTML components:* the rql input form* the logged user link"""from__future__importwith_statement__docformat__="restructuredtext en"_=unicodefromlogilab.mtconverterimportxml_escapefromlogilab.common.deprecationimportclass_renamedfromrqlimportparsefromcubicweb.selectorsimport(yes,multi_etypes_rset,match_form_params,match_context,configuration_values,anonymous_user,authenticated_user)fromcubicweb.schemaimportdisplay_namefromcubicweb.utilsimportwrap_on_writefromcubicweb.uilibimporttoggle_actionfromcubicweb.webimportcomponent,uicfgfromcubicweb.web.htmlwidgetsimportMenuWidget,PopupBoxMenuVISIBLE_PROP_DEF={_('visible'):dict(type='Boolean',default=True,help=_('display the component or not')),}classRQLInputForm(component.Component):"""build the rql input form, usually displayed in the header"""__regid__='rqlinput'cw_property_defs=VISIBLE_PROP_DEFvisible=Falsedefcall(self,view=None):ifhasattr(view,'filter_box_context_info'):rset=view.filter_box_context_info()[0]else:rset=self.cw_rset# display multilines query as one linerql=rsetisnotNoneandrset.printable_rql(encoded=False)orself._cw.form.get('rql','')rql=rql.replace(u"\n",u" ")req=self._cwself.w(u'''<div id="rqlinput" class="%s"> <form action="%s"><fieldset><input type="text" id="rql" name="rql" value="%s" title="%s" tabindex="%s" accesskey="q" class="searchField" /></fieldset>'''%(notself.cw_propval('visible')and'hidden'or'',self._cw.build_url('view'),xml_escape(rql),req._('full text or RQL query'),req.next_tabindex()))ifself._cw.search_state[0]!='normal':self.w(u'<input type="hidden" name="__mode" value="%s"/>'%':'.join(req.search_state[1]))self.w(u'</form></div>')classHeaderComponent(component.CtxComponent):# XXX rename properly along with related context"""if the user is the anonymous user, build a link to login else display a menu with user'action (preference, logout, etc...) """__abstract__=Truecw_property_defs=component.override_ctx(component.CtxComponent,vocabulary=['header-left','header-right'])# don't want user to hide this component using an cwpropertysite_wide=Truecontext=_('header-left')classApplLogo(HeaderComponent):"""build the instance logo, usually displayed in the header"""__regid__='logo'order=-1defrender(self,w):w(u'<a href="%s"><img id="logo" src="%s" alt="logo"/></a>'%(self._cw.base_url(),self._cw.uiprops['LOGO']))classApplicationName(HeaderComponent):"""display the instance name"""__regid__='appliname'defrender(self,w):title=self._cw.property_value('ui.site-title')iftitle:w(u'<span id="appliName"><a href="%s">%s</a></span>'%(self._cw.base_url(),xml_escape(title)))classCookieLoginComponent(HeaderComponent):__regid__='anonuserlink'__select__=(HeaderComponent.__select__&anonymous_user()&configuration_values('auth-mode','cookie'))context='header-right'loginboxid='popupLoginBox'_html=u"""[<a class="logout" title="%s" href="javascript:cw.htmlhelpers.popupLoginBox('%s', '__login');">%s</a>]"""defrender(self,w):# XXX bw compat, though should warn about subclasses redefining callself.w=wself.call()defcall(self):self.w(self._html%(self._cw._('login / password'),self.loginboxid,self._cw._('i18n_login_popup')))self._cw.view('logform',rset=self.cw_rset,id=self.loginboxid,klass='%s hidden'%self.loginboxid,title=False,showmessage=False,w=self.w)classHTTPLoginComponent(CookieLoginComponent):__select__=(HeaderComponent.__select__&anonymous_user()&configuration_values('auth-mode','http'))defrender(self,w):# this redirects to the 'login' controller which in turn# will raise a 401/Unauthorizedreq=self._cww(u'[<a class="logout" title="%s" href="%s">%s</a>]'%(req._('login / password'),req.build_url('login'),req._('login')))_UserLink=class_renamed('_UserLink',HeaderComponent)AnonUserLink=class_renamed('AnonUserLink',CookieLoginComponent)AnonUserLink.__abstract__=TrueAnonUserLink.__select__&=yes(1)classAnonUserStatusLink(HeaderComponent):__regid__='userstatus'__select__=HeaderComponent.__select__&anonymous_user()context=_('header-right')order=HeaderComponent.order-10defrender(self,w):w(u'<span class="caption">%s</span>'%self._cw._('anonymous'))classAuthenticatedUserStatus(AnonUserStatusLink):__select__=HeaderComponent.__select__&authenticated_user()defrender(self,w):# display useractions and siteactionsactions=self._cw.vreg['actions'].possible_actions(self._cw,rset=self.cw_rset)box=MenuWidget('','userActionsBox',_class='',islist=False)menu=PopupBoxMenu(self._cw.user.login,isitem=False)box.append(menu)foractioninactions.get('useractions',()):menu.append(self.action_link(action))ifactions.get('useractions')andactions.get('siteactions'):menu.append(self.separator())foractioninactions.get('siteactions',()):menu.append(self.action_link(action))box.render(w=w)classApplicationMessage(component.Component):"""display messages given using the __message parameter into a special div section """__select__=yes()__regid__='applmessages'# don't want user to hide this component using an cwpropertycw_property_defs={}defcall(self):msgs=[msgformsgin(self._cw.get_shared_data('sources_error',pop=True),self._cw.message)ifmsg]self.w(u'<div id="appMsg" onclick="%s" class="%s">\n'%(toggle_action('appMsg'),(msgsand' 'or'hidden')))formsginmsgs:self.w(u'<div class="message" id="%s">%s</div>'%(self.domid,msg))self.w(u'</div>')classEtypeRestrictionComponent(component.Component):"""displays the list of entity types contained in the resultset to be able to filter accordingly. """__regid__='etypenavigation'__select__=multi_etypes_rset()|match_form_params('__restrtype','__restrtypes','__restrrql')cw_property_defs=VISIBLE_PROP_DEF# don't want user to hide this component using an cwpropertysite_wide=Truevisible=False# disabled by defaultdefcall(self):_=self._cw._self.w(u'<div id="etyperestriction">')restrtype=self._cw.form.get('__restrtype')restrtypes=self._cw.form.get('__restrtypes','').split(',')restrrql=self._cw.form.get('__restrrql')ifnotrestrrql:rqlst=self.cw_rset.syntax_tree()restrrql=rqlst.as_string(self._cw.encoding,self.cw_rset.args)restrtypes=self.cw_rset.column_types(0)else:rqlst=parse(restrrql)html=[]on_etype=Falseetypes=sorted((display_name(self._cw,etype).capitalize(),etype)foretypeinrestrtypes)forelabel,etypeinetypes:ifetype==restrtype:html.append(u'<span class="selected">%s</span>'%elabel)on_etype=Trueelse:rqlst.save_state()forselectinrqlst.children:select.add_type_restriction(select.selection[0],etype)newrql=rqlst.as_string(self._cw.encoding,self.cw_rset.args)url=self._cw.build_url(rql=newrql,__restrrql=restrrql,__restrtype=etype,__restrtypes=','.join(restrtypes))html.append(u'<span><a href="%s">%s</a></span>'%(xml_escape(url),elabel))rqlst.recover()ifon_etype:url=self._cw.build_url(rql=restrrql)html.insert(0,u'<span><a href="%s">%s</a></span>'%(url,_('Any')))else:html.insert(0,u'<span class="selected">%s</span>'%_('Any'))self.w(u' | '.join(html))self.w(u'</div>')# contextual components ########################################################classMetaDataComponent(component.EntityCtxComponent):__regid__='metadata'context='navbottom'order=1defrender_body(self,w):self.entity.view('metadata',w=w)classSectionLayout(component.Layout):__select__=match_context('navtop','navbottom','navcontenttop','navcontentbottom')cssclass='section'defrender(self,w):ifself.init_rendering():view=self.cw_extra_kwargs['view']w(u'<div class="%s%s" id="%s">'%(self.cssclass,view.cssclass,view.domid))withwrap_on_write(w,'<h4>')aswow:view.render_title(wow)view.render_body(w)w(u'</div>\n')