[data] Use correct syntax to unset CSS attributes (closes #8602446)
'default' is actually a recognized CSS cursor name (the regular
pointer). Using this value doesn't revert to whatever cursor DOM
elements have by default ('pointer' on links, 'text' on text, etc).
The proper way to unset a CSS attribute on DOM elements is to set it to
an empty string.
http://stackoverflow.com/questions/2027935/how-to-remove-css-property-using-javascript
# copyright 2003-2014 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/>."""workflow views:* IWorkflowable views and forms* workflow entities views (State, Transition, TrInfo)"""__docformat__="restructuredtext en"_=unicodeimportosfromwarningsimportwarnfromlogilab.mtconverterimportxml_escapefromlogilab.common.graphimportescapefromlogilab.common.deprecationimportclass_deprecatedfromcubicwebimportUnauthorizedfromcubicweb.predicatesimport(has_related_entities,one_line_rset,relation_possible,match_form_params,score_entity,is_instance,adaptable)fromcubicweb.viewimportEntityViewfromcubicweb.schemaimportdisplay_namefromcubicweb.webimportstdmsgs,action,component,form,actionfromcubicweb.webimportformfieldsasff,formwidgetsasfwdgsfromcubicweb.web.viewsimportTmpFileViewMixinfromcubicweb.web.viewsimportuicfg,forms,primary,ibreadcrumbsfromcubicweb.web.views.tabsimportTabbedPrimaryView,PrimaryTabfromcubicweb.web.views.dotgraphviewimportDotGraphView,DotPropsHandler_pvs=uicfg.primaryview_section_pvs.tag_subject_of(('Workflow','initial_state','*'),'hidden')_pvs.tag_object_of(('*','state_of','Workflow'),'hidden')_pvs.tag_object_of(('*','transition_of','Workflow'),'hidden')_pvs.tag_object_of(('*','wf_info_for','*'),'hidden')forrtypein('in_state','by_transition','from_state','to_state'):_pvs.tag_subject_of(('*',rtype,'*'),'hidden')_pvs.tag_object_of(('*',rtype,'*'),'hidden')_pvs.tag_object_of(('*','wf_info_for','*'),'hidden')_abaa=uicfg.actionbox_appearsin_addmenu_abaa.tag_subject_of(('BaseTransition','condition','RQLExpression'),False)_abaa.tag_subject_of(('State','allowed_transition','BaseTransition'),False)_abaa.tag_object_of(('SubWorkflowExitPoint','destination_state','State'),False)_abaa.tag_subject_of(('*','wf_info_for','*'),False)_abaa.tag_object_of(('*','wf_info_for','*'),False)_abaa.tag_object_of(('*','state_of','CWEType'),True)_abaa.tag_object_of(('*','transition_of','CWEType'),True)_abaa.tag_subject_of(('Transition','destination_state','*'),True)_abaa.tag_object_of(('*','allowed_transition','Transition'),True)_abaa.tag_object_of(('*','destination_state','State'),True)_abaa.tag_subject_of(('State','allowed_transition','*'),True)_abaa.tag_object_of(('State','state_of','Workflow'),True)_abaa.tag_object_of(('Transition','transition_of','Workflow'),True)_abaa.tag_object_of(('WorkflowTransition','transition_of','Workflow'),True)_afs=uicfg.autoform_section_affk=uicfg.autoform_field_kwargs# IWorkflowable views #########################################################classChangeStateForm(forms.CompositeEntityForm):# set dom id to ensure there is no conflict with edition form (see# session_key() implementation)__regid__=domid='changestate'form_renderer_id='base'# don't want EntityFormRendererform_buttons=[fwdgs.SubmitButton(),fwdgs.Button(stdmsgs.BUTTON_CANCEL,cwaction='cancel')]classChangeStateFormView(form.FormViewMixIn,EntityView):__regid__='statuschange'title=_('status change')__select__=(one_line_rset()&match_form_params('treid')&adaptable('IWorkflowable'))defcell_call(self,row,col):entity=self.cw_rset.get_entity(row,col)transition=self._cw.entity_from_eid(self._cw.form['treid'])form=self.get_form(entity,transition)self.w(u'<h4>%s%s</h4>\n'%(self._cw._(transition.name),entity.view('oneline')))msg=self._cw._('status will change from %(st1)s to %(st2)s')%{'st1':entity.cw_adapt_to('IWorkflowable').printable_state,'st2':self._cw._(transition.destination(entity).name)}self.w(u'<p>%s</p>\n'%msg)form.render(w=self.w)defredirectpath(self,entity):returnentity.rest_path()defget_form(self,entity,transition,**kwargs):# XXX used to specify both rset/row/col and entity in case implements# selector (and not is_instance) is used on custom formform=self._cw.vreg['forms'].select('changestate',self._cw,entity=entity,transition=transition,redirect_path=self.redirectpath(entity),**kwargs)trinfo=self._cw.vreg['etypes'].etype_class('TrInfo')(self._cw)trinfo.eid=self._cw.varmaker.next()subform=self._cw.vreg['forms'].select('edition',self._cw,entity=trinfo,mainform=False)subform.field_by_name('wf_info_for','subject').value=entity.eidtrfield=subform.field_by_name('by_transition','subject')trfield.widget=fwdgs.HiddenInput()trfield.value=transition.eidform.add_subform(subform)returnformclassWFHistoryView(EntityView):__regid__='wfhistory'__select__=relation_possible('wf_info_for',role='object')& \score_entity(lambdax:x.cw_adapt_to('IWorkflowable').workflow_history)title=_('Workflow history')defcell_call(self,row,col,view=None,title=title):_=self._cw._eid=self.cw_rset[row][col]sel='Any FS,TS,C,D'rql=' ORDERBY D DESC WHERE WF wf_info_for X,'\'WF from_state FS, WF to_state TS, WF comment C,'\'WF creation_date D'ifself._cw.vreg.schema.eschema('CWUser').has_perm(self._cw,'read'):sel+=',U,WF'rql+=', WF owned_by U?'headers=(_('from_state'),_('to_state'),_('comment'),_('date'),_('CWUser'))else:sel+=',WF'headers=(_('from_state'),_('to_state'),_('comment'),_('date'))rql='%s%s, X eid %%(x)s'%(sel,rql)try:rset=self._cw.execute(rql,{'x':eid})exceptUnauthorized:returnifrset:iftitle:self.w(u'<h2>%s</h2>\n'%_(title))self.wview('table',rset,headers=headers,cellvids={2:'editable-final'})classWFHistoryVComponent(component.EntityCtxComponent):"""display the workflow history for entities supporting it"""__regid__='wfhistory'__select__=component.EntityCtxComponent.__select__&WFHistoryView.__select__context='navcontentbottom'title=_('Workflow history')defrender_body(self,w):self.entity.view('wfhistory',w=w,title=None)classInContextWithStateView(EntityView):"""display incontext view for an entity as well as its current state"""__regid__='incontext-state'__select__=adaptable('IWorkflowable')defentity_call(self,entity):iwf=entity.cw_adapt_to('IWorkflowable')self.w(u'%s [%s]'%(entity.view('incontext'),iwf.printable_state))# workflow actions #############################################################classWorkflowActions(action.Action):"""fill 'workflow' sub-menu of the actions box"""__regid__='workflow'__select__=(action.Action.__select__&one_line_rset()&relation_possible('in_state'))submenu=_('workflow')order=10deffill_menu(self,box,menu):entity=self.cw_rset.get_entity(self.cw_rowor0,self.cw_color0)menu.label=u'%s: %s'%(self._cw._('state'),entity.cw_adapt_to('IWorkflowable').printable_state)menu.append_anyway=Truesuper(WorkflowActions,self).fill_menu(box,menu)defactual_actions(self):entity=self.cw_rset.get_entity(self.cw_rowor0,self.cw_color0)iworkflowable=entity.cw_adapt_to('IWorkflowable')hastr=Falsefortriniworkflowable.possible_transitions():url=entity.absolute_url(vid='statuschange',treid=tr.eid)yieldself.build_action(self._cw._(tr.name),url)hastr=True# don't propose to see wf if user can't pass any transitionifhastr:wfurl=iworkflowable.current_workflow.absolute_url()yieldself.build_action(self._cw._('view workflow'),wfurl)ifiworkflowable.workflow_history:wfurl=entity.absolute_url(vid='wfhistory')yieldself.build_action(self._cw._('view history'),wfurl)# workflow entity types views ##################################################_pvs=uicfg.primaryview_section_pvs.tag_subject_of(('Workflow','initial_state','*'),'hidden')_pvs.tag_object_of(('*','state_of','Workflow'),'hidden')_pvs.tag_object_of(('*','transition_of','Workflow'),'hidden')_pvs.tag_object_of(('*','default_workflow','Workflow'),'hidden')_abaa=uicfg.actionbox_appearsin_addmenu_abaa.tag_subject_of(('BaseTransition','condition','RQLExpression'),False)_abaa.tag_subject_of(('State','allowed_transition','BaseTransition'),False)_abaa.tag_object_of(('SubWorkflowExitPoint','destination_state','State'),False)_abaa.tag_object_of(('State','state_of','Workflow'),True)_abaa.tag_object_of(('BaseTransition','transition_of','Workflow'),False)_abaa.tag_object_of(('Transition','transition_of','Workflow'),True)_abaa.tag_object_of(('WorkflowTransition','transition_of','Workflow'),True)classWorkflowPrimaryView(TabbedPrimaryView):__select__=is_instance('Workflow')tabs=[_('wf_tab_info'),_('wfgraph'),]default_tab='wf_tab_info'classStateInContextView(EntityView):"""convenience trick, State's incontext view should not be clickable"""__regid__='incontext'__select__=is_instance('State')defcell_call(self,row,col):self.w(xml_escape(self._cw.view('textincontext',self.cw_rset,row=row,col=col)))classWorkflowTabTextView(PrimaryTab):__regid__='wf_tab_info'__select__=PrimaryTab.__select__&one_line_rset()&is_instance('Workflow')defrender_entity_attributes(self,entity):_=self._cw._self.w(u'<div>%s</div>'%(entity.printable_value('description')))self.w(u'<span>%s%s</span>'%(_("workflow_of").capitalize(),_(" :")))html=[]foreinentity.workflow_of:view=e.view('outofcontext')ifentity.eid==e.default_workflow[0].eid:view+=u' <span>[%s]</span>'%_('default_workflow')html.append(view)self.w(', '.join(vforvinhtml))self.w(u'<h2>%s</h2>'%_("Transition_plural"))rset=self._cw.execute('Any T,T,DS,T,TT ORDERBY TN WHERE T transition_of WF, WF eid %(x)s,''T type TT, T name TN, T destination_state DS?',{'x':entity.eid})self.wview('table',rset,'null',cellvids={1:'trfromstates',2:'outofcontext',3:'trsecurity',},headers=(_('Transition'),_('from_state'),_('to_state'),_('permissions'),_('type')),)classTransitionSecurityTextView(EntityView):__regid__='trsecurity'__select__=is_instance('Transition')defcell_call(self,row,col):_=self._cw._entity=self.cw_rset.get_entity(self.cw_row,self.cw_col)ifentity.require_group:self.w(u'<div>%s%s%s</div>'%(_('groups'),_(" :"),u', '.join((g.view('incontext')forginentity.require_group))))ifentity.condition:self.w(u'<div>%s%s%s</div>'%(_('conditions'),_(" :"),u'<br/>'.join((e.dc_title()foreinentity.condition))))classTransitionAllowedTextView(EntityView):__regid__='trfromstates'__select__=is_instance('Transition')defcell_call(self,row,col):entity=self.cw_rset.get_entity(self.cw_row,self.cw_col)self.w(u', '.join((e.view('outofcontext')foreinentity.reverse_allowed_transition)))# workflow entity types edition ################################################def_wf_items_for_relation(req,wfeid,wfrelation,field):wf=req.entity_from_eid(wfeid)rschema=req.vreg.schema[field.name]param='toeid'iffield.role=='subject'else'fromeid'returnsorted((e.view('combobox'),unicode(e.eid))foreingetattr(wf,'reverse_%s'%wfrelation)ifrschema.has_perm(req,'add',**{param:e.eid}))# TrInfo_afs.tag_subject_of(('TrInfo','to_state','*'),'main','hidden')_afs.tag_subject_of(('TrInfo','from_state','*'),'main','hidden')_afs.tag_attribute(('TrInfo','tr_count'),'main','hidden')# BaseTransition# XXX * allowed_transition BaseTransition# XXX BaseTransition destination_state *deftransition_states_vocabulary(form,field):entity=form.edited_entityifentity.has_eid():wfeid=entity.transition_of[0].eidelse:eids=form.linked_to.get(('transition_of','subject'))ifnoteids:return[]wfeid=eids[0]return_wf_items_for_relation(form._cw,wfeid,'state_of',field)_afs.tag_subject_of(('*','destination_state','*'),'main','attributes')_affk.tag_subject_of(('*','destination_state','*'),{'choices':transition_states_vocabulary})_afs.tag_object_of(('*','allowed_transition','*'),'main','attributes')_affk.tag_object_of(('*','allowed_transition','*'),{'choices':transition_states_vocabulary})# Statedefstate_transitions_vocabulary(form,field):entity=form.edited_entityifentity.has_eid():wfeid=entity.state_of[0].eidelse:eids=form.linked_to.get(('state_of','subject'))ifnoteids:return[]wfeid=eids[0]return_wf_items_for_relation(form._cw,wfeid,'transition_of',field)_afs.tag_subject_of(('State','allowed_transition','*'),'main','attributes')_affk.tag_subject_of(('State','allowed_transition','*'),{'choices':state_transitions_vocabulary})# adaptaters ###################################################################classWorkflowIBreadCrumbsAdapter(ibreadcrumbs.IBreadCrumbsAdapter):__select__=is_instance('Workflow')# XXX what if workflow of multiple types?defparent_entity(self):returnself.entity.workflow_ofandself.entity.workflow_of[0]orNoneclassWorkflowItemIBreadCrumbsAdapter(ibreadcrumbs.IBreadCrumbsAdapter):__select__=is_instance('BaseTransition','State')defparent_entity(self):returnself.entity.workflowclassTransitionItemIBreadCrumbsAdapter(ibreadcrumbs.IBreadCrumbsAdapter):__select__=is_instance('SubWorkflowExitPoint')defparent_entity(self):returnself.entity.reverse_subworkflow_exit[0]classTrInfoIBreadCrumbsAdapter(ibreadcrumbs.IBreadCrumbsAdapter):__select__=is_instance('TrInfo')defparent_entity(self):returnself.entity.for_entity# workflow images ##############################################################classWorkflowDotPropsHandler(DotPropsHandler):defnode_properties(self,stateortransition):"""return default DOT drawing options for a state or transition"""props=super(WorkflowDotPropsHandler,self).node_properties(stateortransition)ifhasattr(stateortransition,'state_of'):props['shape']='box'props['style']='filled'ifstateortransition.reverse_initial_state:props['fillcolor']='#88CC88'else:props['shape']='ellipse'returnpropsclassWorkflowVisitor(object):def__init__(self,entity):self.entity=entitydefnodes(self):forstateinself.entity.reverse_state_of:state.complete()yieldstate.eid,statefortransitioninself.entity.reverse_transition_of:transition.complete()yieldtransition.eid,transitiondefedges(self):fortransitioninself.entity.reverse_transition_of:forincomingstateintransition.reverse_allowed_transition:yieldincomingstate.eid,transition.eid,transitionforoutgoingstateintransition.potential_destinations():yieldtransition.eid,outgoingstate.eid,transitionclassWorkflowGraphView(DotGraphView):__regid__='wfgraph'__select__=EntityView.__select__&one_line_rset()&is_instance('Workflow')defbuild_visitor(self,entity):returnWorkflowVisitor(entity)defbuild_dotpropshandler(self):returnWorkflowDotPropsHandler(self._cw)classTmpPngView(TmpFileViewMixin,EntityView):__metaclass__=class_deprecated__deprecation_warning__='[3.18] %(cls)s is deprecated'__regid__='tmppng'__select__=match_form_params('tmpfile')content_type='image/png'binary=Truedefcell_call(self,row=0,col=0):key=self._cw.form['tmpfile']ifkeynotinself._cw.session.data:# the temp file is gone and there's nothing# we can do about it# we should probably write it to some well# behaved place and serve itreturntmpfile=self._cw.session.data.pop(key)self.w(open(tmpfile,'rb').read())os.unlink(tmpfile)