diff --git a/modoboa/admin/templates/admin/settings_header.html b/modoboa/admin/templates/admin/settings_header.html index ad2c246ee..9be226e95 100644 --- a/modoboa/admin/templates/admin/settings_header.html +++ b/modoboa/admin/templates/admin/settings_header.html @@ -3,10 +3,15 @@ {% block pagetitle %}{% trans "Modoboa settings" %}{% endblock %} {% block html_head %} - + {% endblock %} diff --git a/modoboa/admin/urls.py b/modoboa/admin/urls.py index bede38e01..aea38672a 100644 --- a/modoboa/admin/urls.py +++ b/modoboa/admin/urls.py @@ -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'), diff --git a/modoboa/admin/views.py b/modoboa/admin/views.py index 01eb2ff95..28ea0ac8d 100644 --- a/modoboa/admin/views.py +++ b/modoboa/admin/views.py @@ -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" }) diff --git a/modoboa/extensions/__init__.py b/modoboa/extensions/__init__.py index 1fb2e4910..37cdd3d95 100644 --- a/modoboa/extensions/__init__.py +++ b/modoboa/extensions/__init__.py @@ -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): diff --git a/modoboa/extensions/postfix_autoreply/__init__.py b/modoboa/extensions/postfix_autoreply/__init__.py index 33d762cee..7846cf8a3 100644 --- a/modoboa/extensions/postfix_autoreply/__init__.py +++ b/modoboa/extensions/postfix_autoreply/__init__.py @@ -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")} ] diff --git a/modoboa/extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html b/modoboa/extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html index 4130eec0c..c5f30c794 100644 --- a/modoboa/extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html +++ b/modoboa/extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html @@ -1,20 +1,11 @@ -{% extends "userprefs/section.html" %} -{% block html_head %} - -{% endblock %} +{% load i18n libextras %} +

{% trans "Auto-reply message" %} {% trans "Define a message to automatically send when you are off" %}

+
+
+ {% render_form form %} +
+ +
+
diff --git a/modoboa/extensions/postfix_autoreply/urls.py b/modoboa/extensions/postfix_autoreply/urls.py deleted file mode 100644 index 4d71b3019..000000000 --- a/modoboa/extensions/postfix_autoreply/urls.py +++ /dev/null @@ -1,5 +0,0 @@ -from django.conf.urls.defaults import * - -urlpatterns = patterns('modoboa.extensions.postfix_autoreply.views', - url(r'^$', 'autoreply'), - ) diff --git a/modoboa/extensions/postfix_autoreply/views.py b/modoboa/extensions/postfix_autoreply/views.py index 24903dbc4..3e096c3aa 100644 --- a/modoboa/extensions/postfix_autoreply/views.py +++ b/modoboa/extensions/postfix_autoreply/views.py @@ -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" + }) diff --git a/modoboa/extensions/webmail/__init__.py b/modoboa/extensions/webmail/__init__.py index c36d2066e..342fc2828 100644 --- a/modoboa/extensions/webmail/__init__.py +++ b/modoboa/extensions/webmail/__init__.py @@ -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: diff --git a/modoboa/lib/events.py b/modoboa/lib/events.py index 6fb3245fa..51d82793d 100644 --- a/modoboa/lib/events.py +++ b/modoboa/lib/events.py @@ -59,6 +59,9 @@ events = [ "TopNotifications", "ExtraAdminContent", + + "ExtraUprefsRoutes", + "ExtraUprefsJS" ] callbacks = {} diff --git a/modoboa/static/js/global.js b/modoboa/static/js/global.js index 771176d36..482b1e850 100644 --- a/modoboa/static/js/global.js +++ b/modoboa/static/js/global.js @@ -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); } } }); diff --git a/modoboa/admin/static/admin/js/settings.js b/modoboa/static/js/twocols_nav.js similarity index 53% rename from modoboa/admin/static/admin/js/settings.js rename to modoboa/static/js/twocols_nav.js index bea2ee05d..64e17b1b2 100644 --- a/modoboa/admin/static/admin/js/settings.js +++ b/modoboa/static/js/twocols_nav.js @@ -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); } }; \ No newline at end of file diff --git a/modoboa/userprefs/templates/userprefs/form.html b/modoboa/userprefs/templates/userprefs/form.html deleted file mode 100644 index 53626c558..000000000 --- a/modoboa/userprefs/templates/userprefs/form.html +++ /dev/null @@ -1,5 +0,0 @@ -{% load i18n libextras %} -{% render_form form %} -
- -
diff --git a/modoboa/userprefs/templates/userprefs/forward.html b/modoboa/userprefs/templates/userprefs/forward.html new file mode 100644 index 000000000..5aaf2b009 --- /dev/null +++ b/modoboa/userprefs/templates/userprefs/forward.html @@ -0,0 +1,10 @@ +{% load i18n libextras %} +

{% trans "Forward" %} {% trans "Automatically forward emails to another address" %}

+
+
+ {% render_form form %} +
+ +
+
diff --git a/modoboa/userprefs/templates/userprefs/index.html b/modoboa/userprefs/templates/userprefs/index.html new file mode 100644 index 000000000..9dee42e1c --- /dev/null +++ b/modoboa/userprefs/templates/userprefs/index.html @@ -0,0 +1,19 @@ +{% extends "twocols.html" %}{% load i18n uprefs_extras libextras %} +{% block pagetitle %}{% trans "Settings" %}{% endblock %} +{% block html_head %} + + + +{% endblock %} +{% block leftcol %}{% endblock %} +{% block apparea %}
{% endblock %} diff --git a/modoboa/userprefs/templates/userprefs/preferences.html b/modoboa/userprefs/templates/userprefs/preferences.html index 6e1767d99..f20af214c 100644 --- a/modoboa/userprefs/templates/userprefs/preferences.html +++ b/modoboa/userprefs/templates/userprefs/preferences.html @@ -1,30 +1,9 @@ -{% extends "twocols.html" %}{% load i18n uprefs_extras libextras %} -{% block pagetitle %}{% trans "Settings" %}{% endblock %} -{% block html_head %} - -{% endblock %} -{% block leftcol %}{% endblock %} -{% block apparea %} -

{% trans "Preferences" %} {% trans "Customize Modoboa" %}

+{% load i18n %} +

{% trans "Preferences" %} {% trans "Customize Modoboa" %}

+
+
+ {% include "common/parameters.html" %}
- - {% include "common/parameters.html" %} -
- -
-{% endblock %} + + diff --git a/modoboa/userprefs/templates/userprefs/profile.html b/modoboa/userprefs/templates/userprefs/profile.html new file mode 100644 index 000000000..709f93f37 --- /dev/null +++ b/modoboa/userprefs/templates/userprefs/profile.html @@ -0,0 +1,10 @@ +{% load i18n libextras %} +

{% trans "Profile" %} {% trans "Update your personal information" %}

+
+
+ {% render_form form %} +
+ +
+
diff --git a/modoboa/userprefs/templates/userprefs/section.html b/modoboa/userprefs/templates/userprefs/section.html deleted file mode 100644 index d46aac5d2..000000000 --- a/modoboa/userprefs/templates/userprefs/section.html +++ /dev/null @@ -1,30 +0,0 @@ -{% extends "twocols.html" %}{% load i18n uprefs_extras libextras %} -{% block pagetitle %}{{ title }}{% endblock %} -{% block html_head %} - -{% endblock %} -{% block leftcol %}{% endblock %} -{% block apparea %} -

{{ title }} {{ subtitle }}

-
-
- {% include "userprefs/form.html" %} -
-{% endblock %} diff --git a/modoboa/userprefs/templatetags/uprefs_extras.py b/modoboa/userprefs/templatetags/uprefs_extras.py index 8f162ea77..236a7a63e 100644 --- a/modoboa/userprefs/templatetags/uprefs_extras.py +++ b/modoboa/userprefs/templatetags/uprefs_extras.py @@ -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) diff --git a/modoboa/userprefs/urls.py b/modoboa/userprefs/urls.py index 4b26340b0..3a118ab59 100644 --- a/modoboa/userprefs/urls.py +++ b/modoboa/userprefs/urls.py @@ -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")) diff --git a/modoboa/userprefs/views.py b/modoboa/userprefs/views.py index e6758a3f1..3cdc9229b 100644 --- a/modoboa/userprefs/views.py +++ b/modoboa/userprefs/views.py @@ -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 + }) })