Projet

Général

Profil

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

Valentin Deniaud, 14 décembre 2021 11:27

Télécharger (7,8 ko)

Voir les différences:

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

 tests/admin_pages/test_workflow.py            | 41 +++++++++++++++++++
 tests/test_snapshots.py                       |  7 ++++
 wcs/admin/workflows.py                        | 41 ++++++++++++++++++-
 .../wcs/backoffice/workflow-status.html       |  1 +
 wcs/workflows.py                              | 11 +++--
 5 files changed, 96 insertions(+), 5 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
    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
-