admin: redesign list of form options (#8048)

This commit is contained in:
Frédéric Péters 2015-07-24 12:06:19 +02:00
parent d1884d84f7
commit 70d72878a0
3 changed files with 254 additions and 94 deletions

View File

@ -1,5 +1,6 @@
import datetime
import os
import re
import shutil
import StringIO
import tarfile
@ -168,7 +169,13 @@ def test_forms_new():
assert formdef.disabled == True
assert formdef.last_modification_user_id == 'admin'
def assert_option_display(resp, label, value):
option_line = re.findall('%s.*%s' % (label, value), resp.body, re.DOTALL)
assert option_line
assert not '</li>' in option_line
def test_forms_edit():
create_superuser()
create_role()
FormDef.wipe()
@ -181,16 +188,101 @@ def test_forms_edit():
resp = app.get('/backoffice/forms/1/')
# try changing an option
assert 'Include confirmation page' in resp.body
resp = resp.click(href='options')
# confirmation page
assert_option_display(resp, 'Confirmation Page', 'Enabled')
resp = resp.click('Confirmation Page')
assert resp.forms[0]['confirmation'].checked
resp.forms[0]['confirmation'].checked = False
resp = resp.forms[0].submit()
assert resp.location == 'http://example.net/backoffice/forms/1/'
resp = resp.follow()
assert not 'Include confirmation page' in resp.body
assert_option_display(resp, 'Confirmation Page', 'Disabled')
assert FormDef.get(1).confirmation == False
# try cancel button
resp = resp.click('Confirmation Page')
assert resp.forms[0]['confirmation'].checked is False
resp.forms[0]['confirmation'].checked = True
resp = resp.forms[0].submit('cancel')
assert resp.location == 'http://example.net/backoffice/forms/1/'
resp = resp.follow()
assert_option_display(resp, 'Confirmation Page', 'Disabled')
assert FormDef.get(1).confirmation == False
# history and status
assert_option_display(resp, 'History and Status', 'Public')
resp = resp.click('History and Status')
assert resp.forms[0]['private_status_and_history'].checked is False
resp.forms[0]['private_status_and_history'].checked = True
resp = resp.forms[0].submit()
assert resp.location == 'http://example.net/backoffice/forms/1/'
resp = resp.follow()
assert_option_display(resp, 'History and Status', 'Private')
assert FormDef.get(1).private_status_and_history is True
# Limit to one form
assert_option_display(resp, 'Limit to one form', 'Disabled')
resp = resp.click('Limit to one form')
assert resp.forms[0]['only_allow_one'].checked is False
resp.forms[0]['only_allow_one'].checked = True
resp = resp.forms[0].submit()
assert resp.location == 'http://example.net/backoffice/forms/1/'
resp = resp.follow()
assert_option_display(resp, 'Limit to one form', 'Enabled')
assert FormDef.get(1).only_allow_one is True
# Tracking code
assert_option_display(resp, 'Tracking Code', 'Disabled')
resp = resp.click('Tracking Code')
assert resp.forms[0]['enable_tracking_codes'].checked is False
resp.forms[0]['enable_tracking_codes'].checked = True
resp = resp.forms[0].submit()
assert resp.location == 'http://example.net/backoffice/forms/1/'
resp = resp.follow()
assert_option_display(resp, 'Tracking Code', 'Enabled')
assert FormDef.get(1).enable_tracking_codes is True
# CAPTCHA
assert_option_display(resp, 'CAPTCHA for anonymous users', 'Disabled')
resp = resp.click('CAPTCHA for anonymous users')
assert resp.forms[0]['has_captcha'].checked is False
resp.forms[0]['has_captcha'].checked = True
resp = resp.forms[0].submit()
assert resp.location == 'http://example.net/backoffice/forms/1/'
resp = resp.follow()
assert_option_display(resp, 'CAPTCHA for anonymous users', 'Enabled')
assert FormDef.get(1).has_captcha is True
# Publication
assert_option_display(resp, 'Online Status', 'Published')
resp = resp.click('Online Status')
assert resp.forms[0]['disabled'].checked is False
resp.forms[0]['disabled'].checked = True
resp = resp.forms[0].submit()
assert resp.location == 'http://example.net/backoffice/forms/1/'
resp = resp.follow()
assert_option_display(resp, 'Online Status', 'Disabled')
assert FormDef.get(1).disabled is True
resp = resp.click('Online Status')
assert resp.forms[0]['disabled'].checked is True
resp.forms[0]['disabled_redirection'] = 'http://www.example.net'
resp = resp.forms[0].submit()
assert resp.location == 'http://example.net/backoffice/forms/1/'
resp = resp.follow()
assert_option_display(resp, 'Online Status', 'Redirected')
assert FormDef.get(1).disabled is True
assert FormDef.get(1).disabled_redirection == 'http://www.example.net'
resp = resp.click('Online Status')
resp.forms[0]['disabled'].checked = False
resp.forms[0]['expiration_date'] = '2000-01-01' # this is past(tm)
resp = resp.forms[0].submit()
assert resp.location == 'http://example.net/backoffice/forms/1/'
resp = resp.follow()
assert_option_display(resp, 'Online Status', 'Disabled by date')
# try changing title
resp = app.get('/backoffice/forms/1/')
resp = resp.click('change title')
@ -481,18 +573,20 @@ def test_form_always_advertise():
app = login(get_app(pub))
resp = app.get('/backoffice/forms/1/')
resp = resp.click(href='options')
assert resp.forms[0]['always_advertise'].attrs.get('disabled') is None
# Display to unlogged users
formdef.roles = [role.id]
formdef.store()
resp = app.get('/backoffice/forms/1/')
resp = resp.click(href='options')
assert resp.forms[0]['always_advertise'].attrs.get('disabled') is None
assert_option_display(resp, 'Display to unlogged users', 'Disabled')
resp = resp.click('Display to unlogged users')
assert resp.forms[0]['always_advertise'].checked is False
resp.forms[0]['always_advertise'].checked = True
resp = resp.forms[0].submit()
assert FormDef.get(formdef.id).always_advertise is True
assert resp.location == 'http://example.net/backoffice/forms/1/'
resp = resp.follow()
assert_option_display(resp, 'Display to unlogged users', 'Enabled')
assert FormDef.get(1).always_advertise is True
def test_form_delete():
create_role()

View File

@ -130,6 +130,98 @@ class FieldsDirectory(FieldsDirectory):
return r.getvalue()
class OptionsDirectory(Directory):
_q_exports = ['confirmation', 'private_status', 'only_allow_one',
'always_advertise', 'tracking_code', 'online_status', 'captcha']
def __init__(self, formdef):
self.formdef = formdef
def confirmation(self):
form = Form(enctype='multipart/form-data')
form.add(CheckboxWidget, 'confirmation', title=_('Include confirmation page'),
value=self.formdef.confirmation)
return self.handle(form, _('Confirmation Page'))
def private_status(self):
form = Form(enctype='multipart/form-data')
form.add(CheckboxWidget, 'private_status_and_history',
title=_('Keep workflow status and history private'),
hint=_('Restrict the possibility to see status and history to the recipients'),
value=self.formdef.private_status_and_history)
return self.handle(form, _('History and Status'))
def only_allow_one(self):
form = Form(enctype='multipart/form-data')
form.add(CheckboxWidget, 'only_allow_one',
title=_('Only allow one form per user'),
value=self.formdef.only_allow_one)
return self.handle(form, _('Limit to one form'))
def always_advertise(self):
form = Form(enctype='multipart/form-data')
form.add(CheckboxWidget, 'always_advertise',
title=_('Advertise to unlogged users'),
value=self.formdef.always_advertise)
return self.handle(form, _('Display to unlogged users'))
def tracking_code(self):
form = Form(enctype='multipart/form-data')
form.add(CheckboxWidget, 'enable_tracking_codes',
title=_('Enable support for tracking codes'),
value=self.formdef.enable_tracking_codes)
return self.handle(form, _('Tracking Code'))
def captcha(self):
form = Form(enctype='multipart/form-data')
form.add(CheckboxWidget, 'has_captcha',
title=_('Prepend a CAPTCHA page for anonymous users'),
value=self.formdef.has_captcha)
return self.handle(form, _('CAPTCHA'))
def online_status(self):
form = Form(enctype='multipart/form-data')
form.add(CheckboxWidget, 'disabled',
title=_('Disable access to form'),
value=self.formdef.disabled)
form.add(StringWidget, 'disabled_redirection',
title=_('If disabled, redirect to this URL'), size=40,
hint=_('Redirection will only be performed if the form is disabled and a URL is given. '\
'Common substitution variables are available with the [variable] syntax.'),
value=self.formdef.disabled_redirection)
form.add(DateTimeWidget, 'publication_date',
title=_('Publication Date'),
value=self.formdef.publication_date)
form.add(DateTimeWidget, 'expiration_date',
title=_('Expiration Date'),
value=self.formdef.expiration_date)
return self.handle(form, _('Online Status'))
def handle(self, form, title):
form.add_submit('submit', _('Submit'))
form.add_submit('cancel', _('Cancel'))
if form.get_widget('cancel').parse():
return redirect('..')
if form.is_submitted() and not form.has_errors():
attrs = ['confirmation', 'only_allow_one', 'disabled',
'enable_tracking_codes', 'private_status_and_history',
'always_advertise', 'disabled_redirection',
'publication_date', 'expiration_date', 'has_captcha']
for f in attrs:
widget = form.get_widget(f)
if widget:
setattr(self.formdef, str(f), widget.parse())
self.formdef.store()
return redirect('..')
html_top('forms', title=self.formdef.name)
r = TemplateIO(html=True)
r += htmltext('<h2>%s</h2>') % title
r += form.render()
return r.getvalue()
class WorkflowRoleDirectory(Directory):
def __init__(self, formdef):
self.formdef = formdef
@ -189,6 +281,7 @@ class FormDefPage(Directory):
self.fields.html_top = self.html_top
self.role = WorkflowRoleDirectory(self.formdef)
self.role.html_top = self.html_top
self.options = OptionsDirectory(self.formdef)
def html_top(self, title):
return html_top('forms', title)
@ -318,32 +411,56 @@ class FormDefPage(Directory):
r += htmltext('<div class="splitcontent-right">')
r += htmltext('<div class="bo-block">')
r += htmltext('<h3>%s') % _('Options')
r += htmltext(' <span class="change">(<a rel="popup" href="options">%s</a>)</span></h3>') % _('change')
r += htmltext('<ul>')
if self.formdef.confirmation:
r += htmltext('<li>%s</li>') % _('Include confirmation page')
if self.formdef.private_status_and_history:
r += htmltext('<li>%s</li>') % _('Keep workflow status and history private')
if self.formdef.only_allow_one:
r += htmltext('<li>%s</li>') % _('Only allow one form per user')
if self.formdef.roles and self.formdef.always_advertise:
r += htmltext('<li>%s</li>') % _('Advertise to unlogged users')
if self.formdef.enable_tracking_codes:
r += htmltext('<li>%s</li>') % _('Has support for tracking codes')
r += htmltext('<h3>%s</h3>') % _('Options')
r += htmltext('<ul class="biglist optionslist">')
def add_option_line(link, label, current_value):
return htmltext(
'<li><a rel="popup" href="%(link)s">'
'<span class="label">%(label)s</span> '
'<span class="value">%(current_value)s</span>'
'</a></li>' % {
'link': link,
'label': label,
'current_value': current_value})
r += add_option_line('options/confirmation', _('Confirmation Page'),
self.formdef.confirmation and _('Enabled') or _('Disabled'))
r += add_option_line('options/private_status',
_('History and Status'),
self.formdef.private_status_and_history and _('Private') or _('Public'))
r += add_option_line('options/only_allow_one',
_('Limit to one form'),
self.formdef.only_allow_one and _('Enabled') or _('Disabled'))
if self.formdef.roles:
r += add_option_line('options/always_advertise',
_('Display to unlogged users'),
self.formdef.always_advertise and _('Enabled') or _('Disabled'))
r += add_option_line('options/tracking_code',
_('Tracking Code'),
self.formdef.enable_tracking_codes and _('Enabled') or _('Disabled'))
r += add_option_line('options/captcha',
_('CAPTCHA for anonymous users'),
self.formdef.has_captcha and _('Enabled') or _('Disabled'))
online_status = _('Published')
if self.formdef.disabled:
r += htmltext('<li>%s ') % _('Disabled')
# manually disabled
online_status = _('Disabled')
if self.formdef.disabled_redirection:
r += htmltext('(<a href="%s">') % self.formdef.disabled_redirection
r += _('redirection')
r += htmltext('</a>) ')
r += htmltext(' (<a href="enable">%s</a>)</li>') % _('enable')
if self.formdef.publication_date:
r += htmltext('<li>%s</li>') % _('Publication Date: %s') % self.formdef.publication_date
if self.formdef.expiration_date:
r += htmltext('<li>%s</li>') % _('Expiration Date: %s') % self.formdef.expiration_date
if self.formdef.has_captcha:
r += htmltext('<li>%s</li>') % _('Add CAPTCHA for anonymous users')
online_status = _('Redirected')
elif self.formdef.is_disabled():
# disabled by date
online_status = _('Disabled by date')
r += add_option_line('options/online_status',
_('Online Status'),
online_status)
r += htmltext('</ul>')
r += htmltext('</div>')
r += htmltext('</div>')
@ -583,67 +700,6 @@ class FormDefPage(Directory):
r += form.render()
return r.getvalue()
def options(self):
form = Form(enctype='multipart/form-data')
form.add(CheckboxWidget, 'confirmation', title=_('Include confirmation page'),
value=self.formdef.confirmation)
form.add(CheckboxWidget, 'private_status_and_history',
title=_('Keep workflow status and history private'),
hint=_('Restrict the possibility to see status and history to the recipients'),
value=self.formdef.private_status_and_history)
form.add(CheckboxWidget, 'only_allow_one',
title=_('Only allow one form per user'),
value=self.formdef.only_allow_one)
kwargs = {}
form.add(CheckboxWidget, 'always_advertise',
title=_('Advertise to unlogged users'),
value=self.formdef.always_advertise,
**kwargs)
form.add(CheckboxWidget, 'enable_tracking_codes',
title=_('Enable support for tracking codes'),
value=self.formdef.enable_tracking_codes)
form.add(CheckboxWidget, 'disabled',
title=_('Disable access to form'),
value=self.formdef.disabled)
form.add(StringWidget, 'disabled_redirection',
title=_('If disabled, redirect to this URL'), size=40,
hint=_('Redirection will only be performed if the form is disabled and a URL is given. '\
'Common substitution variables are available with the [variable] syntax.'),
value=self.formdef.disabled_redirection)
form.add(DateTimeWidget, 'publication_date',
title=_('Publication Date'),
value=self.formdef.publication_date)
form.add(DateTimeWidget, 'expiration_date',
title=_('Expiration Date'),
value=self.formdef.expiration_date)
form.add(CheckboxWidget, 'has_captcha',
title=_('Prepend a CAPTCHA page for anonymous users'),
value=self.formdef.has_captcha)
form.add_submit('submit', _('Submit'))
form.add_submit('cancel', _('Cancel'))
if form.get_widget('cancel').parse():
return redirect('.')
if form.is_submitted() and not form.has_errors():
attrs = ['confirmation', 'only_allow_one', 'disabled',
'enable_tracking_codes', 'private_status_and_history',
'disabled_redirection', 'publication_date',
'expiration_date', 'always_advertise', 'has_captcha']
for f in attrs:
widget = form.get_widget(f)
if widget:
setattr(self.formdef, str(f), widget.parse())
self.formdef.store()
return redirect('.')
get_response().breadcrumb.append( ('options', _('Options')) )
self.html_top(title=self.formdef.name)
r = TemplateIO(html=True)
r += htmltext('<h2>%s</h2>') % _('Options')
r += form.render()
return r.getvalue()
def workflow(self):
form = Form(enctype='multipart/form-data')
workflows = get_workflows(condition=lambda x: x.possible_status)

View File

@ -95,6 +95,10 @@ ul.biglist .details {
padding-right: 0.5ex;
}
ul.biglist.optionslist span.value {
float: right;
}
ul.themes p.details {
display: block;
float: none;
@ -544,6 +548,12 @@ div.bo-block ul.biglist h3 {
margin: 0;
}
div.bo-block > h3 {
padding: 1ex 0ex;
font-weight: normal;
margin: 0;
}
div.bo-block ul.biglist li.disabled {
background: none;
}