Merge pull request #735 from tonioo/conditional_wizard_step

Conditional wizard step
This commit is contained in:
Antoine Nguyen
2015-06-03 14:31:48 +02:00
2 changed files with 66 additions and 41 deletions
+53 -31
View File
@@ -24,26 +24,17 @@ class WizardStep(object):
"""A wizard step."""
def __init__(self, cls, title, formtpl=None, new_args=None):
"""Constructor.
"""
self._cls = cls
self._title = title
def __init__(self, uid, formclass, title, formtpl=None, new_args=None):
"""Constructor."""
self.uid = uid
self._cls = formclass
self.title = title
self.formtpl = formtpl
self._new_args = new_args
self._prev = None
self._next = None
self.index = None
self.form = None
@property
def title(self):
"""Return step title"""
if self.index is None:
return self._title
return "%d. %s" % (self.index + 1, self._title)
@property
def prev(self):
return self._prev
@@ -60,7 +51,12 @@ class WizardStep(object):
def next(self, step):
self._next = step
def check_access(self, wizard):
"""Check if this step should be displayed or not."""
return True
def create_form(self, data=None):
"""Instantiate a new form."""
args = []
if self._new_args is not None:
args += self._new_args
@@ -100,44 +96,69 @@ class WizardForm(object):
@property
def first_step(self):
"""Return the first step.
"""
"""Return the first step."""
return self.steps[0] if self.steps else None
def add_step(self, cls, title, formtpl=None, new_args=None):
"""Add a new step to the wizard.
"""
step = WizardStep(cls, title, formtpl, new_args)
def add_step(self, step):
"""Add a new step to the wizard."""
if self.steps:
step.prev = self.steps[-1]
self.steps[-1].next = step
self.steps += [step]
step.index = len(self.steps) - 1
def create_forms(self, data=None):
for step in self.steps:
step.create_form(data)
def validate_step(self):
def _get_step_id(self):
"""Retrieve the step identifier from the request."""
stepid = self.request.POST.get("stepid", None)
if stepid is None:
raise BadRequest(_("Invalid request"))
stepid = int(stepid.replace("step", ""))
if stepid < 0 or stepid > len(self.steps):
if stepid < 0:
raise BadRequest(_("Invalid request"))
return min(stepid, len(self.steps))
def previous_step(self):
"""Go back to the previous step."""
stepid = self._get_step_id()
stepid -= 2
self.create_forms(self.request.POST)
for step in self.steps:
step.form.is_valid()
while stepid >= 0:
if self.steps[stepid].check_access(self):
break
stepid -= 1
return render_to_json_response({
"title": self.steps[stepid].title, "id": self.steps[stepid].uid,
"stepid": stepid
})
def next_step(self):
"""Go to the next step if previous forms are valid."""
stepid = self._get_step_id()
self.create_forms(self.request.POST)
statuses = []
for cpt in xrange(0, stepid):
statuses.append(self.steps[cpt].form.is_valid())
if self.steps[cpt].check_access(self):
statuses.append(self.steps[cpt].form.is_valid())
if False in statuses:
return render_to_json_response({
'stepid': stepid, 'form_errors': self.errors
"stepid": stepid, "id": self.steps[stepid - 1].uid,
"form_errors": self.errors
}, status=400)
while stepid < len(self.steps):
if self.steps[stepid].check_access(self):
break
stepid += 1
if stepid == len(self.steps):
return self.done()
return render_to_json_response(
{'title': self.steps[stepid].title, 'stepid': stepid}
)
return render_to_json_response({
"title": self.steps[stepid].title, "id": self.steps[stepid].uid,
"stepid": stepid
})
def extra_context(self, context):
"""Provide additional information to template's context.
@@ -145,10 +166,11 @@ class WizardForm(object):
pass
def process(self):
"""Process the request.
"""
"""Process the request."""
if self.request.method == "POST":
return self.validate_step()
if self.request.POST.get("target", "next") == "next":
return self.next_step()
return self.previous_step()
self.create_forms()
context = {"wizard": self}
self.extra_context(context)
+13 -10
View File
@@ -34,9 +34,9 @@
$(".modal-header").find("small").html(title);
},
post: function(last) {
post: function(last, target) {
var $form = (this.options.formid) ? $('#' + this.options.formid) : $('form');
var data = $form.serialize() + "&stepid=" + this.get_current_step_id();
var data = $form.serialize() + "&stepid=" + this.get_current_step_id() + "&target=" + target;
$.ajax({
type: 'POST', url: $form.attr("action"), data: data, global: false
@@ -44,11 +44,11 @@
if (!last) {
$('input:text:visible:first').focus();
this.set_current_title(resp.title);
if (this.options.transition_callbacks[resp.stepid] !== undefined) {
this.options.transition_callbacks[resp.stepid]();
if (this.options.transition_callbacks[resp.id] !== undefined) {
this.options.transition_callbacks[resp.id]();
}
$(".carousel-inner").css("overflow", "hidden");
this.$element.carousel('next');
this.$element.carousel(resp.stepid);
} else {
$("#modalbox").modal('hide');
if (this.options.success_callback !== undefined) {
@@ -86,20 +86,23 @@
var step_id = this.get_current_step_id();
this.titles[step_id] = this.get_current_title();
this.$element.on('slid.bs.carousel', this.update_buttons);
this.post(false);
this.post(false, "next");
},
/**
* Go back to the previous step.
*/
prev: function(evt) {
var stepid = this.get_current_step_id();
evt.preventDefault();
this.$element.on('slid.bs.carousel', this.update_buttons);
$(".carousel-inner").css("overflow", "hidden");
this.$element.carousel('prev');
this.set_current_title(this.titles[this.get_current_step_id()]);
this.post(false, "prev", stepid);
},
submit: function(evt) {
evt.preventDefault();
this.post(true);
this.post(true, "next");
}
};