231 |
231 |
return True
|
232 |
232 |
return False
|
233 |
233 |
|
234 |
|
def step(self, step_no, page_no, data=None):
|
235 |
|
if step_no == 0:
|
236 |
|
self.substvars['current_page_no'] = str(page_no + 1)
|
|
234 |
def step(self, step_no, current_page, data=None):
|
237 |
235 |
get_logger().info('form %s - step %s' % (self.formdef.name, step_no))
|
238 |
236 |
|
239 |
237 |
page_labels = []
|
240 |
238 |
current_position = 1
|
241 |
239 |
|
242 |
|
page_index = self.formdef.get_start_page()
|
243 |
|
for field in self.formdef.fields:
|
244 |
|
if field.type != 'page':
|
245 |
|
continue
|
246 |
|
if field.is_visible(data, self.formdef):
|
247 |
|
page_labels.append(field.label)
|
248 |
|
if page_index == page_no:
|
249 |
|
current_position = len(page_labels)
|
250 |
|
page_index += 1
|
251 |
|
|
252 |
|
if not page_labels:
|
253 |
|
page_labels.append(_('Filling'))
|
|
240 |
for i, page in enumerate(self.pages):
|
|
241 |
if page is None: # monopage form
|
|
242 |
page_labels.append(_('Filling'))
|
|
243 |
else:
|
|
244 |
page_labels.append(page.label)
|
|
245 |
if page is current_page:
|
|
246 |
current_position = i + 1
|
254 |
247 |
|
255 |
248 |
if step_no > 0:
|
256 |
249 |
current_position = len(page_labels) + step_no
|
257 |
250 |
|
|
251 |
if step_no == 0:
|
|
252 |
self.substvars['current_page_no'] = current_position
|
|
253 |
|
258 |
254 |
if self.has_confirmation_page() and not self.edit_mode:
|
259 |
255 |
page_labels.append(_('Validating'))
|
260 |
256 |
|
... | ... | |
282 |
278 |
r += htmltext('</ol></div>')
|
283 |
279 |
return r.getvalue()
|
284 |
280 |
|
285 |
|
def page(self, page_no, page_change=True, page_error_messages=None):
|
|
281 |
def page(self, page, page_change=True, page_error_messages=None):
|
286 |
282 |
displayed_fields = []
|
287 |
283 |
|
288 |
284 |
session = get_session()
|
289 |
285 |
|
290 |
|
if page_no > self.formdef.get_start_page():
|
|
286 |
if page and self.pages.index(page) > 0:
|
291 |
287 |
magictoken = get_request().form['magictoken']
|
292 |
288 |
self.feed_current_data(magictoken)
|
293 |
289 |
|
294 |
|
form = self.create_form(page_no, displayed_fields)
|
|
290 |
form = self.create_form(page, displayed_fields)
|
295 |
291 |
if page_error_messages:
|
296 |
292 |
form.add_global_errors(page_error_messages)
|
297 |
293 |
if getattr(session, 'ajax_form_token', None):
|
... | ... | |
309 |
305 |
else:
|
310 |
306 |
form_data = {}
|
311 |
307 |
|
312 |
|
if page_no == self.formdef.get_start_page() and not get_request().form.has_key('magictoken'):
|
|
308 |
if page == self.pages[0] and not get_request().form.has_key('magictoken'):
|
313 |
309 |
magictoken = randbytes(8)
|
314 |
310 |
else:
|
315 |
311 |
magictoken = get_request().form['magictoken']
|
316 |
312 |
form.add_hidden('magictoken', magictoken)
|
317 |
313 |
data = session.get_by_magictoken(magictoken, {})
|
318 |
314 |
|
319 |
|
if page_no == self.formdef.get_start_page() and get_request().form.has_key('cancelurl'):
|
|
315 |
if page == self.pages[0] and get_request().form.has_key('cancelurl'):
|
320 |
316 |
cancelurl = get_request().form['cancelurl']
|
321 |
317 |
session.add_magictoken(magictoken, {'__cancelurl': cancelurl})
|
322 |
318 |
|
323 |
|
if self.edit_mode and page_no == self.page_number - 1:
|
|
319 |
if self.edit_mode and (page is None or page == self.pages[-1]):
|
324 |
320 |
form.add_submit('submit', _('Save Changes'))
|
325 |
|
elif not self.has_confirmation_page() and page_no == self.page_number - 1:
|
|
321 |
elif not self.has_confirmation_page() and (page is None or page == self.pages[-1]):
|
326 |
322 |
form.add_submit('submit', _('Submit'))
|
327 |
323 |
else:
|
328 |
324 |
form.add_submit('submit', _('Next'))
|
329 |
325 |
|
330 |
|
if page_no > self.formdef.get_start_page():
|
|
326 |
if self.pages.index(page) > 0:
|
331 |
327 |
form.add_submit('previous', _('Previous'))
|
332 |
328 |
|
333 |
329 |
if page_change:
|
... | ... | |
394 |
390 |
self.html_top(self.formdef.name)
|
395 |
391 |
|
396 |
392 |
form.add_hidden('step', '0')
|
397 |
|
form.add_hidden('page', page_no)
|
|
393 |
form.add_hidden('page', self.pages.index(page))
|
398 |
394 |
|
399 |
395 |
form.add_submit('cancel', _('Cancel'), css_class = 'cancel')
|
400 |
396 |
if self.formdef.enable_tracking_codes and not self.edit_mode:
|
... | ... | |
404 |
400 |
context = {
|
405 |
401 |
'view': self,
|
406 |
402 |
'form': form,
|
407 |
|
'form_side': lambda: self.form_side(0, page_no, data=data, magictoken=magictoken),
|
408 |
|
'steps': lambda: self.step(0, page_no, data=data),
|
|
403 |
'form_side': lambda: self.form_side(0, page, data=data, magictoken=magictoken),
|
|
404 |
'steps': lambda: self.step(0, page, data=data),
|
409 |
405 |
}
|
410 |
406 |
if self.formdef.enable_tracking_codes and data:
|
411 |
407 |
context['tracking_code_box'] = lambda: self.tracking_code_box(data, magictoken)
|
... | ... | |
414 |
410 |
list(self.get_formdef_template_variants(self.filling_templates)),
|
415 |
411 |
context)
|
416 |
412 |
|
417 |
|
def form_side(self, step_no, page_no, data=None, magictoken=None):
|
|
413 |
def form_side(self, step_no, page, data=None, magictoken=None):
|
418 |
414 |
'''Create the elements that typically appear aside the main form
|
419 |
415 |
(tracking code and steps).'''
|
420 |
416 |
r = TemplateIO(html=True)
|
... | ... | |
424 |
420 |
# data (e.g. the user is not on a insufficient authenticiation
|
425 |
421 |
# context page)
|
426 |
422 |
r += self.tracking_code_box(data, magictoken)
|
427 |
|
r += self.step(step_no, page_no, data=data)
|
|
423 |
r += self.step(step_no, page, data=data)
|
428 |
424 |
r += htmltext('</div> <!-- #side -->')
|
429 |
425 |
return mark_safe(str(r.getvalue()))
|
430 |
426 |
|
... | ... | |
458 |
454 |
r += htmltext('</div>') # <!-- #tracking-code -->
|
459 |
455 |
return r.getvalue()
|
460 |
456 |
|
461 |
|
def feed_current_data(self, magictoken):
|
462 |
|
# create a fake FormData to feed variables
|
|
457 |
def get_transient_formdata(self, magictoken=Ellipsis):
|
|
458 |
if magictoken is Ellipsis:
|
|
459 |
magictoken = get_request().form.get('magictoken')
|
|
460 |
# create a fake FormData with current submission data
|
463 |
461 |
formdata = FormData()
|
464 |
462 |
formdata._formdef = self.formdef
|
465 |
463 |
formdata.user = get_request().user
|
... | ... | |
469 |
467 |
draft_formdata_id = formdata.data.get('draft_formdata_id')
|
470 |
468 |
if draft_formdata_id:
|
471 |
469 |
formdata = self.formdef.data_class().get(draft_formdata_id)
|
472 |
|
formdata.status = str('')
|
|
470 |
formdata.status = ''
|
|
471 |
return formdata
|
|
472 |
|
|
473 |
def feed_current_data(self, magictoken):
|
|
474 |
formdata = self.get_transient_formdata(magictoken)
|
473 |
475 |
get_publisher().substitutions.feed(formdata)
|
474 |
476 |
|
475 |
477 |
def check_disabled(self):
|
... | ... | |
495 |
497 |
|
496 |
498 |
self.html_top(self.formdef.name)
|
497 |
499 |
r = TemplateIO(html=True)
|
498 |
|
r += self.form_side(step_no=0, page_no=self.formdef.get_start_page())
|
|
500 |
r += self.form_side(step_no=0, page=self.pages[0])
|
499 |
501 |
auth_contexts = get_publisher().get_supported_authentication_contexts()
|
500 |
502 |
r += htmltext('<div class="errornotice">')
|
501 |
503 |
r += htmltext('<p>%s</p>') % _('You need a stronger authentication level to fill this form.')
|
... | ... | |
506 |
508 |
root_url, _('Login with %s') % auth_contexts[auth_context])
|
507 |
509 |
return r.getvalue()
|
508 |
510 |
|
|
511 |
_pages = None
|
|
512 |
@property
|
|
513 |
def pages(self):
|
|
514 |
if self._pages:
|
|
515 |
return self._pages
|
|
516 |
current_data = self.get_transient_formdata().data
|
|
517 |
pages = []
|
|
518 |
field_page = None
|
|
519 |
for field in self.formdef.fields:
|
|
520 |
if field.type == 'page':
|
|
521 |
field_page = field
|
|
522 |
if field.is_visible(current_data, self.formdef):
|
|
523 |
pages.append(field)
|
|
524 |
if not field_page: # form without page fields
|
|
525 |
pages = [None]
|
|
526 |
self._pages = pages
|
|
527 |
return pages
|
|
528 |
|
|
529 |
def reset_pages_cache(self):
|
|
530 |
self._pages = None
|
|
531 |
|
509 |
532 |
def _q_index(self):
|
510 |
533 |
self.check_role()
|
511 |
534 |
authentication_context_check_result = self.check_authentication_context()
|
... | ... | |
539 |
562 |
session_magic_token = session.get_by_magictoken(
|
540 |
563 |
get_request().form.get('magictoken'), no_magic)
|
541 |
564 |
if session_magic_token is no_magic:
|
542 |
|
if (get_request().form.get('page') != str(self.formdef.get_start_page()) or
|
|
565 |
if (get_request().form.get('page') != '0' or
|
543 |
566 |
get_request().form.get('step') != '0'):
|
544 |
567 |
# the magictoken that has been submitted is not available
|
545 |
568 |
# in the session and we're not on the first page of the
|
... | ... | |
615 |
638 |
req.form['f%s' % field.id] = field.convert_value_to_str(data[field.id])
|
616 |
639 |
return self.validating(data)
|
617 |
640 |
else:
|
618 |
|
page_no = self.formdef.get_start_page()
|
619 |
|
return self.page(page_no, True)
|
|
641 |
page_no = 0
|
|
642 |
return self.page(self.pages[page_no], True)
|
620 |
643 |
self.feed_current_data(None)
|
621 |
|
if self.formdef.get_start_page() is None:
|
|
644 |
if not self.pages:
|
622 |
645 |
raise errors.TraversalError()
|
623 |
|
return self.page(self.formdef.get_start_page())
|
|
646 |
return self.page(self.pages[0])
|
624 |
647 |
|
625 |
648 |
if form.get_submit() == 'cancel':
|
626 |
649 |
get_logger().info('form %s - cancel' % (self.formdef.name))
|
... | ... | |
660 |
683 |
try:
|
661 |
684 |
page_no = int(form.get_widget('page').parse())
|
662 |
685 |
except TypeError:
|
663 |
|
page_no = -1
|
|
686 |
# this situation shouldn't arise (that likely means the
|
|
687 |
# page hidden field had an error in its submission), in
|
|
688 |
# that case we just fall back to the first page.
|
|
689 |
page_no = 0
|
|
690 |
page = self.pages[page_no]
|
664 |
691 |
try:
|
665 |
692 |
magictoken = form.get_widget('magictoken').parse()
|
666 |
693 |
except KeyError:
|
... | ... | |
668 |
695 |
|
669 |
696 |
self.feed_current_data(magictoken)
|
670 |
697 |
|
671 |
|
form = self.create_form(page_no)
|
|
698 |
form = self.create_form(page=page)
|
672 |
699 |
form.add_submit('previous')
|
673 |
700 |
if self.formdef.enable_tracking_codes:
|
674 |
701 |
form.add_submit('removedraft')
|
675 |
702 |
form.add_submit('savedraft')
|
676 |
703 |
form.add_submit('submit')
|
677 |
|
if page_no > self.formdef.get_start_page() and form.get_submit() == 'previous':
|
|
704 |
if page_no > 0 and form.get_submit() == 'previous':
|
678 |
705 |
return self.previous_page(page_no, magictoken)
|
679 |
706 |
|
680 |
707 |
if self.formdef.enable_tracking_codes and form.get_submit() == 'removedraft':
|
... | ... | |
688 |
715 |
return redirect(filled.get_url().rstrip('/'))
|
689 |
716 |
|
690 |
717 |
page_error_messages = []
|
691 |
|
if form.get_submit() == 'submit':
|
692 |
|
pages = [x for x in self.formdef.fields if x.type == 'page']
|
693 |
|
try:
|
694 |
|
page = pages[page_no]
|
695 |
|
post_conditions = page.post_conditions or []
|
696 |
|
except IndexError:
|
697 |
|
post_conditions = []
|
|
718 |
if form.get_submit() == 'submit' and page:
|
|
719 |
post_conditions = page.post_conditions or []
|
698 |
720 |
form_data = session.get_by_magictoken(magictoken, {})
|
699 |
721 |
data = self.formdef.get_data(form)
|
700 |
722 |
form_data.update(data)
|
... | ... | |
717 |
739 |
# by clicking on a submit widget; for example if an "add row"
|
718 |
740 |
# button is clicked.
|
719 |
741 |
if form.has_errors() or form.get_submit() is True:
|
720 |
|
if page_no == -1:
|
721 |
|
# this situation shouldn't arise (that likely means the
|
722 |
|
# page hidden field had an error in its submission), in
|
723 |
|
# that case we just fall back to the first page.
|
724 |
|
page_no = self.formdef.get_start_page()
|
725 |
|
return self.page(page_no, page_change=False,
|
|
742 |
return self.page(page, page_change=False,
|
726 |
743 |
page_error_messages=page_error_messages)
|
727 |
744 |
|
728 |
745 |
form_data = session.get_by_magictoken(magictoken, {})
|
... | ... | |
731 |
748 |
|
732 |
749 |
session.add_magictoken(magictoken, form_data)
|
733 |
750 |
|
734 |
|
while True:
|
735 |
|
page_no = int(page_no) + 1
|
736 |
|
try:
|
737 |
|
next_page = self.formdef.get_page(page_no)
|
738 |
|
except IndexError:
|
739 |
|
break
|
740 |
|
if next_page.is_visible(form_data, self.formdef):
|
741 |
|
break
|
|
751 |
page_no += 1
|
742 |
752 |
|
743 |
753 |
draft_id = session.get_by_magictoken(magictoken, {}).get('draft_formdata_id')
|
744 |
754 |
if draft_id:
|
... | ... | |
756 |
766 |
# if there's no draft yet and tracking codes are enabled, create one
|
757 |
767 |
filled = self.save_draft(form_data, page_no)
|
758 |
768 |
|
759 |
|
if page_no == self.page_number:
|
|
769 |
# the page has been successfully submitted, maybe new pages
|
|
770 |
# should be revealed.
|
|
771 |
self.feed_current_data(magictoken)
|
|
772 |
self.reset_pages_cache()
|
|
773 |
|
|
774 |
if int(page_no) == len(self.pages):
|
760 |
775 |
# last page has been submitted
|
761 |
776 |
req = get_request()
|
762 |
777 |
for field in self.formdef.fields:
|
... | ... | |
784 |
799 |
form.add_submit('savedraft')
|
785 |
800 |
|
786 |
801 |
else:
|
787 |
|
return self.page(page_no)
|
|
802 |
return self.page(self.pages[page_no])
|
788 |
803 |
|
789 |
804 |
if step == 1:
|
790 |
805 |
form.add_submit('previous')
|
791 |
806 |
magictoken = form.get_widget('magictoken').parse()
|
792 |
807 |
|
793 |
808 |
if form.get_submit() == 'previous':
|
794 |
|
return self.previous_page(self.page_number, magictoken)
|
|
809 |
return self.previous_page(len(self.pages), magictoken)
|
795 |
810 |
magictoken = form.get_widget('magictoken').parse()
|
796 |
811 |
form_data = session.get_by_magictoken(magictoken, {})
|
797 |
812 |
data = self.formdef.get_data(form)
|
... | ... | |
812 |
827 |
form_data = session.get_by_magictoken(magictoken, {})
|
813 |
828 |
|
814 |
829 |
if form.get_submit() == 'previous':
|
815 |
|
return self.previous_page(self.page_number, magictoken)
|
|
830 |
return self.previous_page(len(self.pages), magictoken)
|
816 |
831 |
|
817 |
832 |
if self.formdef.enable_tracking_codes and form.get_submit() == 'removedraft':
|
818 |
833 |
return self.removedraft()
|
... | ... | |
841 |
856 |
session = get_session()
|
842 |
857 |
form_data = session.get_by_magictoken(magictoken, {})
|
843 |
858 |
|
844 |
|
while True:
|
845 |
|
page_no = int(page_no) - 1
|
846 |
|
try:
|
847 |
|
previous_page = self.formdef.get_page(page_no)
|
848 |
|
except IndexError:
|
849 |
|
break
|
850 |
|
if not previous_page.condition:
|
851 |
|
break
|
852 |
|
|
853 |
|
if previous_page.is_visible(form_data, self.formdef):
|
854 |
|
break
|
|
859 |
try:
|
|
860 |
previous_page = self.pages[int(page_no - 1)]
|
|
861 |
except IndexError:
|
|
862 |
previous_page = self.pages[0]
|
855 |
863 |
|
856 |
|
return self.page(page_no, page_change=True)
|
|
864 |
return self.page(previous_page, page_change=True)
|
857 |
865 |
|
858 |
866 |
def removedraft(self):
|
859 |
867 |
magictoken = get_request().form.get('magictoken')
|
... | ... | |
912 |
920 |
if not form_data:
|
913 |
921 |
return result_error('missing data')
|
914 |
922 |
|
915 |
|
form = self.create_form(page_no)
|
|
923 |
form = self.create_form(page=self.pages[page_no])
|
916 |
924 |
data = self.formdef.get_data(form)
|
917 |
925 |
if not data:
|
918 |
926 |
return result_error('nothing to save')
|
... | ... | |
1102 |
1110 |
context = {
|
1103 |
1111 |
'view': self,
|
1104 |
1112 |
'form': form,
|
1105 |
|
'form_side': lambda: self.form_side(step_no=1, page_no=None, data=data,
|
|
1113 |
'form_side': lambda: self.form_side(step_no=1, page=None, data=data,
|
1106 |
1114 |
magictoken=magictoken),
|
1107 |
1115 |
}
|
1108 |
1116 |
|
1109 |
|
-
|