workflows: add conditions on all actions (#16341)
This commit is contained in:
parent
46ef21e541
commit
5fefb61a9e
|
@ -4014,3 +4014,65 @@ def test_backoffice_display_message(pub):
|
|||
resp = app.get(formdata.get_url(backoffice=True))
|
||||
assert 'message-to-all' in resp.body
|
||||
assert resp.body.index('message-to-all') > resp.body.index('message-to-receiver')
|
||||
|
||||
def test_backoffice_forms_condition_on_button(pub):
|
||||
create_superuser(pub)
|
||||
create_environment(pub, set_receiver=True)
|
||||
|
||||
workflow = Workflow.get_default_workflow()
|
||||
workflow.id = '2'
|
||||
workflow.store()
|
||||
|
||||
formdef = FormDef.get_by_urlname('form-title')
|
||||
formdef.workflow = workflow
|
||||
formdef.store()
|
||||
|
||||
# move some forms from new to accepted
|
||||
for i, formdata in enumerate(formdef.data_class().select(lambda x: x.status == 'wf-new')):
|
||||
if i % 2:
|
||||
formdata.status = 'wf-accepted'
|
||||
formdata.store()
|
||||
|
||||
app = login(get_app(pub))
|
||||
resp = app.get('/backoffice/')
|
||||
resp = resp.click('Management', index=0)
|
||||
resp = resp.follow()
|
||||
assert '17 open on 50' in resp.body
|
||||
|
||||
formdata = [x for x in formdef.data_class().select() if x.status == 'wf-new'][0]
|
||||
resp = app.get(formdata.get_url(backoffice=True))
|
||||
assert 'button_commentable' in resp.body
|
||||
assert 'button_accept' in resp.body
|
||||
assert 'button_reject' in resp.body
|
||||
|
||||
# commentable
|
||||
workflow.possible_status[1].items[0].condition = {'type': 'python', 'value': 'False'}
|
||||
# reject
|
||||
workflow.possible_status[1].items[2].condition = {'type': 'python', 'value': 'False'}
|
||||
workflow.store()
|
||||
|
||||
resp = app.get(formdata.get_url(backoffice=True))
|
||||
assert 'button_commentable' not in resp.body
|
||||
assert 'button_accept' in resp.body
|
||||
assert 'button_reject' not in resp.body
|
||||
|
||||
formdef = FormDef.get_by_urlname('form-title')
|
||||
assert formdef.data_class().get(formdata.id).actions_roles == set(['1'])
|
||||
|
||||
# accept
|
||||
workflow.possible_status[1].items[1].condition = {'type': 'python', 'value': 'False'}
|
||||
workflow.store()
|
||||
|
||||
resp = app.get(formdata.get_url(backoffice=True))
|
||||
assert 'button_commentable' not in resp.body
|
||||
assert 'button_accept' not in resp.body
|
||||
assert 'button_reject' not in resp.body
|
||||
|
||||
formdef = FormDef.get_by_urlname('form-title')
|
||||
assert formdef.data_class().get(formdata.id).actions_roles == set()
|
||||
|
||||
app = login(get_app(pub))
|
||||
resp = app.get('/backoffice/')
|
||||
resp = resp.click('Management', index=0)
|
||||
resp = resp.follow()
|
||||
assert '8 open on 50' in resp.body # only the accepted ones
|
||||
|
|
|
@ -3881,6 +3881,45 @@ def test_display_message(pub):
|
|||
page = app.get(formdata.get_url())
|
||||
assert 'warningnotice' in page.body
|
||||
|
||||
def test_workflow_condition_on_message(pub):
|
||||
user = create_user(pub)
|
||||
|
||||
formdef = create_formdef()
|
||||
formdef.fields = []
|
||||
formdef.store()
|
||||
|
||||
workflow = Workflow(name='test')
|
||||
st1 = workflow.add_status('Status1', 'st1')
|
||||
|
||||
display1 = DisplayMessageWorkflowStatusItem()
|
||||
display1.message = 'message-to-all'
|
||||
display1.to = []
|
||||
st1.items.append(display1)
|
||||
display1.parent = st1
|
||||
|
||||
workflow.store()
|
||||
|
||||
formdef.workflow_id = workflow.id
|
||||
formdef.store()
|
||||
|
||||
formdef.data_class().wipe()
|
||||
|
||||
app = login(get_app(pub), username='foo', password='foo')
|
||||
page = app.get('/test/')
|
||||
page = page.forms[0].submit('submit') # form page
|
||||
page = page.forms[0].submit('submit') # confirmation page
|
||||
page = page.follow()
|
||||
assert 'message-to-all' in page.body
|
||||
|
||||
formdata = formdef.data_class().select()[0]
|
||||
page = app.get(formdata.get_url())
|
||||
assert 'message-to-all' in page.body
|
||||
|
||||
display1.condition = {'type': 'django', 'value': 'xxx'}
|
||||
workflow.store()
|
||||
page = app.get(formdata.get_url())
|
||||
assert not 'message-to-all' in page.body
|
||||
|
||||
def test_session_cookie_flags(pub):
|
||||
formdef = create_formdef()
|
||||
app = get_app(pub)
|
||||
|
@ -4404,3 +4443,61 @@ def test_user_global_action(pub):
|
|||
resp = app.get(formdata.get_url())
|
||||
assert 'HELLO WORLD GLOBAL ACTION' in resp.body
|
||||
assert formdef.data_class().get(formdata.id).status == 'wf-finished'
|
||||
|
||||
def test_condition_on_action(pub, emails):
|
||||
user = create_user(pub)
|
||||
|
||||
workflow = Workflow.get_default_workflow()
|
||||
# change email subjects to differentiate them
|
||||
workflow.possible_status[0].items[0].subject = 'New form ([name])'
|
||||
workflow.possible_status[0].items[1].subject = 'New form2 ([name])'
|
||||
workflow.id = '2'
|
||||
workflow.store()
|
||||
|
||||
formdef = FormDef()
|
||||
formdef.name = 'test condition on action'
|
||||
formdef.fields = []
|
||||
formdef.workflow_id = workflow.id
|
||||
formdef.workflow_roles = {}
|
||||
formdef.store()
|
||||
|
||||
formdef.data_class().wipe()
|
||||
|
||||
app = login(get_app(pub), username='foo', password='foo')
|
||||
resp = app.get(formdef.get_url())
|
||||
resp = resp.form.submit('submit')
|
||||
resp = resp.form.submit('submit')
|
||||
assert not emails.get('New form (test condition on action)') # no receiver
|
||||
assert emails.get('New form2 (test condition on action)') # submitter
|
||||
|
||||
emails.empty()
|
||||
|
||||
workflow.possible_status[0].items[1].condition = {'type': 'python', 'value': 'False'}
|
||||
workflow.store()
|
||||
|
||||
app = login(get_app(pub), username='foo', password='foo')
|
||||
resp = app.get(formdef.get_url())
|
||||
resp = resp.form.submit('submit')
|
||||
resp = resp.form.submit('submit')
|
||||
assert not emails.get('New form2 (test condition on action)')
|
||||
|
||||
# check with a condition on field data
|
||||
formdef.fields = [fields.StringField(id='0', label='string', varname='foobar')]
|
||||
formdef.store()
|
||||
workflow.possible_status[0].items[1].condition = {'type': 'django', 'value': 'form_var_foobar'}
|
||||
workflow.store()
|
||||
|
||||
app = login(get_app(pub), username='foo', password='foo')
|
||||
resp = app.get(formdef.get_url())
|
||||
resp.form['f0'] = ''
|
||||
resp = resp.form.submit('submit')
|
||||
resp = resp.form.submit('submit')
|
||||
assert not emails.get('New form2 (test condition on action)')
|
||||
|
||||
# check with condition evaluating positively
|
||||
app = login(get_app(pub), username='foo', password='foo')
|
||||
resp = app.get(formdef.get_url())
|
||||
resp.form['f0'] = 'toto'
|
||||
resp = resp.form.submit('submit')
|
||||
resp = resp.form.submit('submit')
|
||||
assert emails.get('New form2 (test condition on action)')
|
||||
|
|
|
@ -442,6 +442,8 @@ class FormData(StorableObject):
|
|||
return []
|
||||
messages = []
|
||||
for item in wf_status.items:
|
||||
if not item.check_condition(self):
|
||||
continue
|
||||
if hasattr(item, 'get_message'):
|
||||
message = item.get_message(self, position=position)
|
||||
if message:
|
||||
|
@ -815,6 +817,8 @@ class FormData(StorableObject):
|
|||
for item in wf_status.items or []:
|
||||
if not hasattr(item, 'by') or not item.by:
|
||||
continue
|
||||
if not item.check_condition(self):
|
||||
continue
|
||||
for role in item.by:
|
||||
if role == '_submitter':
|
||||
status_action_roles.add(role)
|
||||
|
|
|
@ -41,6 +41,8 @@ class AggregationEmailWorkflowStatusItem(WorkflowStatusItem):
|
|||
return _('not completed')
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
|
||||
super(AggregationEmailWorkflowStatusItem, self).add_parameters_widgets(
|
||||
form, parameters, prefix=prefix, formdef=formdef)
|
||||
if 'to' in parameters:
|
||||
form.add(WidgetList, '%sto' % prefix, title = _('To'), element_type = SingleSelectWidget,
|
||||
value = self.to,
|
||||
|
@ -50,7 +52,7 @@ class AggregationEmailWorkflowStatusItem(WorkflowStatusItem):
|
|||
self.get_list_of_roles(include_logged_in_users=False)})
|
||||
|
||||
def get_parameters(self):
|
||||
return ('to',)
|
||||
return ('to', 'condition')
|
||||
|
||||
def perform(self, formdata):
|
||||
if not self.to:
|
||||
|
|
|
@ -137,13 +137,16 @@ class AddAttachmentWorkflowStatusItem(WorkflowStatusItem):
|
|||
|
||||
def get_parameters(self):
|
||||
parameters = ('by', 'required', 'title', 'display_title', 'button_label',
|
||||
'display_button', 'hint', 'backoffice_info_text', 'varname',
|
||||
'backoffice_filefield_id', 'attach_to_history')
|
||||
'display_button', 'hint', 'backoffice_info_text',
|
||||
'backoffice_filefield_id', 'varname', 'attach_to_history')
|
||||
if has_portfolio():
|
||||
parameters += ('push_to_portfolio',)
|
||||
parameters += ('condition',)
|
||||
return parameters
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
|
||||
super(AddAttachmentWorkflowStatusItem, self).add_parameters_widgets(
|
||||
form, parameters, prefix=prefix, formdef=formdef)
|
||||
if 'by' in parameters:
|
||||
form.add(WidgetList, '%sby' % prefix, title = _('By'),
|
||||
element_type = SingleSelectWidget,
|
||||
|
|
|
@ -76,9 +76,11 @@ class SetBackofficeFieldsWorkflowStatusItem(WorkflowStatusItem):
|
|||
return bool(workflow and getattr(workflow.backoffice_fields_formdef, 'fields', None))
|
||||
|
||||
def get_parameters(self):
|
||||
return ('fields',)
|
||||
return ('fields', 'condition')
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
|
||||
super(SetBackofficeFieldsWorkflowStatusItem, self).add_parameters_widgets(
|
||||
form, parameters, prefix=prefix, formdef=formdef)
|
||||
if 'fields' in parameters:
|
||||
form.add(SetBackofficeFieldsTableWidget, '%sfields' % prefix,
|
||||
title=_('Fields Update'), value=self.fields,
|
||||
|
|
|
@ -33,13 +33,15 @@ class ModifyCriticalityWorkflowStatusItem(WorkflowStatusItem):
|
|||
absolute_value = None
|
||||
|
||||
def get_parameters(self):
|
||||
return ('mode', 'absolute_value')
|
||||
return ('mode', 'absolute_value', 'condition')
|
||||
|
||||
@classmethod
|
||||
def is_available(cls, workflow=None):
|
||||
return workflow and workflow.criticality_levels
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
|
||||
super(ModifyCriticalityWorkflowStatusItem, self).add_parameters_widgets(
|
||||
form, parameters, prefix=prefix, formdef=formdef)
|
||||
if 'mode' in parameters:
|
||||
form.add(SingleSelectWidget, '%smode' % prefix,
|
||||
title=_('Modification Mode'), value=self.mode,
|
||||
|
|
|
@ -89,7 +89,8 @@ class DispatchWorkflowStatusItem(WorkflowStatusItem):
|
|||
rules = None
|
||||
|
||||
def get_parameters(self):
|
||||
return ('role_key', 'role_id', 'dispatch_type', 'variable', 'rules')
|
||||
return ('role_key', 'dispatch_type', 'role_id', 'variable', 'rules',
|
||||
'condition')
|
||||
|
||||
def role_id_export_to_xml(self, item, charset, include_id=False):
|
||||
self._role_export_to_xml('role_id', item, charset,
|
||||
|
@ -129,6 +130,8 @@ class DispatchWorkflowStatusItem(WorkflowStatusItem):
|
|||
return None
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
|
||||
super(DispatchWorkflowStatusItem, self).add_parameters_widgets(
|
||||
form, parameters, prefix=prefix, formdef=formdef)
|
||||
if 'role_key' in parameters:
|
||||
if not self.parent.parent.roles:
|
||||
self.parent.parent.roles = {}
|
||||
|
|
|
@ -277,16 +277,19 @@ class ExportToModel(WorkflowStatusItem):
|
|||
raise UploadValidationError(_('Only RTF and OpenDocument files can be used'))
|
||||
|
||||
def get_parameters(self):
|
||||
parameters = ('method', 'by', 'label', 'model_file', 'attach_to_history',
|
||||
'backoffice_info_text', 'varname', 'backoffice_filefield_id', 'filename')
|
||||
parameters = ('model_file',)
|
||||
if transform_to_pdf is not None:
|
||||
parameters += ('convert_to_pdf',)
|
||||
parameters += ('backoffice_filefield_id', 'attach_to_history', 'varname')
|
||||
if has_portfolio():
|
||||
parameters += ('push_to_portfolio',)
|
||||
parameters += ('method', 'by', 'label', 'backoffice_info_text', 'filename', 'condition')
|
||||
return parameters
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='',
|
||||
formdef=None):
|
||||
super(ExportToModel, self).add_parameters_widgets(
|
||||
form, parameters, prefix=prefix, formdef=formdef)
|
||||
methods = collections.OrderedDict(
|
||||
[('interactive', _('Interactive (button)')),
|
||||
('non-interactive', _('Non interactive'))])
|
||||
|
|
|
@ -89,6 +89,8 @@ class FormWorkflowStatusItem(WorkflowStatusItem):
|
|||
FileDirectory.lookup_wf_form_file = lookup_wf_form_file
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
|
||||
super(FormWorkflowStatusItem, self).add_parameters_widgets(
|
||||
form, parameters, prefix=prefix, formdef=formdef)
|
||||
if 'by' in parameters:
|
||||
form.add(WidgetList, '%sby' % prefix, title = _('To'), element_type = SingleSelectWidget,
|
||||
value = self.by,
|
||||
|
@ -104,7 +106,7 @@ class FormWorkflowStatusItem(WorkflowStatusItem):
|
|||
form.widgets.append(HtmlWidget(htmltext('<p><a href="fields/">%s</a></p>') % _('Edit Fields')))
|
||||
|
||||
def get_parameters(self):
|
||||
return ('by', 'varname')
|
||||
return ('by', 'varname', 'condition')
|
||||
|
||||
def export_to_xml(self, charset, include_id=False):
|
||||
item = WorkflowStatusItem.export_to_xml(self, charset, include_id=include_id)
|
||||
|
|
|
@ -44,9 +44,12 @@ class GeolocateWorkflowStatusItem(WorkflowStatusItem):
|
|||
overwrite = True
|
||||
|
||||
def get_parameters(self):
|
||||
return ('method', 'address_string', 'map_variable', 'photo_variable', 'overwrite')
|
||||
return ('method', 'address_string', 'map_variable', 'photo_variable',
|
||||
'overwrite', 'condition')
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
|
||||
super(GeolocateWorkflowStatusItem, self).add_parameters_widgets(
|
||||
form, parameters, prefix=prefix, formdef=formdef)
|
||||
methods = collections.OrderedDict(
|
||||
[('address_string', _('Address String')),
|
||||
('map_variable', _('Map Variable')),
|
||||
|
|
|
@ -147,6 +147,10 @@ class JumpWorkflowStatusItem(WorkflowStatusJumpItem):
|
|||
return True
|
||||
return False
|
||||
|
||||
def render_as_line(self):
|
||||
# override parent method to avoid mentioning the condition twice.
|
||||
return '%s (%s)' % (_(self.description), self.get_line_details())
|
||||
|
||||
def get_line_details(self):
|
||||
if not self.status:
|
||||
return _('not completed')
|
||||
|
@ -169,13 +173,13 @@ class JumpWorkflowStatusItem(WorkflowStatusJumpItem):
|
|||
return wf_status[0].name
|
||||
|
||||
def get_parameters(self):
|
||||
return ('status', 'set_marker_on_status', 'condition', 'trigger', 'by', 'timeout')
|
||||
return ('status', 'condition', 'trigger', 'by', 'timeout', 'set_marker_on_status')
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
|
||||
WorkflowStatusJumpItem.add_parameters_widgets(self, form, parameters, prefix, formdef)
|
||||
super(JumpWorkflowStatusItem, self).add_parameters_widgets(
|
||||
form, parameters, prefix, formdef)
|
||||
if 'condition' in parameters:
|
||||
form.add(ConditionWidget, '%scondition' % prefix, title=_('Condition (formula)'),
|
||||
value=self.condition, size=40)
|
||||
form.get_widget('%scondition' % prefix).advanced = False
|
||||
if 'trigger' in parameters:
|
||||
form.add(StringWidget, '%strigger' % prefix, title=_('Trigger (string)'),
|
||||
value=self.trigger, size=40)
|
||||
|
@ -219,6 +223,10 @@ class JumpWorkflowStatusItem(WorkflowStatusJumpItem):
|
|||
self.handle_markers_stack(formdata)
|
||||
formdata.status = 'wf-%s' % wf_status[0].id
|
||||
|
||||
def check_condition(self, formdata):
|
||||
# ship condition check here so it is not evaluated twice.
|
||||
return True
|
||||
|
||||
def must_jump(self, formdata):
|
||||
must_jump = True
|
||||
|
||||
|
|
|
@ -109,9 +109,11 @@ class UpdateUserProfileStatusItem(WorkflowStatusItem):
|
|||
fields = None
|
||||
|
||||
def get_parameters(self):
|
||||
return ('fields',)
|
||||
return ('fields', 'condition')
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
|
||||
super(UpdateUserProfileStatusItem, self).add_parameters_widgets(
|
||||
form, parameters, prefix=prefix, formdef=formdef)
|
||||
if 'fields' in parameters:
|
||||
form.add(ProfileUpdateTableWidget, '%sfields' % prefix,
|
||||
title=_('Profile Update'),
|
||||
|
|
|
@ -35,9 +35,11 @@ class RedirectToUrlWorkflowStatusItem(WorkflowStatusItem):
|
|||
return _('not configured')
|
||||
|
||||
def get_parameters(self):
|
||||
return ('url',)
|
||||
return ('url', 'condition')
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
|
||||
super(RedirectToUrlWorkflowStatusItem, self).add_parameters_widgets(
|
||||
form, parameters, prefix=prefix, formdef=formdef)
|
||||
if 'url' in parameters:
|
||||
widget = form.add(ComputedExpressionWidget, '%surl' % prefix,
|
||||
title=_('URL'), value=self.url,
|
||||
|
|
|
@ -80,12 +80,14 @@ class RegisterCommenterWorkflowStatusItem(WorkflowStatusItem):
|
|||
comment = None
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
|
||||
super(RegisterCommenterWorkflowStatusItem, self).add_parameters_widgets(
|
||||
form, parameters, prefix=prefix, formdef=formdef)
|
||||
if 'comment' in parameters:
|
||||
form.add(TextWidget, '%scomment' % prefix, title=_('Comment'),
|
||||
value=self.comment, cols=80, rows=10)
|
||||
|
||||
def get_parameters(self):
|
||||
return ('comment',)
|
||||
return ('comment', 'condition')
|
||||
|
||||
def perform(self, formdata):
|
||||
if not formdata.evolution:
|
||||
|
|
|
@ -112,6 +112,8 @@ class ResubmitWorkflowStatusItem(WorkflowStatusItem):
|
|||
formdata.store()
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
|
||||
super(ResubmitWorkflowStatusItem, self).add_parameters_widgets(
|
||||
form, parameters, prefix=prefix, formdef=formdef)
|
||||
if 'by' in parameters:
|
||||
form.add(WidgetList, '%sby' % prefix, title=_('By'), element_type=SingleSelectWidget,
|
||||
value=self.by,
|
||||
|
@ -132,6 +134,6 @@ class ResubmitWorkflowStatusItem(WorkflowStatusItem):
|
|||
value=self.backoffice_info_text)
|
||||
|
||||
def get_parameters(self):
|
||||
return ('by', 'label', 'formdef_slug', 'backoffice_info_text')
|
||||
return ('by', 'label', 'formdef_slug', 'backoffice_info_text', 'condition')
|
||||
|
||||
register_item_class(ResubmitWorkflowStatusItem)
|
||||
|
|
|
@ -53,9 +53,11 @@ class AddRoleWorkflowStatusItem(WorkflowStatusItem):
|
|||
role_id = None
|
||||
|
||||
def get_parameters(self):
|
||||
return ('role_id',)
|
||||
return ('role_id', 'condition')
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
|
||||
super(AddRoleWorkflowStatusItem, self).add_parameters_widgets(
|
||||
form, parameters, prefix=prefix, formdef=formdef)
|
||||
if 'role_id' in parameters:
|
||||
form.add(SingleSelectWidget, '%srole_id' % prefix,
|
||||
title=_('Role to Add'), value=str(self.role_id),
|
||||
|
@ -127,9 +129,11 @@ class RemoveRoleWorkflowStatusItem(WorkflowStatusItem):
|
|||
role_id = None
|
||||
|
||||
def get_parameters(self):
|
||||
return ('role_id',)
|
||||
return ('role_id', 'condition')
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
|
||||
super(RemoveRoleWorkflowStatusItem, self).add_parameters_widgets(
|
||||
form, parameters, prefix=prefix, formdef=formdef)
|
||||
if 'role_id' in parameters:
|
||||
form.add(SingleSelectWidget, '%srole_id' % prefix,
|
||||
title=_('Role to Remove'), value=self.role_id,
|
||||
|
|
|
@ -143,18 +143,22 @@ class WebserviceCallStatusItem(WorkflowStatusItem):
|
|||
return None
|
||||
|
||||
def get_parameters(self):
|
||||
return ('url', 'post', 'varname', 'request_signature_key', 'post_data',
|
||||
return ('label', 'url', 'request_signature_key', 'qs_data',
|
||||
'method', 'post', 'post_data',
|
||||
'response_type', 'varname', 'backoffice_filefield_id',
|
||||
'action_on_app_error', 'action_on_4xx', 'action_on_5xx', 'action_on_bad_data',
|
||||
'action_on_network_errors', 'notify_on_errors',
|
||||
'record_errors', 'label', 'method', 'response_type',
|
||||
'qs_data', 'backoffice_filefield_id')
|
||||
'action_on_network_errors',
|
||||
'notify_on_errors', 'record_errors',
|
||||
'condition')
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
|
||||
super(WebserviceCallStatusItem, self).add_parameters_widgets(
|
||||
form, parameters, prefix=prefix, formdef=formdef)
|
||||
if 'label' in parameters:
|
||||
form.add(StringWidget, '%slabel' % prefix, size=40, title=_('Label'), value=self.label)
|
||||
|
||||
form.widgets.append(HtmlWidget(htmltext('<h3>%s</h3>') % _('Request')))
|
||||
if 'url' in parameters:
|
||||
form.widgets.append(HtmlWidget(htmltext('<h3>%s</h3>') % _('Request')))
|
||||
form.add(StringWidget, '%surl' % prefix,
|
||||
title=_('URL'), value=self.url, size=80,
|
||||
hint=_('Common substitution variables are available with the {{variable}} syntax.'))
|
||||
|
@ -193,10 +197,10 @@ class WebserviceCallStatusItem(WorkflowStatusItem):
|
|||
'data-dynamic-display-value': methods.get('POST'),
|
||||
})
|
||||
|
||||
form.widgets.append(HtmlWidget(htmltext('<h3>%s</h3>') % _('Response')))
|
||||
response_types = collections.OrderedDict(
|
||||
[('json', _('JSON')), ('attachment', _('Attachment'))])
|
||||
if 'response_type' in parameters:
|
||||
form.widgets.append(HtmlWidget(htmltext('<h3>%s</h3>') % _('Response')))
|
||||
form.add(RadiobuttonsWidget, '%sresponse_type' % prefix,
|
||||
title=_('Response Type'),
|
||||
options=response_types.items(),
|
||||
|
@ -218,7 +222,9 @@ class WebserviceCallStatusItem(WorkflowStatusItem):
|
|||
'data-dynamic-display-value': response_types.get('attachment'),
|
||||
})
|
||||
|
||||
form.widgets.append(HtmlWidget(htmltext('<h3>%s</h3>') % _('Error Handling')))
|
||||
if 'action_on_app_error' in parameters:
|
||||
form.widgets.append(HtmlWidget(htmltext('<h3>%s</h3>') % _('Error Handling')))
|
||||
|
||||
error_actions = [(':stop', _('Stop')), (':pass', _('Ignore'))]
|
||||
error_actions.extend([(x.id, _('Jump to %s') % x.name) for x in
|
||||
self.parent.parent.possible_status])
|
||||
|
|
|
@ -38,6 +38,7 @@ from quixote.html import htmltext
|
|||
import qommon.errors
|
||||
from qommon.template import Template, TemplateError
|
||||
|
||||
from wcs.conditions import Condition
|
||||
from wcs.roles import Role, logged_users_role, get_user_roles
|
||||
from wcs.fields import FileField
|
||||
from wcs.formdef import FormDef
|
||||
|
@ -59,6 +60,8 @@ def perform_items(items, formdata, depth=20):
|
|||
url = None
|
||||
old_status = formdata.status
|
||||
for item in items:
|
||||
if not item.check_condition(formdata):
|
||||
continue
|
||||
try:
|
||||
url = item.perform(formdata) or url
|
||||
except AbortActionException:
|
||||
|
@ -1289,6 +1292,8 @@ class WorkflowStatus(object):
|
|||
for item in self.items:
|
||||
if not item.check_auth(filled, user):
|
||||
continue
|
||||
if not item.check_condition(filled):
|
||||
continue
|
||||
item.fill_form(form, filled, user)
|
||||
|
||||
for action in filled.formdef.workflow.get_global_actions_for_user(filled, user):
|
||||
|
@ -1337,6 +1342,8 @@ class WorkflowStatus(object):
|
|||
break
|
||||
else:
|
||||
continue
|
||||
if not item.check_condition(filled):
|
||||
continue
|
||||
next_url = item.submit_form(form, filled, user, evo)
|
||||
if next_url is True:
|
||||
break
|
||||
|
@ -1491,6 +1498,7 @@ class WorkflowStatusItem(XmlSerialisable):
|
|||
description = 'XX'
|
||||
category = None # (key, label)
|
||||
id = None
|
||||
condition = None
|
||||
|
||||
endpoint = True # means it's not possible to interact, and/or cause a status change
|
||||
waitpoint = False # means it's possible to wait (user interaction, or other event)
|
||||
|
@ -1517,10 +1525,13 @@ class WorkflowStatusItem(XmlSerialisable):
|
|||
return changed
|
||||
|
||||
def render_as_line(self):
|
||||
label = _(self.description)
|
||||
details = self.get_line_details()
|
||||
if details:
|
||||
return _(self.description) + ' (%s)' % details
|
||||
return _(self.description)
|
||||
label += ' (%s)' % details
|
||||
if self.condition and self.condition.get('value'):
|
||||
label += ' (%s)' % _('conditional')
|
||||
return label
|
||||
|
||||
def get_line_details(self):
|
||||
return None
|
||||
|
@ -1560,17 +1571,27 @@ class WorkflowStatusItem(XmlSerialisable):
|
|||
|
||||
return False
|
||||
|
||||
def check_condition(self, formdata):
|
||||
try:
|
||||
return Condition(self.condition).evaluate()
|
||||
except RuntimeError:
|
||||
return False
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
|
||||
pass
|
||||
if 'condition' in parameters:
|
||||
form.add(ConditionWidget, '%scondition' % prefix, title=_('Condition'),
|
||||
value=self.condition, size=40,
|
||||
advanced=not(self.condition))
|
||||
|
||||
def get_parameters(self):
|
||||
return ()
|
||||
return ('condition',)
|
||||
|
||||
def get_parameters_view(self):
|
||||
r = TemplateIO(html=True)
|
||||
form = Form()
|
||||
parameters = [x for x in self.get_parameters() if getattr(self, x, None) is not None]
|
||||
self.add_parameters_widgets(form, parameters)
|
||||
for parameter in parameters:
|
||||
self.add_parameters_widgets(form, [parameter])
|
||||
r += htmltext('<ul>')
|
||||
for parameter in parameters:
|
||||
r += htmltext('<li>')
|
||||
|
@ -1615,7 +1636,8 @@ class WorkflowStatusItem(XmlSerialisable):
|
|||
return str(value)
|
||||
|
||||
def fill_admin_form(self, form):
|
||||
self.add_parameters_widgets(form, self.get_parameters())
|
||||
for parameter in self.get_parameters():
|
||||
self.add_parameters_widgets(form, [parameter])
|
||||
|
||||
def submit_admin_form(self, form):
|
||||
for f in self.get_parameters():
|
||||
|
@ -1724,6 +1746,18 @@ class WorkflowStatusItem(XmlSerialisable):
|
|||
def to_init_with_xml(self, elem, charset, include_id=False):
|
||||
self._roles_init_with_xml('to', elem, charset, include_id)
|
||||
|
||||
def condition_init_with_xml(self, node, charset, include_id=False):
|
||||
if node is None:
|
||||
self.condition = None
|
||||
elif node.findall('type'):
|
||||
self.condition = {
|
||||
'type': node.find('type').text.encode(charset),
|
||||
'value': node.find('value').text.encode(charset),
|
||||
}
|
||||
else:
|
||||
# backward compatibility
|
||||
self.condition = {'type': 'python', 'value': node.text.encode(charset)}
|
||||
|
||||
def q_admin_lookup(self, workflow, status, component, html_top):
|
||||
return None
|
||||
|
||||
|
@ -1741,6 +1775,8 @@ class WorkflowStatusJumpItem(WorkflowStatusItem):
|
|||
category = 'status-change'
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
|
||||
super(WorkflowStatusJumpItem, self).add_parameters_widgets(
|
||||
form, parameters, prefix=prefix, formdef=formdef)
|
||||
if 'status' in parameters:
|
||||
destinations = [(x.id, x.name) for x in self.parent.parent.possible_status]
|
||||
|
||||
|
@ -1776,7 +1812,7 @@ class WorkflowStatusJumpItem(WorkflowStatusItem):
|
|||
formdata.update_workflow_data({'_markers_stack': markers_stack})
|
||||
|
||||
def get_parameters(self):
|
||||
return ('status', 'set_marker_on_status')
|
||||
return ('status', 'set_marker_on_status', 'condition')
|
||||
|
||||
|
||||
def get_role_translation(formdata, role_name):
|
||||
|
@ -1880,10 +1916,12 @@ class CommentableWorkflowStatusItem(WorkflowStatusItem):
|
|||
self.add_parameters_widgets(form, self.get_parameters())
|
||||
|
||||
def get_parameters(self):
|
||||
return ('label', 'button_label', 'by', 'hint', 'varname',
|
||||
'backoffice_info_text')
|
||||
return ('label', 'button_label', 'hint', 'by', 'varname',
|
||||
'backoffice_info_text', 'condition')
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
|
||||
super(CommentableWorkflowStatusItem, self).add_parameters_widgets(
|
||||
form, parameters, prefix=prefix, formdef=formdef)
|
||||
if 'label' in parameters:
|
||||
if self.label is None:
|
||||
self.label = _('Comment')
|
||||
|
@ -1993,10 +2031,11 @@ class ChoiceWorkflowStatusItem(WorkflowStatusJumpItem):
|
|||
return True # get out of processing loop
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
|
||||
super(ChoiceWorkflowStatusItem, self).add_parameters_widgets(
|
||||
form, parameters, prefix=prefix, formdef=formdef)
|
||||
if 'label' in parameters:
|
||||
form.add(ComputedExpressionWidget, '%slabel' % prefix,
|
||||
title=_('Label'), value=self.label)
|
||||
WorkflowStatusJumpItem.add_parameters_widgets(self, form, parameters, prefix, formdef)
|
||||
if 'by' in parameters:
|
||||
form.add(WidgetList, '%sby' % prefix, title = _('By'), element_type = SingleSelectWidget,
|
||||
value = self.by,
|
||||
|
@ -2013,8 +2052,11 @@ class ChoiceWorkflowStatusItem(WorkflowStatusJumpItem):
|
|||
value=self.backoffice_info_text)
|
||||
|
||||
def get_parameters(self):
|
||||
return ('by', 'status', 'label', 'backoffice_info_text',
|
||||
'require_confirmation', 'set_marker_on_status')
|
||||
return ('label', 'by', 'status',
|
||||
'require_confirmation',
|
||||
'backoffice_info_text',
|
||||
'set_marker_on_status',
|
||||
'condition')
|
||||
|
||||
register_item_class(ChoiceWorkflowStatusItem)
|
||||
|
||||
|
@ -2041,7 +2083,7 @@ class JumpOnSubmitWorkflowStatusItem(WorkflowStatusJumpItem):
|
|||
self.handle_markers_stack(formdata)
|
||||
|
||||
def get_parameters(self):
|
||||
return ('status', 'set_marker_on_status')
|
||||
return ('status', 'set_marker_on_status', 'condition')
|
||||
register_item_class(JumpOnSubmitWorkflowStatusItem)
|
||||
|
||||
|
||||
|
@ -2100,7 +2142,7 @@ class SendmailWorkflowStatusItem(WorkflowStatusItem):
|
|||
return _('not completed')
|
||||
|
||||
def get_parameters(self):
|
||||
return ('to', 'subject', 'body', 'attachments', 'custom_from')
|
||||
return ('to', 'subject', 'body', 'attachments', 'custom_from', 'condition')
|
||||
|
||||
def fill_admin_form(self, form):
|
||||
self.add_parameters_widgets(form, self.get_parameters())
|
||||
|
@ -2124,6 +2166,8 @@ class SendmailWorkflowStatusItem(WorkflowStatusItem):
|
|||
return attachments_options, attachments
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
|
||||
super(SendmailWorkflowStatusItem, self).add_parameters_widgets(
|
||||
form, parameters, prefix=prefix, formdef=formdef)
|
||||
if 'to' in parameters:
|
||||
form.add(WidgetList, '%sto' % prefix, title=_('To'),
|
||||
element_type=SingleSelectWidgetWithOther,
|
||||
|
@ -2355,9 +2399,11 @@ class SendSMSWorkflowStatusItem(WorkflowStatusItem):
|
|||
self.add_parameters_widgets(form, self.get_parameters())
|
||||
|
||||
def get_parameters(self):
|
||||
return ('to', 'body')
|
||||
return ('to', 'body', 'condition')
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
|
||||
super(SendSMSWorkflowStatusItem, self).add_parameters_widgets(
|
||||
form, parameters, prefix=prefix, formdef=formdef)
|
||||
if 'to' in parameters:
|
||||
form.add(WidgetList, '%sto' % prefix, title=_('To'),
|
||||
element_type=ComputedExpressionWidget,
|
||||
|
@ -2460,6 +2506,8 @@ class DisplayMessageWorkflowStatusItem(WorkflowStatusItem):
|
|||
return Template(message, ezt_format=ezt.FORMAT_HTML).render(dict)
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
|
||||
super(DisplayMessageWorkflowStatusItem, self).add_parameters_widgets(
|
||||
form, parameters, prefix=prefix, formdef=formdef)
|
||||
if 'message' in parameters:
|
||||
form.add(TextWidget, '%smessage' % prefix, title = _('Message'),
|
||||
value=self.message, cols=80, rows=10,
|
||||
|
@ -2489,7 +2537,7 @@ class DisplayMessageWorkflowStatusItem(WorkflowStatusItem):
|
|||
self.get_list_of_roles(include_logged_in_users=False)})
|
||||
|
||||
def get_parameters(self):
|
||||
return ('message', 'level', 'position', 'to')
|
||||
return ('message', 'level', 'position', 'to', 'condition')
|
||||
|
||||
def get_message_parameter_view_value(self):
|
||||
if self.message.startswith('<'):
|
||||
|
@ -2511,6 +2559,8 @@ class RedirectToStatusWorkflowStatusItem(WorkflowStatusItem):
|
|||
return formdata.get_url(self.backoffice)
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
|
||||
super(RedirectToStatusWorkflowStatusItem, self).add_parameters_widgets(
|
||||
form, parameters, prefix=prefix, formdef=formdef)
|
||||
if 'backoffice' in parameters:
|
||||
form.add(CheckboxWidget, '%sbackoffice' % prefix,
|
||||
title = _('Redirect to backoffice page'),
|
||||
|
@ -2554,6 +2604,8 @@ class EditableWorkflowStatusItem(WorkflowStatusItem):
|
|||
return formdata.get_url(backoffice=get_request().is_in_backoffice()) + 'wfedit-%s' % self.id
|
||||
|
||||
def add_parameters_widgets(self, form, parameters, prefix='', formdef=None):
|
||||
super(EditableWorkflowStatusItem, self).add_parameters_widgets(
|
||||
form, parameters, prefix=prefix, formdef=formdef)
|
||||
if 'by' in parameters:
|
||||
form.add(WidgetList, '%sby' % prefix, title = _('By'), element_type = SingleSelectWidget,
|
||||
value = self.by,
|
||||
|
@ -2572,7 +2624,7 @@ class EditableWorkflowStatusItem(WorkflowStatusItem):
|
|||
value=self.backoffice_info_text)
|
||||
|
||||
def get_parameters(self):
|
||||
return ('by', 'status', 'label', 'backoffice_info_text')
|
||||
return ('by', 'status', 'label', 'backoffice_info_text', 'condition')
|
||||
|
||||
register_item_class(EditableWorkflowStatusItem)
|
||||
|
||||
|
|
Loading…
Reference in New Issue