All listing pages (domains and identities) are now more responsive. No full reload anymore.

see #315
This commit is contained in:
Antoine Nguyen
2012-11-30 16:17:49 +01:00
parent ab2c9e3e9a
commit 0724e91484
16 changed files with 396 additions and 279 deletions
+12 -12
View File
@@ -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)
})
+273 -139
View File
@@ -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('<div class="alert alert-info">'
+ gettext("No domain administrator defined") + "</div>");
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);
}
}
}
};
/*
* 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('<div class="alert alert-info">'
+ gettext("No domain administrator defined") + "</div>");
}
}
}]);
});
$(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);
+2 -2
View File
@@ -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"),
+6 -22
View File
@@ -3,27 +3,11 @@
{% block html_head %}
{{ block.super }}
<script type="text/javascript">
$(document).ready(function() {
$("a[name=deldomain]").confirm({
question: gettext("Delete this domain?"),
checkboxes: {keepdir: gettext("Do not delete domain directory")}
});
$("#searchquery").focus(function() {
$(this).attr("value", "");
}).blur(function() {
var $this = $(this);
if ($this.attr("value") == "") {
$this.attr("value", gettext("Search"));
}
});
$(document).ready(function() {
admin = new Domains({
squery: "{{ squery }}"
});
</script>
});
</script>
{% endblock %}
{% block leftcol %}<div class="well sidebar-nav">
<li class="nav-header">
{% trans "Filter" %}
</li>{% include "admin/searchform.html" %}
<li class="nav-header">
{% trans "Actions" %}
</li>{% domains_menu "domains" user %}
</div>{{ block.super }}{% endblock %}
{% block actions %}{% domains_menu "domains" user %}{% endblock %}
@@ -1,5 +1,6 @@
{% extends "twocols.html" %}
{% block html_head %}
<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}admin/css/admin.css" />
<script type="text/javascript" src="{{ STATIC_URL }}js/history.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/admin.js"></script>
{% endblock %}
+4 -24
View File
@@ -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 }}"
});
});
</script>
{% endblock %}
{% block leftcol %}<div class="well sidebar-nav">
<li class="nav-header">
{% trans "Filter" %}
</li>{% include "admin/searchform.html" %}
<li class="nav-header">
{% trans "Actions" %}
</li>{% identities_menu user %}
</div>{{ block.super }}{% endblock %}
{% block actions %}{% identities_menu user %}{% endblock %}
@@ -4,7 +4,7 @@
<head profile="http://www.w3.org/2005/10/profile">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript">
parent.importdone("{{ status }}", "{{ msg|escapejs }}");
parent.admin.importdone("{{ status }}", "{{ msg|escapejs }}");
</script>
</head>
<body></body>
+12 -14
View File
@@ -3,20 +3,18 @@
{{ block.super }}
<script type="text/javascript" src="{{ STATIC_URL }}js/dynamic_input.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$("#searchquery").focus(function() {
$(this).attr("value", "");
}).blur(function() {
var $this = $(this);
if ($this.attr("value") == "") {
$this.attr("value", {% if squery %}"{{ squery }}"{% else %}"{% trans 'Search' %}"{% endif %});
}
});
});
var admin;
</script>
{% endblock %}
{% block leftcol %}{% get_extra_admin_content user "leftcol" selection %}{% endblock %}
{% block apparea %}
{{ table|safe }}
{% block leftcol %}<div class="well sidebar-nav">
<ul class="nav nav-list">
<li class="nav-header">{% trans "Filter" %}</li>
<li>{% include "admin/searchform.html" %}</li>
<li class="nav-header">{% trans "Actions" %}</li>
{% block actions %}{% endblock %}
{% get_extra_admin_content user "leftcol" selection %}
</ul>
</div>
{% endblock %}
{% block footerright %}{% pagination_bar page %}{% endblock %}
{% block apparea %}<div id="listing"></div>{% endblock %}
{% block footerright %}{% endblock %}
+9 -11
View File
@@ -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
})
+3 -1
View File
@@ -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<dom_id>\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'),
+40 -36
View File
@@ -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)
+2 -2
View File
@@ -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 {
+8 -2
View File
@@ -46,11 +46,13 @@
var ok_btn = $('<a href="#" class="btn btn-primary">Ok</a>');
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();
}
+5 -1
View File
@@ -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;
}
+2 -1
View File
@@ -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();
+16 -11
View File
@@ -1,22 +1,27 @@
<div id="pagination_bar" class="simplepagination pull-right padded5">
<ul>
<li class="{% if not page.has_previous %}disabled{% endif %}">
<a href="{{ baseurl }}page=1"><i class="icon-white icon-fast-backward"></i></a>
<li>
{% if page.has_previous %}<a href="{{ baseurl }}page=1">
<i class="icon-white icon-fast-backward"></i></a>{% else %}
<i class="icon-white icon-fast-backward"></i>{% endif %}
</li>
<li class="{% if not page.has_previous %}disabled{% endif %}">
<a href="{{ baseurl }}page={{ page.previous_page_number }}">
<i class="icon-step-backward icon-white"></i></a>
<li>
{% if page.has_previous %}<a href="{{ baseurl }}page={{ page.previous_page_number }}">
<i class="icon-step-backward icon-white"></i></a>{% else %}
<i class="icon-step-backward icon-white"></i>{% endif %}
</li>
<li class="disabled">
{{ page.number }}/{{ page.paginator.num_pages }}
</li>
<li class="{% if not page.has_next %}disabled{% endif %}">
<a href="{{ baseurl }}page={{ page.next_page_number }}">
<i class="icon-step-forward icon-white"></i></a>
<li>
{% if page.has_next %}<a href="{{ baseurl }}page={{ page.next_page_number }}">
<i class="icon-step-forward icon-white"></i></a>{% else %}
<i class="icon-step-forward icon-white"></i>{% endif %}
</li>
<li class="{% if not page.has_next %}disabled{% endif %}">
<a href="{{ baseurl }}page={{ page.paginator.num_pages }}">
<i class="icon-fast-forward icon-white"></i></a>
<li>
{% if page.has_next %}<a href="{{ baseurl }}page={{ page.paginator.num_pages }}">
<i class="icon-fast-forward icon-white"></i></a>{% else %}
<i class="icon-fast-forward icon-white"></i>{% endif %}
</li>
</ul>
</div>