Projet

Général

Profil

0001-workflows-add-possibility-to-jump-to-previous-status.patch

Frédéric Péters, 25 mai 2017 10:48

Télécharger (10,1 ko)

Voir les différences:

Subject: [PATCH] workflows: add possibility to jump to previous status
 (#16473)

 tests/test_backoffice_pages.py | 91 ++++++++++++++++++++++++++++++++++++++++++
 wcs/admin/workflows.py         |  3 +-
 wcs/formdata.py                | 15 +++++++
 wcs/wf/jump.py                 |  2 +-
 wcs/workflows.py               | 45 +++++++++++++--------
 5 files changed, 137 insertions(+), 19 deletions(-)
tests/test_backoffice_pages.py
7 7
import StringIO
8 8
import time
9 9
import hashlib
10
import random
10 11

  
11 12
import pytest
12 13
from webtest import Upload
......
3153 3154
    resp = app.get(formdata.get_url(backoffice=True))
3154 3155
    assert 'Backoffice Data' in resp.body
3155 3156
    assert 'Not set' in resp.body
3157

  
3158
def test_workflow_jump_previous(pub):
3159
    user = create_user(pub)
3160
    create_environment(pub)
3161

  
3162
    wf = Workflow(name='jump around')
3163
    #       North
3164
    #     /      \
3165
    # West <----> East
3166
    #   |          |
3167
    #   |         autojump
3168
    #    |         |
3169
    #     \       /
3170
    #       South
3171

  
3172
    st1 = wf.add_status('North')
3173
    st1.id = 'north'
3174
    st2 = wf.add_status('West')
3175
    st2.id = 'west'
3176
    st3 = wf.add_status('East')
3177
    st3.id = 'east'
3178
    st4 = wf.add_status('Autojump')
3179
    st4.id = 'autojump'
3180
    st5 = wf.add_status('South')
3181
    st5.id = 'south'
3182

  
3183
    button_by_id = {}
3184

  
3185
    def add_jump(label, src, dst_id):
3186
        jump = ChoiceWorkflowStatusItem()
3187
        jump.id = str(random.random())
3188
        jump.label = label
3189
        jump.by = ['logged-users']
3190
        jump.status = dst_id
3191
        src.items.append(jump)
3192
        jump.parent = src
3193
        button_by_id[label] = 'button%s' % jump.id
3194

  
3195
    add_jump('Go West', st1, st2.id)
3196
    add_jump('Go East', st1, st3.id)
3197
    add_jump('Go South', st2, st5.id)
3198
    add_jump('Go Autojump', st3, st4.id)
3199
    add_jump('Go Back', st5, '_previous')
3200

  
3201
    add_jump('Jump West', st3, st2.id)
3202
    add_jump('Jump East', st2, st3.id)
3203

  
3204
    jump = JumpWorkflowStatusItem()
3205
    jump.id = '_auto-jump'
3206
    jump.status = st5.id
3207
    st4.items.append(jump)
3208
    jump.parent = st4
3209

  
3210
    wf.store()
3211

  
3212
    formdef = FormDef.get_by_urlname('form-title')
3213
    formdef.data_class().wipe()
3214
    formdef.workflow = wf
3215
    formdef.store()
3216

  
3217
    formdata = formdef.data_class()()
3218
    formdata.data = {}
3219
    formdata.just_created()
3220
    formdata.store()
3221

  
3222
    app = login(get_app(pub))
3223
    resp = app.get('/backoffice/management/form-title/%s/' % formdata.id)
3224

  
3225
    # jump around using buttons
3226
    resp = resp.form.submit(button_by_id['Go West']).follow()
3227
    assert formdef.data_class().get(formdata.id).status == 'wf-%s' % st2.id
3228
    resp = resp.form.submit(button_by_id['Go South']).follow()
3229
    assert formdef.data_class().get(formdata.id).status == 'wf-%s' % st5.id
3230
    resp = resp.form.submit(button_by_id['Go Back']).follow()
3231
    assert formdef.data_class().get(formdata.id).status == 'wf-%s' % st2.id
3232
    resp = resp.form.submit(button_by_id['Go South']).follow()
3233
    assert formdef.data_class().get(formdata.id).status == 'wf-%s' % st5.id
3234
    resp = resp.form.submit(button_by_id['Go Back']).follow()
3235
    assert formdef.data_class().get(formdata.id).status == 'wf-%s' % st2.id
3236
    resp = resp.form.submit(button_by_id['Jump East']).follow()
3237
    assert formdef.data_class().get(formdata.id).status == 'wf-%s' % st3.id
3238
    resp = resp.form.submit(button_by_id['Go Autojump']).follow()
3239
    assert formdef.data_class().get(formdata.id).status == 'wf-%s' % st5.id
3240
    resp = resp.form.submit(button_by_id['Go Back']).follow()
3241
    assert formdef.data_class().get(formdata.id).status == 'wf-%s' % st3.id
3242

  
3243
    # and do a last jump using the API
3244
    formdata = formdef.data_class().get(formdata.id)
3245
    formdata.jump_status('_previous')
3246
    assert formdata.status == 'wf-%s' % st5.id
wcs/admin/workflows.py
152 152
    for status in workflow.possible_status:
153 153
        i = status.id
154 154
        for item in status.items:
155
            next_status_ids = [x.id for x in item.get_target_status() if x.id != status.id]
155
            next_status_ids = [x.id for x in item.get_target_status()
156
                               if x.id and x.id != status.id]
156 157
            if not next_status_ids:
157 158
                next_status_ids = [status.id]
158 159
            done = {}
wcs/formdata.py
452 452
            return None
453 453
        return wf_status.handle_form(form, self, user)
454 454

  
455
    def get_previous_status(self):
456
        for evolution in reversed(self.evolution[:-1]):
457
            status_id = evolution.status
458
            if not status_id:
459
                continue
460
            status = self.formdef.workflow.get_status(status_id[3:])
461
            if not status.is_waitpoint():
462
                continue
463
            return status
464
        return None
465

  
455 466
    def jump_status(self, status_id):
467
        if status_id == '_previous':
468
            previous_status = self.get_previous_status()
469
            assert previous_status, 'failed to compute previous status'
470
            status_id = previous_status.id
456 471
        evo = Evolution()
457 472
        evo.time = time.localtime()
458 473
        evo.status = 'wf-%s' % status_id
wcs/wf/jump.py
190 190
            return
191 191

  
192 192
        if self.must_jump(formdata):
193
            wf_status = self.get_target_status()
193
            wf_status = self.get_target_status(formdata)
194 194
            if wf_status:
195 195
                formdata.status = 'wf-%s' % wf_status[0].id
196 196

  
wcs/workflows.py
421 421
        # a waitpoint status is a status waiting for an event (be it user
422 422
        # interaction or something else), but can also be an endpoint (where
423 423
        # the user would wait, infinitely).
424
        waitpoint_status = []
425
        for status in self.possible_status:
426
            waitpoint = False
427
            endpoint = True
428
            if status.forced_endpoint:
429
                endpoint = True
430
            else:
431
                for item in status.items:
432
                    endpoint = item.endpoint and endpoint
433
                    waitpoint = item.waitpoint or waitpoint
434
            if endpoint or waitpoint:
435
                waitpoint_status.append(status)
436
        return waitpoint_status
424
        return [x for x in self.possible_status if x.is_waitpoint()]
437 425

  
438 426
    def get_endpoint_status(self):
439 427
        not_endpoint_status = self.get_not_endpoint_status()
......
1411 1399
                return True
1412 1400
        return False
1413 1401

  
1402
    def is_waitpoint(self):
1403
        waitpoint = False
1404
        endpoint = True
1405
        if self.forced_endpoint:
1406
            endpoint = True
1407
        else:
1408
            for item in self.items:
1409
                endpoint = item.endpoint and endpoint
1410
                waitpoint = item.waitpoint or waitpoint
1411
        return bool(endpoint or waitpoint)
1412

  
1414 1413
    def __getstate__(self):
1415 1414
        odict = self.__dict__.copy()
1416 1415
        if odict.has_key('parent'):
......
1634 1633
    def get_substitution_variables(self, formdata):
1635 1634
        return {}
1636 1635

  
1637
    def get_target_status(self):
1636
    def get_target_status(self, formdata=None):
1638 1637
        """Returns a list of status this item can lead to."""
1639 1638
        if not getattr(self, 'status', None):
1640 1639
            return []
1641 1640

  
1641
        if self.status == '_previous':
1642
            if formdata is None:
1643
                # must be in a formdata to compute destination, just give a
1644
                # fake status for presentation purpose
1645
                return [WorkflowStatus(_('Previous Status'))]
1646
            previous_status = formdata.get_previous_status()
1647
            if previous_status:
1648
                return [previous_status]
1649
            return []
1650

  
1642 1651
        try:
1643 1652
            return [x for x in self.parent.parent.possible_status if x.id == self.status]
1644 1653
        except IndexError:
......
1689 1698
    def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
1690 1699
        if 'status' in parameters:
1691 1700
            form.add(SingleSelectWidget, '%sstatus' % prefix, title = _('Status'), value = self.status,
1692
                options = [(None, '---')] + [(x.id, x.name) for x in self.parent.parent.possible_status])
1701
                options = [(None, '---')] +
1702
                          [(x.id, x.name) for x in self.parent.parent.possible_status] +
1703
                          [('_previous', _('Previous Status'))])
1693 1704

  
1694 1705
    def get_parameters(self):
1695 1706
        return ('status',)
......
1892 1903

  
1893 1904
    def submit_form(self, form, formdata, user, evo):
1894 1905
        if form.get_submit() == 'button%s' % self.id:
1895
            wf_status = self.get_target_status()
1906
            wf_status = self.get_target_status(formdata)
1896 1907
            if wf_status:
1897 1908
                evo.status = 'wf-%s' % wf_status[0].id
1898 1909
                form.clear_errors()
......
1940 1951

  
1941 1952
    def submit_form(self, form, formdata, user, evo):
1942 1953
        if form.is_submitted() and not form.has_errors():
1943
            wf_status = self.get_target_status()
1954
            wf_status = self.get_target_status(formdata)
1944 1955
            if wf_status:
1945 1956
                evo.status = 'wf-%s' % wf_status[0].id
1946 1957

  
1947
-