web/views/workflow.py
changeset 5556 9ab2b4c74baf
parent 5426 0d4853a6e5ee
child 5685 17883ced01f8
equal deleted inserted replaced
5555:a64f48dd5fe4 5556:9ab2b4c74baf
    31 from logilab.common.graph import escape, GraphGenerator, DotBackend
    31 from logilab.common.graph import escape, GraphGenerator, DotBackend
    32 
    32 
    33 from cubicweb import Unauthorized, view
    33 from cubicweb import Unauthorized, view
    34 from cubicweb.selectors import (implements, has_related_entities, one_line_rset,
    34 from cubicweb.selectors import (implements, has_related_entities, one_line_rset,
    35                                 relation_possible, match_form_params,
    35                                 relation_possible, match_form_params,
    36                                 implements, score_entity)
    36                                 implements, score_entity, adaptable)
    37 from cubicweb.interfaces import IWorkflowable
       
    38 from cubicweb.view import EntityView
    37 from cubicweb.view import EntityView
    39 from cubicweb.schema import display_name
    38 from cubicweb.schema import display_name
    40 from cubicweb.web import uicfg, stdmsgs, action, component, form, action
    39 from cubicweb.web import uicfg, stdmsgs, action, component, form, action
    41 from cubicweb.web import formfields as ff, formwidgets as fwdgs
    40 from cubicweb.web import formfields as ff, formwidgets as fwdgs
    42 from cubicweb.web.views import TmpFileViewMixin, forms, primary, autoform
    41 from cubicweb.web.views import TmpFileViewMixin
       
    42 from cubicweb.web.views import forms, primary, autoform, ibreadcrumbs
    43 from cubicweb.web.views.tabs import TabbedPrimaryView, PrimaryTab
    43 from cubicweb.web.views.tabs import TabbedPrimaryView, PrimaryTab
    44 
    44 
    45 _pvs = uicfg.primaryview_section
    45 _pvs = uicfg.primaryview_section
    46 _pvs.tag_subject_of(('Workflow', 'initial_state', '*'), 'hidden')
    46 _pvs.tag_subject_of(('Workflow', 'initial_state', '*'), 'hidden')
    47 _pvs.tag_object_of(('*', 'state_of', 'Workflow'), 'hidden')
    47 _pvs.tag_object_of(('*', 'state_of', 'Workflow'), 'hidden')
    87 
    87 
    88 
    88 
    89 class ChangeStateFormView(form.FormViewMixIn, view.EntityView):
    89 class ChangeStateFormView(form.FormViewMixIn, view.EntityView):
    90     __regid__ = 'statuschange'
    90     __regid__ = 'statuschange'
    91     title = _('status change')
    91     title = _('status change')
    92     __select__ = (one_line_rset() & implements(IWorkflowable)
    92     __select__ = (one_line_rset()
    93                   & match_form_params('treid'))
    93                   & match_form_params('treid')
       
    94                   & adaptable('IWorkflowable'))
    94 
    95 
    95     def cell_call(self, row, col):
    96     def cell_call(self, row, col):
    96         entity = self.cw_rset.get_entity(row, col)
    97         entity = self.cw_rset.get_entity(row, col)
    97         transition = self._cw.entity_from_eid(self._cw.form['treid'])
    98         transition = self._cw.entity_from_eid(self._cw.form['treid'])
    98         form = self.get_form(entity, transition)
    99         form = self.get_form(entity, transition)
    99         self.w(u'<h4>%s %s</h4>\n' % (self._cw._(transition.name),
   100         self.w(u'<h4>%s %s</h4>\n' % (self._cw._(transition.name),
   100                                       entity.view('oneline')))
   101                                       entity.view('oneline')))
   101         msg = self._cw._('status will change from %(st1)s to %(st2)s') % {
   102         msg = self._cw._('status will change from %(st1)s to %(st2)s') % {
   102             'st1': entity.printable_state,
   103             'st1': entity.cw_adapt_to('IWorkflowable').printable_state,
   103             'st2': self._cw._(transition.destination(entity).name)}
   104             'st2': self._cw._(transition.destination(entity).name)}
   104         self.w(u'<p>%s</p>\n' % msg)
   105         self.w(u'<p>%s</p>\n' % msg)
   105         self.w(form.render())
   106         self.w(form.render())
   106 
   107 
   107     def redirectpath(self, entity):
   108     def redirectpath(self, entity):
   126 
   127 
   127 
   128 
   128 class WFHistoryView(EntityView):
   129 class WFHistoryView(EntityView):
   129     __regid__ = 'wfhistory'
   130     __regid__ = 'wfhistory'
   130     __select__ = relation_possible('wf_info_for', role='object') & \
   131     __select__ = relation_possible('wf_info_for', role='object') & \
   131                  score_entity(lambda x: x.workflow_history)
   132                  score_entity(lambda x: x.cw_adapt_to('IWorkflowable').workflow_history)
   132 
   133 
   133     title = _('Workflow history')
   134     title = _('Workflow history')
   134 
   135 
   135     def cell_call(self, row, col, view=None):
   136     def cell_call(self, row, col, view=None):
   136         _ = self._cw._
   137         _ = self._cw._
   181     submenu = _('workflow')
   182     submenu = _('workflow')
   182     order = 10
   183     order = 10
   183 
   184 
   184     def fill_menu(self, box, menu):
   185     def fill_menu(self, box, menu):
   185         entity = self.cw_rset.get_entity(self.cw_row or 0, self.cw_col or 0)
   186         entity = self.cw_rset.get_entity(self.cw_row or 0, self.cw_col or 0)
   186         menu.label = u'%s: %s' % (self._cw._('state'), entity.printable_state)
   187         menu.label = u'%s: %s' % (self._cw._('state'),
       
   188                                   entity.cw_adapt_to('IWorkflowable').printable_state)
   187         menu.append_anyway = True
   189         menu.append_anyway = True
   188         super(WorkflowActions, self).fill_menu(box, menu)
   190         super(WorkflowActions, self).fill_menu(box, menu)
   189 
   191 
   190     def actual_actions(self):
   192     def actual_actions(self):
   191         entity = self.cw_rset.get_entity(self.cw_row or 0, self.cw_col or 0)
   193         entity = self.cw_rset.get_entity(self.cw_row or 0, self.cw_col or 0)
       
   194         iworkflowable = entity.cw_adapt_to('IWorkflowable')
   192         hastr = False
   195         hastr = False
   193         for tr in entity.possible_transitions():
   196         for tr in iworkflowable.possible_transitions():
   194             url = entity.absolute_url(vid='statuschange', treid=tr.eid)
   197             url = entity.absolute_url(vid='statuschange', treid=tr.eid)
   195             yield self.build_action(self._cw._(tr.name), url)
   198             yield self.build_action(self._cw._(tr.name), url)
   196             hastr = True
   199             hastr = True
   197         # don't propose to see wf if user can't pass any transition
   200         # don't propose to see wf if user can't pass any transition
   198         if hastr:
   201         if hastr:
   199             wfurl = entity.current_workflow.absolute_url()
   202             wfurl = iworkflowable.current_workflow.absolute_url()
   200             yield self.build_action(self._cw._('view workflow'), wfurl)
   203             yield self.build_action(self._cw._('view workflow'), wfurl)
   201         if entity.workflow_history:
   204         if iworkflowable.workflow_history:
   202             wfurl = entity.absolute_url(vid='wfhistory')
   205             wfurl = entity.absolute_url(vid='wfhistory')
   203             yield self.build_action(self._cw._('view history'), wfurl)
   206             yield self.build_action(self._cw._('view history'), wfurl)
   204 
   207 
   205 
   208 
   206 # workflow entity types views ##################################################
   209 # workflow entity types views ##################################################
   343             eids = self.edited_entity.linked_to('state_of', 'subject')
   346             eids = self.edited_entity.linked_to('state_of', 'subject')
   344             if eids:
   347             if eids:
   345                 return workflow_items_for_relation(self._cw, eids[0], 'transition_of',
   348                 return workflow_items_for_relation(self._cw, eids[0], 'transition_of',
   346                                                    'allowed_transition')
   349                                                    'allowed_transition')
   347         return []
   350         return []
       
   351 
       
   352 class WorkflowIBreadCrumbsAdapter(ibreadcrumbs.IBreadCrumbsAdapter):
       
   353     __select__ = implements('Workflow')
       
   354     # XXX what if workflow of multiple types?
       
   355     def parent_entity(self):
       
   356         return self.entity.workflow_of and self.entity.workflow_of[0] or None
       
   357 
       
   358 class WorkflowItemIBreadCrumbsAdapter(ibreadcrumbs.IBreadCrumbsAdapter):
       
   359     __select__ = implements('BaseTransition', 'State')
       
   360     def parent_entity(self):
       
   361         return self.entity.workflow
       
   362 
       
   363 class TransitionItemIBreadCrumbsAdapter(ibreadcrumbs.IBreadCrumbsAdapter):
       
   364     __select__ = implements('SubWorkflowExitPoint')
       
   365     def parent_entity(self):
       
   366         return self.entity.reverse_subworkflow_exit[0]
       
   367 
       
   368 class TrInfoIBreadCrumbsAdapter(ibreadcrumbs.IBreadCrumbsAdapter):
       
   369     __select__ = implements('TrInfo')
       
   370     def parent_entity(self):
       
   371         return self.entity.for_entity
   348 
   372 
   349 
   373 
   350 # workflow images ##############################################################
   374 # workflow images ##############################################################
   351 
   375 
   352 class WorkflowDotPropsHandler(object):
   376 class WorkflowDotPropsHandler(object):