0001-workflows-copy-action-from-one-status-to-another-578.patch
tests/admin_pages/test_workflow.py | ||
---|---|---|
470 | 470 |
assert Workflow.get(workflow.id).possible_status[2].id == status1_id |
471 | 471 | |
472 | 472 | |
473 |
def test_workflows_copy_status_item(pub): |
|
474 |
create_superuser(pub) |
|
475 |
Workflow.wipe() |
|
476 |
workflow = Workflow(name='foo') |
|
477 |
st1 = workflow.add_status('Status1') |
|
478 |
st2 = workflow.add_status('Status2') |
|
479 |
st3 = workflow.add_status('Status3') |
|
480 | ||
481 |
item = SendmailWorkflowStatusItem() |
|
482 |
item.to = ['_submitter'] |
|
483 |
item.subject = 'bla' |
|
484 |
st1.items.append(item) |
|
485 |
item.parent = st1 |
|
486 |
workflow.store() |
|
487 | ||
488 |
create_superuser(pub) |
|
489 |
app = login(get_app(pub)) |
|
490 | ||
491 |
resp = app.get('/backoffice/workflows/%s/status/%s/' % (workflow.id, st1.id)) |
|
492 |
resp = resp.click('Copy') |
|
493 |
resp.form['status'] = 'Status3' |
|
494 |
resp = resp.form.submit() |
|
495 |
assert resp.location == 'http://example.net/backoffice/workflows/%s/status/%s/' % (workflow.id, st1.id) |
|
496 | ||
497 |
resp = app.get('/backoffice/workflows/%s/status/%s/' % (workflow.id, st3.id)) |
|
498 |
resp = resp.click('Email') |
|
499 |
assert resp.form['to$element0$choice'].value == '_submitter' |
|
500 |
assert resp.form['subject'].value == 'bla' |
|
501 | ||
502 |
resp = app.get('/backoffice/workflows/%s/status/%s/' % (workflow.id, st3.id)) |
|
503 |
resp = resp.click('Copy') |
|
504 |
resp.form['status'] = 'Status1' |
|
505 |
resp = resp.form.submit() |
|
506 |
assert resp.location == 'http://example.net/backoffice/workflows/%s/status/%s/' % (workflow.id, st3.id) |
|
507 | ||
508 |
resp = app.get('/backoffice/workflows/%s/status/%s/' % (workflow.id, st1.id)) |
|
509 |
assert len(resp.pyquery('#items-list li')) == 2 |
|
510 |
assert 'items/1/' in resp.text |
|
511 |
assert 'items/2/' in resp.text |
|
512 | ||
513 | ||
473 | 514 |
def test_workflows_delete(pub): |
474 | 515 |
Workflow.wipe() |
475 | 516 |
workflow = Workflow(name='foo') |
tests/test_snapshots.py | ||
---|---|---|
867 | 867 |
Workflow.wipe() |
868 | 868 |
workflow = Workflow(name='test') |
869 | 869 |
workflow.add_status(name='baz') |
870 |
workflow.add_status(name='hop') |
|
870 | 871 |
workflow.store() |
871 | 872 | |
872 | 873 |
app = login(get_app(pub)) |
... | ... | |
889 | 890 |
resp = resp.follow() |
890 | 891 |
resp = resp.follow() |
891 | 892 | |
893 |
resp = resp.click(href='items/1/copy') |
|
894 |
resp.form['status'] = 'hop' |
|
895 |
resp = resp.forms[0].submit('submit') |
|
896 |
resp = resp.follow() |
|
897 | ||
892 | 898 |
resp = resp.click(href='items/1/delete') |
893 | 899 |
resp = resp.form.submit('submit') |
894 | 900 | |
... | ... | |
899 | 905 |
] |
900 | 906 |
assert comments == [ |
901 | 907 |
'Deletion of action "Webservice (foo)" in status "baz"', |
908 |
'Copy of action "Webservice (foo)" from status "baz" to status "hop"', |
|
902 | 909 |
'Change in action "Webservice (foo)" in status "baz"', |
903 | 910 |
'Change in action "Webservice" in status "baz"', |
904 | 911 |
'New action "Webservice" in status "baz"', |
wcs/admin/workflows.py | ||
---|---|---|
14 | 14 |
# You should have received a copy of the GNU General Public License |
15 | 15 |
# along with this program; if not, see <http://www.gnu.org/licenses/>. |
16 | 16 | |
17 |
import copy |
|
17 | 18 |
import io |
18 | 19 |
import textwrap |
19 | 20 |
import time |
... | ... | |
358 | 359 | |
359 | 360 | |
360 | 361 |
class WorkflowItemPage(Directory): |
361 |
_q_exports = ['', 'delete'] |
|
362 |
_q_exports = ['', 'delete', 'copy']
|
|
362 | 363 | |
363 | 364 |
def __init__(self, workflow, parent, component, html_top): |
364 | 365 |
try: |
... | ... | |
437 | 438 |
) |
438 | 439 |
return redirect('../../') |
439 | 440 | |
441 |
def copy(self): |
|
442 |
form = Form(enctype='multipart/form-data') |
|
443 |
destinations = [(x.id, x.name) for x in self.workflow.possible_status] |
|
444 | ||
445 |
form.add(SingleSelectWidget, 'status', title=_('Target status'), options=destinations) |
|
446 | ||
447 |
form.add_submit('copy', _('Copy')) |
|
448 |
form.add_submit('cancel', _('Cancel')) |
|
449 |
if form.get_widget('cancel').parse(): |
|
450 |
return redirect('../../') |
|
451 |
if not form.is_submitted() or form.has_errors(): |
|
452 |
get_response().breadcrumb.append(('copy', _('Copy'))) |
|
453 |
self.html_top(title=_('Copy Item')) |
|
454 |
r = TemplateIO(html=True) |
|
455 |
r += htmltext('<h2>%s</h2>') % _('Copy Item') |
|
456 |
r += form.render() |
|
457 |
return r.getvalue() |
|
458 |
else: |
|
459 |
status_id = form.get_widget('status').parse() |
|
460 |
destination_status = self.workflow.get_status(status_id) |
|
461 | ||
462 |
new_item = copy.deepcopy(self.item) |
|
463 |
new_item.id = destination_status.get_new_item_id() |
|
464 |
new_item.parent = destination_status |
|
465 |
destination_status.items.append(new_item) |
|
466 | ||
467 |
self.workflow.store( |
|
468 |
comment=_( |
|
469 |
'Copy of action "%(description)s" from status "%(from_status)s" to status "%(destination_status)s"' |
|
470 |
) |
|
471 |
% { |
|
472 |
'description': self.item.render_as_line(), |
|
473 |
'from_status': self.parent.name, |
|
474 |
'destination_status': destination_status.name, |
|
475 |
} |
|
476 |
) |
|
477 |
return redirect('../../') |
|
478 | ||
440 | 479 |
def _q_lookup(self, component): |
441 | 480 |
t = self.item.q_admin_lookup(self.workflow, self.parent, component, self.html_top) |
442 | 481 |
if t: |
wcs/templates/wcs/backoffice/workflow-status.html | ||
---|---|---|
35 | 35 |
{% with item.get_target_status_url as url %} |
36 | 36 |
{% if url %}<span class="jump"><a href="{{ url }}" title="{% trans "Go to Target" %}">{% trans "Go to Target" %}</a></span>{% endif %} |
37 | 37 |
{% endwith %} |
38 |
<span class="copy"><a href="items/{{ item.id }}/copy" rel="popup" title="{% trans "Copy" %}">{% trans "Copy" %}</a></span> |
|
38 | 39 |
{% if not workflow.is_readonly %} |
39 | 40 |
<span class="edit"><a href="items/{{ item.id }}/" title="{% trans "Edit" %}">{% trans "Edit" %}</a></span> |
40 | 41 |
<span class="remove"><a href="items/{{ item.id }}/delete" rel="popup" title="{% trans "Delete" %}">{% trans "Delete" %}</a></span> |
wcs/workflows.py | ||
---|---|---|
1787 | 1787 |
for klass in item_classes: |
1788 | 1788 |
if klass.key == type: |
1789 | 1789 |
o = klass() |
1790 |
if self.items: |
|
1791 |
o.id = str(max(lax_int(x.id) for x in self.items) + 1) |
|
1792 |
else: |
|
1793 |
o.id = '1' |
|
1790 |
o.id = self.get_new_item_id() |
|
1794 | 1791 |
self.items.append(o) |
1795 | 1792 |
break |
1796 | 1793 |
else: |
1797 | 1794 |
raise KeyError() |
1798 | 1795 | |
1796 |
def get_new_item_id(self): |
|
1797 |
if self.items: |
|
1798 |
return str(max(lax_int(x.id) for x in self.items) + 1) |
|
1799 |
else: |
|
1800 |
return '1' |
|
1801 | ||
1799 | 1802 |
def get_item(self, id): |
1800 | 1803 |
for item in self.items: |
1801 | 1804 |
if item.id == id: |
1802 |
- |