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 |
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 | ||
514 |
def test_workflows_copy_status_item_create_document(pub): |
|
515 |
create_superuser(pub) |
|
516 |
Workflow.wipe() |
|
517 | ||
518 |
workflow = Workflow(name='foo') |
|
519 |
st1 = workflow.add_status('Status1') |
|
520 |
st2 = workflow.add_status('Status2') |
|
521 |
workflow.store() |
|
522 | ||
523 |
app = login(get_app(pub)) |
|
524 |
resp = app.get('/backoffice/workflows/%s/status/%s/' % (workflow.id, st1.id)) |
|
525 | ||
526 |
resp.forms[0]['action-formdata-action'] = 'Document Creation' |
|
527 |
resp = resp.forms[0].submit() |
|
528 |
resp = resp.follow() |
|
529 | ||
530 |
resp = resp.click('Document Creation') |
|
531 |
resp.form['model_file$file'] = Upload('test.rtf', b'Model content') |
|
532 |
resp = resp.form.submit('submit').follow().follow() |
|
533 |
resp = resp.click('Document Creation') |
|
534 |
resp_model_content = resp.click('test.rtf') |
|
535 |
assert resp_model_content.body == b'Model content' |
|
536 | ||
537 |
resp = app.get('/backoffice/workflows/%s/status/%s/' % (workflow.id, st1.id)) |
|
538 |
resp = resp.click('Copy') |
|
539 |
resp.form['status'] = 'Status2' |
|
540 |
resp = resp.form.submit() |
|
541 | ||
542 |
resp = app.get('/backoffice/workflows/%s/status/%s/' % (workflow.id, st2.id)) |
|
543 |
resp = resp.click('Document Creation') |
|
544 |
resp_model_content = resp.click('test.rtf') |
|
545 |
assert resp_model_content.body == b'Model content' |
|
546 | ||
547 |
# modify file in initial status |
|
548 |
resp = app.get('/backoffice/workflows/%s/status/%s/' % (workflow.id, st1.id)) |
|
549 |
resp = resp.click('Document Creation') |
|
550 |
resp.form['model_file$file'] = Upload('test2.rtf', b'Something else') |
|
551 |
resp.form['model_file$orexisting'].checked = False |
|
552 |
resp = resp.form.submit('submit').follow().follow() |
|
553 | ||
554 |
resp = resp.click('Document Creation') |
|
555 |
resp_model_content = resp.click('test2.rtf') |
|
556 |
assert resp_model_content.body == b'Something else' |
|
557 | ||
558 |
# check file is not changed in the copied item |
|
559 |
resp = app.get('/backoffice/workflows/%s/status/%s/' % (workflow.id, st2.id)) |
|
560 |
resp = resp.click('Document Creation') |
|
561 |
resp_model_content = resp.click('test.rtf') |
|
562 |
assert resp_model_content.body == b'Model content' |
|
563 | ||
564 | ||
473 | 565 |
def test_workflows_delete(pub): |
474 | 566 |
Workflow.wipe() |
475 | 567 |
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 json |
19 | 20 |
import textwrap |
... | ... | |
373 | 374 | |
374 | 375 | |
375 | 376 |
class WorkflowItemPage(Directory): |
376 |
_q_exports = ['', 'delete'] |
|
377 |
_q_exports = ['', 'delete', 'copy']
|
|
377 | 378 | |
378 | 379 |
def __init__(self, workflow, parent, component, html_top): |
379 | 380 |
try: |
... | ... | |
452 | 453 |
) |
453 | 454 |
return redirect('../../') |
454 | 455 | |
456 |
def copy(self): |
|
457 |
form = Form(enctype='multipart/form-data') |
|
458 |
destinations = [(x.id, x.name) for x in self.workflow.possible_status] |
|
459 | ||
460 |
form.add(SingleSelectWidget, 'status', title=_('Target status'), options=destinations) |
|
461 | ||
462 |
form.add_submit('copy', _('Copy')) |
|
463 |
form.add_submit('cancel', _('Cancel')) |
|
464 |
if form.get_widget('cancel').parse(): |
|
465 |
return redirect('../../') |
|
466 |
if not form.is_submitted() or form.has_errors(): |
|
467 |
get_response().breadcrumb.append(('copy', _('Copy'))) |
|
468 |
self.html_top(title=_('Copy Item')) |
|
469 |
r = TemplateIO(html=True) |
|
470 |
r += htmltext('<h2>%s</h2>') % _('Copy Item') |
|
471 |
r += form.render() |
|
472 |
return r.getvalue() |
|
473 |
else: |
|
474 |
status_id = form.get_widget('status').parse() |
|
475 |
destination_status = self.workflow.get_status(status_id) |
|
476 | ||
477 |
item = self.item.export_to_xml('utf-8') |
|
478 |
item_type = item.attrib['type'] |
|
479 |
new_item = destination_status.append_item(item_type) |
|
480 |
new_item.parent = destination_status |
|
481 |
new_item.init_with_xml(item, 'utf-8') |
|
482 | ||
483 |
self.workflow.store( |
|
484 |
comment=_( |
|
485 |
'Copy of action "%(description)s" from status "%(from_status)s" to status "%(destination_status)s"' |
|
486 |
) |
|
487 |
% { |
|
488 |
'description': self.item.render_as_line(), |
|
489 |
'from_status': self.parent.name, |
|
490 |
'destination_status': destination_status.name, |
|
491 |
} |
|
492 |
) |
|
493 |
return redirect('../../') |
|
494 | ||
455 | 495 |
def _q_lookup(self, component): |
456 | 496 |
t = self.item.q_admin_lookup(self.workflow, self.parent, component, self.html_top) |
457 | 497 |
if t: |
wcs/qommon/static/css/dc2/admin.scss | ||
---|---|---|
1 | 1 |
$primary-color: #386ede; |
2 | 2 |
$secondary-color: #00d6eb; |
3 | 3 |
$string-color: str-slice($primary-color + '', 2); |
4 |
$actions: add, duplicate, edit, jump, remove; |
|
4 |
$actions: add, duplicate, edit, jump, remove, copy;
|
|
5 | 5 | |
6 | 6 |
@mixin clearfix { |
7 | 7 |
&::after { |
... | ... | |
2076 | 2076 |
&.view { |
2077 | 2077 |
margin-top: 2px; |
2078 | 2078 |
} |
2079 |
&.remove, &.add, &.edit, &.duplicate, &.jump { |
|
2079 |
&.remove, &.add, &.edit, &.duplicate, &.jump, &.copy {
|
|
2080 | 2080 |
padding: 0; |
2081 | 2081 |
border: 0; |
2082 | 2082 |
background: transparent; |
wcs/templates/wcs/backoffice/workflow-status.html | ||
---|---|---|
37 | 37 |
{% endwith %} |
38 | 38 |
{% if not workflow.is_readonly %} |
39 | 39 |
<span class="edit"><a href="items/{{ item.id }}/" title="{% trans "Edit" %}">{% trans "Edit" %}</a></span> |
40 |
<span class="copy"><a href="items/{{ item.id }}/copy" rel="popup" title="{% trans "Copy" %}">{% trans "Copy" %}</a></span> |
|
40 | 41 |
<span class="remove"><a href="items/{{ item.id }}/delete" rel="popup" title="{% trans "Delete" %}">{% trans "Delete" %}</a></span> |
41 | 42 |
{% endif %} |
42 | 43 |
</p> |
43 |
- |