diff --git a/modoboa/lib/form_utils.py b/modoboa/lib/form_utils.py index 7a6ab32c1..2d8469dc5 100644 --- a/modoboa/lib/form_utils.py +++ b/modoboa/lib/form_utils.py @@ -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 @@ -114,20 +105,40 @@ class WizardForm(object): 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: raise BadRequest(_("Invalid request")) - stepid = min(stepid, len(self.steps)) + 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): @@ -135,7 +146,8 @@ class WizardForm(object): 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): @@ -143,9 +155,10 @@ class WizardForm(object): 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. @@ -153,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) diff --git a/modoboa/static/js/creation_wizard.js b/modoboa/static/js/creation_wizard.js index 1dd544917..20a1a8ab9 100644 --- a/modoboa/static/js/creation_wizard.js +++ b/modoboa/static/js/creation_wizard.js @@ -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,8 +44,8 @@ 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(resp.stepid); @@ -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"); } };