add conditions to fields (#19752)

This commit is contained in:
Frédéric Péters 2018-07-28 17:02:53 +02:00
parent d46c4c0451
commit 668a04f96a
9 changed files with 90 additions and 32 deletions

View File

@ -5048,3 +5048,30 @@ def test_form_and_category_same_slug(pub):
# check we get to the form, not the category
resp = get_app(pub).get('/foobar/')
assert resp.form
def test_field_condition(pub):
FormDef.wipe()
formdef = FormDef()
formdef.name = 'Foo'
formdef.fields = [
fields.StringField(type='string', id='1', label='Bar', size='40',
required=True,
condition={'type': 'django', 'value': '1'}),
fields.StringField(type='string', id='2', label='Foo', size='40',
required=True,
condition={'type': 'django', 'value': '0'}),
]
formdef.store()
resp = get_app(pub).get('/foo/')
assert 'f1' in resp.form.fields
assert 'f2' not in resp.form.fields
resp.form['f1'] = 'hello'
resp = resp.form.submit('submit')
assert 'Check values then click submit.' in resp.body
assert 'name="f1"' in resp.body
assert 'name="f2"' not in resp.body
resp = resp.form.submit('submit')
resp = resp.follow()
assert '<span class="label">Bar</span>' in resp.body
assert '<span class="label">Foo</span>' not in resp.body

View File

@ -457,3 +457,14 @@ def test_required_authentication_contexts():
formdef.required_authentication_contexts = ['fedict']
fd2 = assert_xml_import_export_works(formdef, include_id=True)
assert fd2.required_authentication_contexts == formdef.required_authentication_contexts
def test_field_condition():
formdef = FormDef()
formdef.name = 'Foo'
formdef.fields = [
fields.StringField(type='string', id=1, label='Bar', size='40',
condition={'type': 'django', 'value': '1'})
]
f2 = assert_xml_import_export_works(formdef)
assert len(f2.fields) == len(formdef.fields)
assert f2.fields[0].condition == {'type': 'django', 'value': '1'}

View File

@ -36,6 +36,7 @@ class FieldDefPage(Directory):
large = False
page_id = None
blacklisted_attributes = []
def __init__(self, objectdef, field_id):
self.objectdef = objectdef
@ -52,10 +53,8 @@ class FieldDefPage(Directory):
form = Form(enctype='multipart/form-data',
advanced_label=_('Additional parameters'))
self.field.fill_admin_form(form)
#form.add(SingleSelectWidget, 'type', title = _('Type'),
# value = self.field.type, required=True,
# options = [(x, _(y)) for x,y in get_field_types()])
#current_type = form.get_widget('type').parse()
form.widgets = [x for x in form.widgets
if getattr(x, 'name', None) not in self.blacklisted_attributes]
form.add_submit('submit', _('Submit'))
form.add_submit('cancel', _('Cancel'))
return form

View File

@ -105,8 +105,11 @@ authentication is unavailable. Lasso must be installed to use it.'))
get_response().breadcrumb.append( ('identification/', _('Identification')) )
return qommon.ident.get_method_admin_directory(component)
class UserFieldDefPage(FieldDefPage):
section = 'settings'
blacklisted_attributes = ['condition']
class UserFieldsDirectory(FieldsDirectory):
_q_exports = ['', 'update_order', 'new', 'mapping']

View File

@ -822,6 +822,7 @@ class WorkflowVariableWidget(CompositeWidget):
class WorkflowVariablesFieldDefPage(FieldDefPage):
section = 'workflows'
blacklisted_attributes = ['condition']
def form(self):
form = super(WorkflowVariablesFieldDefPage, self).form()
@ -834,6 +835,7 @@ class WorkflowVariablesFieldDefPage(FieldDefPage):
class WorkflowBackofficeFieldDefPage(FieldDefPage):
section = 'workflows'
blacklisted_attributes = ['condition']
def form(self):
form = super(WorkflowBackofficeFieldDefPage, self).form()
@ -870,6 +872,7 @@ class WorkflowBackofficeFieldsDirectory(FieldsDirectory):
field_def_page_class = WorkflowBackofficeFieldDefPage
support_import = False
blacklisted_types = ['page']
blacklisted_attributes = ['condition']
field_var_prefix = 'form_var_'
def index_top(self):

View File

@ -160,6 +160,7 @@ class Field(object):
prefill = None
store_display_value = None
store_structured_value = None
condition = None
# flag a field for removal by AnonymiseWorkflowStatusItem
# can be overriden in field' settings
@ -181,7 +182,7 @@ class Field(object):
re.sub('<.*?>', ' ', self.label), charset)).strip().encode(charset)
def get_admin_attributes(self):
return ['label', 'type']
return ['label', 'type', 'condition']
def export_to_json(self, include_id=False):
field = {}
@ -284,6 +285,18 @@ class Field(object):
except:
pass
def condition_init_with_xml(self, node, charset, include_id=False):
self.condition = None
if node is None:
return
if node.findall('type'):
self.condition = {
'type': node.find('type').text.encode(charset),
'value': node.find('value').text.encode(charset),
}
elif node.text:
self.condition = {'type': 'python', 'value': node.text.strip().encode(charset)}
def get_rst_view_value(self, value, indent=''):
return indent + self.get_view_value(value)
@ -359,6 +372,15 @@ class Field(object):
def migrate(self):
return False
def evaluate_condition(self, dict_vars, formdef, condition):
return PageCondition(condition, {'dict_vars': dict_vars, 'formdef': formdef}).evaluate()
def is_visible(self, dict, formdef):
try:
return self.evaluate_condition(dict, formdef, self.condition)
except RuntimeError:
return True
class WidgetField(Field):
hint = None
@ -443,6 +465,9 @@ class WidgetField(Field):
form.add(PrefillSelectionWidget, 'prefill', title=_('Prefill'),
value=self.prefill, advanced=prefill_in_advanced,
field=self)
form.add(ConditionWidget, 'condition', title=_('Display Condition'), value=self.condition,
required=False, size=50, django_only=True,
advanced=not(bool(self.condition)))
if 'anonymise' in self.get_admin_attributes():
# override anonymise flag default value
form.add(CheckboxWidget, 'anonymise', title=_('Anonymise'),
@ -507,6 +532,9 @@ class TitleField(Field):
required = True, size = 50)
form.add(StringWidget, 'extra_css_class', title = _('Extra classes for CSS styling'),
value=self.extra_css_class, size=30, advanced=(not self.extra_css_class))
form.add(ConditionWidget, 'condition', title=_('Display Condition'), value=self.condition,
required=False, size=50, django_only=True,
advanced=not(bool(self.condition)))
def get_admin_attributes(self):
return Field.get_admin_attributes(self) + ['extra_css_class']
@ -568,6 +596,9 @@ class CommentField(Field):
required=True)
form.add(StringWidget, 'extra_css_class', title = _('Extra classes for CSS styling'),
value=self.extra_css_class, size=30, advanced=(not self.extra_css_class))
form.add(ConditionWidget, 'condition', title=_('Display Condition'), value=self.condition,
required=False, size=50, django_only=True,
advanced=not(bool(self.condition)))
def get_admin_attributes(self):
return Field.get_admin_attributes(self) + ['extra_css_class']
@ -1545,21 +1576,8 @@ class PageField(Field):
key = 'page'
description = N_('Page')
condition = None
post_conditions = None
def condition_init_with_xml(self, node, charset, include_id=False):
self.condition = None
if node is None:
return
if node.findall('type'):
self.condition = {
'type': node.find('type').text.encode(charset),
'value': node.find('value').text.encode(charset),
}
elif node.text:
self.condition = {'type': 'python', 'value': node.text.strip().encode(charset)}
def post_conditions_init_with_xml(self, node, charset, include_id=False):
if node is None:
return
@ -1600,7 +1618,7 @@ class PageField(Field):
def fill_admin_form(self, form):
form.add(StringWidget, 'label', title = _('Label'), value = self.label,
required = True, size = 50)
form.add(ConditionWidget, 'condition', title=_('Condition'), value=self.condition,
form.add(ConditionWidget, 'condition', title=_('Display Condition'), value=self.condition,
required=False, size=50)
form.add(PostConditionsTableWidget, 'post_conditions',
title=_('Post Conditions'),
@ -1631,15 +1649,6 @@ class PageField(Field):
def add_to_view_form(self, *args):
pass
def evaluate_condition(self, dict_vars, formdef, condition):
return PageCondition(condition, {'dict_vars': dict_vars, 'formdef': formdef}).evaluate()
def is_visible(self, dict, formdef):
try:
return self.evaluate_condition(dict, formdef, self.condition)
except RuntimeError:
return True
register_field_class(PageField)

View File

@ -536,6 +536,8 @@ class FormDef(StorableObject):
continue
if not on_page:
continue
if not field.is_visible(form_data, self):
continue
if type(displayed_fields) is list:
displayed_fields.append(field)
value = None
@ -586,6 +588,9 @@ class FormDef(StorableObject):
# same text as the page.
continue
if not field.is_visible(dict, self):
continue
value = dict.get(field.id, '')
field.add_to_view_form(form, value)

View File

@ -2359,10 +2359,10 @@ class ConditionWidget(CompositeWidget):
if not value:
value = {}
options = [
('python', _('Python Expression'), 'python'),
('django', _('Django Expression'), 'django'),
]
options = []
if not kwargs.get('django_only'):
options.append(('python', _('Python Expression'), 'python'))
options.append(('django', _('Django Expression'), 'django'))
self.add(StringWidget, 'value_django', size=80,
value=value.get('value') if value.get('type') == 'django' else None)

View File

@ -67,6 +67,7 @@ class WorkflowFormFieldsDirectory(FieldsDirectory):
section = 'workflows'
support_import = False
blacklisted_types = ['page']
blacklisted_attributes = ['condition']
field_def_page_class = WorkflowFormFieldDefPage