Job's done! All modoboa applications are now using ajax based navigation.

fixes #315
This commit is contained in:
Antoine Nguyen
2012-12-02 11:41:56 +01:00
parent 9ad3f8b240
commit 4d86968d63
21 changed files with 194 additions and 165 deletions
@@ -3,10 +3,15 @@
{% block pagetitle %}{% trans "Modoboa settings" %}{% endblock %}
{% block html_head %}
<script type="text/javascript" src="{{ STATIC_URL }}js/history.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}admin/js/settings.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}js/twocols_nav.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var settings = new Settings({});
var settings = new TwocolsNav({
deflocation: "parameters/",
formid: "settings_form",
divid: "settings_content",
reload_exceptions: ["extensions"]
});
});
</script>
{% endblock %}
+1 -1
View File
@@ -2,7 +2,7 @@ from django.conf.urls.defaults import *
urlpatterns = patterns(
'modoboa.admin.views',
url(r'^$', 'domains', name="index"),
url(r'^$', 'index', name="index"),
url(r'^domains/$', 'domains', name="domains"),
(r'^domains/list/$', '_domains'),
(r'^domains/flatlist/$', 'domains_list'),
+11 -6
View File
@@ -21,13 +21,12 @@ from modoboa.lib.models import Parameter
from modoboa.lib.permissions import *
@login_required
def _domains(request):
if not request.user.has_perm("admin.view_domains"):
if request.user.has_perm("admin.view_mailboxes"):
return HttpResponseRedirect(reverse(identities))
def index(request):
return HttpResponseRedirect(reverse(domains))
return HttpResponseRedirect(reverse("modoboa.userprefs.views.index"))
@login_required
@user_passes_test(lambda u: u.has_perm("admin.view_domains") or u.has_perm("admin.view_mailboxes"))
def _domains(request):
domains = request.user.get_domains()
squery = request.GET.get("searchquery", None)
if squery is not None:
@@ -38,6 +37,12 @@ def _domains(request):
@login_required
def domains(request, tplname="admin/domains.html"):
if not request.user.has_perm("admin.view_domains"):
if request.user.has_perm("admin.view_mailboxes"):
return HttpResponseRedirect(reverse(identities))
return HttpResponseRedirect(reverse("modoboa.userprefs.views.index"))
return render(request, tplname, {
"selection" : "domains"
})
+7 -3
View File
@@ -64,9 +64,13 @@ class ExtensionsPool(object):
extinstance.load()
except Extension.DoesNotExist:
pass
baseurl = extinstance.url if extinstance.url is not None else extname
result += [(r'^%s/' % (baseurl),
include("%s.urls" % extinstance.__module__))]
try:
baseurl = extinstance.url if extinstance.url is not None else extname
result += [(r'^%s/' % (baseurl),
include("%s.urls" % extinstance.__module__))]
except ImportError:
# No urls for this extension
pass
return result
def list_all(self):
@@ -54,6 +54,17 @@ class PostfixAutoreply(ModoExtension):
exts_pool.register_extension(PostfixAutoreply)
@events.observe("ExtraUprefsRoutes")
def extra_routes():
return [(r'^autoreply/$', 'modoboa.extensions.postfix_autoreply.views.autoreply'),]
@events.observe("ExtraUprefsJS")
def extra_js():
return ["""function autoreply_cb() {
$('#id_untildate').datepicker({format: 'yyyy-mm-dd', language: '%s'});
}
""" % 'en']
@events.observe("UserMenuDisplay")
def menu(target, user):
import views
@@ -64,7 +75,8 @@ def menu(target, user):
return []
return [
{"name" : "autoreply",
"url" : reverse(views.autoreply),
"class" : "ajaxlink",
"url" : "autoreply/",
"label" : ugettext_lazy("Auto-reply message")}
]
@@ -1,20 +1,11 @@
{% extends "userprefs/section.html" %}
{% block html_head %}
<script type="text/javascript">
$(document).ready(function() {
$('#id_untildate').datepicker({format: 'yyyy-mm-dd', language: '{{ LANGUAGE_CODE }}'});
$(document).on("click", "#update", function(evt) {
evt.preventDefault();
var $form = $("#form");
$.post($form.attr("action"), $form.serialize(), function(data) {
if (data.status == "ok") {
$("body").notify("success", data.respmsg, 2000);
} else {
$("#form").html(data.content);
$('#id_untildate').datepicker({format: 'yyyy-mm-dd', language: '{{ LANGUAGE_CODE }}'});
}
});
});
});
</script>
{% endblock %}
{% load i18n libextras %}
<h2>{% trans "Auto-reply message" %} <small>{% trans "Define a message to automatically send when you are off" %}</small></h2>
<hr>
<form class="form-horizontal" method="POST"
action="{% url modoboa.extensions.postfix_autoreply.views.autoreply %}"
id="uprefs_form">
{% render_form form %}
<div class="form-actions">
<button type="submit" class="btn btn-primary" id="update" name="update">{% trans 'Update' %}</button>
</div>
</form>
@@ -1,5 +0,0 @@
from django.conf.urls.defaults import *
urlpatterns = patterns('modoboa.extensions.postfix_autoreply.views',
url(r'^$', 'autoreply'),
)
+12 -11
View File
@@ -1,7 +1,7 @@
# coding: utf-8
from datetime import date
from django.http import HttpResponse
from django.utils import simplejson
from django.template.loader import render_to_string
from django.contrib.auth.decorators \
import login_required
from django.contrib import messages
@@ -14,7 +14,7 @@ from models import *
@login_required
@needs_mailbox()
def autoreply(request, tplname="userprefs/section.html"):
def autoreply(request, tplname="postfix_autoreply/autoreply.html"):
mb = Mailbox.objects.get(user=request.user.id)
try:
arm = ARmessage.objects.get(mbox=mb.id)
@@ -36,18 +36,19 @@ def autoreply(request, tplname="userprefs/section.html"):
status="ok", respmsg=_("Auto reply message updated successfully.")
))
return ajax_response(request, status="ko", template="userprefs/form.html", form=form)
return ajax_simple_response({
"status" : "ko",
"content" : render_to_string(tplname, {"form" : form}),
"onload_cb" : "autoreply_cb"
})
ctx = dict(
title=_("Auto-reply message"),
subtitle=_("Define a message to automatically send when you are off"),
action=reverse(autoreply),
left_selection="autoreply",
)
form = ARmessageForm(instance=arm)
if arm is not None:
form.fields['untildate'].initial = arm.untildate
else:
form.fields['untildate'].initial = date.today()
ctx.update(form=form)
return _render(request, "postfix_autoreply/autoreply.html", ctx)
return ajax_simple_response({
"status" : "ok",
"content" : render_to_string(tplname, {"form" : form}),
"onload_cb" : "autoreply_cb"
})
+1 -1
View File
@@ -99,7 +99,7 @@ def userlogout(request):
m = IMAPconnector(user=request.user.username,
password=request.session["password"])
except Exception, e:
pass
return
# The following statement may fail under Python 2.6...
try:
+3
View File
@@ -59,6 +59,9 @@ events = [
"TopNotifications",
"ExtraAdminContent",
"ExtraUprefsRoutes",
"ExtraUprefsJS"
]
callbacks = {}
+9 -7
View File
@@ -98,7 +98,7 @@ if (!Object.keys) {
function simple_ajax_form_post(e, options) {
e.preventDefault();
var $form = (options.formid != undefined) ? $("#" + options.formid) : $("form");
var defaults = {reload_on_success: true, reload_mode: 'full'};
var defaults = {reload_on_success: true, reload_mode: 'full', modal: true};
var opts = $.extend({}, defaults, options);
var args = $form.serialize();
@@ -123,14 +123,16 @@ function simple_ajax_form_post(e, options) {
$("body").notify('success', data.respmsg, 2000);
}
} else {
if (data.content != "") {
$('.modal').html(data.content);
}
if (data.respmsg) {
$('.modal-body').prepend(build_error_alert(data.respmsg));
if (opts.modal) {
if (data.content != "") {
$('.modal').html(data.content);
}
if (data.respmsg) {
$('.modal-body').prepend(build_error_alert(data.respmsg));
}
}
if (opts.error_cb != undefined) {
opts.error_cb();
opts.error_cb(data);
}
}
});
@@ -1,19 +1,21 @@
var Settings = function(options) {
var TwocolsNav = function(options) {
this.initialize(options);
};
Settings.prototype = {
constructor: Settings,
TwocolsNav.prototype = {
constructor: TwocolsNav,
defaults: {
deflocation: "parameters/"
deflocation: null,
formid: "#form",
divid: "#content",
reload_exceptions: null
},
initialize: function(options) {
this.options = $.extend({}, this.defaults, options);
this.options.defcallback = $.proxy(this.default_cb, this);
this.navobj = new History(this.options);
this.listen();
},
@@ -21,16 +23,31 @@ Settings.prototype = {
$("a.ajaxlink").click($.proxy(this.load_page, this));
$(document).on("click", "#update", $.proxy(function(e) {
simple_ajax_form_post(e, {
formid: "settings_form",
formid: this.options.formid,
modal: false,
reload_on_success: false,
error_cb: $.proxy(this.update_content, this),
success_cb: $.proxy(this.save_cb, this)
});
}, this));
},
update_content: function(data) {
$('#' + this.options.divid).html(data.content);
if (data.onload_cb) {
eval(data.onload_cb + '()');
}
$(".help").popover().click(function(e) {e.preventDefault();});
},
save_cb: function(data) {
if (this.navobj.getbaseurl() == 'extensions') {
window.location.reload();
if (this.options.reload_exceptions) {
for (var i = 0; i < this.options.reload_exceptions.length; i++) {
if (this.navobj.getbaseurl() == this.options.reload_exceptions[i]) {
window.location.reload();
break;
}
}
}
$("body").notify("success", data.respmsg, 2000);
},
@@ -44,6 +61,6 @@ Settings.prototype = {
default_cb: function(data) {
$("a.ajaxlink").parent().removeClass("active");
$("a[name=" + this.navobj.getbaseurl() + "]").parent().addClass("active");
$("#settings_content").html(data.content);
this.update_content(data);
}
};
@@ -1,5 +0,0 @@
{% load i18n libextras %}
{% render_form form %}
<div class="form-actions">
<button type="submit" class="btn btn-primary" id="update" name="update">{% trans 'Update' %}</button>
</div>
@@ -0,0 +1,10 @@
{% load i18n libextras %}
<h2>{% trans "Forward" %} <small>{% trans "Automatically forward emails to another address" %}</small></h2>
<hr>
<form class="form-horizontal" method="POST" action="{% url modoboa.userprefs.views.forward %}"
id="uprefs_form">
{% render_form form %}
<div class="form-actions">
<button type="submit" class="btn btn-primary" id="update" name="update">{% trans 'Update' %}</button>
</div>
</form>
@@ -0,0 +1,19 @@
{% extends "twocols.html" %}{% load i18n uprefs_extras libextras %}
{% block pagetitle %}{% trans "Settings" %}{% endblock %}
{% block html_head %}
<script type="text/javascript" src="{{ STATIC_URL }}js/history.js"></script>
<script type="text/javascript" src="{{ STATIC_URL }}js/twocols_nav.js"></script>
<script type="text/javascript">
{{ extrajs|safe }}
$(document).ready(function() {
var userprefs = new TwocolsNav({
deflocation: "profile/",
formid: "uprefs_form",
divid: "uprefs_content",
reload_exceptions: ["profile"]
});
});
</script>
{% endblock %}
{% block leftcol %}<div class="well sidebar-nav">{% uprefs_menu left_selection user %}</div>{% endblock %}
{% block apparea %}<div id="uprefs_content"></div>{% endblock %}
@@ -1,30 +1,9 @@
{% extends "twocols.html" %}{% load i18n uprefs_extras libextras %}
{% block pagetitle %}{% trans "Settings" %}{% endblock %}
{% block html_head %}
<script type="text/javascript">
$(document).ready(function() {
$("#update").click(function(evt) {
evt.preventDefault();
var $form = $("form");
$.post($form.attr("action"), $form.serialize(), function(data) {
if (data.status == "ok") {
$("body").notify("success", data.message, 2000);
}
});
});
});
</script>
{% endblock %}
{% block leftcol %}<div class="well sidebar-nav">{% uprefs_menu left_selection user %}</div>{% endblock %}
{% block apparea %}
<h2>{% trans "Preferences" %} <small>{% trans "Customize Modoboa" %}</small></h2>
{% load i18n %}
<h2>{% trans "Preferences" %} <small>{% trans "Customize Modoboa" %}</small></h2>
<hr>
<form class="form-horizontal" method="POST" action="{% url modoboa.userprefs.views.preferences %}"
id="uprefs_form">
{% include "common/parameters.html" %}
<hr>
<form class="form-horizontal" method="POST"
action="{% url modoboa.userprefs.views.preferences %}"
id="uparams_form">
{% include "common/parameters.html" %}
<hr>
<button type="submit" class="btn btn-primary" id="update" name="update">{% trans 'Save' %}</button>
</form>
{% endblock %}
<button type="submit" class="btn btn-primary" id="update" name="update">{% trans 'Save' %}</button>
</form>
@@ -0,0 +1,10 @@
{% load i18n libextras %}
<h2>{% trans "Profile" %} <small>{% trans "Update your personal information" %}</small></h2>
<hr>
<form class="form-horizontal" method="POST" action="{% url modoboa.userprefs.views.profile %}"
id="uprefs_form">
{% render_form form %}
<div class="form-actions">
<button type="submit" class="btn btn-primary" id="update" name="update">{% trans 'Update' %}</button>
</div>
</form>
@@ -1,30 +0,0 @@
{% extends "twocols.html" %}{% load i18n uprefs_extras libextras %}
{% block pagetitle %}{{ title }}{% endblock %}
{% block html_head %}
<script type="text/javascript">
$(document).ready(function() {
$(document).on("click", "#update", function(evt) {
evt.preventDefault();
var $form = $("#form");
$.post($form.attr("action"), $form.serialize(), function(data) {
if (data.status == "ok") {
$("body").notify("success", data.respmsg, 2000);
} else {
$("#form").html(data.content);
if (data.respmsg) {
$("body").notify("error", data.respmsg);
}
}
});
});
});
</script>
{% endblock %}
{% block leftcol %}<div class="well sidebar-nav">{% uprefs_menu left_selection user %}</div>{% endblock %}
{% block apparea %}
<h2>{{ title }} <small>{{ subtitle }}</small></h2>
<hr>
<form class="form-horizontal" method="POST" action="{{ action }}" id="form">
{% include "userprefs/form.html" %}
</form>
{% endblock %}
@@ -12,16 +12,18 @@ register = template.Library()
def uprefs_menu(selection, user):
entries = [
{"name" : "profile",
"url" : reverse("modoboa.userprefs.views.profile"),
"class" : "ajaxlink",
"url" : "profile/",
"label" : _("Profile")},
{"name" : "preferences",
"url" : reverse("modoboa.userprefs.views.preferences"),
"class" : "ajaxlink",
"url" : "preferences/",
"label" : _("Preferences")},
]
if user.group == 'SimpleUsers':
if user.group == 'SimpleUsers' and user.has_mailbox:
entries.insert(0, {"name" : "forward",
"url" : reverse("modoboa.userprefs.views.forward"),
"modalcb" : "forwardform_cb",
"class" : "ajaxlink",
"url" : "forward/",
"label" : _("Forward")})
entries += events.raiseQueryEvent("UserMenuDisplay", "uprefs_menu", user)
+4
View File
@@ -1,4 +1,5 @@
from django.conf.urls.defaults import *
from modoboa.lib import events
urlpatterns = patterns('modoboa.userprefs.views',
url(r'^$', 'index'),
@@ -6,3 +7,6 @@ urlpatterns = patterns('modoboa.userprefs.views',
(r'^profile/$', 'profile'),
(r'^forward/$', 'forward'),
)
urlpatterns += patterns('',
*events.raiseQueryEvent("ExtraUprefsRoutes"))
+35 -30
View File
@@ -9,6 +9,7 @@ from django.contrib.auth.decorators \
from django.conf import settings
from django.utils.translation import ugettext as _
from modoboa.lib import parameters, events
from modoboa.lib.exceptions import ModoboaException
from modoboa.lib.webutils import ajax_response, ajax_simple_response
from forms import *
from modoboa.admin.models import Mailbox, Alias
@@ -16,19 +17,20 @@ from modoboa.admin.lib import AdminError
from modoboa.auth.lib import encrypt
@login_required
def index(request):
return HttpResponseRedirect(reverse(profile))
def index(request, tplname="userprefs/index.html"):
extrajs = events.raiseQueryEvent("ExtraUprefsJS")
return render(request, tplname, {
"selection" : "user",
"extrajs" : "".join(extrajs)
})
@login_required
@user_passes_test(lambda u: u.belongs_to_group('SimpleUsers'))
def forward(request):
mb = request.user.mailbox_set.all()[0]
ctx = dict(
title=_("Forward"),
subtitle=_("Automatically forward emails to another address"),
action=reverse(forward),
left_selection="forward",
)
def forward(request, tplname='userprefs/forward.html'):
try:
mb = request.user.mailbox_set.all()[0]
except IndexError:
raise ModoboaException(_("You need a mailbox in order to define a forward"))
try:
al = Alias.objects.get(address=mb.address,
domain__name=mb.domain.name)
@@ -53,10 +55,9 @@ def forward(request):
except BadDestination, e:
error = str(e)
ctx.update(form=form, error=error)
return ajax_simple_response(dict(
status="ko",
content=render_to_string("userprefs/form.html", dict(form=form)),
content=render_to_string(tplname, {"form" : form}),
respmsg=error
))
@@ -69,11 +70,15 @@ def forward(request):
pass
else:
form.fields["keepcopies"].initial = True
ctx.update(form=form)
return render(request, "userprefs/section.html", ctx)
return ajax_simple_response({
"status" : "ok",
"content" : render_to_string(tplname, {
"form" : form
})
})
@login_required
def profile(request):
def profile(request, tplname='userprefs/profile.html'):
update_password = True
if True in events.raiseQueryEvent("PasswordChange", request.user):
update_password = False
@@ -87,18 +92,17 @@ def profile(request):
return ajax_simple_response(dict(
status="ok", respmsg=_("Profile updated")
))
return ajax_simple_response(dict(
status="ko",
content=render_to_string("userprefs/form.html", dict(form=form))
))
return ajax_simple_response({
"status" : "ko",
"content" : render_to_string(tplname, {"form" : form})
})
form = ProfileForm(update_password, instance=request.user)
return render(request, 'userprefs/section.html', {
"title" : _("Profile"),
"subtitle" : _("Update your personal information"),
"action" : reverse(profile),
"left_selection" : "profile",
"form" : form
return ajax_simple_response({
"status" : "ok",
"content" : render_to_string(tplname, {
"form" : form
})
})
@login_required
@@ -111,7 +115,7 @@ def preferences(request):
parameters.save_user(request.user, name, v, app=app)
return ajax_simple_response(dict(
status="ok", message=_("Preferences saved")
status="ok", respmsg=_("Preferences saved")
))
apps = sorted(parameters._params.keys())
@@ -132,8 +136,9 @@ def preferences(request):
tmp["params"] += [newdef]
gparams += [tmp]
return render(request, 'userprefs/preferences.html', {
"selection" : "user",
"left_selection" : "preferences",
"gparams" : gparams
return ajax_simple_response({
"status" : "ok",
"content" : render_to_string("userprefs/preferences.html", {
"gparams" : gparams
})
})