From 0724e91484ae1117fdd743eff37d50732c245305 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Fri, 30 Nov 2012 16:17:49 +0100 Subject: [PATCH] All listing pages (domains and identities) are now more responsive. No full reload anymore. see #315 --- modoboa/admin/lib.py | 24 +- modoboa/admin/static/admin/js/admin.js | 412 ++++++++++++------ modoboa/admin/tables.py | 4 +- modoboa/admin/templates/admin/domains.html | 28 +- modoboa/admin/templates/admin/header.html | 1 + modoboa/admin/templates/admin/identities.html | 28 +- .../admin/templates/admin/import_done.html | 2 +- modoboa/admin/templates/admin/listing.html | 26 +- modoboa/admin/templatetags/admin_extras.py | 20 +- modoboa/admin/urls.py | 4 +- modoboa/admin/views.py | 76 ++-- modoboa/static/js/autocompleter.js | 4 +- modoboa/static/js/confirmation.js | 10 +- modoboa/static/js/creation_wizard.js | 6 +- modoboa/static/js/global.js | 3 +- modoboa/templates/common/pagination_bar.html | 27 +- 16 files changed, 396 insertions(+), 279 deletions(-) diff --git a/modoboa/admin/lib.py b/modoboa/admin/lib.py index e1e9a2a57..96037cb48 100644 --- a/modoboa/admin/lib.py +++ b/modoboa/admin/lib.py @@ -1,13 +1,13 @@ # coding: utf-8 from django.utils.translation import ugettext as _ from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger -from modoboa.lib.webutils import _render +from modoboa.lib.webutils import ajax_simple_response from modoboa.lib import parameters +from modoboa.lib.templatetags.libextras import pagination_bar from modoboa.admin.tables import * from exceptions import * -def render_listing(request, objtype, tplname="admin/listing.html", - **kwargs): +def render_listing(request, objtype, **kwargs): """Common function to render a listing All listing pages available into the admin application use the @@ -15,7 +15,6 @@ def render_listing(request, objtype, tplname="admin/listing.html", :param request: a ``Request`` object :param objtype: the object type's name (lowercase) - :param tplname: the template used to render the HTML """ tblclass = "%sTable" % objtype.capitalize() if not globals().has_key(tblclass): @@ -26,18 +25,19 @@ def render_listing(request, objtype, tplname="admin/listing.html", kwargs["domid"] = request.GET["domid"] else: kwargs["domid"] = "" - kwargs["selection"] = objtype paginator = Paginator(kwargs["objects"], int(parameters.get_admin("ITEMS_PER_PAGE"))) try: - page = request.GET.get("page", "1") + pagenum = request.GET.get("page", "1") except ValueError: - page = 1 + pagenum = 1 try: - kwargs["page"] = paginator.page(page) + page = paginator.page(pagenum) except (EmptyPage, PageNotAnInteger): - kwargs["page"] = paginator.page(paginator.num_pages) - kwargs["table"] = tblclass(request, kwargs["page"].object_list) - kwargs["selection"] = objtype + page = paginator.page(paginator.num_pages) - return _render(request, tplname, kwargs) + return ajax_simple_response({ + "table" : tblclass(request, page.object_list).render(), + "page" : page.number, + "paginbar" : pagination_bar(page) + }) diff --git a/modoboa/admin/static/admin/js/admin.js b/modoboa/admin/static/admin/js/admin.js index 4aeb47e1d..0267ba8d4 100644 --- a/modoboa/admin/static/admin/js/admin.js +++ b/modoboa/admin/static/admin/js/admin.js @@ -1,147 +1,281 @@ -function domainform_cb() { - $('input:text:visible:first').focus(); - $("#id_aliases").dynamic_input(); - $(".submit").one('click', function(e) { - simple_ajax_form_post(e, { - formid: "domform", - error_cb: domainform_cb - }); - }); - $("a[name=removeperm]").click(function(e) { - var $tr = $(this).parent().parent(); - simple_ajax_request.apply(this, [e, { - ok_cb: function(resp) { - $tr.remove(); - if (!$("#domadmins").children("tr").length) { - $("#admins").html('
' - + gettext("No domain administrator defined") + "
"); +var Admin = function(options) { + this.initialize(options); +}; + +Admin.prototype = { + constructor: Admin, + + defaults: { + deflocation: "list/", + squery: null + }, + + initialize: function(options) { + this.options = $.extend({}, this.defaults, options); + this.options.defcallback = $.proxy(this.list_cb, this); + + this.navobj = new History(this.options); + + $("#searchquery").focus(function() { + $(this).attr("value", ""); + }).blur($.proxy(function(e) { + var $this = $(e.target); + if ($this.attr("value") == "") { + if (this.options.squery && this.options.squery == "") { + $this.attr("value", this.options.squery); + } else { + $this.attr("value", gettext("Search")); } } - }]); - }); - $(document).trigger('domform_init'); -} + }, this)); -function simpleuser_mode() { - $("#id_username").autocompleter({ - from_character: "@", - choices: get_domains_list - }); - $("#id_email").addClass("disabled") - .attr("readonly", "") - .autocompleter("unbind"); -} + this.listen(); + }, -function normal_mode() { - $("#id_email").removeClass("disabled") - .attr("readonly", null) - .autocompleter("listen"); -} - -function generalform_init() { - $("#id_role").change(function(e) { - if ($(this).attr("value") == "SimpleUsers") { - simpleuser_mode(); - } else { - normal_mode(); - } - }); -} - -function mailform_init() { - $("#id_aliases").autocompleter({ - from_character: "@", - choices: get_domains_list - }).dynamic_input(); - $("#id_email").autocompleter({ - from_character: "@", - choices: get_domains_list - }); - if ($("#id_role").length) { - $("#id_role").trigger("change"); - } else { - simpleuser_mode(); - } - $("#id_domains") - .autocompleter({ - choices: get_domains_list - }) - .dynamic_input(); - -} - -function accountform_init() { - generalform_init(); - mailform_init(); -} - -function mailform_prefill() { - if (!$("#id_role").length || $("#id_role").attr("value") == "SimpleUsers") { - $("#id_email").attr("value", $("#id_username").attr("value")); - } -} - -function newaccount_cb() { - accountform_init(); - $("#wizard").cwizard({ - formid: "newaccount_form", - transition_callbacks: { - 1: mailform_prefill - }, - error_callbacks: { - 1: generalform_init, - 2: mailform_init - } - }); -} - -function editaccount_cb() { - accountform_init(); - $('.submit').one('click', function(e) { - simple_ajax_form_post(e, { - formid: "accountform", - error_cb: editaccount_cb - }); - }); -} - -function aliasform_cb() { - $("#id_email").autocompleter({ - from_character: "@", - choices: get_domains_list - }); - $("#id_recipients").dynamic_input(); - $("#id_int_recipient").autocompleter({ - choices: get_mboxes_list - }); - $(".submit").one('click', function(e) { - simple_ajax_form_post(e, { - formid: "aliasform", - error_cb: aliasform_cb - }); - }); -} - -function importform_cb() { - $(".submit").one('click', function(e) { - if ($("#id_sourcefile").attr("value") == "") { + list_cb: function(data) { + $("#listing").html(data.table); + $("#bottom-bar-right").html(data.paginbar); + $("#pagination_bar").find(".disabled a").click(function(e) { e.preventDefault(); - return; + }); + if (data.page != this.navobj.getparam("page")) { + this.navobj.setparam("page", data.page).update(false, false); } - $("#import_status").css("display", "block"); - $("#import_result").html("").removeClass("alert alert-error"); - $("#importform").submit(); - }); -} + }, -function importdone(status, msg) { - $("#import_status").css("display", "none"); - if (status == "ok") { - $("#modalbox").modal('hide'); - window.location.reload(); - } else { - $("#import_result").addClass("alert alert-error"); - $("#import_result").html(msg); - importform_cb(); + listen: function() { + $(document).on("click", "#bottom-bar-right a", + $.proxy(this.getpage_loader, this)); + $("#searchform").submit($.proxy(this.do_search, this)); + }, + + do_search: function(e) { + e.preventDefault(); + this.navobj.setparam("searchquery", $("#searchquery").attr("value")).update(); + }, + + getpage_loader: function(e) { + var $link = $(e.target).parent(); + e.preventDefault(); + this.navobj.updateparams($link.attr("href")).update(); + }, + + importform_cb: function() { + $(".submit").one('click', function(e) { + e.preventDefault(); + if ($("#id_sourcefile").attr("value") == "") { + return; + } + $("#import_status").css("display", "block"); + $("#import_result").html("").removeClass("alert alert-error"); + $("#importform").submit(); + }); + }, + + importdone: function(status, msg) { + $("#import_status").css("display", "none"); + if (status == "ok") { + $("#modalbox").modal('hide'); + this.reload_listing({respmsg: msg}); + } else { + $("#import_result").addClass("alert alert-error"); + $("#import_result").html(msg); + this.importform_cb(); + } + }, + + reload_listing: function(data) { + this.navobj.update(true); + if (data.respmsg) { + $("body").notify("success", data.respmsg, 2000); + } } -} \ No newline at end of file +}; + +/* + * Domains + */ +var Domains = function(options) { + Admin.call(this, options); +}; + +Domains.prototype = { + list_cb: function(data) { + Admin.prototype.list_cb.call(this, data); + + $("a[name=deldomain]").confirm({ + question: gettext("Delete this domain?"), + checkboxes: {keepdir: gettext("Do not delete domain directory")}, + success_cb: $.proxy(this.reload_listing, this) + }); + }, + + domainform_cb: function() { + $('input:text:visible:first').focus(); + $("#id_aliases").dynamic_input(); + $(".submit").one('click', $.proxy(function(e) { + simple_ajax_form_post(e, { + formid: "domform", + error_cb: this.domainform_cb, + reload_on_success: false, + success_cb: $.proxy(this.reload_listing, this) + }); + }, this)); + $("a[name=removeperm]").click(function(e) { + var $tr = $(this).parent().parent(); + simple_ajax_request.apply(this, [e, { + ok_cb: function(resp) { + $tr.remove(); + if (!$("#domadmins").children("tr").length) { + $("#admins").html('
' + + gettext("No domain administrator defined") + "
"); + } + } + }]); + }); + $(document).trigger('domform_init'); + } + +}; + +Domains.prototype = $.extend({}, Admin.prototype, Domains.prototype); + +/* + * Identities + */ +var Identities = function(options) { + Admin.call(this, options); +}; + +Identities.prototype = { + list_cb: function(data) { + Admin.prototype.list_cb.call(this, data); + + $("a[name=delaccount]").confirm({ + question: gettext("Delete this account?"), + checkboxes: {keepdir: gettext("Do not delete mailbox directory")}, + success_cb: $.proxy(this.reload_listing, this) + }); + $("a[name=deldlist]").confirm({ + question: gettext("Delete this list?"), + success_cb: $.proxy(this.reload_listing, this) + }); + $("a[name=delforward]").confirm({ + question: gettext("Delete this forward?"), + success_cb: $.proxy(this.reload_listing, this) + }); + $("a[name=delalias]").confirm({ + question: gettext("Delete this alias?"), + success_cb: $.proxy(this.reload_listing, this) + }); + }, + + simpleuser_mode: function() { + $("#id_username").autocompleter({ + from_character: "@", + choices: get_domains_list + }); + $("#id_email").addClass("disabled") + .attr("readonly", "") + .autocompleter("unbind"); + }, + + normal_mode: function() { + $("#id_email").removeClass("disabled") + .attr("readonly", null) + .autocompleter("listen"); + }, + + generalform_init: function() { + $("#id_role").change($.proxy(function(e) { + var $this = $(e.target); + if ($this.attr("value") == "SimpleUsers") { + this.simpleuser_mode(); + } else { + this.normal_mode(); + } + }, this)); + }, + + mailform_init: function() { + $("#id_aliases").autocompleter({ + from_character: "@", + choices: get_domains_list + }).dynamic_input(); + $("#id_email").autocompleter({ + from_character: "@", + choices: get_domains_list + }); + if ($("#id_role").length) { + $("#id_role").trigger("change"); + } else { + this.simpleuser_mode(); + } + $("#id_domains") + .autocompleter({ + choices: get_domains_list + }) + .dynamic_input(); + + }, + + accountform_init: function() { + this.generalform_init(); + this.mailform_init(); + }, + + mailform_prefill: function() { + if (!$("#id_role").length || $("#id_role").attr("value") == "SimpleUsers") { + $("#id_email").attr("value", $("#id_username").attr("value")); + } + }, + + newaccount_cb: function() { + this.accountform_init(); + $("#wizard").cwizard({ + formid: "newaccount_form", + transition_callbacks: { + 1: this.mailform_prefill + }, + error_callbacks: { + 1: this.generalform_init, + 2: this.mailform_init + }, + success_callback: $.proxy(this.reload_listing, this) + }); + }, + + editaccount_cb: function() { + this.accountform_init(); + $('.submit').one('click', $.proxy(function(e) { + simple_ajax_form_post(e, { + formid: "accountform", + error_cb: this.editaccount_cb, + reload_on_success: false, + success_cb: $.proxy(this.reload_listing, this) + }); + }, this)); + }, + + aliasform_cb: function() { + $("#id_email").autocompleter({ + from_character: "@", + choices: get_domains_list + }); + $("#id_recipients").dynamic_input(); + $("#id_int_recipient").autocompleter({ + choices: get_mboxes_list + }); + $(".submit").one('click', $.proxy(function(e) { + simple_ajax_form_post(e, { + formid: "aliasform", + error_cb: this.aliasform_cb, + reload_on_success: false, + success_cb: $.proxy(this.reload_listing, this) + }); + }, this)); + } + +}; + +Identities.prototype = $.extend({}, Admin.prototype, Identities.prototype); diff --git a/modoboa/admin/tables.py b/modoboa/admin/tables.py index cf95c95a3..85e6844a2 100644 --- a/modoboa/admin/tables.py +++ b/modoboa/admin/tables.py @@ -11,7 +11,7 @@ class DomainsTable(tables.Table): name = tables.LinkColumn( "name", label=ugettext_lazy("Name"), urlpattern="modoboa.admin.views.editdomain", - title=_("Edit domain"), modal=True, modalcb="domainform_cb" + title=_("Edit domain"), modal=True, modalcb="admin.domainform_cb" ) domaliases = tables.Column("domainalias_set", label=ugettext_lazy("Alias(es)"), safe=True) @@ -55,7 +55,7 @@ class IdentitiesTable(tables.Table): modal=True, urlpattern={"User" : "modoboa.admin.views.editaccount", "Alias" : "modoboa.admin.views.editalias_dispatcher"}, - modalcb={"User" : "editaccount_cb", "Alias" : "aliasform_cb"} + modalcb={"User" : "admin.editaccount_cb", "Alias" : "admin.aliasform_cb"} ) name_or_rcpt = tables.Column("name_or_rcpt", label=ugettext_lazy("Fullname/Recipient")) actions = tables.ActionColumn("actions", label=ugettext_lazy("Actions"), diff --git a/modoboa/admin/templates/admin/domains.html b/modoboa/admin/templates/admin/domains.html index 03cc3f609..ab64cfcdc 100644 --- a/modoboa/admin/templates/admin/domains.html +++ b/modoboa/admin/templates/admin/domains.html @@ -3,27 +3,11 @@ {% block html_head %} {{ block.super }} +}); + {% endblock %} -{% block leftcol %}{{ block.super }}{% endblock %} +{% block actions %}{% domains_menu "domains" user %}{% endblock %} diff --git a/modoboa/admin/templates/admin/header.html b/modoboa/admin/templates/admin/header.html index d020aed58..8b749dcff 100644 --- a/modoboa/admin/templates/admin/header.html +++ b/modoboa/admin/templates/admin/header.html @@ -1,5 +1,6 @@ {% extends "twocols.html" %} {% block html_head %} + {% endblock %} diff --git a/modoboa/admin/templates/admin/identities.html b/modoboa/admin/templates/admin/identities.html index 52b59a6fd..12432a462 100644 --- a/modoboa/admin/templates/admin/identities.html +++ b/modoboa/admin/templates/admin/identities.html @@ -24,30 +24,10 @@ function get_mboxes_list(container) { } $(document).ready(function() { - $("a[name=delaccount]").confirm({ - question: gettext("Delete this account?"), - checkboxes: {keepdir: gettext("Do not delete mailbox directory")} - }); - $("a[name=deldlist]").confirm({ - question: gettext("Delete this list?") - }); - $("a[name=delforward]").confirm({ - question: gettext("Delete this forward?") - }); - $("a[name=delalias]").confirm({ - question: gettext("Delete this alias?") - }); - $("#pagination_bar").find(".disabled").click(function(e) { - e.preventDefault(); - }); + admin = new Identities({ + squery: "{{ squery }}" + }); }); {% endblock %} -{% block leftcol %}{{ block.super }}{% endblock %} +{% block actions %}{% identities_menu user %}{% endblock %} diff --git a/modoboa/admin/templates/admin/import_done.html b/modoboa/admin/templates/admin/import_done.html index a95ddfcd1..55a3191b0 100644 --- a/modoboa/admin/templates/admin/import_done.html +++ b/modoboa/admin/templates/admin/import_done.html @@ -4,7 +4,7 @@ diff --git a/modoboa/admin/templates/admin/listing.html b/modoboa/admin/templates/admin/listing.html index 64402ddef..39f1b429e 100644 --- a/modoboa/admin/templates/admin/listing.html +++ b/modoboa/admin/templates/admin/listing.html @@ -3,20 +3,18 @@ {{ block.super }} {% endblock %} -{% block leftcol %}{% get_extra_admin_content user "leftcol" selection %}{% endblock %} -{% block apparea %} -{{ table|safe }} +{% block leftcol %} {% endblock %} -{% block footerright %}{% pagination_bar page %}{% endblock %} +{% block apparea %}
{% endblock %} +{% block footerright %}{% endblock %} diff --git a/modoboa/admin/templatetags/admin_extras.py b/modoboa/admin/templatetags/admin_extras.py index 506a57d84..a7831a741 100644 --- a/modoboa/admin/templatetags/admin_extras.py +++ b/modoboa/admin/templatetags/admin_extras.py @@ -70,19 +70,18 @@ def domains_menu(selection, user): "label" : _("Add domain"), "img" : "icon-plus", "modal" : True, - "modalcb" : "domainform_cb", + "modalcb" : "admin.domainform_cb", "url" : reverse("modoboa.admin.views.newdomain")}, {"name" : "import", "label" : _("Import"), "img" : "icon-folder-open", "url" : reverse(admin.views.import_domains), "modal" : True, - "modalcb" : "importform_cb"} + "modalcb" : "admin.importform_cb"} ] - return render_to_string('common/menu.html', { + return render_to_string('common/menulist.html', { "entries" : entries, - "css" : "nav nav-list", "selection" : selection, "user" : user }) @@ -94,37 +93,36 @@ def identities_menu(user): "label" : _("Add account"), "img" : "icon-plus", "modal" : True, - "modalcb" : "newaccount_cb", + "modalcb" : "admin.newaccount_cb", "url" : reverse(admin.views.newaccount)}, {"name" : "newalias", "label" : _("Add alias"), "img" : "icon-plus", "modal" : True, - "modalcb" : "aliasform_cb", + "modalcb" : "admin.aliasform_cb", "url" : reverse(admin.views.newalias)}, {"name" : "newforward", "label" : _("Add forward"), "img" : "icon-plus", "modal" : True, - "modalcb" : "aliasform_cb", + "modalcb" : "admin.aliasform_cb", "url" : reverse(admin.views.newforward)}, {"name" : "newdlist", "label" : _("Add distribution list"), "img" : "icon-plus", "modal" : True, - "modalcb" : "aliasform_cb", + "modalcb" : "admin.aliasform_cb", "url" : reverse(admin.views.newdlist)}, {"name" : "import", "label" : _("Import"), "img" : "icon-folder-open", "url" : reverse(admin.views.import_identities), "modal" : True, - "modalcb" : "importform_cb"} + "modalcb" : "admin.importform_cb"} ] - return render_to_string('common/menu.html', { + return render_to_string('common/menulist.html', { "entries" : entries, - "css" : "nav nav-list", "user" : user }) diff --git a/modoboa/admin/urls.py b/modoboa/admin/urls.py index 231f7c321..bd2133c07 100644 --- a/modoboa/admin/urls.py +++ b/modoboa/admin/urls.py @@ -4,7 +4,8 @@ urlpatterns = patterns( 'modoboa.admin.views', url(r'^$', 'domains', name="index"), url(r'^domains/$', 'domains', name="domains"), - (r'^domains/list/$', 'domains_list'), + (r'^domains/list/$', '_domains'), + (r'^domains/flatlist/$', 'domains_list'), (r'^domains/new/', 'newdomain'), (r'^domains/(?P\d+)/edit/$', 'editdomain'), (r'^domains/delete/$', 'deldomain'), @@ -19,6 +20,7 @@ urlpatterns = patterns( (r'^permissions/remove/$', 'remove_permission'), (r'^identities/$', 'identities'), + (r'^identities/list/$', '_identities'), (r'^identities/import/$', 'import_identities'), (r'^accounts/list/$', 'accounts_list'), diff --git a/modoboa/admin/views.py b/modoboa/admin/views.py index 46888f4e3..c26ed50dd 100644 --- a/modoboa/admin/views.py +++ b/modoboa/admin/views.py @@ -5,7 +5,7 @@ from django.core.urlresolvers import reverse from django.contrib.auth.decorators \ import login_required, permission_required, user_passes_test from django.db.models import Q -from django.contrib import messages +from django.shortcuts import render from django.db import transaction, IntegrityError from lib import render_listing @@ -21,7 +21,7 @@ from modoboa.lib.models import Parameter from modoboa.lib.permissions import * @login_required -def domains(request): +def _domains(request): if not request.user.has_perm("admin.view_domains"): if request.user.has_perm("admin.view_mailboxes"): return HttpResponseRedirect(reverse(identities)) @@ -34,8 +34,13 @@ def domains(request): q = Q(name__contains=squery) q |= Q(domainalias__name__contains=squery) domains = domains.filter(q).distinct() - return render_listing(request, "domains", "admin/domains.html", - objects=domains, squery=squery) + return render_listing(request, "domains", objects=domains, squery=squery) + +@login_required +def domains(request, tplname="admin/domains.html"): + return render(request, tplname, { + "selection" : "domains" + }) @login_required @permission_required("auth.add_user") @@ -60,8 +65,7 @@ def _validate_domain(request, form, successmsg, commonctx, tplname, else: if callback is not None: callback(request.user, domain) - messages.info(request, successmsg, fail_silently=True) - return ajax_response(request, url=reverse("modoboa.admin.views.domains")) + return ajax_simple_response({"status" : "ok", "respmsg" : successmsg}) commonctx[tpl_form_name] = form commonctx["error"] = error @@ -87,7 +91,7 @@ def newdomain(request, tplname="admin/newdomainform.html"): tplname, callback=newdomain_cb) form = DomainFormGeneral() commonctx["form"] = form - return _render(request, tplname, commonctx) + return render(request, tplname, commonctx) @login_required @permission_required("admin.view_domains") @@ -123,7 +127,7 @@ def editdomain(request, dom_id, tplname="admin/editdomainform.html"): commonctx["tabs"] = DomainForm(request.user, instances=instances) commonctx["domadmins"] = domadmins - return _render(request, tplname, commonctx) + return render(request, tplname, commonctx) @login_required @permission_required("admin.delete_domain") @@ -145,8 +149,7 @@ def deldomain(request): dom.delete(keepdir=keepdir) msg = ungettext("Domain deleted", "Domains deleted", len(selection)) - messages.info(request, msg, fail_silently=True) - return ajax_response(request) + return ajax_simple_response({"status" : "ok", "respmsg" : msg}) def _validate_alias(request, form, successmsg, tplname, commonctx, callback=None): """Alias validation @@ -163,9 +166,7 @@ def _validate_alias(request, form, successmsg, tplname, commonctx, callback=None if callback: callback(request.user, alias) - - messages.info(request, successmsg) - return ajax_response(request, url=reverse("modoboa.admin.views.identities")) + return ajax_simple_response({"status" : "ok", "respmsg" : successmsg}) if request.POST.has_key("targets"): targets = request.POST.getlist("targets") @@ -191,7 +192,7 @@ def _new_alias(request, tplname, formclass, ctx, successmsg): form = formclass(request.user) ctx["form"] = form - return _render(request, tplname, ctx) + return render(request, tplname, ctx) @login_required @permission_required("admin.add_alias") @@ -234,7 +235,7 @@ def _edit_alias(request, alias, tplname, formclass, ctx, successmsg): form = formclass(request.user, instance=alias) ctx["form"] = form - return _render(request, tplname, ctx) + return render(request, tplname, ctx) def editalias(request, alias, ctx): return _edit_alias(request, alias, "common/generic_modal_form.html", @@ -268,8 +269,7 @@ def _del_alias(request, msg, msgs): alias.delete() msg = ungettext(msg, msgs, len(selection)) - messages.info(request, msg) - return ajax_response(request) + return ajax_simple_response({"status" : "ok", "respmsg" : msg}) @login_required @permission_required("admin.delete_alias") @@ -291,7 +291,7 @@ def delforward(request): @login_required @user_passes_test(lambda u: u.has_perm("auth.add_user") or u.has_perm("admin.add_alias")) -def identities(request, tplname='admin/identities.html'): +def _identities(request): idents_list = request.user.get_identities() squery = request.GET.get("searchquery", None) if squery: @@ -314,8 +314,15 @@ def identities(request, tplname='admin/identities.html'): if oa.content_object: objects.append(oa.content_object) objects = sorted(objects, key=lambda o: o.identity) - return render_listing(request, "identities", tplname, - objects=objects, squery=squery) + return render_listing(request, "identities", objects=objects, squery=squery) + +@login_required +@user_passes_test(lambda u: u.has_perm("auth.add_user") or u.has_perm("admin.add_alias")) +def identities(request, tplname="admin/identities.html"): + return render(request, tplname, { + "selection" : "identities", + "deflocation" : "list/" + }) @login_required @permission_required("auth.add_user") @@ -376,8 +383,7 @@ def newaccount(request, tplname='admin/newaccount.html'): status="ok", title=cwizard.get_title(data + 1), stepid=data )) if retcode == 2: - messages.info(request, _("Account created")) - return ajax_simple_response(dict(status="ok")) + return ajax_simple_response(dict(status="ok", respmsg=_("Account created"))) from modoboa.lib.templatetags.libextras import render_form return ajax_simple_response(dict( @@ -387,7 +393,7 @@ def newaccount(request, tplname='admin/newaccount.html'): cwizard.create_forms() ctx.update(steps=cwizard.steps) ctx.update(subtitle="1. %s" % cwizard.steps[0]['title']) - return _render(request, tplname, ctx) + return render(request, tplname, ctx) @login_required @permission_required("auth.change_user") @@ -421,15 +427,14 @@ def editaccount(request, accountid, tplname="common/tabforms.html"): if form.is_valid(optional_only=True): events.raiseEvent("AccountModified", account, form.account) form.save() - messages.info(request, _("Account updated")) - return ajax_simple_response(dict(status="ok")) + return ajax_simple_response(dict(status="ok", respmsg=_("Account updated"))) transaction.rollback() ctx["tabs"] = form return ajax_response(request, status="ko", template=tplname, **ctx) ctx["tabs"] = AccountForm(request.user, instances=instances) - return _render(request, tplname, ctx) + return render(request, tplname, ctx) @login_required @permission_required("auth.delete_user") @@ -442,8 +447,7 @@ def delaccount(request): account.delete(request.user, keepdir) msg = ungettext("Account deleted", "Accounts deleted", len(selection)) - messages.info(request, msg, fail_silently=True) - return ajax_response(request) + return ajax_simple_response({"status" : "ok", "respmsg" : msg}) @login_required @permission_required("admin.add_domain") @@ -482,7 +486,7 @@ def viewparameters(request, tplname='admin/parameters.html'): tmp["params"] += [newdef] gparams += [tmp] - return _render(request, tplname, { + return render(request, tplname, { "selection" : "settings", "left_selection" : "parameters", "gparams" : gparams @@ -516,7 +520,7 @@ def viewextensions(request, tplname='admin/extensions.html'): ext["selection"] = False tbl = ExtensionsTable(request, exts) - return _render(request, tplname, { + return render(request, tplname, { "selection" : "settings", "left_selection" : "extensions", "extensions" : tbl @@ -599,14 +603,14 @@ def importdata(request): continue fct(request.user, row) cpt += 1 - messages.info(request, _("%d objects imported successfully" % cpt)) - return _render(request, "admin/import_done.html", { - "status" : "ok", "msg" : "" + msg = _("%d objects imported successfully" % cpt) + return render(request, "admin/import_done.html", { + "status" : "ok", "msg" : msg }) except (IntegrityError, ModoboaException), e: error = str(e) - return _render(request, "admin/import_done.html", { + return render(request, "admin/import_done.html", { "status" : "ko", "msg" : error }) @@ -635,7 +639,7 @@ You can use a different character as separator. form=ImportDataForm(), helptext=helptext ) - return _render(request, "admin/importform.html", ctx) + return render(request, "admin/importform.html", ctx) @login_required @permission_required("admin.add_domain") @@ -661,4 +665,4 @@ You can use a different character as separator. helptext=helptext, form=ImportDataForm() ) - return _render(request, "admin/importform.html", ctx) + return render(request, "admin/importform.html", ctx) diff --git a/modoboa/static/js/autocompleter.js b/modoboa/static/js/autocompleter.js index 8a6ab432f..534f21d42 100644 --- a/modoboa/static/js/autocompleter.js +++ b/modoboa/static/js/autocompleter.js @@ -67,9 +67,9 @@ position: "absolute", top: coords.top + this.$element.outerHeight(), left: coords.left, - width: this.$element.outerWidth() + width: this.$element.outerWidth(), + 'z-index': 1051 }); - if (this.$menu.children().length) { this.$menu.show(); } else { diff --git a/modoboa/static/js/confirmation.js b/modoboa/static/js/confirmation.js index 0d65e3bf3..2debf103d 100644 --- a/modoboa/static/js/confirmation.js +++ b/modoboa/static/js/confirmation.js @@ -46,11 +46,13 @@ var ok_btn = $('Ok'); ok_btn.click(function(evt) { + evt.preventDefault(); box.data('result', true); box.modal('hide'); }); cancel_btn.click(function(evt) { + evt.preventDefault(); box.modal('hide'); }); @@ -76,7 +78,7 @@ cache: false, data: params, url: this.$element.attr('href'), - complete: function(XMLHttpRequest, textStatus) { + complete: $.proxy(function(XMLHttpRequest, textStatus) { var data; try { data = $.parseJSON(XMLHttpRequest.responseText); @@ -84,11 +86,15 @@ data = { status: 'ko', respmsg: gettext('Internal Error') }; } if (data.status == "ok") { + if (this.options.success_cb != undefined) { + this.options.success_cb(data); + return; + } window.location.reload(); } else { $("body").notify("error", data.respmsg); } - } + }, this) }); this.box.remove(); } diff --git a/modoboa/static/js/creation_wizard.js b/modoboa/static/js/creation_wizard.js index 548545aeb..d15701611 100644 --- a/modoboa/static/js/creation_wizard.js +++ b/modoboa/static/js/creation_wizard.js @@ -37,7 +37,11 @@ this.$element.carousel('next'); } else { $("#modalbox").modal('hide').remove(); - window.location.reload(); + if (this.options.success_callback != undefined) { + this.options.success_callback(resp); + } else { + window.location.reload(); + } } return; } diff --git a/modoboa/static/js/global.js b/modoboa/static/js/global.js index 7b14ac1c9..771176d36 100644 --- a/modoboa/static/js/global.js +++ b/modoboa/static/js/global.js @@ -107,10 +107,11 @@ function simple_ajax_form_post(e, options) { } $.post($form.attr("action"), args, function(data) { if (data.status == "ok") { + $("#modalbox").modal('hide'); if (opts.success_cb != undefined) { opts.success_cb(data); + return; } - $("#modalbox").modal('hide'); if (opts.reload_on_success) { if (opts.reload_mode == 'full') { window.location.reload(); diff --git a/modoboa/templates/common/pagination_bar.html b/modoboa/templates/common/pagination_bar.html index d602d094f..953fa4a7a 100644 --- a/modoboa/templates/common/pagination_bar.html +++ b/modoboa/templates/common/pagination_bar.html @@ -1,22 +1,27 @@
    -
  • - +
  • + {% if page.has_previous %} + {% else %} + {% endif %}
  • -
  • - - +
  • + {% if page.has_previous %} + {% else %} + {% endif %}
  • {{ page.number }}/{{ page.paginator.num_pages }}
  • -
  • - - +
  • + {% if page.has_next %} + {% else %} + {% endif %}
  • -
  • - - +
  • + {% if page.has_next %} + {% else %} + {% endif %}