0001-workflows-add-possibility-to-jump-to-previous-status.patch
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 |
- |