web/views/workflow.py
branchstable
changeset 3867 06ac8f00a99f
parent 3805 ad0b38e1a4eb
child 3868 161a5f7d1190
equal deleted inserted replaced
3866:2783c166ad1a 3867:06ac8f00a99f
    14 from logilab.mtconverter import xml_escape
    14 from logilab.mtconverter import xml_escape
    15 from logilab.common.graph import escape, GraphGenerator, DotBackend
    15 from logilab.common.graph import escape, GraphGenerator, DotBackend
    16 
    16 
    17 from cubicweb import Unauthorized, view
    17 from cubicweb import Unauthorized, view
    18 from cubicweb.selectors import (implements, has_related_entities, one_line_rset,
    18 from cubicweb.selectors import (implements, has_related_entities, one_line_rset,
    19                                 relation_possible, match_form_params)
    19                                 relation_possible, match_form_params,
       
    20                                 entity_implements)
    20 from cubicweb.interfaces import IWorkflowable
    21 from cubicweb.interfaces import IWorkflowable
    21 from cubicweb.view import EntityView
    22 from cubicweb.view import EntityView
    22 from cubicweb.schema import display_name
    23 from cubicweb.schema import display_name
    23 from cubicweb.web import uicfg, stdmsgs, action, component, form, action
    24 from cubicweb.web import uicfg, stdmsgs, action, component, form, action
    24 from cubicweb.web import formfields as ff, formwidgets as fwdgs
    25 from cubicweb.web import formfields as ff, formwidgets as fwdgs
    25 from cubicweb.web.views import TmpFileViewMixin, forms, primary
    26 from cubicweb.web.views import TmpFileViewMixin, forms, primary, autoform
    26 
       
    27 _pvs = uicfg.primaryview_section
       
    28 _pvs.tag_subject_of(('Workflow', 'initial_state', '*'), 'hidden')
       
    29 _pvs.tag_object_of(('*', 'state_of', 'Workflow'), 'hidden')
       
    30 _pvs.tag_object_of(('*', 'transition_of', 'Workflow'), 'hidden')
       
    31 
       
    32 _abaa = uicfg.actionbox_appearsin_addmenu
       
    33 _abaa.tag_subject_of(('BaseTransition', 'condition', 'RQLExpression'), False)
       
    34 _abaa.tag_subject_of(('State', 'allowed_transition', 'BaseTransition'), False)
       
    35 _abaa.tag_object_of(('SubWorkflowExitPoint', 'destination_state', 'State'),
       
    36                     False)
       
    37 _abaa.tag_object_of(('State', 'state_of', 'Workflow'), True)
       
    38 _abaa.tag_object_of(('Transition', 'transition_of', 'Workflow'), True)
       
    39 _abaa.tag_object_of(('WorkflowTransition', 'transition_of', 'Workflow'), True)
       
    40 
       
    41 _afs = uicfg.autoform_section
       
    42 _afs.tag_subject_of(('TrInfo', 'to_state', '*'), 'generated')
       
    43 _afs.tag_subject_of(('TrInfo', 'from_state', '*'), 'generated')
       
    44 _afs.tag_object_of(('State', 'allowed_transition', '*'), 'primary')
       
    45 
    27 
    46 
    28 
    47 # IWorkflowable views #########################################################
    29 # IWorkflowable views #########################################################
    48 
    30 
    49 class ChangeStateForm(forms.CompositeEntityForm):
    31 class ChangeStateForm(forms.CompositeEntityForm):
   168             yield self.build_action(self.req._('view history'), wfurl)
   150             yield self.build_action(self.req._('view history'), wfurl)
   169 
   151 
   170 
   152 
   171 # workflow entity types views ##################################################
   153 # workflow entity types views ##################################################
   172 
   154 
   173 class CellView(view.EntityView):
   155 _pvs = uicfg.primaryview_section
   174     id = 'cell'
   156 _pvs.tag_subject_of(('Workflow', 'initial_state', '*'), 'hidden')
   175     __select__ = implements('TrInfo')
   157 _pvs.tag_object_of(('*', 'state_of', 'Workflow'), 'hidden')
   176 
   158 _pvs.tag_object_of(('*', 'transition_of', 'Workflow'), 'hidden')
   177     def cell_call(self, row, col, cellvid=None):
   159 
   178         self.w(self.rset.get_entity(row, col).view('reledit', rtype='comment'))
   160 _abaa = uicfg.actionbox_appearsin_addmenu
   179 
   161 _abaa.tag_subject_of(('BaseTransition', 'condition', 'RQLExpression'), False)
   180 
   162 _abaa.tag_subject_of(('State', 'allowed_transition', 'BaseTransition'), False)
   181 class StateInContextView(view.EntityView):
   163 _abaa.tag_object_of(('SubWorkflowExitPoint', 'destination_state', 'State'),
   182     """convenience trick, State's incontext view should not be clickable"""
   164                     False)
   183     id = 'incontext'
   165 _abaa.tag_object_of(('State', 'state_of', 'Workflow'), True)
   184     __select__ = implements('State')
   166 _abaa.tag_object_of(('BaseTransition', 'transition_of', 'Workflow'), False)
   185 
   167 _abaa.tag_object_of(('Transition', 'transition_of', 'Workflow'), True)
   186     def cell_call(self, row, col):
   168 _abaa.tag_object_of(('WorkflowTransition', 'transition_of', 'Workflow'), True)
   187         self.w(xml_escape(self.view('textincontext', self.rset,
       
   188                                      row=row, col=col)))
       
   189 
       
   190 
   169 
   191 class WorkflowPrimaryView(primary.PrimaryView):
   170 class WorkflowPrimaryView(primary.PrimaryView):
   192     __select__ = implements('Workflow')
   171     __select__ = implements('Workflow')
   193 
   172 
   194     def render_entity_attributes(self, entity):
   173     def render_entity_attributes(self, entity):
   195         self.w(entity.view('reledit', rtype='description'))
   174         self.w(entity.view('reledit', rtype='description'))
   196         self.w(u'<img src="%s" alt="%s"/>' % (
   175         self.w(u'<img src="%s" alt="%s"/>' % (
   197             xml_escape(entity.absolute_url(vid='wfgraph')),
   176             xml_escape(entity.absolute_url(vid='wfgraph')),
   198             xml_escape(self.req._('graphical workflow for %s') % entity.name)))
   177             xml_escape(self.req._('graphical workflow for %s') % entity.name)))
       
   178 
       
   179 
       
   180 class CellView(view.EntityView):
       
   181     id = 'cell'
       
   182     __select__ = implements('TrInfo')
       
   183 
       
   184     def cell_call(self, row, col, cellvid=None):
       
   185         self.w(self.rset.get_entity(row, col).view('reledit', rtype='comment'))
       
   186 
       
   187 
       
   188 class StateInContextView(view.EntityView):
       
   189     """convenience trick, State's incontext view should not be clickable"""
       
   190     id = 'incontext'
       
   191     __select__ = implements('State')
       
   192 
       
   193     def cell_call(self, row, col):
       
   194         self.w(xml_escape(self.view('textincontext', self.rset,
       
   195                                      row=row, col=col)))
       
   196 
       
   197 
       
   198 # workflow entity types edition ################################################
       
   199 
       
   200 _afs = uicfg.autoform_section
       
   201 _afs.tag_subject_of(('TrInfo', 'to_state', '*'), 'generated')
       
   202 _afs.tag_subject_of(('TrInfo', 'from_state', '*'), 'generated')
       
   203 _afs.tag_object_of(('State', 'allowed_transition', '*'), 'primary')
       
   204 _afs.tag_subject_of(('State', 'allowed_transition', '*'), 'primary')
       
   205 
       
   206 def workflow_items_for_relation(req, wfeid, wfrelation, targetrelation):
       
   207     wf = req.entity_from_eid(wfeid)
       
   208     rschema = req.vreg.schema[targetrelation]
       
   209     return sorted((e.view('combobox'), e.eid)
       
   210                   for e in getattr(wf, 'reverse_%s' % wfrelation)
       
   211                   if rschema.has_perm(req, 'add', toeid=e.eid))
       
   212 
       
   213 
       
   214 class TransitionEditionForm(autoform.AutomaticEntityForm):
       
   215     __select__ = entity_implements('Transition')
       
   216 
       
   217     def workflow_transition_for_relation(self, targetrelation):
       
   218         eids = self.edited_entity.linked_to('transition_of', 'subject')
       
   219         if eids:
       
   220             return workflow_items_for_relation(self.req, eids[0], 'state_of',
       
   221                                                targetrelation)
       
   222         return []
       
   223 
       
   224     def subject_destination_state_vocabulary(self, rtype, limit=None):
       
   225         if not self.edited_entity.has_eid():
       
   226             return self.workflow_states_for_relation('destination_state')
       
   227         return self.subject_relation_vocabulary(rtype, limit)
       
   228 
       
   229     def object_allowed_transition_vocabulary(self, rtype, limit=None):
       
   230         if not self.edited_entity.has_eid():
       
   231             return self.workflow_states_for_relation('allowed_transition')
       
   232         return self.subject_relation_vocabulary(rtype, limit)
       
   233 
       
   234 
       
   235 class StateEditionForm(autoform.AutomaticEntityForm):
       
   236     __select__ = entity_implements('State')
       
   237 
       
   238     def subject_allowed_transition_vocabulary(self, rtype, limit=None):
       
   239         if not self.edited_entity.has_eid():
       
   240             eids = self.edited_entity.linked_to('transition_of', 'subject')
       
   241             if eids:
       
   242                 return workflow_items_for_relation(self.req, eids[0], 'transition_of',
       
   243                                                    'allowed_transition')
       
   244         return []
   199 
   245 
   200 
   246 
   201 # workflow images ##############################################################
   247 # workflow images ##############################################################
   202 
   248 
   203 class WorkflowDotPropsHandler(object):
   249 class WorkflowDotPropsHandler(object):