diff --git a/admin/forms.py b/admin/forms.py
index 5d9a5cb71..8f868dccd 100644
--- a/admin/forms.py
+++ b/admin/forms.py
@@ -246,11 +246,11 @@ class AccountFormGeneral(forms.ModelForm):
role = self.cleaned_data["role"]
else:
role = "SimpleUsers"
+ account.groups.clear()
if role == "SuperAdmins":
account.is_superuser = True
else:
account.is_superuser = False
- account.groups.clear()
account.groups.add(Group.objects.get(name=role))
account.save()
return account
diff --git a/admin/models.py b/admin/models.py
index 1e771ac3b..bb476e456 100644
--- a/admin/models.py
+++ b/admin/models.py
@@ -167,7 +167,7 @@ class User(DUser):
@property
def group(self):
if self.is_superuser:
- return "SuperAdmin"
+ return "SuperAdmins"
try:
return self.groups.all()[0].name
except IndexError:
diff --git a/extensions/amavis_quarantine/sql_listing.py b/extensions/amavis_quarantine/sql_listing.py
index a1deb238c..6086d7452 100644
--- a/extensions/amavis_quarantine/sql_listing.py
+++ b/extensions/amavis_quarantine/sql_listing.py
@@ -76,14 +76,15 @@ class SQLconnector(MBconnector):
return emails
class SQLlisting(EmailListing):
- tpl = "amavis_quarantine/index.html"
+ tpl = "amavis_quarantine/index2.html"
tbltype = Qtable
deflocation = "listing/"
defcallback = "updatelisting"
reset_wm_url = True
+ table_styles = "table-condensed"
def __init__(self, user, msgs, filter, **kwargs):
- if user.belongs_to_group('SimpleUsers'):
+ if user.group == 'SimpleUsers':
Qtable.cols_order = ['type', 'rstatus', 'from_', 'subject', 'time']
else:
Qtable.cols_order = ['type', 'rstatus', 'to', 'from_', 'subject', 'time']
diff --git a/extensions/amavis_quarantine/static/css/quarantine.css b/extensions/amavis_quarantine/static/css/quarantine.css
index da2ff19ad..3c46ce99b 100644
--- a/extensions/amavis_quarantine/static/css/quarantine.css
+++ b/extensions/amavis_quarantine/static/css/quarantine.css
@@ -1,8 +1,29 @@
+#menubar {
+ position: fixed;
+ top: 60px;
+ padding-left: 15px;
+}
+
+#listing {
+ position: fixed;
+ padding: 0 15px;
+ right: 0;
+ left: 0;
+}
+
+#mailcontent {
+ border: 0;
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ height: 100%;
+}
+
thead tr {
position: relative;
z-index: 1;
}
-tr.table-tr-selected {
- background: #ffffcc;
-}
\ No newline at end of file
+td.unseen {
+ font-weight: bold;
+}
diff --git a/extensions/amavis_quarantine/static/js/quarantine.js b/extensions/amavis_quarantine/static/js/quarantine.js
index 5a6347947..bfc349bf1 100644
--- a/extensions/amavis_quarantine/static/js/quarantine.js
+++ b/extensions/amavis_quarantine/static/js/quarantine.js
@@ -1,136 +1,180 @@
-function updatehash(evt) {
- evt.stop();
- var url = $defined(this.get("href")) ? this.get("href") : "";
- current_anchor.parse_string(url, true).setparams(navparams);
- current_anchor.update();
-}
+var Quarantine = function(options) {
+ this.initialize(options);
+};
-function appendhash(evt) {
- evt.stop();
- location.hash += evt.target.get("href");
-}
+Quarantine.prototype = {
+ constructor: Quarantine,
-function updateparams(evt) {
- evt.stop();
- current_anchor.updateparams(evt.target.get("href"));
- current_anchor.update();
-}
+ defaults: {
+ deflocation: "listing",
+ defcallback: "listing_cb"
+ },
-function actioncallback(resp) {
- $("listing").set("html", "");
- $("menubar").set("html", "");
- $("navbar").set("html", "");
- if (resp.status == "ok") {
- infobox.info(resp.respmsg);
- current_anchor.parse_string(resp.url, true).setparams(navparams);
- current_anchor.update(1);
- } else {
- infobox.error(resp.respmsg);
- }
-}
+ initialize: function(options) {
+ this.options = $.extend({}, this.defaults, options);
+ this.navobj = new History(this.options);
-function actionclick(evt) {
- new Request.JSON.mdb({
- url: evt.target.get("href"),
- onSuccess: actioncallback
- }).get();
-}
+ this.register_navcallbacks();
+ this.listen();
+ },
-function deleteclick(evt) {
- evt.stop();
- if (!confirm(gettext("Delete this message?"))) {
- return false;
+ update_page: function(data) {
+ if (data.menu != undefined) {
+ $("#menubar").html(data.menu);
+ $("#searchfield").searchbar({navobj: this.navobj});
+ }
+ if (data.navbar) {
+ $("#bottom-bar-in").html(data.navbar);
+ }
+ if (data.listing != undefined) {
+ $("#listing").html(data.listing);
+ $("#listing").css({
+ top: $("#menubar").outerHeight() + 60 + "px",
+ bottom: $("#bottom-bar").outerHeight() + "px",
+ overflow: "auto"
+ });
+ }
+ },
+
+ listen: function() {
+ $(document).on("dblclick", "tbody>tr", $.proxy(this.viewmail_loader, this));
+ $(document).on("click", "a[name=selectmsgs]", $.proxy(this.selectmsgs, this));
+ $(document).on("click", "a[name=release-multi]",
+ $.proxy(this.release_selection, this));
+ $(document).on("click", "a[name=delete-multi]",
+ $.proxy(this.delete_selection, this));
+ $(document).on("click", "#bottom-bar a", $.proxy(this.load_page, this));
+
+ $(document).on("click", "a[name=release]", $.proxy(this.release, this));
+ $(document).on("click", "a[name=delete]", $.proxy(this.delete, this));
+ $(document).on("click", "a[name=viewmode]", $.proxy(this.update_params, this));
+ },
+
+ load_page: function(e) {
+ e.preventDefault();
+ var $link = $(e.target).parent();
+
+ this.navobj.deleteParam("rcpt");
+ this.navobj.from_string($link.attr("href")).update();
+ },
+
+ viewmail_loader: function(e) {
+ e.preventDefault();
+ var $tr = $(e.target).parent();
+ var $to = $tr.find("td[name=to]");
+
+ this.navobj.baseurl($tr.attr("id"));
+ if ($to.length) {
+ this.navobj.setparam("rcpt", $to.html().trim());
+ }
+ this.navobj.update();
+ },
+
+ selectmsgs: function(e) {
+ e.preventDefault();
+ var type = $(e.target).attr("href");
+
+ if (type == "") {
+ $("#emails").htmltable("clear_selection");
+ return;
+ }
+ $("td[name=type]").each(function() {
+ var $this = $(this);
+ if ($this.html().trim() == type) {
+ $("#emails").htmltable("select_row", $this.parent());
+ }
+ });
+ },
+
+ _send_selection: function(e, name, message) {
+ var $link = $(e.target);
+
+ e.preventDefault();
+ if (!this.htmltable.current_selection().length ||
+ !confirm(message)) {
+ return;
+ }
+ var selection = [];
+
+ this.htmltable.current_selection().each(function() {
+ var $tr = $(this);
+ var $to = $tr.find("td[name=to]");
+
+ if ($to.length) {
+ selection.push($to.html().trim() + " " + $tr.attr("id"));
+ } else {
+ selection.push($tr.attr("id"));
+ }
+ });
+ $.ajax({
+ url: $link.attr("href"),
+ data: "action=" + name + "&selection=" + selection.join(","),
+ type: 'POST',
+ dataType: 'json',
+ success: $.proxy(this.action_cb, this)
+ });
+ },
+
+ release_selection: function(e) {
+ this._send_selection(e, "release", gettext("Release this selection?"));
+ },
+
+ delete_selection: function(e) {
+ this._send_selection(e, "delete", gettext("Delete this selection?"));
+ },
+
+ _send_action: function(e, message) {
+ var $link = $(e.target);
+
+ e.preventDefault();
+ if (!confirm(message)) {
+ return;
+ }
+ $.ajax({
+ url: $link.attr("href"),
+ dataType: 'json',
+ success: $.proxy(this.action_cb, this)
+ });
+ },
+
+ release: function(e) {
+ this._send_action(e, gettext("Release this message?"));
+ },
+
+ delete: function(e) {
+ this._send_action(e, gettext("Delete this message?"));
+ },
+
+ update_params: function(e) {
+ var $link = $(e.target);
+ e.preventDefault();
+ this.navobj.updateparams($link.attr("href")).update();
+ },
+
+ register_navcallbacks: function() {
+ this.navobj.register_callback("_listing",
+ $.proxy(this.listing_cb, this));
+ this.navobj.register_callback("viewmail",
+ $.proxy(this.viewmail_cb, this));
+ },
+
+ listing_cb: function(data) {
+ this.update_page(data);
+ $("#emails").htmltable();
+ this.htmltable = $("#emails").data("htmltable");
+ },
+
+ viewmail_cb: function(data) {
+ this.update_page(data);
+ $("#listing").css("overflow", "hidden");
+ },
+
+ action_cb: function(data) {
+ if (data.status == "ok") {
+ this.navobj.parse_string(data.url, true).update(true);
+ $("body").notify("success", data.respmsg, 2000);
+ } else {
+ $("body").notify("error", data.respmsg);
+ }
}
- actionclick(evt);
-}
-
-function releaseclick(evt) {
- evt.stop();
- if (!confirm(gettext("Release this message?"))) {
- return false;
- }
- actionclick(evt);
-}
-
-function viewmail_cs(evt) {
- evt.stop();
- var to = this.getFirst("td[name=to]");
-
- current_anchor.baseurl(this.get("id"));
- if ($defined(to)) {
- current_anchor.setparam("rcpt", to.get("html").trim());
- }
- current_anchor.update();
-}
-
-/*
- * Callback of the 'listing' action (the main screen)
- */
-function listing_cb(resp) {
- updatelisting(resp);
-
- var tbl = new HtmlTable($("emails"), {
- useKeyboard: false,
- selectable: true
- });
-
- if ($("toggleselect")) {
- $("toggleselect").addEvent("click", function(evt) {
- if ($$("tr[class*=table-tr-selected]").length) {
- tbl.selectNone();
- } else {
- tbl.selectAll();
- }
- });
- }
- $$("a[name=selectmsgs]").addEvent("click", function(evt) {
- evt.stop();
- var type = evt.target.get("href");
-
- if (!$chk(type)) {
- $$("tr[class*=table-tr-selected]").each(function(item) {
- item.removeClass("table-tr-selected");
- });
- if ($("toggleselect").checked) {
- $("toggleselect").checked = false;
- tbl.selectNone();
- }
- return;
- }
- $$("td[name=type]").each(function(item) {
- if (item.get("html").trim() == type) {
- item.getParent().addClass("table-tr-selected");
- }
- });
- });
- $$("a[name=release]").addEvent("click", function(event) {
- if (!checkTableSelection(gettext("Release this selection?"))) {
- event.stop();
- return;
- }
- mysubmit(event, "release");
- });
- $$("a[name=delete]").addEvent("click", function(event) {
- if (!checkTableSelection(gettext("Delete this selection?"))) {
- event.stop();
- return;
- }
- mysubmit(event, "delete");
- });
- searchbox_init();
- init_sortable_columns();
- update_sortable_column();
- $$("tbody>tr").addEvent("dblclick", viewmail_cs);
-}
-
-/*
- * Callback of the 'viewmail' action
- */
-function viewmail_cb(resp) {
- updatelisting(resp);
- $$("a[name=back]").addEvent("click", updatehash);
- $$("a[name=delete]").addEvent("click", deleteclick);
- $$("a[name=release]").addEvent("click", releaseclick);
- $$("a[name=viewmode]").addEvent("click", updateparams);
- setDivHeight("mailcontent", 5, 0);
-}
\ No newline at end of file
+};
\ No newline at end of file
diff --git a/extensions/amavis_quarantine/templates/amavis_quarantine/index.html b/extensions/amavis_quarantine/templates/amavis_quarantine/index.html
index fb8ff89c9..de5331cd7 100644
--- a/extensions/amavis_quarantine/templates/amavis_quarantine/index.html
+++ b/extensions/amavis_quarantine/templates/amavis_quarantine/index.html
@@ -1,42 +1,22 @@
-{% extends "common/email_listing.html" %}
-{% load i18n %}
+{% extends "fixed.html" %}
{% block html_head %}
+
+
+
-{{ block.super }}
{% endblock %}
-{% block js %}
- current_anchor.register_callback("_listing", listing_cb);
- current_anchor.register_callback("viewmail", viewmail_cb);
+{% block fixed_content %}
+
+
+{% endblock %}
+{% block footer %}
{% endblock %}
-{% block middletitle %}{% trans "Quarantine" %}{% endblock %}
diff --git a/extensions/amavis_quarantine/templates/amavis_quarantine/viewheader.html b/extensions/amavis_quarantine/templates/amavis_quarantine/viewheader.html
index 8b187503f..50c749ef8 100644
--- a/extensions/amavis_quarantine/templates/amavis_quarantine/viewheader.html
+++ b/extensions/amavis_quarantine/templates/amavis_quarantine/viewheader.html
@@ -1,43 +1,11 @@
-{% extends "layout_simple.html" %}
+{% extends "common/generic_modal.html" %}
{% load i18n %}
-{% block html_head %}
-
-{% endblock %}
-
-{% block content %}
-
-| {% trans "Message headers" %} |
+{% block modalbody %}
+
{% for k, v in headers %}
| {{ k }} | {{ v }} |
{% endfor %}
-{% endblock %}
\ No newline at end of file
+{% endblock %}
diff --git a/extensions/amavis_quarantine/templatetags/amextras.py b/extensions/amavis_quarantine/templatetags/amextras.py
index 8f8bb0c4e..c7bc2addc 100644
--- a/extensions/amavis_quarantine/templatetags/amextras.py
+++ b/extensions/amavis_quarantine/templatetags/amextras.py
@@ -24,46 +24,44 @@ def viewm_menu(selection, backurl, mail_id, rcpt, perms):
entries = [
{"name" : "back",
- "url" : backurl,
- "img" : static_url("pics/back.png"),
+ "img" : "icon-arrow-left",
+ "url" : "javascript:history.go(-1);",
"label" : _("Back to list")},
{"name" : "headers",
"url" : reverse(amavis_quarantine.views.viewheaders, args=[mail_id]),
- "img" : static_url("pics/add.png"),
"label" : _("View full headers"),
- "class" : "boxed",
- "rel" : "{handler:'iframe',size:{x:600,y:500}}"},
+ "modal" : True,
+ "autowidth" : True},
{"name" : "release",
+ "img" : "icon-ok",
"url" : reverse(amavis_quarantine.views.release, args=[mail_id]) \
+ "?rcpt=%s" % rcpt,
- "img" : static_url("pics/release.png"),
"label" : _("Release")},
{"name" : "delete",
+ "img" : "icon-remove",
"url" : reverse(amavis_quarantine.views.delete, args=[mail_id]) \
+ "?rcpt=%s" % rcpt,
- "img" : static_url("pics/remove.png"),
"label" : _("Delete")},
{"name" : "options",
"label" : _("Options"),
- "img" : static_url("pics/settings.png"),
- "class" : "menubardropdown",
+ "img" : "icon-cog",
"menu" : options_menu}
]
- return render_to_string('common/menu.html',
+ return render_to_string('common/buttons_list.html',
{"selection" : selection, "entries" : entries,
"perms" : perms})
@register.simple_tag
def quar_menu(selection, user):
entries = [
- {"name" : "release",
- "url" : "",
- "img" : static_url("pics/release.png"),
+ {"name" : "release-multi",
+ "url" : reverse(amavis_quarantine.views.process),
+ "img" : "icon-ok",
"label" : _("Release")},
- {"name" : "delete",
- "url" : "",
- "img" : static_url("pics/remove.png"),
+ {"name" : "delete-multi",
+ "img" : "icon-remove",
+ "url" : reverse(amavis_quarantine.views.process),
"label" : _("Delete")},
{"name" : "select",
"url" : "",
@@ -87,9 +85,7 @@ def quar_menu(selection, user):
}
]
- menu = render_to_string('common/menu.html',
- {"selection" : selection, "entries" : entries})
- if not user.belongs_to_group('SimpleUsers'):
+ if user.group != 'SimpleUsers':
extraopts = [{"name" : "to", "label" : _("To")}]
else:
extraopts = []
@@ -97,4 +93,7 @@ def quar_menu(selection, user):
"MEDIA_URL" : settings.MEDIA_URL,
"extraopts" : extraopts
})
- return menu + searchbar
+
+ return render_to_string('common/buttons_list.html', dict(
+ selection=selection, entries=entries, extracontent=searchbar
+ ))
diff --git a/extensions/amavis_quarantine/views.py b/extensions/amavis_quarantine/views.py
index 009c2442a..a48973905 100644
--- a/extensions/amavis_quarantine/views.py
+++ b/extensions/amavis_quarantine/views.py
@@ -1,5 +1,4 @@
-# -*- coding: utf-8 -*-
-
+# coding: utf-8
import email
from django.http import HttpResponseRedirect, HttpResponse
from django.template import Template, Context
@@ -29,14 +28,14 @@ def __get_current_url(request):
return res
def empty_quarantine(request):
- content = "%s
" % _("Empty quarantine")
+ content = "%s
" % _("Empty quarantine")
ctx = getctx("ok", level=2, listing=content, navbar="",
menu=quar_menu("", request.user))
return HttpResponse(simplejson.dumps(ctx), mimetype="application/json")
@login_required
def _listing(request):
- filter = None
+ flt = None
rcptfilter = None
msgs = None
@@ -60,11 +59,11 @@ def _listing(request):
continue
else:
raise Exception("unsupported search criteria %s" % c)
- filter = nfilter if filter is None else filter | nfilter
+ flt = nfilter if flt is None else flt | nfilter
q = ~Q(rs='D')
if not request.user.is_superuser:
- if not request.user.belongs_to_group('SimpleUsers'):
+ if request.user.group != 'SimpleUsers':
doms = request.user.get_domains()
if not len(doms):
return empty_quarantine(request)
@@ -73,7 +72,7 @@ def _listing(request):
else:
q &= Q(rid__email=request.user.email)
- if not request.user.belongs_to_group('SimpleUsers') \
+ if request.user.group != 'SimpleUsers' \
and rcptfilter is not None:
q &= Q(rid__email__contains=rcptfilter)
msgs = Msgrcpt.objects.filter(q).values("mail_id")
@@ -86,7 +85,7 @@ def _listing(request):
del request.session["page"]
pageid = 1
- lst = SQLlisting(request.user, msgs, filter, baseurl="listing/",
+ lst = SQLlisting(request.user, msgs, flt,
navparams=request.session["navparams"],
elems_per_page=int(parameters.get_user(request.user,
"MESSAGES_PER_PAGE")))
@@ -95,14 +94,16 @@ def _listing(request):
return empty_quarantine(request)
content = lst.fetch(request, page.id_start, page.id_stop)
- navbar = lst.render_navbar(page)
+ navbar = lst.render_navbar(page, "listing/")
ctx = getctx("ok", listing=content, navbar=navbar,
menu=quar_menu("", request.user))
return HttpResponse(simplejson.dumps(ctx), mimetype="application/json")
@login_required
def index(request):
- return SQLlisting(request.user, None, None, empty=True).render(request)
+ return _render(request, "amavis_quarantine/index.html", dict(
+ deflocation="listing/", defcallback="listing_cb", selection="quarantine"
+ ))
@login_required
def getmailcontent(request, mail_id):
@@ -123,7 +124,7 @@ def getmailcontent(request, mail_id):
@login_required
def viewmail(request, mail_id):
- if not request.user.belongs_to_group('SimpleUsers'):
+ if request.user.group != 'SimpleUsers':
rcpt = request.GET["rcpt"]
else:
mb = Mailbox.objects.get(user=request.user)
@@ -137,7 +138,7 @@ def viewmail(request, mail_id):
args += ["%s=%s" % (kw, request.GET[kw])]
content = Template("""
-
+
""").render(Context({"url" : reverse(getmailcontent, args=[mail_id]) \
+ "?%s" % "&".join(args)}))
menu = viewm_menu("", __get_current_url(request), mail_id, rcpt,
@@ -152,6 +153,7 @@ def viewheaders(request, mail_id):
content += qm.mail_text
msg = email.message_from_string(content)
return _render(request, 'amavis_quarantine/viewheader.html', {
+ "title" : _("Message headers"),
"headers" : msg.items()
})
@@ -166,7 +168,7 @@ def check_mail_id(request, mail_id):
@login_required
def delete(request, mail_id):
mail_id = check_mail_id(request, mail_id)
- if request.user.belongs_to_group('SimpleUsers'):
+ if request.user.group == 'SimpleUsers':
mb = Mailbox.objects.get(user=request.user)
msgrcpts = Msgrcpt.objects.filter(mail__in=mail_id, rid__email=mb.full_address)
msgrcpts.update(rs='D')
@@ -186,7 +188,7 @@ def delete(request, mail_id):
@login_required
def release(request, mail_id):
mail_id = check_mail_id(request, mail_id)
- if request.user.belongs_to_group('SimpleUsers'):
+ if request.user.group == 'SimpleUsers':
mb = Mailbox.objects.get(user=request.user)
msgrcpts = Msgrcpt.objects.filter(mail__in=mail_id, rid__email=mb.full_address)
else:
diff --git a/extensions/webmail/imaputils.py b/extensions/webmail/imaputils.py
index cec5e83ab..ab74df89d 100644
--- a/extensions/webmail/imaputils.py
+++ b/extensions/webmail/imaputils.py
@@ -367,13 +367,13 @@ class IMAPconnector(object):
if len(topmailbox):
md_mailboxes = []
else:
- md_mailboxes = [{"name" : "INBOX", "class" : "inbox"},
+ md_mailboxes = [{"name" : "INBOX", "class" : "icon-home"},
{"name" : parameters.get_user(user, "DRAFTS_FOLDER"),
- "class" : "drafts"},
+ "class" : "icon-file"},
{"name" : 'Junk'},
{"name" : parameters.get_user(user, "SENT_FOLDER")},
{"name" : parameters.get_user(user, "TRASH_FOLDER"),
- "class" : "trash"}]
+ "class" : "icon-trash"}]
md_mailboxes += self._listfolders(topmailbox, md_mailboxes)
if unseen_messages:
for fd in md_mailboxes:
@@ -476,7 +476,10 @@ class IMAPconnector(object):
return
data = self._cmd("GETQUOTAROOT", self._encodefolder(mailbox))
- print data
+ if data is None:
+ self.quota_limit = self.quota_actual = None
+ return
+
quotadef = data[1][0]
m = re.match("[^\s]+ \(STORAGE (\d+) (\d+)\)", quotadef)
if not m:
diff --git a/extensions/webmail/templates/webmail/compose.html b/extensions/webmail/templates/webmail/compose.html
index 5091355d8..5284049c4 100644
--- a/extensions/webmail/templates/webmail/compose.html
+++ b/extensions/webmail/templates/webmail/compose.html
@@ -1,8 +1,8 @@
-{% load i18n %}
+{% load i18n libextras %}