workflows: add possibility of backoffice info texts for workflows (#7738)
This commit is contained in:
parent
c14d3d8f48
commit
99e00744f3
|
@ -1220,6 +1220,14 @@ def test_workflows_edit_status():
|
|||
resp = resp.follow()
|
||||
assert Workflow.get(1).possible_status[0].colour == 'FF0000'
|
||||
|
||||
resp = resp.click('Change Backoffice Information Text')
|
||||
assert resp.forms[0]['backoffice_info_text'].value == ''
|
||||
resp.forms[0]['backoffice_info_text'] = '<p>Hello</p>'
|
||||
resp = resp.forms[0].submit()
|
||||
assert resp.location == 'http://example.net/backoffice/workflows/1/status/1/'
|
||||
resp = resp.follow()
|
||||
assert Workflow.get(1).possible_status[0].backoffice_info_text == '<p>Hello</p>'
|
||||
|
||||
def test_workflows_delete():
|
||||
Workflow.wipe()
|
||||
workflow = Workflow(name='foo')
|
||||
|
|
|
@ -12,7 +12,7 @@ from wcs.qommon import errors, sessions
|
|||
from qommon.ident.password_accounts import PasswordAccount
|
||||
from wcs.qommon.http_request import HTTPRequest
|
||||
from wcs.roles import Role
|
||||
from wcs.workflows import Workflow
|
||||
from wcs.workflows import Workflow, CommentableWorkflowStatusItem
|
||||
from wcs.formdef import FormDef
|
||||
from wcs import fields
|
||||
|
||||
|
@ -393,6 +393,84 @@ def test_backoffice_handling(pub):
|
|||
assert FormDef.get_by_urlname('form-title').data_class().get(number31).status == 'wf-accepted'
|
||||
assert 'HELLO WORLD' in resp.body
|
||||
|
||||
def test_backoffice_info_text(pub):
|
||||
create_user(pub)
|
||||
create_environment(pub)
|
||||
formdef = FormDef.get_by_urlname('form-title')
|
||||
form_class = formdef.data_class()
|
||||
|
||||
number31 = [x for x in form_class.select() if x.data['1'] == 'FOO BAR 30'][0].id
|
||||
number31_status = [x for x in form_class.select() if x.data['1'] == 'FOO BAR 30'][0].status
|
||||
|
||||
# attach a custom workflow
|
||||
workflow = Workflow(name='info texts')
|
||||
st1 = workflow.add_status('Status1', number31_status.split('-')[1])
|
||||
|
||||
commentable = CommentableWorkflowStatusItem()
|
||||
commentable.id = '_commentable'
|
||||
commentable.by = ['_submitter', '_receiver']
|
||||
commentable.button_label = 'CLICK ME!'
|
||||
st1.items.append(commentable)
|
||||
commentable.parent = st1
|
||||
|
||||
commentable2 = CommentableWorkflowStatusItem()
|
||||
commentable2.id = '_commentable2'
|
||||
commentable2.by = ['_submitter']
|
||||
commentable2.button_label = 'CLICK ME2!'
|
||||
st1.items.append(commentable2)
|
||||
commentable2.parent = st1
|
||||
|
||||
workflow.store()
|
||||
|
||||
formdef.workflow_id = workflow.id
|
||||
formdef.store()
|
||||
|
||||
app = login(get_app(pub))
|
||||
|
||||
resp = app.get('/backoffice/management/form-title/%s/' % number31)
|
||||
assert (' with the number %s.' % number31) in resp.body
|
||||
assert 'CLICK ME!' in resp.body
|
||||
assert not 'CLICK ME2!' in resp.body
|
||||
assert not 'backoffice-description' in resp.body
|
||||
|
||||
# add an info text to the status
|
||||
st1.backoffice_info_text = '<p>Foo</p>'
|
||||
workflow.store()
|
||||
resp = app.get('/backoffice/management/form-title/%s/' % number31)
|
||||
assert 'backoffice-description' in resp.body
|
||||
assert '<p>Foo</p>' in resp.body
|
||||
|
||||
# add an info text to the button
|
||||
commentable.backoffice_info_text = '<p>Bar</p>'
|
||||
workflow.store()
|
||||
resp = app.get('/backoffice/management/form-title/%s/' % number31)
|
||||
assert 'backoffice-description' in resp.body
|
||||
assert '<p>Foo</p>' in resp.body
|
||||
assert '<p>Bar</p>' in resp.body
|
||||
|
||||
# remove info text from the status
|
||||
st1.backoffice_info_text = None
|
||||
workflow.store()
|
||||
resp = app.get('/backoffice/management/form-title/%s/' % number31)
|
||||
assert 'backoffice-description' in resp.body
|
||||
assert not '<p>Foo</p>' in resp.body
|
||||
assert '<p>Bar</p>' in resp.body
|
||||
|
||||
# add info text to second button
|
||||
commentable2.backoffice_info_text = '<p>Baz</p>'
|
||||
workflow.store()
|
||||
resp = app.get('/backoffice/management/form-title/%s/' % number31)
|
||||
assert 'backoffice-description' in resp.body
|
||||
assert not '<p>Foo</p>' in resp.body
|
||||
assert '<p>Bar</p>' in resp.body
|
||||
assert not '<p>Baz</p>' in resp.body
|
||||
|
||||
# remove info text from first button
|
||||
commentable.backoffice_info_text = None
|
||||
workflow.store()
|
||||
resp = app.get('/backoffice/management/form-title/%s/' % number31)
|
||||
assert not 'backoffice-description' in resp.body
|
||||
|
||||
def test_backoffice_handling_post_dispatch(pub):
|
||||
# check a formdata that has been dispatched to another role is accessible
|
||||
# by an user with that role.
|
||||
|
|
|
@ -279,7 +279,6 @@ def test_variables_formdef():
|
|||
wf2 = assert_import_export_works(wf)
|
||||
assert wf2.variables_formdef.fields[0].label == 'Test'
|
||||
|
||||
|
||||
def test_wscall_action():
|
||||
wf = Workflow(name='status')
|
||||
st1 = wf.add_status('Status1', 'st1')
|
||||
|
@ -301,3 +300,19 @@ def test_wscall_action():
|
|||
assert wscall2.post == False
|
||||
assert wscall2.request_signature_key == 'key'
|
||||
assert wscall2.post_data == {'one': '1', 'two': '=2', 'good:name': 'ok'}
|
||||
|
||||
def test_backoffice_info_text():
|
||||
wf = Workflow(name='info texts')
|
||||
st1 = wf.add_status('Status1', 'st1')
|
||||
st1.backoffice_info_text = '<p>Foo</p>'
|
||||
|
||||
commentable = CommentableWorkflowStatusItem()
|
||||
commentable.id = '_commentable'
|
||||
commentable.by = ['_submitter', '_receiver']
|
||||
commentable.backoffice_info_text = '<p>Bar</p>'
|
||||
st1.items.append(commentable)
|
||||
commentable.parent = st1
|
||||
|
||||
wf2 = assert_import_export_works(wf)
|
||||
assert wf2.possible_status[0].backoffice_info_text == '<p>Foo</p>'
|
||||
assert wf2.possible_status[0].items[0].backoffice_info_text == '<p>Bar</p>'
|
||||
|
|
|
@ -316,7 +316,8 @@ class WorkflowItemsDir(Directory):
|
|||
class WorkflowStatusPage(Directory):
|
||||
_q_exports = ['', 'delete', 'newitem', ('items', 'items_dir'),
|
||||
'update_order', 'edit', 'reassign', 'visibility',
|
||||
'endpoint', 'colour']
|
||||
'endpoint', 'colour',
|
||||
('backoffice-info-text', 'backoffice_info_text'),]
|
||||
|
||||
def __init__(self, workflow, status_id, html_top):
|
||||
self.html_top = html_top
|
||||
|
@ -332,7 +333,8 @@ class WorkflowStatusPage(Directory):
|
|||
def _q_index(self):
|
||||
self.html_top('%s - %s' % (_('Workflow'), self.workflow.name))
|
||||
r = TemplateIO(html=True)
|
||||
get_response().add_javascript(['jquery.js', 'jquery-ui.js', 'biglist.js', 'svg-pan-zoom.js'])
|
||||
get_response().add_javascript(['jquery.js', 'jquery-ui.js', 'biglist.js', 'svg-pan-zoom.js',
|
||||
'ckeditor/ckeditor.js', 'qommon.wysiwyg.js', 'ckeditor/adapters/jquery.js'])
|
||||
get_response().add_javascript_code('$(function () { svgPanZoom("svg", {controlIconsEnabled: true}); });');
|
||||
|
||||
r += htmltext('<h2>%s - ') % _('Workflow')
|
||||
|
@ -425,6 +427,8 @@ class WorkflowStatusPage(Directory):
|
|||
r += htmltext('<li><a href="visibility" rel="popup">%s</a></li>') % _('Change Status Visibility')
|
||||
r += htmltext('<li><a href="endpoint" rel="popup">%s</a></li>') % _('Change Terminal Status')
|
||||
r += htmltext('<li><a href="colour" rel="popup">%s</a></li>') % _('Change Status Colour')
|
||||
r += htmltext('<li><a href="backoffice-info-text" rel="popup">%s</a></li>'
|
||||
) % _('Change Backoffice Information Text')
|
||||
r += htmltext('<li><a href="delete" rel="popup">%s</a></li>') % _('Delete')
|
||||
r += htmltext('</ul>')
|
||||
r += htmltext('<div id="new-field">')
|
||||
|
@ -677,6 +681,26 @@ class WorkflowStatusPage(Directory):
|
|||
get_response().breadcrumb.append( ('colour', _('Status Colour')) )
|
||||
return form.render()
|
||||
|
||||
def backoffice_info_text(self):
|
||||
form = Form(enctype = 'multipart/form-data')
|
||||
form.add(WysiwygTextWidget, 'backoffice_info_text',
|
||||
title=_('Information text for backoffice'),
|
||||
value=self.status.backoffice_info_text)
|
||||
form.add_submit('submit', _('Submit'))
|
||||
form.add_submit('cancel', _('Cancel'))
|
||||
if form.get_widget('cancel').parse():
|
||||
return redirect('..')
|
||||
|
||||
if form.is_submitted() and not form.has_errors():
|
||||
self.status.backoffice_info_text = form.get_widget('backoffice_info_text').parse()
|
||||
self.workflow.store()
|
||||
return redirect('.')
|
||||
|
||||
self.html_top(title = _('Edit Backoffice Information Text'))
|
||||
get_response().breadcrumb.append( ('backoffice_info_text',
|
||||
_('Backoffice Information Text')) )
|
||||
return form.render()
|
||||
|
||||
|
||||
class WorkflowStatusDirectory(Directory):
|
||||
_q_exports = ['']
|
||||
|
|
|
@ -464,6 +464,21 @@ class FormStatusPage(Directory):
|
|||
if form:
|
||||
r += form.render()
|
||||
|
||||
if (self.filled.get_status() and self.filled.get_status().backoffice_info_text) or (
|
||||
form and any((getattr(button, 'backoffice_info_text', None)
|
||||
for button in form.get_submit_widgets()))):
|
||||
r += htmltext('<div class="backoffice-description bo-block">')
|
||||
if self.filled.get_status().backoffice_info_text:
|
||||
r += htmltext(self.filled.get_status().backoffice_info_text)
|
||||
if form:
|
||||
for button in form.get_submit_widgets():
|
||||
if not getattr(button, 'backoffice_info_text', None):
|
||||
continue
|
||||
r += htmltext('<div class="action-info-text">')
|
||||
r += htmltext(button.backoffice_info_text)
|
||||
r += htmltext('</div>')
|
||||
r += htmltext('</div>')
|
||||
|
||||
r += htmltext('<a href="..">%s</a>') % _('Back to Listing')
|
||||
return r.getvalue()
|
||||
|
||||
|
|
|
@ -1012,6 +1012,19 @@ a#filter-settings {
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
.bo-block.backoffice-description:before {
|
||||
font-family: FontAwesome;
|
||||
content: "\f05a"; /* info-circle */
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
.bo-block.backoffice-description {
|
||||
position: relative;
|
||||
padding-left: 40px;
|
||||
}
|
||||
|
||||
@media print {
|
||||
div#sidebar {
|
||||
display: none;
|
||||
|
|
|
@ -68,6 +68,7 @@ class AddAttachmentWorkflowStatusItem(WorkflowStatusItem):
|
|||
required = False
|
||||
hint = None
|
||||
by = []
|
||||
backoffice_info_text = None
|
||||
|
||||
def init(cls):
|
||||
FormStatusPage._q_extra_exports.append('attachment')
|
||||
|
@ -92,6 +93,7 @@ class AddAttachmentWorkflowStatusItem(WorkflowStatusItem):
|
|||
required=self.required, hint=self.hint)
|
||||
if self.display_button:
|
||||
form.add_submit('button%s' % self.id, self.button_label or _('Upload File'))
|
||||
form.get_widget('button%s' % self.id).backoffice_info_text = self.backoffice_info_text
|
||||
|
||||
def submit_form(self, form, formdata, user, evo):
|
||||
if form.get_widget('attachment%s' % self.id):
|
||||
|
@ -103,7 +105,8 @@ class AddAttachmentWorkflowStatusItem(WorkflowStatusItem):
|
|||
evo.add_part(AttachmentEvolutionPart.from_upload(f))
|
||||
|
||||
def get_parameters(self):
|
||||
return ('by', 'required', 'title', 'display_title', 'button_label', 'display_button', 'hint')
|
||||
return ('by', 'required', 'title', 'display_title', 'button_label',
|
||||
'display_button', 'hint', 'backoffice_info_text')
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
|
||||
if 'by' in parameters:
|
||||
|
@ -126,6 +129,10 @@ class AddAttachmentWorkflowStatusItem(WorkflowStatusItem):
|
|||
form.add(CheckboxWidget, '%sdisplay_button' % prefix, title = _('Display Button'), value = self.display_button)
|
||||
if 'hint' in parameters:
|
||||
form.add(StringWidget, '%shint' % prefix, size=40, title=_('Hint'), value=self.hint)
|
||||
if 'backoffice_info_text' in parameters:
|
||||
form.add(WysiwygTextWidget, 'backoffice_info_text',
|
||||
title=_('Information Text for Backoffice'),
|
||||
value=self.backoffice_info_text)
|
||||
|
||||
|
||||
register_item_class(AddAttachmentWorkflowStatusItem)
|
||||
|
|
|
@ -549,6 +549,7 @@ class WorkflowStatus(object):
|
|||
visibility = None
|
||||
forced_endpoint = False
|
||||
colour = 'FFFFFF'
|
||||
backoffice_info_text = None
|
||||
|
||||
def __init__(self, name = None):
|
||||
self.name = name
|
||||
|
@ -722,6 +723,10 @@ class WorkflowStatus(object):
|
|||
if self.forced_endpoint:
|
||||
ET.SubElement(status, 'forced_endpoint').text = 'true'
|
||||
|
||||
if self.backoffice_info_text:
|
||||
ET.SubElement(status, 'backoffice_info_text').text = unicode(
|
||||
self.backoffice_info_text, charset)
|
||||
|
||||
visibility_node = ET.SubElement(status, 'visibility')
|
||||
for role in self.visibility or []:
|
||||
ET.SubElement(visibility_node, 'role').text = str(role)
|
||||
|
@ -739,6 +744,8 @@ class WorkflowStatus(object):
|
|||
self.colour = elem.find('colour').text.encode(charset)
|
||||
if elem.find('forced_endpoint') is not None:
|
||||
self.forced_endpoint = (elem.find('forced_endpoint').text == 'true')
|
||||
if elem.find('backoffice_info_text') is not None:
|
||||
self.backoffice_info_text = elem.find('backoffice_info_text').text.encode(charset)
|
||||
|
||||
self.visibility = []
|
||||
for visibility_role in elem.findall('visibility/role'):
|
||||
|
@ -1089,6 +1096,7 @@ class CommentableWorkflowStatusItem(WorkflowStatusItem):
|
|||
button_label = 0 # hack to handle legacy commentable items
|
||||
hint = None
|
||||
by = []
|
||||
backoffice_info_text = None
|
||||
|
||||
def render_as_line(self):
|
||||
if self.by:
|
||||
|
@ -1109,6 +1117,7 @@ class CommentableWorkflowStatusItem(WorkflowStatusItem):
|
|||
form.add_submit('button%s' % self.id, _('Add Comment'))
|
||||
elif self.button_label:
|
||||
form.add_submit('button%s' % self.id, self.button_label)
|
||||
form.get_widget('button%s' % self.id).backoffice_info_text = self.backoffice_info_text
|
||||
|
||||
def submit_form(self, form, formdata, user, evo):
|
||||
if form.get_widget('comment'):
|
||||
|
@ -1129,7 +1138,8 @@ class CommentableWorkflowStatusItem(WorkflowStatusItem):
|
|||
self.add_parameters_widgets(form, self.get_parameters())
|
||||
|
||||
def get_parameters(self):
|
||||
return ('label', 'button_label', 'by', 'hint', 'varname')
|
||||
return ('label', 'button_label', 'by', 'hint', 'varname',
|
||||
'backoffice_info_text')
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
|
||||
if 'label' in parameters:
|
||||
|
@ -1155,6 +1165,10 @@ class CommentableWorkflowStatusItem(WorkflowStatusItem):
|
|||
form.add(VarnameWidget, '%svarname' % prefix,
|
||||
title=_('Variable Name'), value=self.varname,
|
||||
hint=_('This will make the comment available in a variable named comment_varname.'))
|
||||
if 'backoffice_info_text' in parameters:
|
||||
form.add(WysiwygTextWidget, 'backoffice_info_text',
|
||||
title=_('Information Text for Backoffice'),
|
||||
value=self.backoffice_info_text)
|
||||
|
||||
def button_label_export_to_xml(self, xml_item, charset, include_id=False):
|
||||
if self.button_label == 0:
|
||||
|
@ -1193,6 +1207,7 @@ class ChoiceWorkflowStatusItem(WorkflowStatusJumpItem):
|
|||
|
||||
label = None
|
||||
by = []
|
||||
backoffice_info_text = None
|
||||
|
||||
def render_as_line(self):
|
||||
if self.label:
|
||||
|
@ -1207,6 +1222,7 @@ class ChoiceWorkflowStatusItem(WorkflowStatusJumpItem):
|
|||
|
||||
def fill_form(self, form, formdata, user):
|
||||
form.add_submit('button%s' % self.id, self.label)
|
||||
form.get_widget('button%s' % self.id).backoffice_info_text = self.backoffice_info_text
|
||||
|
||||
def submit_form(self, form, formdata, user, evo):
|
||||
if form.get_submit() == 'button%s' % self.id:
|
||||
|
@ -1226,9 +1242,13 @@ class ChoiceWorkflowStatusItem(WorkflowStatusJumpItem):
|
|||
add_element_label = _('Add Role'),
|
||||
element_kwargs={'render_br': False,
|
||||
'options': [(None, '---')] + self.get_list_of_roles()})
|
||||
if 'backoffice_info_text' in parameters:
|
||||
form.add(WysiwygTextWidget, 'backoffice_info_text',
|
||||
title=_('Information Text for Backoffice'),
|
||||
value=self.backoffice_info_text)
|
||||
|
||||
def get_parameters(self):
|
||||
return ('by', 'status', 'label')
|
||||
return ('by', 'status', 'label', 'backoffice_info_text')
|
||||
|
||||
register_item_class(ChoiceWorkflowStatusItem)
|
||||
|
||||
|
@ -1536,6 +1556,7 @@ class EditableWorkflowStatusItem(WorkflowStatusItem):
|
|||
by = []
|
||||
status = None
|
||||
label = None
|
||||
backoffice_info_text = None
|
||||
|
||||
def render_as_line(self):
|
||||
if self.by:
|
||||
|
@ -1548,6 +1569,7 @@ class EditableWorkflowStatusItem(WorkflowStatusItem):
|
|||
if not label:
|
||||
label = _('Edit Form')
|
||||
form.add_submit('button%s' % self.id, label)
|
||||
form.get_widget('button%s' % self.id).backoffice_info_text = self.backoffice_info_text
|
||||
|
||||
def submit_form(self, form, formdata, user, evo):
|
||||
if form.get_submit() == 'button%s' % self.id:
|
||||
|
@ -1568,9 +1590,13 @@ class EditableWorkflowStatusItem(WorkflowStatusItem):
|
|||
options = [(None, '---')] + [(x.id, x.name) for x in self.parent.parent.possible_status])
|
||||
if 'label' in parameters:
|
||||
form.add(StringWidget, '%slabel' % prefix, title = _('Button Label'), value = self.label)
|
||||
if 'backoffice_info_text' in parameters:
|
||||
form.add(WysiwygTextWidget, 'backoffice_info_text',
|
||||
title=_('Information Text for Backoffice'),
|
||||
value=self.backoffice_info_text)
|
||||
|
||||
def get_parameters(self):
|
||||
return ('by', 'status', 'label')
|
||||
return ('by', 'status', 'label', 'backoffice_info_text')
|
||||
|
||||
register_item_class(EditableWorkflowStatusItem)
|
||||
|
||||
|
@ -1622,6 +1648,7 @@ class ExportToModel(WorkflowStatusItem):
|
|||
attach_to_history = False
|
||||
directory_class = ExportToModelDirectory
|
||||
by = ['_receiver']
|
||||
backoffice_info_text = None
|
||||
|
||||
def render_as_line(self):
|
||||
if self.label:
|
||||
|
@ -1642,6 +1669,7 @@ class ExportToModel(WorkflowStatusItem):
|
|||
if not label:
|
||||
label = _('Create Document')
|
||||
form.add_submit('button%s' % self.id, label)
|
||||
form.get_widget('button%s' % self.id).backoffice_info_text = self.backoffice_info_text
|
||||
|
||||
def submit_form(self, form, formdata, user, evo):
|
||||
if form.get_submit() == 'button%s' % self.id:
|
||||
|
@ -1707,6 +1735,10 @@ class ExportToModel(WorkflowStatusItem):
|
|||
form.add(UploadWidget, widget_name, directory='models',
|
||||
filename=filename, title=_('Model'), hint=hint,
|
||||
validation=self.model_file_validation, value=value)
|
||||
if 'backoffice_info_text' in parameters:
|
||||
form.add(WysiwygTextWidget, 'backoffice_info_text',
|
||||
title=_('Information Text for Backoffice'),
|
||||
value=self.backoffice_info_text)
|
||||
|
||||
def get_directory_name(self):
|
||||
return qommon.misc.simplify(self.label or 'export_to_model', space='_')
|
||||
|
@ -1729,7 +1761,7 @@ class ExportToModel(WorkflowStatusItem):
|
|||
raise TemplatingError(_('Unknown error in the template: %s') % str(e))
|
||||
|
||||
def get_parameters(self):
|
||||
return ('by', 'label', 'model_file', 'attach_to_history')
|
||||
return ('by', 'label', 'model_file', 'attach_to_history', 'backoffice_info_text')
|
||||
|
||||
def model_file_export_to_xml(self, xml_item, charset, include_id=False):
|
||||
if not self.model_file:
|
||||
|
|
Loading…
Reference in New Issue