Projet

Général

Profil

0001-workflows-copy-action-from-one-status-to-another-578.patch

Valentin Deniaud, 16 février 2022 11:41

Télécharger (9,55 ko)

Voir les différences:

Subject: [PATCH] workflows: copy action from one status to another (#57894)

 tests/admin_pages/test_workflow.py            | 92 +++++++++++++++++++
 tests/test_snapshots.py                       |  7 ++
 wcs/admin/workflows.py                        | 42 ++++++++-
 wcs/qommon/static/css/dc2/admin.scss          |  4 +-
 .../wcs/backoffice/workflow-status.html       |  1 +
 5 files changed, 143 insertions(+), 3 deletions(-)
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
-