# copyright 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/>.__docformat__="restructuredtext en"_=unicodefromlogilab.common.registryimportPredicatefromcubicwebimportUnknownEid,tags,transactionastxfromcubicweb.viewimportView,StartupViewfromcubicweb.predicatesimportmatch_kwargs,ExpectedValuePredicatefromcubicweb.schemaimportdisplay_nameclassundoable_action(Predicate):"""Select only undoable actions depending on filters provided. Undo Action is expected to be specified by the `tx_action` argument. Currently the only implemented filter is: :param action_type: chars among CUDAR (standing for Create, Update, Delete, Add, Remove) """# XXX FIXME : this selector should be completed to allow selection on the# entity or relation types and public / private.def__init__(self,action_type='CUDAR'):assertnotset(action_type)-set('CUDAR')self.action_type=action_typedef__str__(self):return'%s(%s)'%(self.__class__.__name__,', '.join("%s=%v"%(str(k),str(v))fork,vinkwargs.iteritems()))def__call__(self,cls,req,tx_action=None,**kwargs):# tx_action is expected to be a transaction.AbstractActionifnotisinstance(tx_action,tx.AbstractAction):return0# Filter according to action typereturnint(tx_action.actioninself.action_type)classUndoHistoryView(StartupView):__regid__='undohistory'title=_('Undoing')item_vid='undoable-transaction-view'cache_max_age=0redirect_path='view'#TODOredirect_params=dict(vid='undohistory')#TODOpublic_actions_only=True# TODO Allow to choose if if want all actions or only the public ones# (default)defcall(self,**kwargs):txs=self._cw.cnx.undoable_transactions()iftxs:self.w(u"<ul class='undo-transactions'>")fortxintxs:self.cell_call(tx)self.w(u"</ul>")defcell_call(self,tx):self.w(u'<li>')self.wview(self.item_vid,None,txuuid=tx.uuid,public=self.public_actions_only,redirect_path=self.redirect_path,redirect_params=self.redirect_params)self.w(u'</li>\n')classUndoableTransactionView(View):__regid__='undoable-transaction-view'__select__=View.__select__&match_kwargs('txuuid')item_vid='undoable-action-list-view'cache_max_age=0defbuild_undo_link(self,txuuid,redirect_path=None,redirect_params=None):""" the kwargs are passed to build_url"""_=self._cw._redirect={}ifredirect_path:redirect['__redirectpath']=redirect_pathifredirect_params:ifisinstance(redirect_params,dict):redirect['__redirectparams']=self._cw.build_url_params(**redirect_params)else:redirect['__redirectparams']=redirect_paramslink_url=self._cw.build_url('undo',txuuid=txuuid,**redirect)msg=u"<span class='undo'>%s</span>"%tags.a(_('undo'),href=link_url)returnmsgdefcall(self,txuuid,public=True,redirect_path=None,redirect_params=None):_=self._cw._txinfo=self._cw.cnx.transaction_info(txuuid)try:#XXX Under some unknown circumstances txinfo.user_eid=-1user=self._cw.entity_from_eid(txinfo.user_eid)exceptUnknownEid:user=Noneundo_url=self.build_undo_link(txuuid,redirect_path=redirect_path,redirect_params=redirect_params)txinfo_dict=dict(dt=self._cw.format_date(txinfo.datetime,time=True),user_eid=txinfo.user_eid,user=useranduser.view('outofcontext')or_("undefined user"),txuuid=txuuid,undo_link=undo_url)self.w(_("By %(user)s on %(dt)s [%(undo_link)s]")%txinfo_dict)tx_actions=txinfo.actions_list(public=public)iftx_actions:self.wview(self.item_vid,None,tx_actions=tx_actions)classUndoableActionListView(View):__regid__='undoable-action-list-view'__select__=View.__select__&match_kwargs('tx_actions')title=_('Undoable actions')item_vid='undoable-action-view'cache_max_age=0defcall(self,tx_actions):iftx_actions:self.w(u"<ol class='undo-actions'>")foractionintx_actions:self.cell_call(action)self.w(u"</ol>")defcell_call(self,action):self.w(u'<li>')self.wview(self.item_vid,None,tx_action=action)self.w(u'</li>\n')classUndoableActionBaseView(View):__regid__='undoable-action-view'__abstract__=Truedefcall(self,tx_action):raiseNotImplementedError(self)def_build_entity_link(self,eid):try:entity=self._cw.entity_from_eid(eid)returnentity.view('outofcontext')exceptUnknownEid:return_("(suppressed) entity #%d")%eiddef_build_relation_info(self,rtype,eid_from,eid_to):returndict(rtype=display_name(self._cw,rtype),entity_from=self._build_entity_link(eid_from),entity_to=self._build_entity_link(eid_to))def_build_entity_info(self,etype,eid,changes):returndict(etype=display_name(self._cw,etype),entity=self._build_entity_link(eid),eid=eid,changes=changes)classUndoableAddActionView(UndoableActionBaseView):__select__=UndoableActionBaseView.__select__&undoable_action(action_type='A')defcall(self,tx_action):_=self._cw._self.w(_("Added relation : %(entity_from)s%(rtype)s%(entity_to)s")%self._build_relation_info(tx_action.rtype,tx_action.eid_from,tx_action.eid_to))classUndoableRemoveActionView(UndoableActionBaseView):__select__=UndoableActionBaseView.__select__&undoable_action(action_type='R')defcall(self,tx_action):_=self._cw._self.w(_("Delete relation : %(entity_from)s%(rtype)s%(entity_to)s")%self._build_relation_info(tx_action.rtype,tx_action.eid_from,tx_action.eid_to))classUndoableCreateActionView(UndoableActionBaseView):__select__=UndoableActionBaseView.__select__&undoable_action(action_type='C')defcall(self,tx_action):_=self._cw._self.w(_("Created %(etype)s : %(entity)s")%# : %(changes)sself._build_entity_info(tx_action.etype,tx_action.eid,tx_action.changes))classUndoableDeleteActionView(UndoableActionBaseView):__select__=UndoableActionBaseView.__select__&undoable_action(action_type='D')defcall(self,tx_action):_=self._cw._self.w(_("Deleted %(etype)s : %(entity)s")%self._build_entity_info(tx_action.etype,tx_action.eid,tx_action.changes))classUndoableUpdateActionView(UndoableActionBaseView):__select__=UndoableActionBaseView.__select__&undoable_action(action_type='U')defcall(self,tx_action):_=self._cw._self.w(_("Updated %(etype)s : %(entity)s")%self._build_entity_info(tx_action.etype,tx_action.eid,tx_action.changes))