0001-admin-redesign-list-of-form-options-8048.patch
tests/test_admin_pages.py | ||
---|---|---|
1 | 1 |
import datetime |
2 | 2 |
import os |
3 |
import re |
|
3 | 4 |
import shutil |
4 | 5 |
import StringIO |
5 | 6 |
import tarfile |
... | ... | |
168 | 169 |
assert formdef.disabled == True |
169 | 170 |
assert formdef.last_modification_user_id == 'admin' |
170 | 171 | |
172 |
def assert_option_display(resp, label, value): |
|
173 |
option_line = re.findall('%s.*%s' % (label, value), resp.body, re.DOTALL) |
|
174 |
assert option_line |
|
175 |
assert not '</li>' in option_line |
|
176 | ||
171 | 177 |
def test_forms_edit(): |
178 |
create_superuser() |
|
172 | 179 |
create_role() |
173 | 180 | |
174 | 181 |
FormDef.wipe() |
... | ... | |
181 | 188 |
resp = app.get('/backoffice/forms/1/') |
182 | 189 | |
183 | 190 |
# try changing an option |
184 |
assert 'Include confirmation page' in resp.body |
|
185 |
resp = resp.click(href='options') |
|
191 | ||
192 |
# confirmation page |
|
193 |
assert_option_display(resp, 'Confirmation Page', 'Enabled') |
|
194 |
resp = resp.click('Confirmation Page') |
|
186 | 195 |
assert resp.forms[0]['confirmation'].checked |
187 | 196 |
resp.forms[0]['confirmation'].checked = False |
188 | 197 |
resp = resp.forms[0].submit() |
189 | 198 |
assert resp.location == 'http://example.net/backoffice/forms/1/' |
190 | 199 |
resp = resp.follow() |
191 |
assert not 'Include confirmation page' in resp.body |
|
200 |
assert_option_display(resp, 'Confirmation Page', 'Disabled') |
|
201 |
assert FormDef.get(1).confirmation == False |
|
202 | ||
203 |
# try cancel button |
|
204 |
resp = resp.click('Confirmation Page') |
|
205 |
assert resp.forms[0]['confirmation'].checked is False |
|
206 |
resp.forms[0]['confirmation'].checked = True |
|
207 |
resp = resp.forms[0].submit('cancel') |
|
208 |
assert resp.location == 'http://example.net/backoffice/forms/1/' |
|
209 |
resp = resp.follow() |
|
210 |
assert_option_display(resp, 'Confirmation Page', 'Disabled') |
|
192 | 211 |
assert FormDef.get(1).confirmation == False |
193 | 212 | |
213 |
# history and status |
|
214 |
assert_option_display(resp, 'History and Status', 'Public') |
|
215 |
resp = resp.click('History and Status') |
|
216 |
assert resp.forms[0]['private_status_and_history'].checked is False |
|
217 |
resp.forms[0]['private_status_and_history'].checked = True |
|
218 |
resp = resp.forms[0].submit() |
|
219 |
assert resp.location == 'http://example.net/backoffice/forms/1/' |
|
220 |
resp = resp.follow() |
|
221 |
assert_option_display(resp, 'History and Status', 'Private') |
|
222 |
assert FormDef.get(1).private_status_and_history is True |
|
223 | ||
224 |
# Limit to one form |
|
225 |
assert_option_display(resp, 'Limit to one form', 'Disabled') |
|
226 |
resp = resp.click('Limit to one form') |
|
227 |
assert resp.forms[0]['only_allow_one'].checked is False |
|
228 |
resp.forms[0]['only_allow_one'].checked = True |
|
229 |
resp = resp.forms[0].submit() |
|
230 |
assert resp.location == 'http://example.net/backoffice/forms/1/' |
|
231 |
resp = resp.follow() |
|
232 |
assert_option_display(resp, 'Limit to one form', 'Enabled') |
|
233 |
assert FormDef.get(1).only_allow_one is True |
|
234 | ||
235 |
# Tracking code |
|
236 |
assert_option_display(resp, 'Tracking Code', 'Disabled') |
|
237 |
resp = resp.click('Tracking Code') |
|
238 |
assert resp.forms[0]['enable_tracking_codes'].checked is False |
|
239 |
resp.forms[0]['enable_tracking_codes'].checked = True |
|
240 |
resp = resp.forms[0].submit() |
|
241 |
assert resp.location == 'http://example.net/backoffice/forms/1/' |
|
242 |
resp = resp.follow() |
|
243 |
assert_option_display(resp, 'Tracking Code', 'Enabled') |
|
244 |
assert FormDef.get(1).enable_tracking_codes is True |
|
245 | ||
246 |
# Publication |
|
247 |
assert_option_display(resp, 'Online Status', 'Published') |
|
248 |
resp = resp.click('Online Status') |
|
249 |
assert resp.forms[0]['disabled'].checked is False |
|
250 |
resp.forms[0]['disabled'].checked = True |
|
251 |
resp = resp.forms[0].submit() |
|
252 |
assert resp.location == 'http://example.net/backoffice/forms/1/' |
|
253 |
resp = resp.follow() |
|
254 |
assert_option_display(resp, 'Online Status', 'Disabled') |
|
255 |
assert FormDef.get(1).disabled is True |
|
256 | ||
257 |
resp = resp.click('Online Status') |
|
258 |
assert resp.forms[0]['disabled'].checked is True |
|
259 |
resp.forms[0]['disabled_redirection'] = 'http://www.example.net' |
|
260 |
resp = resp.forms[0].submit() |
|
261 |
assert resp.location == 'http://example.net/backoffice/forms/1/' |
|
262 |
resp = resp.follow() |
|
263 |
assert_option_display(resp, 'Online Status', 'Redirected') |
|
264 |
assert FormDef.get(1).disabled is True |
|
265 |
assert FormDef.get(1).disabled_redirection == 'http://www.example.net' |
|
266 | ||
267 |
resp = resp.click('Online Status') |
|
268 |
resp.forms[0]['disabled'].checked = False |
|
269 |
resp.forms[0]['expiration_date'] = '2000-01-01' # this is past(tm) |
|
270 |
resp = resp.forms[0].submit() |
|
271 |
assert resp.location == 'http://example.net/backoffice/forms/1/' |
|
272 |
resp = resp.follow() |
|
273 |
assert_option_display(resp, 'Online Status', 'Disabled by date') |
|
274 | ||
194 | 275 |
# try changing title |
195 | 276 |
resp = app.get('/backoffice/forms/1/') |
196 | 277 |
resp = resp.click('change title') |
... | ... | |
481 | 562 | |
482 | 563 |
app = login(get_app(pub)) |
483 | 564 |
resp = app.get('/backoffice/forms/1/') |
484 |
resp = resp.click(href='options') |
|
485 |
assert resp.forms[0]['always_advertise'].attrs.get('disabled') is None |
|
486 | 565 | |
566 |
# Display to unlogged users |
|
487 | 567 |
formdef.roles = [role.id] |
488 | 568 |
formdef.store() |
489 | 569 |
resp = app.get('/backoffice/forms/1/') |
490 |
resp = resp.click(href='options') |
|
491 |
assert resp.forms[0]['always_advertise'].attrs.get('disabled') is None |
|
570 |
assert_option_display(resp, 'Display to unlogged users', 'Disabled') |
|
571 |
resp = resp.click('Display to unlogged users') |
|
572 |
assert resp.forms[0]['always_advertise'].checked is False |
|
492 | 573 |
resp.forms[0]['always_advertise'].checked = True |
493 | 574 |
resp = resp.forms[0].submit() |
494 | ||
495 |
assert FormDef.get(formdef.id).always_advertise is True |
|
575 |
assert resp.location == 'http://example.net/backoffice/forms/1/' |
|
576 |
resp = resp.follow() |
|
577 |
assert_option_display(resp, 'Display to unlogged users', 'Enabled') |
|
578 |
assert FormDef.get(1).always_advertise is True |
|
496 | 579 | |
497 | 580 |
def test_form_delete(): |
498 | 581 |
create_role() |
wcs/admin/forms.py | ||
---|---|---|
130 | 130 |
return r.getvalue() |
131 | 131 | |
132 | 132 | |
133 |
class OptionsDirectory(Directory): |
|
134 |
_q_exports = ['confirmation', 'private_status', 'only_allow_one', |
|
135 |
'always_advertise', 'tracking_code', 'online_status'] |
|
136 | ||
137 |
def __init__(self, formdef): |
|
138 |
self.formdef = formdef |
|
139 | ||
140 |
def confirmation(self): |
|
141 |
form = Form(enctype='multipart/form-data') |
|
142 |
form.add(CheckboxWidget, 'confirmation', title=_('Include confirmation page'), |
|
143 |
value=self.formdef.confirmation) |
|
144 |
return self.handle(form, _('Confirmation Page')) |
|
145 | ||
146 |
def private_status(self): |
|
147 |
form = Form(enctype='multipart/form-data') |
|
148 |
form.add(CheckboxWidget, 'private_status_and_history', |
|
149 |
title=_('Keep workflow status and history private'), |
|
150 |
hint=_('Restrict the possibility to see status and history to the recipients'), |
|
151 |
value=self.formdef.private_status_and_history) |
|
152 |
return self.handle(form, _('History and Status')) |
|
153 | ||
154 |
def only_allow_one(self): |
|
155 |
form = Form(enctype='multipart/form-data') |
|
156 |
form.add(CheckboxWidget, 'only_allow_one', |
|
157 |
title=_('Only allow one form per user'), |
|
158 |
value=self.formdef.only_allow_one) |
|
159 |
return self.handle(form, _('Limit to one form')) |
|
160 | ||
161 |
def always_advertise(self): |
|
162 |
form = Form(enctype='multipart/form-data') |
|
163 |
form.add(CheckboxWidget, 'always_advertise', |
|
164 |
title=_('Advertise to unlogged users'), |
|
165 |
value=self.formdef.always_advertise) |
|
166 |
return self.handle(form, _('Dispaly to unlogged users')) |
|
167 | ||
168 |
def tracking_code(self): |
|
169 |
form = Form(enctype='multipart/form-data') |
|
170 |
form.add(CheckboxWidget, 'enable_tracking_codes', |
|
171 |
title=_('Enable support for tracking codes'), |
|
172 |
value=self.formdef.enable_tracking_codes) |
|
173 |
return self.handle(form, _('Tracking Code')) |
|
174 | ||
175 |
def online_status(self): |
|
176 |
form = Form(enctype='multipart/form-data') |
|
177 |
form.add(CheckboxWidget, 'disabled', |
|
178 |
title=_('Disable access to form'), |
|
179 |
value=self.formdef.disabled) |
|
180 |
form.add(StringWidget, 'disabled_redirection', |
|
181 |
title=_('If disabled, redirect to this URL'), size=40, |
|
182 |
hint=_('Redirection will only be performed if the form is disabled and a URL is given. '\ |
|
183 |
'Common substitution variables are available with the [variable] syntax.'), |
|
184 |
value=self.formdef.disabled_redirection) |
|
185 |
form.add(DateTimeWidget, 'publication_date', |
|
186 |
title=_('Publication Date'), |
|
187 |
value=self.formdef.publication_date) |
|
188 |
form.add(DateTimeWidget, 'expiration_date', |
|
189 |
title=_('Expiration Date'), |
|
190 |
value=self.formdef.expiration_date) |
|
191 |
return self.handle(form, _('Online Status')) |
|
192 | ||
193 |
def handle(self, form, title): |
|
194 |
form.add_submit('submit', _('Submit')) |
|
195 |
form.add_submit('cancel', _('Cancel')) |
|
196 |
if form.get_widget('cancel').parse(): |
|
197 |
return redirect('..') |
|
198 | ||
199 |
if form.is_submitted() and not form.has_errors(): |
|
200 |
attrs = ['confirmation', 'only_allow_one', 'disabled', |
|
201 |
'enable_tracking_codes', 'private_status_and_history', |
|
202 |
'always_advertise', 'disabled_redirection', |
|
203 |
'publication_date', 'expiration_date'] |
|
204 |
for f in attrs: |
|
205 |
widget = form.get_widget(f) |
|
206 |
if widget: |
|
207 |
setattr(self.formdef, str(f), widget.parse()) |
|
208 |
self.formdef.store() |
|
209 |
return redirect('..') |
|
210 | ||
211 |
html_top('forms', title=self.formdef.name) |
|
212 |
r = TemplateIO(html=True) |
|
213 |
r += htmltext('<h2>%s</h2>') % title |
|
214 |
r += form.render() |
|
215 |
return r.getvalue() |
|
216 | ||
217 | ||
133 | 218 |
class WorkflowRoleDirectory(Directory): |
134 | 219 |
def __init__(self, formdef): |
135 | 220 |
self.formdef = formdef |
... | ... | |
189 | 274 |
self.fields.html_top = self.html_top |
190 | 275 |
self.role = WorkflowRoleDirectory(self.formdef) |
191 | 276 |
self.role.html_top = self.html_top |
277 |
self.options = OptionsDirectory(self.formdef) |
|
192 | 278 | |
193 | 279 |
def html_top(self, title): |
194 | 280 |
return html_top('forms', title) |
... | ... | |
318 | 404 | |
319 | 405 |
r += htmltext('<div class="splitcontent-right">') |
320 | 406 |
r += htmltext('<div class="bo-block">') |
321 |
r += htmltext('<h3>%s') % _('Options') |
|
322 |
r += htmltext(' <span class="change">(<a rel="popup" href="options">%s</a>)</span></h3>') % _('change') |
|
323 |
r += htmltext('<ul>') |
|
324 |
if self.formdef.confirmation: |
|
325 |
r += htmltext('<li>%s</li>') % _('Include confirmation page') |
|
326 |
if self.formdef.private_status_and_history: |
|
327 |
r += htmltext('<li>%s</li>') % _('Keep workflow status and history private') |
|
328 |
if self.formdef.only_allow_one: |
|
329 |
r += htmltext('<li>%s</li>') % _('Only allow one form per user') |
|
330 |
if self.formdef.roles and self.formdef.always_advertise: |
|
331 |
r += htmltext('<li>%s</li>') % _('Advertise to unlogged users') |
|
332 |
if self.formdef.enable_tracking_codes: |
|
333 |
r += htmltext('<li>%s</li>') % _('Has support for tracking codes') |
|
407 |
r += htmltext('<h3>%s</h3>') % _('Options') |
|
408 |
r += htmltext('<ul class="biglist optionslist">') |
|
409 | ||
410 |
def add_option_line(link, label, current_value): |
|
411 |
return htmltext( |
|
412 |
'<li><a rel="popup" href="%(link)s">' |
|
413 |
'<span class="label">%(label)s</span> ' |
|
414 |
'<span class="value">%(current_value)s</span>' |
|
415 |
'</a></li>' % { |
|
416 |
'link': link, |
|
417 |
'label': label, |
|
418 |
'current_value': current_value}) |
|
419 | ||
420 |
r += add_option_line('options/confirmation', _('Confirmation Page'), |
|
421 |
self.formdef.confirmation and _('Enabled') or _('Disabled')) |
|
422 | ||
423 |
r += add_option_line('options/private_status', |
|
424 |
_('History and Status'), |
|
425 |
self.formdef.private_status_and_history and _('Private') or _('Public')) |
|
426 | ||
427 |
r += add_option_line('options/only_allow_one', |
|
428 |
_('Limit to one form'), |
|
429 |
self.formdef.only_allow_one and _('Enabled') or _('Disabled')) |
|
430 | ||
431 |
if self.formdef.roles: |
|
432 |
r += add_option_line('options/always_advertise', |
|
433 |
_('Display to unlogged users'), |
|
434 |
self.formdef.always_advertise and _('Enabled') or _('Disabled')) |
|
435 | ||
436 |
r += add_option_line('options/tracking_code', |
|
437 |
_('Tracking Code'), |
|
438 |
self.formdef.enable_tracking_codes and _('Enabled') or _('Disabled')) |
|
439 | ||
440 |
online_status = _('Published') |
|
334 | 441 |
if self.formdef.disabled: |
335 |
r += htmltext('<li>%s ') % _('Disabled') |
|
442 |
# manually disabled |
|
443 |
online_status = _('Disabled') |
|
336 | 444 |
if self.formdef.disabled_redirection: |
337 |
r += htmltext('(<a href="%s">') % self.formdef.disabled_redirection
|
|
338 |
r += _('redirection')
|
|
339 |
r += htmltext('</a>) ')
|
|
340 |
r += htmltext(' (<a href="enable">%s</a>)</li>') % _('enable')
|
|
341 |
if self.formdef.publication_date:
|
|
342 |
r += htmltext('<li>%s</li>') % _('Publication Date: %s') % self.formdef.publication_date
|
|
343 |
if self.formdef.expiration_date:
|
|
344 |
r += htmltext('<li>%s</li>') % _('Expiration Date: %s') % self.formdef.expiration_date |
|
445 |
online_status = _('Redirected')
|
|
446 |
elif self.formdef.is_disabled():
|
|
447 |
# disabled by date
|
|
448 |
online_status = _('Disabled by date')
|
|
449 |
r += add_option_line('options/online_status',
|
|
450 |
_('Online Status'),
|
|
451 |
online_status)
|
|
452 | ||
345 | 453 |
r += htmltext('</ul>') |
346 | 454 |
r += htmltext('</div>') |
347 | 455 |
r += htmltext('</div>') |
... | ... | |
581 | 689 |
r += form.render() |
582 | 690 |
return r.getvalue() |
583 | 691 | |
584 |
def options(self): |
|
585 |
form = Form(enctype='multipart/form-data') |
|
586 |
form.add(CheckboxWidget, 'confirmation', title=_('Include confirmation page'), |
|
587 |
value=self.formdef.confirmation) |
|
588 |
form.add(CheckboxWidget, 'private_status_and_history', |
|
589 |
title=_('Keep workflow status and history private'), |
|
590 |
hint=_('Restrict the possibility to see status and history to the recipients'), |
|
591 |
value=self.formdef.private_status_and_history) |
|
592 |
form.add(CheckboxWidget, 'only_allow_one', |
|
593 |
title=_('Only allow one form per user'), |
|
594 |
value=self.formdef.only_allow_one) |
|
595 |
kwargs = {} |
|
596 |
form.add(CheckboxWidget, 'always_advertise', |
|
597 |
title=_('Advertise to unlogged users'), |
|
598 |
value=self.formdef.always_advertise, |
|
599 |
**kwargs) |
|
600 |
form.add(CheckboxWidget, 'enable_tracking_codes', |
|
601 |
title=_('Enable support for tracking codes'), |
|
602 |
value=self.formdef.enable_tracking_codes) |
|
603 |
form.add(CheckboxWidget, 'disabled', |
|
604 |
title=_('Disable access to form'), |
|
605 |
value=self.formdef.disabled) |
|
606 |
form.add(StringWidget, 'disabled_redirection', |
|
607 |
title=_('If disabled, redirect to this URL'), size=40, |
|
608 |
hint=_('Redirection will only be performed if the form is disabled and a URL is given. '\ |
|
609 |
'Common substitution variables are available with the [variable] syntax.'), |
|
610 |
value=self.formdef.disabled_redirection) |
|
611 |
form.add(DateTimeWidget, 'publication_date', |
|
612 |
title=_('Publication Date'), |
|
613 |
value=self.formdef.publication_date) |
|
614 |
form.add(DateTimeWidget, 'expiration_date', |
|
615 |
title=_('Expiration Date'), |
|
616 |
value=self.formdef.expiration_date) |
|
617 | ||
618 |
form.add_submit('submit', _('Submit')) |
|
619 |
form.add_submit('cancel', _('Cancel')) |
|
620 |
if form.get_widget('cancel').parse(): |
|
621 |
return redirect('.') |
|
622 | ||
623 |
if form.is_submitted() and not form.has_errors(): |
|
624 |
attrs = ['confirmation', 'only_allow_one', 'disabled', |
|
625 |
'enable_tracking_codes', 'private_status_and_history', |
|
626 |
'disabled_redirection', 'publication_date', |
|
627 |
'expiration_date', 'always_advertise'] |
|
628 |
for f in attrs: |
|
629 |
widget = form.get_widget(f) |
|
630 |
if widget: |
|
631 |
setattr(self.formdef, str(f), widget.parse()) |
|
632 |
self.formdef.store() |
|
633 |
return redirect('.') |
|
634 | ||
635 |
get_response().breadcrumb.append( ('options', _('Options')) ) |
|
636 |
self.html_top(title=self.formdef.name) |
|
637 |
r = TemplateIO(html=True) |
|
638 |
r += htmltext('<h2>%s</h2>') % _('Options') |
|
639 |
r += form.render() |
|
640 |
return r.getvalue() |
|
641 | ||
642 | 692 |
def workflow(self): |
643 | 693 |
form = Form(enctype='multipart/form-data') |
644 | 694 |
workflows = get_workflows(condition=lambda x: x.possible_status) |
wcs/qommon/static/css/dc2/admin.css | ||
---|---|---|
95 | 95 |
padding-right: 0.5ex; |
96 | 96 |
} |
97 | 97 | |
98 |
ul.biglist.optionslist span.value { |
|
99 |
float: right; |
|
100 |
} |
|
101 | ||
98 | 102 |
ul.themes p.details { |
99 | 103 |
display: block; |
100 | 104 |
float: none; |
... | ... | |
544 | 548 |
margin: 0; |
545 | 549 |
} |
546 | 550 | |
551 |
div.bo-block > h3 { |
|
552 |
padding: 1ex 0ex; |
|
553 |
font-weight: normal; |
|
554 |
margin: 0; |
|
555 |
} |
|
556 | ||
547 | 557 |
div.bo-block ul.biglist li.disabled { |
548 | 558 |
background: none; |
549 | 559 |
} |
550 |
- |