forms: add appearance keywords to formdefs (#21370)
This commit is contained in:
parent
9e612e8858
commit
ae765a6618
|
@ -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')
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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():
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 '
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue