forms: add appearance keywords to formdefs (#21370)

This commit is contained in:
Frédéric Péters 2018-01-31 13:50:41 +01:00
parent 9e612e8858
commit ae765a6618
6 changed files with 88 additions and 6 deletions

View File

@ -300,6 +300,17 @@ def test_forms_edit(pub):
assert_option_display(resp, 'CAPTCHA for anonymous users', 'Enabled')
assert FormDef.get(1).has_captcha is True
# Appearance
assert_option_display(resp, 'Appearance', 'Default')
resp = resp.click('Appearance')
assert resp.forms[0]['appearance_keywords'].value == ''
resp.forms[0]['appearance_keywords'] = 'foobar'
resp = resp.forms[0].submit()
assert resp.location == 'http://example.net/backoffice/forms/1/'
resp = resp.follow()
assert_option_display(resp, 'Appearance', 'foobar')
assert FormDef.get(1).appearance_keywords == 'foobar'
# Publication
assert_option_display(resp, 'Online Status', 'Active')
resp = resp.click('Online Status')

View File

@ -37,6 +37,7 @@ from wcs.wscalls import NamedWsCall
from wcs import fields
from wcs.sessions import BasicSession
from wcs.logged_errors import LoggedError
from wcs.forms.root import PublicFormStatusPage
from utilities import get_app, login, create_temporary_pub, clean_temporary_pub
@ -3937,3 +3938,33 @@ def test_form_custom_select_template(pub):
assert 'TEST TEMPLATE' in resp.body
# make sure request is available in context
assert '<!-- backoffice: False -->' in resp.body
def test_form_status_appearance_keywords(pub):
formdef = create_formdef()
formdef.fields = [
fields.ItemField(id='1', label='select', type='item',
required=True,
varname='foo', items=['Foo', 'Bar', 'Baz'])]
formdef.store()
formdata = formdef.data_class()()
formdata.just_created()
formdata.store()
root = PublicFormStatusPage(formdef, formdata, register_workflow_subdirs=False)
template_names = root.get_formdef_template_variants(root.status_templates)
assert list(template_names) == root.status_templates
formdef.appearance_keywords = 'foobar plop'
formdef.store()
template_names = root.get_formdef_template_variants(root.status_templates)
assert list(template_names) == [
'wcs/front/appearance-foobar/formdata_status.html',
'wcs/front/appearance-plop/formdata_status.html',
'wcs/front/formdata_status.html',
'wcs/appearance-foobar/formdata_status.html',
'wcs/appearance-plop/formdata_status.html',
'wcs/formdata_status.html']
resp = get_app(pub).get('/test/')
assert 'class="quixote foobar plop"' in resp.body

View File

@ -102,6 +102,7 @@ def create_temporary_pub(sql_mode=False):
fd.write('\n')
fd.write('[options]\n')
fd.write('formdef-captcha-option = true\n')
fd.write('formdef-appearance-keywords = true\n')
fd.write('workflow-resubmit-action = true\n')
if sql_mode:
fd.write('postgresql = true\n')
@ -124,6 +125,9 @@ def create_temporary_pub(sql_mode=False):
fd.close()
# make sure site options are not cached
pub.site_options = None
return pub
def clean_temporary_pub():

View File

@ -136,7 +136,7 @@ class OptionsDirectory(Directory):
_q_exports = ['confirmation', 'private_status', 'only_allow_one',
'always_advertise', 'tracking_code', 'online_status', 'captcha',
'description', 'keywords', 'category', ('360_view', 'p_360_view'),
'geolocations']
'geolocations', 'appearance']
def __init__(self, formdef):
self.formdef = formdef
@ -238,6 +238,14 @@ class OptionsDirectory(Directory):
hint=_('Location label (empty to disable geolocation)'))
return self.handle(form, _('Geolocation'))
def appearance(self):
form = Form(enctype='multipart/form-data')
form.add(StringWidget, 'appearance_keywords', title=_('Appearance keywords'),
value=self.formdef.appearance_keywords, size=50,
hint=_('Serie of keywords to alter form appearance using CSS or '
'custom templates, separated by spaces.'))
return self.handle(form, _('Appearance'))
def handle(self, form, title):
form.add_submit('submit', _('Submit'))
form.add_submit('cancel', _('Cancel'))
@ -250,7 +258,7 @@ class OptionsDirectory(Directory):
'always_advertise', 'disabled_redirection',
'publication_date', 'expiration_date', 'has_captcha',
'description', 'keywords', 'category_id',
'skip_from_360_view', 'geoloc_label']
'skip_from_360_view', 'geoloc_label', 'appearance_keywords']
for attr in attrs:
widget = form.get_widget(attr)
if widget:
@ -486,6 +494,12 @@ class FormDefPage(Directory):
self.formdef.has_captcha and
C_('captcha|Enabled') or C_('captcha|Disabled'))
if get_publisher().has_site_option('formdef-appearance-keywords'):
r += add_option_line('options/appearance',
_('Appearance'),
self.formdef.appearance_keywords and
self.formdef.appearance_keywords or C_('appearance|Standard'))
online_status = C_('online status|Active')
if self.formdef.disabled:
# manually disabled

View File

@ -96,6 +96,7 @@ class FormDef(StorableObject):
has_captcha = False
skip_from_360_view = False
private_status_and_history = False
appearance_keywords = None
geolocations = None
@ -107,7 +108,7 @@ class FormDef(StorableObject):
# declarations for serialization
TEXT_ATTRIBUTES = ['name', 'url_name', 'description', 'keywords',
'publication_date', 'expiration_date', 'internal_identifier',
'disabled_redirection',]
'disabled_redirection', 'appearance_keywords']
BOOLEAN_ATTRIBUTES = ['discussion', 'detailed_emails', 'disabled',
'only_allow_one', 'enable_tracking_codes', 'confirmation',
'always_advertise', 'private_status_and_history',
@ -420,6 +421,14 @@ class FormDef(StorableObject):
return []
return [x.strip() for x in self.keywords.split(',')]
@property
def appearance_keywords_list(self):
if not get_publisher().has_site_option('formdef-appearance-keywords'):
return []
if not self.appearance_keywords:
return []
return [x.strip() for x in self.appearance_keywords.split()]
_start_page = None
def get_start_page(self):
if self._start_page is not None:
@ -505,7 +514,9 @@ class FormDef(StorableObject):
return '[formdef_id]-[form_number_raw]'
def create_form(self, page_no=0, displayed_fields=None):
form = Form(enctype = "multipart/form-data", use_tokens=False)
form = Form(enctype="multipart/form-data", use_tokens=False)
if self.appearance_keywords:
form.attrs['class'] = 'quixote %s' % self.appearance_keywords
if self.keywords:
form.attrs['data-keywords'] = ' '.join(self.keywords_list)
form.ERROR_NOTICE = _('There were errors processing the form and '

View File

@ -205,6 +205,13 @@ class FormStatusPage(Directory):
r += htmltext('</p>')
return r.getvalue()
def get_formdef_template_variants(self, template_names):
template_part_names = [(os.path.dirname(x), os.path.basename(x)) for x in template_names]
for dirname, basename in template_part_names:
for keyword in self.formdef.appearance_keywords_list:
yield os.path.join(dirname, 'appearance-' + keyword, basename)
yield os.path.join(dirname, basename)
def _q_index(self):
mine = self.check_auth()
get_logger().info('form %s - id: %s - view' % (self.formdef.name, self.filled.id))
@ -231,7 +238,9 @@ class FormStatusPage(Directory):
'workflow_form': form,
}
return template.render(self.status_templates, context)
return template.render(
list(self.get_formdef_template_variants(self.status_templates)),
context)
def export_to_json(self, anonymise=False):
get_response().set_content_type('application/json')
@ -243,7 +252,9 @@ class FormStatusPage(Directory):
if not self.formdef.is_user_allowed_read_status_and_history(get_request().user, self.filled):
return
return template.render(self.history_templates, {'formdata': self.filled})
return template.render(
list(self.get_formdef_template_variants(self.history_templates)),
{'formdata': self.filled})
def check_receiver(self):
session = get_session()