"""generic boxes for CubicWeb web client:* actions box* possible views boxadditional (disabled by default) boxes* schema box* startup views box:organization: Logilab:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses"""__docformat__="restructuredtext en"_=unicodefromwarningsimportwarnfromlogilab.mtconverterimportxml_escapefromcubicweb.selectorsimportmatch_user_groups,non_final_entityfromcubicweb.viewimportEntityViewfromcubicweb.schemaimportdisplay_namefromcubicweb.web.htmlwidgetsimportBoxWidget,BoxMenu,BoxHtml,RawBoxItemfromcubicweb.webimportuicfgfromcubicweb.web.boximportBoxTemplateclassEditBox(BoxTemplate):# XXX rename to ActionsBox""" box with all actions impacting the entity displayed: edit, copy, delete change state, add related entities """id='edit_box'__select__=BoxTemplate.__select__&non_final_entity()title=_('actions')order=2defcall(self,view=None,**kwargs):_=self.req._title=_(self.title)ifself.rset:etypes=self.rset.column_types(0)iflen(etypes)==1:plural=self.rset.rowcount>1and'plural'or''etypelabel=display_name(self.req,iter(etypes).next(),plural)title=u'%s - %s'%(title,etypelabel.lower())box=BoxWidget(title,self.id,_class="greyBoxFrame")self._menus_in_order=[]self._menus_by_id={}# build list of actionsactions=self.vreg['actions'].possible_actions(self.req,self.rset,view=view)other_menu=self._get_menu('moreactions',_('more actions'))forcategory,defaultmenuin(('mainactions',box),('moreactions',other_menu),('addrelated',None)):foractioninactions.get(category,()):ifcategory=='addrelated':warn('[3.5] "addrelated" category is deprecated, use ''"moreactions" category w/ "addrelated" submenu',DeprecationWarning)defaultmenu=self._get_menu('addrelated',_('add'),_('add'))ifaction.submenu:menu=self._get_menu(action.submenu)else:menu=defaultmenuaction.fill_menu(self,menu)ifbox.is_empty()andnotother_menu.is_empty():box.items=other_menu.itemsother_menu.items=[]else:# ensure 'more actions' menu appears lastself._menus_in_order.remove(other_menu)self._menus_in_order.append(other_menu)forsubmenuinself._menus_in_order:self.add_submenu(box,submenu)ifnotbox.is_empty():box.render(self.w)def_get_menu(self,id,title=None,label_prefix=None):try:returnself._menus_by_id[id]exceptKeyError:iftitleisNone:title=self.req._(id)self._menus_by_id[id]=menu=BoxMenu(title)menu.label_prefix=label_prefixself._menus_in_order.append(menu)returnmenudefadd_submenu(self,box,submenu,label_prefix=None):appendanyway=getattr(submenu,'append_anyway',False)iflen(submenu.items)==1andnotappendanyway:boxlink=submenu.items[0]ifsubmenu.label_prefix:boxlink.label=u'%s%s'%(submenu.label_prefix,boxlink.label)box.append(boxlink)elifsubmenu.items:box.append(submenu)elifappendanyway:box.append(RawBoxItem(xml_escape(submenu.label)))classSearchBox(BoxTemplate):"""display a box with a simple search form"""id='search_box'visible=True# enabled by defaulttitle=_('search')order=0formdef=u"""<form action="%s"><table id="tsearch"><tr><td><input id="norql" type="text" accesskey="q" tabindex="%s" title="search text" value="%s" name="rql" /><input type="hidden" name="__fromsearchbox" value="1" /><input type="hidden" name="subvid" value="tsearch" /></td><td><input tabindex="%s" type="submit" id="rqlboxsubmit" class="rqlsubmit" value="" /></td></tr></table></form>"""defcall(self,view=None,**kwargs):req=self.reqifreq.form.pop('__fromsearchbox',None):rql=req.form.get('rql','')else:rql=''form=self.formdef%(req.build_url('view'),req.next_tabindex(),xml_escape(rql),req.next_tabindex())title=u"""<span onclick="javascript: toggleVisibility('rqlinput')">%s</span>"""%req._(self.title)box=BoxWidget(title,self.id,_class="searchBoxFrame",islist=False,escape=False)box.append(BoxHtml(form))box.render(self.w)# boxes disabled by default ###################################################classPossibleViewsBox(BoxTemplate):"""display a box containing links to all possible views"""id='possible_views_box'__select__=BoxTemplate.__select__&match_user_groups('users','managers')visible=Falsetitle=_('possible views')order=10defcall(self,**kwargs):box=BoxWidget(self.req._(self.title),self.id)views=[vforvinself.vreg['views'].possible_views(self.req,rset=self.rset)ifv.category!='startupview']forcategory,viewsinself.sort_actions(views):menu=BoxMenu(category)forviewinviews:menu.append(self.box_action(view))box.append(menu)ifnotbox.is_empty():box.render(self.w)classStartupViewsBox(BoxTemplate):"""display a box containing links to all startup views"""id='startup_views_box'visible=False# disabled by defaulttitle=_('startup views')order=70defcall(self,**kwargs):box=BoxWidget(self.req._(self.title),self.id)forviewinself.vreg['views'].possible_views(self.req,None):ifview.category=='startupview':box.append(self.box_action(view))ifnotbox.is_empty():box.render(self.w)# helper classes ##############################################################classSideBoxView(EntityView):"""helper view class to display some entities in a sidebox"""id='sidebox'defcall(self,boxclass='sideBox',title=u''):"""display a list of entities by calling their <item_vid> view"""iftitle:self.w(u'<div class="sideBoxTitle"><span>%s</span></div>'%title)self.w(u'<div class="%s"><div class="sideBoxBody">'%boxclass)# if not too much entities, show them all in a listmaxrelated=self.req.property_value('navigation.related-limit')ifself.rset.rowcount<=maxrelated:iflen(self.rset)==1:self.wview('incontext',self.rset,row=0)elif1<len(self.rset)<5:self.wview('csv',self.rset)else:self.wview('simplelist',self.rset)# else show links to display related entitieselse:self.rset.limit(maxrelated)rql=self.rset.printable_rql(encoded=False)self.wview('simplelist',self.rset)self.w(u'[<a href="%s">%s</a>]'%(self.build_url(rql=rql),self.req._('see them all')))self.w(u'</div>\n</div>\n')