web/views/workflow.py
author Sylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 20 Aug 2009 17:44:27 +0200
branch3.5
changeset 2920 64322aa83a1d
parent 2726 03e7a6efd960
child 2968 0e3460341023
child 3215 bf30ab5ba6ee
permissions -rw-r--r--
start a new workflow engine
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
     1
"""workflow views:
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
     2
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
     3
* IWorkflowable views and forms
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
     4
* workflow entities views (State, Transition, TrInfo)
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     5
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     6
:organization: Logilab
1977
606923dff11b big bunch of copyright / docstring update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1739
diff changeset
     7
:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
     8
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
1977
606923dff11b big bunch of copyright / docstring update
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 1739
diff changeset
     9
:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    10
"""
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    11
__docformat__ = "restructuredtext en"
1739
78b0819162a8 final rtag api
sylvain.thenault@logilab.fr
parents: 1721
diff changeset
    12
_ = unicode
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    13
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2005
diff changeset
    14
from logilab.mtconverter import xml_escape
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    15
from logilab.common.graph import escape, GraphGenerator, DotBackend
822
e3d8db01f3f5 test_views fixes
sylvain.thenault@logilab.fr
parents: 795
diff changeset
    16
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    17
from cubicweb import Unauthorized, view
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    18
from cubicweb.selectors import (implements, has_related_entities,
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    19
                                relation_possible, match_form_params)
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    20
from cubicweb.interfaces import IWorkflowable
2438
576f4d51f826 [cleanup] fix deprecation warnings
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2381
diff changeset
    21
from cubicweb.view import EntityView
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    22
from cubicweb.web import stdmsgs, action, component, form
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2726
diff changeset
    23
from cubicweb.web import formfields as ff, formwidgets as fwdgs
2005
e8032965f37a turn every form class into appobject. They should not be instantiated manually anymore.
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1995
diff changeset
    24
from cubicweb.web.views import TmpFileViewMixin, forms
1151
b20677336ee6 turn old __rtags__ the new way
sylvain.thenault@logilab.fr
parents: 1132
diff changeset
    25
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    26
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    27
# IWorkflowable views #########################################################
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    28
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2726
diff changeset
    29
class ChangeStateForm(forms.CompositeEntityForm):
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    30
    id = 'changestate'
1504
c6051f141807 register to catalog, delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
    31
1995
ec95eaa2b711 turn renderers into appobjects
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 1977
diff changeset
    32
    form_renderer_id = 'base' # don't want EntityFormRenderer
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2726
diff changeset
    33
    form_buttons = [fwdgs.SubmitButton(stdmsgs.YES),
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2726
diff changeset
    34
                    fwdgs.Button(stdmsgs.NO, cwaction='cancel')]
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    35
1504
c6051f141807 register to catalog, delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
    36
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2726
diff changeset
    37
class ChangeStateFormView(form.FormViewMixIn, view.EntityView):
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    38
    id = 'statuschange'
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    39
    title = _('status change')
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    40
    __select__ = implements(IWorkflowable) & match_form_params('treid')
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
    41
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    42
    def cell_call(self, row, col):
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    43
        entity = self.entity(row, col)
2680
66472d85d548 [R] use req.entity_from_eid
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2506
diff changeset
    44
        transition = self.req.entity_from_eid(self.req.form['treid'])
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    45
        dest = transition.destination()
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    46
        _ = self.req._
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2726
diff changeset
    47
        form = self.vreg['forms'].select('changestate', self.req, entity=entity,
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2726
diff changeset
    48
                                         redirect_path=self.redirectpath(entity))
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    49
        self.w(form.error_message())
1305
395ef7f2b95b cleanup, remove some unnecessary (sometime buggy) stuff
sylvain.thenault@logilab.fr
parents: 1304
diff changeset
    50
        self.w(u'<h4>%s %s</h4>\n' % (_(transition.name),
395ef7f2b95b cleanup, remove some unnecessary (sometime buggy) stuff
sylvain.thenault@logilab.fr
parents: 1304
diff changeset
    51
                                      entity.view('oneline')))
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    52
        msg = _('status will change from %(st1)s to %(st2)s') % {
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2726
diff changeset
    53
            'st1': _(entity.current_state.name),
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    54
            'st2': _(dest.name)}
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    55
        self.w(u'<p>%s</p>\n' % msg)
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2726
diff changeset
    56
        trinfo = self.vreg['etypes'].etype_class('TrInfo')(self.req)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2726
diff changeset
    57
        self.initialize_varmaker()
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2726
diff changeset
    58
        trinfo.eid = self.varmaker.next()
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2726
diff changeset
    59
        subform = self.vreg['forms'].select('edition', self.req, entity=trinfo,
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2726
diff changeset
    60
                                            mainform=False)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2726
diff changeset
    61
        subform.field_by_name('by_transition').widget = fwdgs.HiddenInput()
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2726
diff changeset
    62
        form.form_add_subform(subform)
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2726
diff changeset
    63
        self.w(form.form_render(wf_info_for=entity.eid,
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2726
diff changeset
    64
                                by_transition=transition.eid))
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    65
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    66
    def redirectpath(self, entity):
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    67
        return entity.rest_path()
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    68
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    69
2440
8e6b83e3b6b5 #343227: display the workflow history of any entity
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2438
diff changeset
    70
class WFHistoryView(EntityView):
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    71
    id = 'wfhistory'
2440
8e6b83e3b6b5 #343227: display the workflow history of any entity
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2438
diff changeset
    72
    __select__ = relation_possible('wf_info_for', role='object')
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    73
    title = _('Workflow history')
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    74
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    75
    def cell_call(self, row, col, view=None):
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    76
        _ = self.req._
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    77
        eid = self.rset[row][col]
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    78
        sel = 'Any FS,TS,WF,D'
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    79
        rql = ' ORDERBY D DESC WHERE WF wf_info_for X,'\
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    80
              'WF from_state FS, WF to_state TS, WF comment C,'\
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    81
              'WF creation_date D'
1398
5fe84a5f7035 rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents: 1318
diff changeset
    82
        if self.vreg.schema.eschema('CWUser').has_perm(self.req, 'read'):
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    83
            sel += ',U,C'
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    84
            rql += ', WF owned_by U?'
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    85
            displaycols = range(5)
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    86
            headers = (_('from_state'), _('to_state'), _('comment'), _('date'),
1504
c6051f141807 register to catalog, delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
    87
                       _('CWUser'))
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    88
        else:
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    89
            sel += ',C'
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    90
            displaycols = range(4)
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    91
            headers = (_('from_state'), _('to_state'), _('comment'), _('date'))
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    92
        rql = '%s %s, X eid %%(x)s' % (sel, rql)
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    93
        try:
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    94
            rset = self.req.execute(rql, {'x': eid}, 'x')
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    95
        except Unauthorized:
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    96
            return
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    97
        if rset:
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    98
            self.wview('table', rset, title=_(self.title), displayactions=False,
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
    99
                       displaycols=displaycols, headers=headers)
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   100
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   101
2440
8e6b83e3b6b5 #343227: display the workflow history of any entity
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2438
diff changeset
   102
class WFHistoryVComponent(component.EntityVComponent):
8e6b83e3b6b5 #343227: display the workflow history of any entity
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2438
diff changeset
   103
    """display the workflow history for entities supporting it"""
8e6b83e3b6b5 #343227: display the workflow history of any entity
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2438
diff changeset
   104
    id = 'wfhistory'
8e6b83e3b6b5 #343227: display the workflow history of any entity
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2438
diff changeset
   105
    __select__ = WFHistoryView.__select__ & component.EntityVComponent.__select__
8e6b83e3b6b5 #343227: display the workflow history of any entity
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2438
diff changeset
   106
    context = 'navcontentbottom'
8e6b83e3b6b5 #343227: display the workflow history of any entity
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2438
diff changeset
   107
    title = _('Workflow history')
8e6b83e3b6b5 #343227: display the workflow history of any entity
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2438
diff changeset
   108
8e6b83e3b6b5 #343227: display the workflow history of any entity
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2438
diff changeset
   109
    def cell_call(self, row, col, view=None):
8e6b83e3b6b5 #343227: display the workflow history of any entity
Nicolas Chauvat <nicolas.chauvat@logilab.fr>
parents: 2438
diff changeset
   110
        self.wview('wfhistory', self.rset, row=row, col=col, view=view)
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   111
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   112
# workflow entity types views #################################################
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   113
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   114
class CellView(view.EntityView):
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   115
    id = 'cell'
728
a95b284150d1 first pass to use __select__ instead of __selectors__
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 688
diff changeset
   116
    __select__ = implements('TrInfo')
1504
c6051f141807 register to catalog, delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   117
0
b97547f5f1fa Showtime !
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents:
diff changeset
   118
    def cell_call(self, row, col, cellvid=None):
2506
965d5e1557ed #343714: Enable workflow transition comments editing
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2487
diff changeset
   119
        self.w(self.entity(row, col).view('reledit', rtype='comment'))
795
63f4f81e19f1 restore appropriate in State's incontext view, moved it into wfentities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 728
diff changeset
   120
63f4f81e19f1 restore appropriate in State's incontext view, moved it into wfentities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 728
diff changeset
   121
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   122
class StateInContextView(view.EntityView):
795
63f4f81e19f1 restore appropriate in State's incontext view, moved it into wfentities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 728
diff changeset
   123
    """convenience trick, State's incontext view should not be clickable"""
63f4f81e19f1 restore appropriate in State's incontext view, moved it into wfentities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 728
diff changeset
   124
    id = 'incontext'
63f4f81e19f1 restore appropriate in State's incontext view, moved it into wfentities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 728
diff changeset
   125
    __select__ = implements('State')
1504
c6051f141807 register to catalog, delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   126
795
63f4f81e19f1 restore appropriate in State's incontext view, moved it into wfentities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 728
diff changeset
   127
    def cell_call(self, row, col):
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2005
diff changeset
   128
        self.w(xml_escape(self.view('textincontext', self.rset,
795
63f4f81e19f1 restore appropriate in State's incontext view, moved it into wfentities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 728
diff changeset
   129
                                     row=row, col=col)))
63f4f81e19f1 restore appropriate in State's incontext view, moved it into wfentities
Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
parents: 728
diff changeset
   130
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   131
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   132
# workflow images #############################################################
1504
c6051f141807 register to catalog, delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   133
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   134
class ViewWorkflowAction(action.Action):
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   135
    id = 'workflow'
2920
64322aa83a1d start a new workflow engine
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2726
diff changeset
   136
    __select__ = implements('CWEType') & has_related_entities('workflow_of', 'object')
1504
c6051f141807 register to catalog, delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   137
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   138
    category = 'mainactions'
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   139
    title = _('view workflow')
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   140
    def url(self):
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   141
        entity = self.rset.get_entity(self.row or 0, self.col or 0)
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   142
        return entity.absolute_url(vid='workflow')
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   143
1504
c6051f141807 register to catalog, delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   144
1398
5fe84a5f7035 rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents: 1318
diff changeset
   145
class CWETypeWorkflowView(view.EntityView):
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   146
    id = 'workflow'
1398
5fe84a5f7035 rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents: 1318
diff changeset
   147
    __select__ = implements('CWEType')
1504
c6051f141807 register to catalog, delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   148
    cache_max_age = 60*60*2 # stay in http cache for 2 hours by default
c6051f141807 register to catalog, delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   149
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   150
    def cell_call(self, row, col, **kwargs):
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   151
        entity = self.entity(row, col)
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   152
        self.w(u'<h1>%s</h1>' % (self.req._('workflow for %s')
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   153
                                 % display_name(self.req, entity.name)))
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   154
        self.w(u'<img src="%s" alt="%s"/>' % (
2312
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2005
diff changeset
   155
            xml_escape(entity.absolute_url(vid='ewfgraph')),
af4d8f75c5db use xml_escape
Sylvain Thénault <sylvain.thenault@logilab.fr>
parents: 2005
diff changeset
   156
            xml_escape(self.req._('graphical workflow for %s') % entity.name)))
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   157
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   158
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   159
class WorkflowDotPropsHandler(object):
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   160
    def __init__(self, req):
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   161
        self._ = req._
1504
c6051f141807 register to catalog, delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   162
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   163
    def node_properties(self, stateortransition):
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   164
        """return default DOT drawing options for a state or transition"""
1504
c6051f141807 register to catalog, delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   165
        props = {'label': stateortransition.name,
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   166
                 'fontname': 'Courier'}
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   167
        if hasattr(stateortransition, 'state_of'):
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   168
            props['shape'] = 'box'
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   169
            props['style'] = 'filled'
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   170
            if stateortransition.reverse_initial_state:
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   171
                props['color'] = '#88CC88'
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   172
        else:
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   173
            props['shape'] = 'ellipse'
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   174
            descr = []
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   175
            tr = stateortransition
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   176
            if tr.require_group:
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   177
                descr.append('%s %s'% (
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   178
                    self._('groups:'),
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   179
                    ','.join(g.name for g in tr.require_group)))
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   180
            if tr.condition:
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   181
                descr.append('%s %s'% (self._('condition:'), tr.condition))
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   182
            if descr:
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   183
                props['label'] += escape('\n'.join(descr))
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   184
        return props
1504
c6051f141807 register to catalog, delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   185
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   186
    def edge_properties(self, transition, fromstate, tostate):
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   187
        return {'label': '', 'dir': 'forward',
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   188
                'color': 'black', 'style': 'filled'}
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   189
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   190
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   191
class WorkflowVisitor:
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   192
    def __init__(self, entity):
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   193
        self.entity = entity
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   194
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   195
    def nodes(self):
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   196
        for state in self.entity.reverse_state_of:
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   197
            state.complete()
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   198
            yield state.eid, state
1504
c6051f141807 register to catalog, delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   199
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   200
        for transition in self.entity.reverse_transition_of:
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   201
            transition.complete()
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   202
            yield transition.eid, transition
1504
c6051f141807 register to catalog, delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   203
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   204
    def edges(self):
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   205
        for transition in self.entity.reverse_transition_of:
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   206
            for incomingstate in transition.reverse_allowed_transition:
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   207
                yield incomingstate.eid, transition.eid, transition
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   208
            yield transition.eid, transition.destination().eid, transition
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   209
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   210
1398
5fe84a5f7035 rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents: 1318
diff changeset
   211
class CWETypeWorkflowImageView(TmpFileViewMixin, view.EntityView):
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   212
    id = 'ewfgraph'
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   213
    content_type = 'image/png'
1398
5fe84a5f7035 rename internal entity types to have CW prefix instead of E
sylvain.thenault@logilab.fr
parents: 1318
diff changeset
   214
    __select__ = implements('CWEType')
1504
c6051f141807 register to catalog, delete-trailing-whitespaces
sylvain.thenault@logilab.fr
parents: 1398
diff changeset
   215
1091
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   216
    def _generate(self, tmpfile):
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   217
        """display schema information for an entity"""
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   218
        entity = self.entity(self.row, self.col)
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   219
        visitor = WorkflowVisitor(entity)
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   220
        prophdlr = WorkflowDotPropsHandler(self.req)
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   221
        generator = GraphGenerator(DotBackend('workflow', 'LR',
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   222
                                              ratio='compress', size='30,12'))
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   223
        return generator.generate(visitor, prophdlr, tmpfile)
b5e253c0dd13 a bit of reorganisation inside web/views:
sylvain.thenault@logilab.fr
parents: 984
diff changeset
   224