Projet

Général

Profil

0001-workflows-add-possibility-of-backoffice-info-texts-f.patch

Frédéric Péters, 08 septembre 2015 10:27

Télécharger (20,5 ko)

Voir les différences:

Subject: [PATCH] workflows: add possibility of backoffice info texts for
 workflows (#7738)

 tests/test_admin_pages.py           |  8 ++++
 tests/test_backoffice_pages.py      | 80 ++++++++++++++++++++++++++++++++++++-
 tests/test_workflow_import.py       | 17 ++++++++
 wcs/admin/workflows.py              | 28 ++++++++++++-
 wcs/forms/common.py                 | 15 +++++++
 wcs/qommon/static/css/dc2/admin.css | 13 ++++++
 wcs/wf/attachment.py                |  9 ++++-
 wcs/workflows.py                    | 40 +++++++++++++++++--
 8 files changed, 202 insertions(+), 8 deletions(-)
tests/test_admin_pages.py
1220 1220
    resp = resp.follow()
1221 1221
    assert Workflow.get(1).possible_status[0].colour == 'FF0000'
1222 1222

  
1223
    resp = resp.click('Change Backoffice Information Text')
1224
    assert resp.forms[0]['backoffice_info_text'].value == ''
1225
    resp.forms[0]['backoffice_info_text'] = '<p>Hello</p>'
1226
    resp = resp.forms[0].submit()
1227
    assert resp.location == 'http://example.net/backoffice/workflows/1/status/1/'
1228
    resp = resp.follow()
1229
    assert Workflow.get(1).possible_status[0].backoffice_info_text == '<p>Hello</p>'
1230

  
1223 1231
def test_workflows_delete():
1224 1232
    Workflow.wipe()
1225 1233
    workflow = Workflow(name='foo')
tests/test_backoffice_pages.py
12 12
from qommon.ident.password_accounts import PasswordAccount
13 13
from wcs.qommon.http_request import HTTPRequest
14 14
from wcs.roles import Role
15
from wcs.workflows import Workflow
15
from wcs.workflows import Workflow, CommentableWorkflowStatusItem
16 16
from wcs.formdef import FormDef
17 17
from wcs import fields
18 18

  
......
393 393
    assert FormDef.get_by_urlname('form-title').data_class().get(number31).status == 'wf-accepted'
394 394
    assert 'HELLO WORLD' in resp.body
395 395

  
396
def test_backoffice_info_text(pub):
397
    create_user(pub)
398
    create_environment(pub)
399
    formdef = FormDef.get_by_urlname('form-title')
400
    form_class = formdef.data_class()
401

  
402
    number31 = [x for x in form_class.select() if x.data['1'] == 'FOO BAR 30'][0].id
403
    number31_status = [x for x in form_class.select() if x.data['1'] == 'FOO BAR 30'][0].status
404

  
405
    # attach a custom workflow
406
    workflow = Workflow(name='info texts')
407
    st1 = workflow.add_status('Status1', number31_status.split('-')[1])
408

  
409
    commentable = CommentableWorkflowStatusItem()
410
    commentable.id = '_commentable'
411
    commentable.by = ['_submitter', '_receiver']
412
    commentable.button_label = 'CLICK ME!'
413
    st1.items.append(commentable)
414
    commentable.parent = st1
415

  
416
    commentable2 = CommentableWorkflowStatusItem()
417
    commentable2.id = '_commentable2'
418
    commentable2.by = ['_submitter']
419
    commentable2.button_label = 'CLICK ME2!'
420
    st1.items.append(commentable2)
421
    commentable2.parent = st1
422

  
423
    workflow.store()
424

  
425
    formdef.workflow_id = workflow.id
426
    formdef.store()
427

  
428
    app = login(get_app(pub))
429

  
430
    resp = app.get('/backoffice/management/form-title/%s/' % number31)
431
    assert (' with the number %s.' % number31) in resp.body
432
    assert 'CLICK ME!' in resp.body
433
    assert not 'CLICK ME2!' in resp.body
434
    assert not 'backoffice-description' in resp.body
435

  
436
    # add an info text to the status
437
    st1.backoffice_info_text = '<p>Foo</p>'
438
    workflow.store()
439
    resp = app.get('/backoffice/management/form-title/%s/' % number31)
440
    assert 'backoffice-description' in resp.body
441
    assert '<p>Foo</p>' in resp.body
442

  
443
    # add an info text to the button
444
    commentable.backoffice_info_text = '<p>Bar</p>'
445
    workflow.store()
446
    resp = app.get('/backoffice/management/form-title/%s/' % number31)
447
    assert 'backoffice-description' in resp.body
448
    assert '<p>Foo</p>' in resp.body
449
    assert '<p>Bar</p>' in resp.body
450

  
451
    # remove info text from the status
452
    st1.backoffice_info_text = None
453
    workflow.store()
454
    resp = app.get('/backoffice/management/form-title/%s/' % number31)
455
    assert 'backoffice-description' in resp.body
456
    assert not '<p>Foo</p>' in resp.body
457
    assert '<p>Bar</p>' in resp.body
458

  
459
    # add info text to second button
460
    commentable2.backoffice_info_text = '<p>Baz</p>'
461
    workflow.store()
462
    resp = app.get('/backoffice/management/form-title/%s/' % number31)
463
    assert 'backoffice-description' in resp.body
464
    assert not '<p>Foo</p>' in resp.body
465
    assert '<p>Bar</p>' in resp.body
466
    assert not '<p>Baz</p>' in resp.body
467

  
468
    # remove info text from first button
469
    commentable.backoffice_info_text = None
470
    workflow.store()
471
    resp = app.get('/backoffice/management/form-title/%s/' % number31)
472
    assert not 'backoffice-description' in resp.body
473

  
396 474
def test_backoffice_handling_post_dispatch(pub):
397 475
    # check a formdata that has been dispatched to another role is accessible
398 476
    # by an user with that role.
tests/test_workflow_import.py
277 277
    wf.variables_formdef.fields.append(StringField(label='Test', type='string'))
278 278
    wf2 = assert_import_export_works(wf)
279 279
    assert wf2.variables_formdef.fields[0].label == 'Test'
280

  
281

  
282
def test_backoffice_info_text():
283
    wf = Workflow(name='info texts')
284
    st1 = wf.add_status('Status1', 'st1')
285
    st1.backoffice_info_text = '<p>Foo</p>'
286

  
287
    commentable = CommentableWorkflowStatusItem()
288
    commentable.id = '_commentable'
289
    commentable.by = ['_submitter', '_receiver']
290
    commentable.backoffice_info_text = '<p>Bar</p>'
291
    st1.items.append(commentable)
292
    commentable.parent = st1
293

  
294
    wf2 = assert_import_export_works(wf)
295
    assert wf2.possible_status[0].backoffice_info_text == '<p>Foo</p>'
296
    assert wf2.possible_status[0].items[0].backoffice_info_text == '<p>Bar</p>'
wcs/admin/workflows.py
316 316
class WorkflowStatusPage(Directory):
317 317
    _q_exports = ['', 'delete', 'newitem', ('items', 'items_dir'),
318 318
                  'update_order', 'edit', 'reassign', 'visibility',
319
                  'endpoint', 'colour']
319
                  'endpoint', 'colour',
320
                  ('backoffice-info-text', 'backoffice_info_text'),]
320 321

  
321 322
    def __init__(self, workflow, status_id, html_top):
322 323
        self.html_top = html_top
......
332 333
    def _q_index(self):
333 334
        self.html_top('%s - %s' % (_('Workflow'), self.workflow.name))
334 335
        r = TemplateIO(html=True)
335
        get_response().add_javascript(['jquery.js', 'jquery-ui.js', 'biglist.js', 'svg-pan-zoom.js'])
336
        get_response().add_javascript(['jquery.js', 'jquery-ui.js', 'biglist.js', 'svg-pan-zoom.js',
337
            'ckeditor/ckeditor.js', 'qommon.wysiwyg.js', 'ckeditor/adapters/jquery.js'])
336 338
        get_response().add_javascript_code('$(function () { svgPanZoom("svg", {controlIconsEnabled: true}); });');
337 339

  
338 340
        r += htmltext('<h2>%s - ') % _('Workflow')
......
425 427
            r += htmltext('<li><a href="visibility" rel="popup">%s</a></li>') % _('Change Status Visibility')
426 428
            r += htmltext('<li><a href="endpoint" rel="popup">%s</a></li>') % _('Change Terminal Status')
427 429
            r += htmltext('<li><a href="colour" rel="popup">%s</a></li>') % _('Change Status Colour')
430
            r += htmltext('<li><a href="backoffice-info-text" rel="popup">%s</a></li>'
431
                    ) % _('Change Backoffice Information Text')
428 432
            r += htmltext('<li><a href="delete" rel="popup">%s</a></li>') % _('Delete')
429 433
            r += htmltext('</ul>')
430 434
            r += htmltext('<div id="new-field">')
......
677 681
        get_response().breadcrumb.append( ('colour', _('Status Colour')) )
678 682
        return form.render()
679 683

  
684
    def backoffice_info_text(self):
685
        form = Form(enctype = 'multipart/form-data')
686
        form.add(WysiwygTextWidget, 'backoffice_info_text',
687
                 title=_('Information text for backoffice'),
688
                 value=self.status.backoffice_info_text)
689
        form.add_submit('submit', _('Submit'))
690
        form.add_submit('cancel', _('Cancel'))
691
        if form.get_widget('cancel').parse():
692
            return redirect('..')
693

  
694
        if form.is_submitted() and not form.has_errors():
695
            self.status.backoffice_info_text = form.get_widget('backoffice_info_text').parse()
696
            self.workflow.store()
697
            return redirect('.')
698

  
699
        self.html_top(title = _('Edit Backoffice Information Text'))
700
        get_response().breadcrumb.append( ('backoffice_info_text',
701
            _('Backoffice Information Text')) )
702
        return form.render()
703

  
680 704

  
681 705
class WorkflowStatusDirectory(Directory):
682 706
    _q_exports = ['']
wcs/forms/common.py
464 464
        if form:
465 465
            r += form.render()
466 466

  
467
        if (self.filled.get_status() and self.filled.get_status().backoffice_info_text) or (
468
                form and any((getattr(button, 'backoffice_info_text', None)
469
                             for button in form.get_submit_widgets()))):
470
            r += htmltext('<div class="backoffice-description bo-block">')
471
            if self.filled.get_status().backoffice_info_text:
472
                r += htmltext(self.filled.get_status().backoffice_info_text)
473
            if form:
474
                for button in form.get_submit_widgets():
475
                    if not getattr(button, 'backoffice_info_text', None):
476
                        continue
477
                    r += htmltext('<div class="action-info-text">')
478
                    r += htmltext(button.backoffice_info_text)
479
                    r += htmltext('</div>')
480
            r += htmltext('</div>')
481

  
467 482
        r += htmltext('<a href="..">%s</a>') % _('Back to Listing')
468 483
        return r.getvalue()
469 484

  
wcs/qommon/static/css/dc2/admin.css
1012 1012
	cursor: pointer;
1013 1013
}
1014 1014

  
1015
.bo-block.backoffice-description:before {
1016
	font-family: FontAwesome;
1017
	content: "\f05a"; /* info-circle */
1018
	position: absolute;
1019
	left: 10px;
1020
	font-size: 2em;
1021
}
1022

  
1023
.bo-block.backoffice-description {
1024
	position: relative;
1025
	padding-left: 40px;
1026
}
1027

  
1015 1028
@media print {
1016 1029
	div#sidebar {
1017 1030
		display: none;
wcs/wf/attachment.py
68 68
    required = False
69 69
    hint = None
70 70
    by = []
71
    backoffice_info_text = None
71 72

  
72 73
    def init(cls):
73 74
        FormStatusPage._q_extra_exports.append('attachment')
......
92 93
                    required=self.required, hint=self.hint)
93 94
        if self.display_button:
94 95
            form.add_submit('button%s' % self.id, self.button_label or _('Upload File'))
96
            form.get_widget('button%s' % self.id).backoffice_info_text = self.backoffice_info_text
95 97

  
96 98
    def submit_form(self, form, formdata, user, evo):
97 99
        if form.get_widget('attachment%s' % self.id):
......
103 105
            evo.add_part(AttachmentEvolutionPart.from_upload(f))
104 106

  
105 107
    def get_parameters(self):
106
        return ('by', 'required', 'title', 'display_title', 'button_label', 'display_button', 'hint')
108
        return ('by', 'required', 'title', 'display_title', 'button_label',
109
                'display_button', 'hint', 'backoffice_info_text')
107 110

  
108 111
    def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
109 112
        if 'by' in parameters:
......
126 129
            form.add(CheckboxWidget, '%sdisplay_button' % prefix, title = _('Display Button'), value = self.display_button)
127 130
        if 'hint' in parameters:
128 131
            form.add(StringWidget, '%shint' % prefix, size=40, title=_('Hint'), value=self.hint)
132
        if 'backoffice_info_text' in parameters:
133
            form.add(WysiwygTextWidget, 'backoffice_info_text',
134
                     title=_('Information Text for Backoffice'),
135
                     value=self.backoffice_info_text)
129 136

  
130 137

  
131 138
register_item_class(AddAttachmentWorkflowStatusItem)
wcs/workflows.py
549 549
    visibility = None
550 550
    forced_endpoint = False
551 551
    colour = 'FFFFFF'
552
    backoffice_info_text = None
552 553

  
553 554
    def __init__(self, name = None):
554 555
        self.name = name
......
722 723
        if self.forced_endpoint:
723 724
            ET.SubElement(status, 'forced_endpoint').text = 'true'
724 725

  
726
        if self.backoffice_info_text:
727
            ET.SubElement(status, 'backoffice_info_text').text = unicode(
728
                    self.backoffice_info_text, charset)
729

  
725 730
        visibility_node = ET.SubElement(status, 'visibility')
726 731
        for role in self.visibility or []:
727 732
            ET.SubElement(visibility_node, 'role').text = str(role)
......
739 744
            self.colour = elem.find('colour').text.encode(charset)
740 745
        if elem.find('forced_endpoint') is not None:
741 746
            self.forced_endpoint = (elem.find('forced_endpoint').text == 'true')
747
        if elem.find('backoffice_info_text') is not None:
748
            self.backoffice_info_text = elem.find('backoffice_info_text').text.encode(charset)
742 749

  
743 750
        self.visibility = []
744 751
        for visibility_role in elem.findall('visibility/role'):
......
1089 1096
    button_label = 0 # hack to handle legacy commentable items
1090 1097
    hint = None
1091 1098
    by = []
1099
    backoffice_info_text = None
1092 1100

  
1093 1101
    def render_as_line(self):
1094 1102
        if self.by:
......
1109 1117
                form.add_submit('button%s' % self.id, _('Add Comment'))
1110 1118
            elif self.button_label:
1111 1119
                form.add_submit('button%s' % self.id, self.button_label)
1120
            form.get_widget('button%s' % self.id).backoffice_info_text = self.backoffice_info_text
1112 1121

  
1113 1122
    def submit_form(self, form, formdata, user, evo):
1114 1123
        if form.get_widget('comment'):
......
1129 1138
        self.add_parameters_widgets(form, self.get_parameters())
1130 1139

  
1131 1140
    def get_parameters(self):
1132
        return ('label', 'button_label', 'by', 'hint', 'varname')
1141
        return ('label', 'button_label', 'by', 'hint', 'varname',
1142
                'backoffice_info_text')
1133 1143

  
1134 1144
    def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
1135 1145
        if 'label' in parameters:
......
1155 1165
            form.add(VarnameWidget, '%svarname' % prefix,
1156 1166
                     title=_('Variable Name'), value=self.varname,
1157 1167
                     hint=_('This will make the comment available in a variable named comment_varname.'))
1168
        if 'backoffice_info_text' in parameters:
1169
            form.add(WysiwygTextWidget, 'backoffice_info_text',
1170
                     title=_('Information Text for Backoffice'),
1171
                     value=self.backoffice_info_text)
1158 1172

  
1159 1173
    def button_label_export_to_xml(self, xml_item, charset, include_id=False):
1160 1174
        if self.button_label == 0:
......
1193 1207

  
1194 1208
    label = None
1195 1209
    by = []
1210
    backoffice_info_text = None
1196 1211

  
1197 1212
    def render_as_line(self):
1198 1213
        if self.label:
......
1207 1222

  
1208 1223
    def fill_form(self, form, formdata, user):
1209 1224
        form.add_submit('button%s' % self.id, self.label)
1225
        form.get_widget('button%s' % self.id).backoffice_info_text = self.backoffice_info_text
1210 1226

  
1211 1227
    def submit_form(self, form, formdata, user, evo):
1212 1228
        if form.get_submit() == 'button%s' % self.id:
......
1226 1242
                add_element_label = _('Add Role'),
1227 1243
                element_kwargs={'render_br': False,
1228 1244
                                'options': [(None, '---')] + self.get_list_of_roles()})
1245
        if 'backoffice_info_text' in parameters:
1246
            form.add(WysiwygTextWidget, 'backoffice_info_text',
1247
                     title=_('Information Text for Backoffice'),
1248
                     value=self.backoffice_info_text)
1229 1249

  
1230 1250
    def get_parameters(self):
1231
        return ('by', 'status', 'label')
1251
        return ('by', 'status', 'label', 'backoffice_info_text')
1232 1252

  
1233 1253
register_item_class(ChoiceWorkflowStatusItem)
1234 1254

  
......
1536 1556
    by = []
1537 1557
    status = None
1538 1558
    label = None
1559
    backoffice_info_text = None
1539 1560

  
1540 1561
    def render_as_line(self):
1541 1562
        if self.by:
......
1548 1569
        if not label:
1549 1570
            label = _('Edit Form')
1550 1571
        form.add_submit('button%s' % self.id, label)
1572
        form.get_widget('button%s' % self.id).backoffice_info_text = self.backoffice_info_text
1551 1573

  
1552 1574
    def submit_form(self, form, formdata, user, evo):
1553 1575
        if form.get_submit() == 'button%s' % self.id:
......
1568 1590
                options = [(None, '---')] + [(x.id, x.name) for x in self.parent.parent.possible_status])
1569 1591
        if 'label' in parameters:
1570 1592
            form.add(StringWidget, '%slabel' % prefix, title = _('Button Label'), value = self.label)
1593
        if 'backoffice_info_text' in parameters:
1594
            form.add(WysiwygTextWidget, 'backoffice_info_text',
1595
                     title=_('Information Text for Backoffice'),
1596
                     value=self.backoffice_info_text)
1571 1597

  
1572 1598
    def get_parameters(self):
1573
        return ('by', 'status', 'label')
1599
        return ('by', 'status', 'label', 'backoffice_info_text')
1574 1600

  
1575 1601
register_item_class(EditableWorkflowStatusItem)
1576 1602

  
......
1622 1648
    attach_to_history = False
1623 1649
    directory_class = ExportToModelDirectory
1624 1650
    by = ['_receiver']
1651
    backoffice_info_text = None
1625 1652

  
1626 1653
    def render_as_line(self):
1627 1654
        if self.label:
......
1642 1669
        if not label:
1643 1670
            label = _('Create Document')
1644 1671
        form.add_submit('button%s' % self.id, label)
1672
        form.get_widget('button%s' % self.id).backoffice_info_text = self.backoffice_info_text
1645 1673

  
1646 1674
    def submit_form(self, form, formdata, user, evo):
1647 1675
        if form.get_submit() == 'button%s' % self.id:
......
1707 1735
            form.add(UploadWidget, widget_name, directory='models',
1708 1736
                    filename=filename, title=_('Model'), hint=hint,
1709 1737
                    validation=self.model_file_validation, value=value)
1738
        if 'backoffice_info_text' in parameters:
1739
            form.add(WysiwygTextWidget, 'backoffice_info_text',
1740
                     title=_('Information Text for Backoffice'),
1741
                     value=self.backoffice_info_text)
1710 1742

  
1711 1743
    def get_directory_name(self):
1712 1744
        return qommon.misc.simplify(self.label or 'export_to_model', space='_')
......
1729 1761
            raise TemplatingError(_('Unknown error in the template: %s') % str(e))
1730 1762

  
1731 1763
    def get_parameters(self):
1732
        return ('by', 'label', 'model_file', 'attach_to_history')
1764
        return ('by', 'label', 'model_file', 'attach_to_history', 'backoffice_info_text')
1733 1765

  
1734 1766
    def model_file_export_to_xml(self, xml_item, charset, include_id=False):
1735 1767
        if not self.model_file:
1736
-