add live field conditions (#436)
This commit is contained in:
parent
668a04f96a
commit
1e852f8d88
|
@ -984,7 +984,7 @@ def test_form_new_field(pub):
|
|||
|
||||
# check it's in the preview
|
||||
resp = app.get('/backoffice/forms/1/')
|
||||
assert '<h3>baz</h3>' in resp.body
|
||||
assert '<h3 data-field-id="1">baz</h3>' in resp.body
|
||||
|
||||
def test_form_delete_field(pub):
|
||||
create_role()
|
||||
|
|
|
@ -4123,7 +4123,7 @@ def test_backoffice_formdata_named_wscall(http_requests, pub):
|
|||
app = login(get_app(pub))
|
||||
|
||||
resp = app.get('/backoffice/submission/test/')
|
||||
assert '<p class="comment-field ">XbarY</p>' in resp.body
|
||||
assert '<p data-field-id="7" class="comment-field ">XbarY</p>' in resp.body
|
||||
|
||||
# check with publisher variable in named webservice call
|
||||
if not pub.site_options.has_section('variables'):
|
||||
|
@ -4138,13 +4138,13 @@ def test_backoffice_formdata_named_wscall(http_requests, pub):
|
|||
wscall.store()
|
||||
|
||||
resp = app.get('/backoffice/submission/test/')
|
||||
assert '<p class="comment-field ">XbarY</p>' in resp.body
|
||||
assert '<p data-field-id="7" class="comment-field ">XbarY</p>' in resp.body
|
||||
|
||||
# django-templated URL
|
||||
wscall.request = {'url': '{{ example_url }}json'}
|
||||
wscall.store()
|
||||
resp = app.get('/backoffice/submission/test/')
|
||||
assert '<p class="comment-field ">XbarY</p>' in resp.body
|
||||
assert '<p data-field-id="7" class="comment-field ">XbarY</p>' in resp.body
|
||||
|
||||
# webservice call in django template
|
||||
formdef.fields = [
|
||||
|
@ -4153,7 +4153,7 @@ def test_backoffice_formdata_named_wscall(http_requests, pub):
|
|||
formdef.store()
|
||||
formdef.data_class().wipe()
|
||||
resp = app.get('/backoffice/submission/test/')
|
||||
assert '<p class="comment-field ">dja-bar-ngo</p>' in resp.body
|
||||
assert '<p data-field-id="7" class="comment-field ">dja-bar-ngo</p>' in resp.body
|
||||
|
||||
def test_backoffice_session_var(pub):
|
||||
open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w').write('''[options]
|
||||
|
@ -4177,7 +4177,7 @@ query_string_allowed_vars = foo,bar
|
|||
resp = app.get('/backoffice/submission/test/?session_var_foo=bar')
|
||||
assert resp.location.endswith('/backoffice/submission/test/')
|
||||
resp = resp.follow()
|
||||
assert '<p class="comment-field ">XbarY</p>' in resp.body
|
||||
assert '<p data-field-id="7" class="comment-field ">XbarY</p>' in resp.body
|
||||
|
||||
# django template
|
||||
formdef.fields = [
|
||||
|
@ -4188,7 +4188,7 @@ query_string_allowed_vars = foo,bar
|
|||
resp = app.get('/backoffice/submission/test/?session_var_foo=jang')
|
||||
assert resp.location.endswith('/backoffice/submission/test/')
|
||||
resp = resp.follow()
|
||||
assert '<p class="comment-field ">django</p>' in resp.body
|
||||
assert '<p data-field-id="7" class="comment-field ">django</p>' in resp.body
|
||||
|
||||
def test_backoffice_display_message(pub):
|
||||
user = create_user(pub)
|
||||
|
|
|
@ -133,65 +133,65 @@ def test_title():
|
|||
field = fields.TitleField(label='Foobar')
|
||||
form = Form(use_tokens=False)
|
||||
field.add_to_form(form)
|
||||
assert '<h3>Foobar</h3>' in str(form.render())
|
||||
assert '<h3 data-field-id="None">Foobar</h3>' in str(form.render())
|
||||
|
||||
field = fields.TitleField(label='Foobar', extra_css_class='test')
|
||||
form = Form(use_tokens=False)
|
||||
field.add_to_form(form)
|
||||
assert '<h3 class="test">Foobar</h3>' in str(form.render())
|
||||
assert '<h3 data-field-id="None" class="test">Foobar</h3>' in str(form.render())
|
||||
|
||||
def test_subtitle():
|
||||
field = fields.SubtitleField(label='Foobar')
|
||||
form = Form(use_tokens=False)
|
||||
field.add_to_form(form)
|
||||
assert '<h4>Foobar</h4>' in str(form.render())
|
||||
assert '<h4 data-field-id="None">Foobar</h4>' in str(form.render())
|
||||
|
||||
field = fields.SubtitleField(label='Foobar', extra_css_class='test')
|
||||
form = Form(use_tokens=False)
|
||||
field.add_to_form(form)
|
||||
assert '<h4 class="test">Foobar</h4>' in str(form.render())
|
||||
assert '<h4 data-field-id="None" class="test">Foobar</h4>' in str(form.render())
|
||||
|
||||
def test_comment():
|
||||
field = fields.CommentField(label='Foobar')
|
||||
form = Form(use_tokens=False)
|
||||
field.add_to_form(form)
|
||||
assert '<p class="comment-field ">Foobar</p>' in str(form.render())
|
||||
assert '<p data-field-id="None" class="comment-field ">Foobar</p>' in str(form.render())
|
||||
|
||||
field = fields.CommentField(label='Foo\n\nBar\n\nBaz')
|
||||
form = Form(use_tokens=False)
|
||||
field.add_to_form(form)
|
||||
assert '<p>Foo</p>\n<p>Bar</p>\n<p>Baz</p>' in str(form.render())
|
||||
assert '<div class="comment-field "' in str(form.render())
|
||||
assert '<div data-field-id="None" class="comment-field "' in str(form.render())
|
||||
|
||||
# test for variable substitution
|
||||
pub.substitutions.feed(MockSubstitutionVariables())
|
||||
field = fields.CommentField(label='{{ bar }}')
|
||||
form = Form(use_tokens=False)
|
||||
field.add_to_form(form)
|
||||
assert '<p class="comment-field ">Foobar</p>' in str(form.render())
|
||||
assert '<p data-field-id="None" class="comment-field ">Foobar</p>' in str(form.render())
|
||||
|
||||
field = fields.CommentField(label='[bar]')
|
||||
form = Form(use_tokens=False)
|
||||
field.add_to_form(form)
|
||||
assert '<p class="comment-field ">Foobar</p>' in str(form.render())
|
||||
assert '<p data-field-id="None" class="comment-field ">Foobar</p>' in str(form.render())
|
||||
|
||||
# test for proper escaping of substitution variables
|
||||
field = fields.CommentField(label='{{ foo }}')
|
||||
form = Form(use_tokens=False)
|
||||
field.add_to_form(form)
|
||||
assert '<p class="comment-field ">1 < 3</p>' in str(form.render())
|
||||
assert '<p data-field-id="None" class="comment-field ">1 < 3</p>' in str(form.render())
|
||||
|
||||
field = fields.CommentField(label='[foo]')
|
||||
form = Form(use_tokens=False)
|
||||
field.add_to_form(form)
|
||||
assert '<p class="comment-field ">1 < 3</p>' in str(form.render())
|
||||
assert '<p data-field-id="None" class="comment-field ">1 < 3</p>' in str(form.render())
|
||||
|
||||
# test for html content
|
||||
field = fields.CommentField(label='<p>Foobar</p>')
|
||||
form = Form(use_tokens=False)
|
||||
field.add_to_form(form)
|
||||
assert '<p>Foobar</p>' in str(form.render())
|
||||
assert '<div class="comment-field "' in str(form.render())
|
||||
assert '<div data-field-id="None" class="comment-field "' in str(form.render())
|
||||
assert field.unhtmled_label == 'Foobar'
|
||||
|
||||
field = fields.CommentField(label='<p>Foobaré</p>')
|
||||
|
|
|
@ -1086,15 +1086,15 @@ def test_form_titles(pub):
|
|||
formdef.data_class().wipe()
|
||||
|
||||
resp = get_app(pub).get('/test/')
|
||||
assert not '<h3>1st page/h3>' in resp.body
|
||||
assert '<h4>subtitle of 1st page</h4>' in resp.body
|
||||
assert not '<h3 data-field-id="0">1st page/h3>' in resp.body
|
||||
assert '<h4 data-field-id="5">subtitle of 1st page</h4>' in resp.body
|
||||
resp.form['f1'] = 'foo'
|
||||
resp = resp.form.submit('submit')
|
||||
assert '<h3>title of second page</h3>' in resp.body
|
||||
assert '<h3 data-field-id="6">title of second page</h3>' in resp.body
|
||||
resp = resp.form.submit('submit') # -> validation page
|
||||
assert '<h3>1st page</h3>' in resp.body
|
||||
assert '<h4>subtitle of 1st page</h4>' in resp.body
|
||||
assert '<h3>title of second page</h3>' in resp.body
|
||||
assert '<h4 data-field-id="5">subtitle of 1st page</h4>' in resp.body
|
||||
assert '<h3 data-field-id="6">title of second page</h3>' in resp.body
|
||||
resp.form['f3'] = 'foo'
|
||||
resp = resp.form.submit('submit').follow() # -> submit
|
||||
assert '<h3>1st page</h3>' in resp.body
|
||||
|
@ -5075,3 +5075,105 @@ def test_field_condition(pub):
|
|||
resp = resp.follow()
|
||||
assert '<span class="label">Bar</span>' in resp.body
|
||||
assert '<span class="label">Foo</span>' not in resp.body
|
||||
|
||||
def test_field_live_condition(pub):
|
||||
FormDef.wipe()
|
||||
formdef = FormDef()
|
||||
formdef.name = 'Foo'
|
||||
formdef.fields = [
|
||||
fields.StringField(type='string', id='1', label='Bar', size='40',
|
||||
required=True, varname='bar'),
|
||||
fields.StringField(type='string', id='2', label='Foo', size='40',
|
||||
required=True, varname='foo',
|
||||
condition={'type': 'django', 'value': 'form_var_bar == "bye"'}),
|
||||
]
|
||||
formdef.store()
|
||||
|
||||
app = get_app(pub)
|
||||
resp = app.get('/foo/')
|
||||
assert 'f1' in resp.form.fields
|
||||
assert 'f2' in resp.form.fields
|
||||
assert resp.html.find('div', {'data-field-id': '1'}).attrs['data-live-source'] == 'true'
|
||||
assert resp.html.find('div', {'data-field-id': '2'}).attrs.get('style') == 'display: none'
|
||||
resp.form['f1'] = 'hello'
|
||||
live_resp = app.post('/foo/live', params=resp.form.submit_fields())
|
||||
assert live_resp.json['result']['1']['visible']
|
||||
assert not live_resp.json['result']['2']['visible']
|
||||
resp.form['f1'] = 'bye'
|
||||
live_resp = app.post('/foo/live', params=resp.form.submit_fields())
|
||||
assert live_resp.json['result']['1']['visible']
|
||||
assert live_resp.json['result']['2']['visible']
|
||||
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
|
||||
|
||||
resp = get_app(pub).get('/foo/')
|
||||
assert 'f1' in resp.form.fields
|
||||
assert 'f2' in resp.form.fields
|
||||
resp.form['f1'] = 'bye'
|
||||
resp = resp.form.submit('submit')
|
||||
assert 'There were errors' in resp.body
|
||||
assert resp.html.find('div', {'data-field-id': '2'}).attrs.get('style') is None
|
||||
resp.form['f2'] = 'bye'
|
||||
resp = resp.form.submit('submit')
|
||||
assert 'Check values then click submit.' in resp.body
|
||||
assert 'name="f1"' in resp.body
|
||||
assert 'name="f2"' 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>' in resp.body
|
||||
|
||||
def test_field_live_condition_multipages(pub):
|
||||
FormDef.wipe()
|
||||
formdef = FormDef()
|
||||
formdef.name = 'Foo'
|
||||
formdef.fields = [
|
||||
fields.PageField(id='0', label='2nd page', type='page'),
|
||||
fields.StringField(type='string', id='1', label='Bar', size='40',
|
||||
required=True, varname='bar'),
|
||||
fields.StringField(type='string', id='2', label='Foo', size='40',
|
||||
required=True, varname='foo',
|
||||
condition={'type': 'django', 'value': 'form_var_bar == "bye"'}),
|
||||
fields.PageField(id='3', label='1st page', type='page'),
|
||||
fields.StringField(type='string', id='4', label='Baz', size='40',
|
||||
required=True, varname='baz'),
|
||||
]
|
||||
formdef.store()
|
||||
|
||||
app = get_app(pub)
|
||||
resp = app.get('/foo/')
|
||||
assert 'f1' in resp.form.fields
|
||||
assert 'f2' in resp.form.fields
|
||||
assert resp.html.find('div', {'data-field-id': '1'}).attrs['data-live-source'] == 'true'
|
||||
assert resp.html.find('div', {'data-field-id': '2'}).attrs.get('style') == 'display: none'
|
||||
resp.form['f1'] = 'hello'
|
||||
live_resp = app.post('/foo/live', params=resp.form.submit_fields())
|
||||
assert live_resp.json['result']['1']['visible']
|
||||
assert not live_resp.json['result']['2']['visible']
|
||||
resp.form['f1'] = 'bye'
|
||||
live_resp = app.post('/foo/live', params=resp.form.submit_fields())
|
||||
assert live_resp.json['result']['1']['visible']
|
||||
assert live_resp.json['result']['2']['visible']
|
||||
resp.form['f1'] = 'bye'
|
||||
resp.form['f2'] = 'bye'
|
||||
resp = resp.form.submit('submit')
|
||||
resp = resp.form.submit('previous')
|
||||
assert resp.html.find('div', {'data-field-id': '2'}).attrs.get('style') is None
|
||||
live_resp = app.post('/foo/live', params=resp.form.submit_fields())
|
||||
assert live_resp.json['result']['1']['visible']
|
||||
assert live_resp.json['result']['2']['visible']
|
||||
resp = resp.form.submit('submit')
|
||||
resp.form['f4'] = 'plop'
|
||||
resp = resp.form.submit('submit')
|
||||
assert 'Check values then click submit.' in resp.body
|
||||
assert 'name="f1"' in resp.body
|
||||
assert 'name="f2"' in resp.body
|
||||
assert 'name="f4"' in resp.body
|
||||
resp = resp.form.submit('submit')
|
||||
|
|
|
@ -76,7 +76,7 @@ class RemoveDraftDirectory(Directory):
|
|||
|
||||
class FormFillPage(PublicFormFillPage):
|
||||
_q_exports = ['', 'tempfile', 'autosave', 'code',
|
||||
('remove', 'remove_draft')]
|
||||
('remove', 'remove_draft'), 'live']
|
||||
|
||||
filling_templates = ['wcs/formdata_filling.html']
|
||||
validation_templates = ['wcs/formdata_validation.html']
|
||||
|
|
|
@ -381,6 +381,29 @@ class Field(object):
|
|||
except RuntimeError:
|
||||
return True
|
||||
|
||||
def get_condition_varnames(self):
|
||||
return re.findall(r'\bform[_\.]var[_\.]([a-zA-Z0-9_]+?)(?:_raw|\b)', self.condition['value'])
|
||||
|
||||
def has_live_conditions(self, formdef):
|
||||
varnames = self.get_condition_varnames()
|
||||
if not varnames:
|
||||
return False
|
||||
field_position = formdef.fields.index(self)
|
||||
# rewind to field page
|
||||
for field_position in range(field_position, -1, -1):
|
||||
if formdef.fields[field_position].type == 'page':
|
||||
break
|
||||
else:
|
||||
field_position = -1 # form with no page
|
||||
# start from there
|
||||
for field in formdef.fields[field_position+1:]:
|
||||
if field.type == 'page':
|
||||
# stop at next page
|
||||
break
|
||||
if field.varname in varnames:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class WidgetField(Field):
|
||||
hint = None
|
||||
|
@ -413,6 +436,7 @@ class WidgetField(Field):
|
|||
widget.extra_css_class = self.extra_css_class
|
||||
if self.varname:
|
||||
widget.div_id = 'var_%s' % self.varname
|
||||
return widget
|
||||
|
||||
def perform_more_widget_changes(self, form, kwargs, edit = True):
|
||||
pass
|
||||
|
@ -519,12 +543,12 @@ class TitleField(Field):
|
|||
description = N_('Title')
|
||||
|
||||
def add_to_form(self, form, value = None):
|
||||
extra_attributes = ' data-field-id="%s"' % self.id
|
||||
if self.extra_css_class:
|
||||
extra_css_class = ' class="%s"' % self.extra_css_class
|
||||
else:
|
||||
extra_css_class = ''
|
||||
form.widgets.append(HtmlWidget(
|
||||
htmltext('<h3%s>%s</h3>' % (extra_css_class, self.label))))
|
||||
extra_attributes += ' class="%s"' % self.extra_css_class
|
||||
widget = HtmlWidget(htmltext('<h3%s>%s</h3>' % (extra_attributes, self.label)))
|
||||
form.widgets.append(widget)
|
||||
return widget
|
||||
add_to_view_form = add_to_form
|
||||
|
||||
def fill_admin_form(self, form):
|
||||
|
@ -547,12 +571,12 @@ class SubtitleField(TitleField):
|
|||
description = N_('Subtitle')
|
||||
|
||||
def add_to_form(self, form, value = None):
|
||||
extra_attributes = ' data-field-id="%s"' % self.id
|
||||
if self.extra_css_class:
|
||||
extra_css_class = ' class="%s"' % self.extra_css_class
|
||||
else:
|
||||
extra_css_class = ''
|
||||
form.widgets.append(HtmlWidget(
|
||||
htmltext('<h4%s>%s</h4>' % (extra_css_class, self.label))))
|
||||
extra_attributes += ' class="%s"' % self.extra_css_class
|
||||
widget = HtmlWidget(htmltext('<h4%s>%s</h4>' % (extra_attributes, self.label)))
|
||||
form.widgets.append(widget)
|
||||
return widget
|
||||
add_to_view_form = add_to_form
|
||||
|
||||
register_field_class(SubtitleField)
|
||||
|
@ -563,7 +587,8 @@ class CommentField(Field):
|
|||
description = N_('Comment')
|
||||
|
||||
def add_to_form(self, form, value = None):
|
||||
class_attribute = 'class="comment-field %s"' % (self.extra_css_class or '')
|
||||
tag_attributes = 'data-field-id="%s" class="comment-field %s"' % (
|
||||
self.id, self.extra_css_class or '')
|
||||
|
||||
if '\n\n' in self.label:
|
||||
label = '<p>' + re.sub('\n\n+', '</p>\n<p>', self.label) + '</p>'
|
||||
|
@ -579,9 +604,10 @@ class CommentField(Field):
|
|||
enclosing_tag = 'div'
|
||||
break
|
||||
|
||||
form.widgets.append(HtmlWidget(
|
||||
htmltext('<%s %s>%s</%s>' % (enclosing_tag, class_attribute,
|
||||
label, enclosing_tag))))
|
||||
widget = HtmlWidget(htmltext('<%s %s>%s</%s>' % (
|
||||
enclosing_tag, tag_attributes, label, enclosing_tag)))
|
||||
form.widgets.append(widget)
|
||||
return widget
|
||||
|
||||
def add_to_view_form(self, *args):
|
||||
pass
|
||||
|
@ -1050,7 +1076,7 @@ class DateField(WidgetField):
|
|||
def add_to_form(self, form, value=None):
|
||||
if value and type(value) is not str:
|
||||
value = self.convert_value_to_str(value)
|
||||
WidgetField.add_to_form(self, form, value=value)
|
||||
return WidgetField.add_to_form(self, form, value=value)
|
||||
|
||||
def add_to_view_form(self, form, value = None):
|
||||
value = localstrftime(value)
|
||||
|
@ -1531,8 +1557,11 @@ class PageCondition(Condition):
|
|||
# create variables with values currently being evaluated, not yet
|
||||
# available in the formdata.
|
||||
from formdata import get_dict_with_varnames
|
||||
live_data = get_dict_with_varnames(formdef.fields, dict_vars)
|
||||
form_live_data = dict(('form_' + x, y) for x, y in live_data.items())
|
||||
live_data = {}
|
||||
form_live_data = {}
|
||||
if dict_vars is not None:
|
||||
live_data = get_dict_with_varnames(formdef.fields, dict_vars)
|
||||
form_live_data = dict(('form_' + x, y) for x, y in live_data.items())
|
||||
|
||||
# 1) feed the form_var_* variables in the global substitution system,
|
||||
# they will shadow formdata context variables with their new "live"
|
||||
|
|
|
@ -536,14 +536,19 @@ class FormDef(StorableObject):
|
|||
continue
|
||||
if not on_page:
|
||||
continue
|
||||
if not field.is_visible(form_data, self):
|
||||
continue
|
||||
visible = field.is_visible(form_data, self)
|
||||
if not visible:
|
||||
if not field.has_live_conditions(self):
|
||||
# no live conditions so field can be skipped
|
||||
continue
|
||||
if type(displayed_fields) is list:
|
||||
displayed_fields.append(field)
|
||||
value = None
|
||||
if form_data:
|
||||
value = form_data.get(field.id)
|
||||
field.add_to_form(form, value)
|
||||
widget = field.add_to_form(form, value)
|
||||
widget.is_hidden = not(visible)
|
||||
widget.field = field
|
||||
|
||||
def get_page(self, page_no):
|
||||
return [x for x in self.fields if x.type == 'page'][page_no]
|
||||
|
|
|
@ -22,7 +22,7 @@ from .root import FormPage
|
|||
|
||||
|
||||
class PreviewFormPage(FormPage):
|
||||
_q_exports = ['', 'tempfile']
|
||||
_q_exports = ['', 'tempfile', 'live']
|
||||
|
||||
def check_role(self):
|
||||
pass
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
import copy
|
||||
import json
|
||||
import re
|
||||
import time
|
||||
from StringIO import StringIO
|
||||
import sys
|
||||
|
@ -171,7 +172,7 @@ class TrackingCodesDirectory(Directory):
|
|||
|
||||
class FormPage(Directory, FormTemplateMixin):
|
||||
_q_exports = ['', 'tempfile', 'schema', 'tryauth',
|
||||
'auth', 'qrcode', 'autosave', 'code', 'removedraft']
|
||||
'auth', 'qrcode', 'autosave', 'code', 'removedraft', 'live']
|
||||
|
||||
filling_templates = ['wcs/front/formdata_filling.html', 'wcs/formdata_filling.html']
|
||||
validation_templates = ['wcs/front/formdata_validation.html', 'wcs/formdata_validation.html']
|
||||
|
@ -378,16 +379,29 @@ class FormPage(Directory, FormTemplateMixin):
|
|||
if not one:
|
||||
req.form = {}
|
||||
|
||||
live_condition_fields = {}
|
||||
for field in displayed_fields:
|
||||
if field.prefill:
|
||||
# always set additional attributes as they will be used for
|
||||
# "live prefill", regardless of existing data.
|
||||
form.get_widget('f%s' % field.id).prefill_attributes = field.get_prefill_attributes()
|
||||
if field.condition:
|
||||
field.varnames = field.get_condition_varnames()
|
||||
for varname in field.varnames:
|
||||
if not varname in live_condition_fields:
|
||||
live_condition_fields[varname] = []
|
||||
live_condition_fields[varname].append(field)
|
||||
|
||||
for field in displayed_fields:
|
||||
if field.varname in live_condition_fields:
|
||||
form.get_widget('f%s' % field.id).live_condition_source = True
|
||||
|
||||
self.html_top(self.formdef.name)
|
||||
|
||||
form.add_hidden('step', '0')
|
||||
form.add_hidden('page', self.pages.index(page))
|
||||
if page:
|
||||
form.add_hidden('page_id', page.id)
|
||||
|
||||
form.add_submit('cancel', _('Cancel'), css_class = 'cancel')
|
||||
if self.formdef.enable_tracking_codes and not self.edit_mode:
|
||||
|
@ -696,7 +710,8 @@ class FormPage(Directory, FormTemplateMixin):
|
|||
|
||||
self.feed_current_data(magictoken)
|
||||
|
||||
form = self.create_form(page=page)
|
||||
submitted_fields = []
|
||||
form = self.create_form(page=page, displayed_fields=submitted_fields)
|
||||
form.add_submit('previous')
|
||||
if self.formdef.enable_tracking_codes:
|
||||
form.add_submit('removedraft')
|
||||
|
@ -708,13 +723,18 @@ class FormPage(Directory, FormTemplateMixin):
|
|||
if self.formdef.enable_tracking_codes and form.get_submit() == 'removedraft':
|
||||
return self.removedraft()
|
||||
|
||||
form_data = session.get_by_magictoken(magictoken, {})
|
||||
data = self.formdef.get_data(form)
|
||||
form_data.update(data)
|
||||
|
||||
if self.formdef.enable_tracking_codes and form.get_submit() == 'savedraft':
|
||||
form_data = session.get_by_magictoken(magictoken, {})
|
||||
data = self.formdef.get_data(form)
|
||||
form_data.update(data)
|
||||
filled = self.save_draft(form_data, page_no)
|
||||
return redirect(filled.get_url().rstrip('/'))
|
||||
|
||||
for field in submitted_fields:
|
||||
if not field.is_visible(form_data, self.formdef) and 'f%s' % field.id in form._names:
|
||||
del form._names['f%s' % field.id]
|
||||
|
||||
page_error_messages = []
|
||||
if form.get_submit() == 'submit' and page:
|
||||
post_conditions = page.post_conditions or []
|
||||
|
@ -988,6 +1008,39 @@ class FormPage(Directory, FormTemplateMixin):
|
|||
pass
|
||||
return None
|
||||
|
||||
def live(self):
|
||||
get_request().ignore_session = True
|
||||
# live evaluation of fields
|
||||
get_response().set_content_type('application/json')
|
||||
def result_error(reason):
|
||||
return json.dumps({'result': 'error', 'reason': reason})
|
||||
|
||||
session = get_session()
|
||||
if not session:
|
||||
return result_error('missing session')
|
||||
|
||||
formdata = self.get_transient_formdata()
|
||||
get_publisher().substitutions.feed(formdata)
|
||||
|
||||
page_id = get_request().form.get('page_id')
|
||||
if page_id:
|
||||
for field in self.formdef.fields:
|
||||
if str(field.id) == page_id:
|
||||
page = field
|
||||
break
|
||||
else:
|
||||
page = None
|
||||
|
||||
displayed_fields = []
|
||||
form = self.create_form(page=page, displayed_fields=displayed_fields)
|
||||
formdata.data.update(self.formdef.get_data(form))
|
||||
|
||||
result = {}
|
||||
for field in displayed_fields:
|
||||
result[field.id] = {'visible': field.is_visible(formdata.data, self.formdef)}
|
||||
|
||||
return json.dumps({'result': result})
|
||||
|
||||
def submitted(self, form, existing_formdata = None):
|
||||
if existing_formdata: # modifying
|
||||
filled = existing_formdata
|
||||
|
|
|
@ -418,9 +418,10 @@ class HtmlWidget(object):
|
|||
return self.render_content()
|
||||
|
||||
def render_content(self):
|
||||
if self.title:
|
||||
return htmltext(self.title)
|
||||
return htmltext(self.string)
|
||||
content = self.title or self.string or ''
|
||||
if getattr(self, 'is_hidden', False):
|
||||
content = htmltext(str(content).replace('>', ' style="display: none">', 1))
|
||||
return htmltext(content)
|
||||
|
||||
def has_error(self, request):
|
||||
return False
|
||||
|
|
|
@ -47,6 +47,7 @@ $(function() {
|
|||
$(base_widget).find('input[type=hidden]').val(token);
|
||||
$(base_widget).find('input[type=file]').hide();
|
||||
$(base_widget).find('.use-file-from-fargo').hide();
|
||||
$(base_widget).find('input[type=file]').trigger('wcs:change');
|
||||
}
|
||||
document.fargo_close_dialog();
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ $(function() {
|
|||
$(this).hide();
|
||||
$(base_widget).find('.use-file-from-fargo').hide();
|
||||
$(base_widget).addClass('has-file').removeClass('has-no-file');
|
||||
$(this).trigger('wcs:change');
|
||||
},
|
||||
progress: function (e, data) {
|
||||
var progress = parseInt(data.loaded / data.total * 100, 10);
|
||||
|
@ -41,6 +42,7 @@ $(function() {
|
|||
$(base_widget).find('input[type=file]').show();
|
||||
$(base_widget).find('.use-file-from-fargo').show();
|
||||
$(base_widget).removeClass('has-file').addClass('has-no-file');
|
||||
$(base_widget).find('input[type=file]').trigger('wcs:change');
|
||||
return false;
|
||||
});
|
||||
$(this).find('a.change').click(function() {
|
||||
|
|
|
@ -67,4 +67,28 @@ $(function() {
|
|||
}
|
||||
return true;
|
||||
});
|
||||
var live_evaluation = null;
|
||||
$('form div[data-live-source] input, form div[data-live-source] select, form div[data-live-source] textarea').on('change keyup paste wcs:change', function() {
|
||||
var new_data = $(this).parents('form').serialize();
|
||||
if (live_evaluation) {
|
||||
live_evaluation.abort();
|
||||
}
|
||||
live_evaluation = $.ajax({
|
||||
type: 'POST',
|
||||
url: window.location.pathname + 'live',
|
||||
dataType: 'json',
|
||||
data: new_data,
|
||||
headers: {'accept': 'application/json'},
|
||||
success: function(json) {
|
||||
$.each(json.result, function(key, value) {
|
||||
var $widget = $('[data-field-id="' + key + '"]');
|
||||
if (value.visible) {
|
||||
$widget.show();
|
||||
} else {
|
||||
$widget.hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
{% if widget.get_error %}widget-with-error{% endif %}
|
||||
{% if widget.is_required %}widget-required{% else %}widget-optional{% endif %}
|
||||
{% if widget.is_prefilled %}widget-prefilled{% endif %}"
|
||||
{% if widget.is_hidden %}style="display: none"{% endif %}
|
||||
{% if widget.field %}data-field-id="{{ widget.field.id }}"{% endif %}
|
||||
{% if widget.div_id %}id="{{widget.div_id}}" data-valuecontainerid="form_{{widget.name}}"{% endif %}
|
||||
{% for attr in widget.prefill_attributes %}
|
||||
data-{{attr}}="{{widget.prefill_attributes|get:attr}}"
|
||||
|
@ -13,7 +15,9 @@
|
|||
{% endif %}
|
||||
{% if "data-dynamic-display-value" in widget.attrs %}
|
||||
data-dynamic-display-value="{{widget.attrs|get:"data-dynamic-display-value"}}"
|
||||
{% endif %}>
|
||||
{% endif %}
|
||||
{% if widget.live_condition_source %}data-live-source="true"{% endif %}
|
||||
>
|
||||
{% block widget-title %}
|
||||
{{widget.rendered_title}}
|
||||
{% endblock %}
|
||||
|
|
Loading…
Reference in New Issue