diff --git a/extensions/amavis_quarantine/main.py b/extensions/amavis_quarantine/main.py
index 79758e3dd..f2ba4d2d4 100644
--- a/extensions/amavis_quarantine/main.py
+++ b/extensions/amavis_quarantine/main.py
@@ -8,6 +8,7 @@ import email
import re
import os
from django.http import HttpResponseRedirect, HttpResponse
+from django.template import Template, Context
from django.utils import simplejson
from django.conf.urls.defaults import *
from django.utils.translation import ugettext as _, ungettext
@@ -15,10 +16,11 @@ from django.core.urlresolvers import reverse
from django.contrib.auth.decorators \
import login_required
from mailng.lib import events, parameters
-from mailng.lib import _render, _ctx_ok, _ctx_ko, decode
+from mailng.lib import _render, _ctx_ok, _ctx_ko, decode, getctx
from mailng.lib import db
from mailng.admin.models import Mailbox
from lib import AMrelease
+from templatetags.amextras import *
from sql_listing import *
def init():
@@ -40,21 +42,71 @@ def menu(**kwargs):
return []
@login_required
-def index(request, message=None):
- start = time.time()
+def _listing(request, internal=False, filter=None):
+ #start = time.time()
if not request.user.is_superuser:
mb = Mailbox.objects.get(user=request.user.id)
- filter = ["&maddr.email='%s'" % mb.full_address]
+ if filter is None:
+ filter = ["&maddr.email='%s'" % mb.full_address]
+ else:
+ filter += ["&maddr.email='%s'" % mb.full_address]
+ pageid = request.GET.has_key("page") and int(request.GET["page"]) or 1
+ request.session["page"] = pageid # ?? nécessaire
+ lst = SQLlisting(filter, baseurl="listing/", empty=internal)
+ if internal:
+ return lst.render(request, pageid=int(pageid))
+ page = lst.paginator.getpage(pageid)
+ if page:
+ content = lst.fetch(request, page.id_start, page.id_stop)
+ navbar = lst.render_navbar(page)
else:
- filter = None
- try:
- pageid = request.GET["page"]
- if pageid == "":
- pageid = 1
- except KeyError:
- pageid = 1
- lst = SQLlisting(filter)
- return lst.render(request, pageid=int(pageid), start=start)
+ content = _("Empty quarantine")
+ navbar = ""
+ ctx = getctx("ok", listing=content, navbar=navbar,
+ menu=quar_menu("", request.user.get_all_permissions()))
+ return HttpResponse(simplejson.dumps(ctx), mimetype="application/json")
+
+@login_required
+def index(request, message=None):
+ return _listing(request, True)
+
+# @login_required
+# def getmailcontent(request, mail_id):
+# from mailng.lib.email_listing import Email
+
+# conn = db.getconnection("amavis_quarantine")
+# status, cursor = db.execute(conn, """
+# SELECT mail_text
+# FROM quarantine
+# WHERE quarantine.mail_id='%s'
+# """ % mail_id)
+# content = ""
+# for part in cursor.fetchall():
+# content += part[0]
+# msg = email.message_from_string(content)
+# links = request.GET.has_key("links") and request.GET["links"] or "0"
+# mode = request.GET.has_key("mode") and request.GET["mode"] or "plain"
+# mail = Email(msg, mode, links)
+# return mail.render(request)
+
+# @login_required
+# def viewmail(request, mail_id):
+# conn = db.getconnection("amavis_quarantine")
+# status, cursor = db.execute(conn, """
+# SELECT mail_text
+# FROM quarantine
+# WHERE quarantine.mail_id='%s'
+# """ % mail_id)
+# content = ""
+# for part in cursor.fetchall():
+# content += part[0]
+# msg = email.message_from_string(content)
+# ctx = getctx("ok", )
+# return _render(request, 'amavis_quarantine/viewmail.html', {
+# "headers" : msg, "alert" : msg.get("X-Amavis-Alert"),
+# "mail_id" : mail_id, "page_id" : request.session["page"],
+# "params" : request.GET
+# })
@login_required
def getmailcontent(request, mail_id):
@@ -73,25 +125,25 @@ WHERE quarantine.mail_id='%s'
links = request.GET.has_key("links") and request.GET["links"] or "0"
mode = request.GET.has_key("mode") and request.GET["mode"] or "plain"
mail = Email(msg, mode, links)
- return mail.render(request)
-
+ return _render(request, "common/viewmail.html", {
+ "headers" : "",
+ "mailbody" : mail.body,
+ "pre" : mail.pre
+ })
+
@login_required
def viewmail(request, mail_id):
- conn = db.getconnection("amavis_quarantine")
- status, cursor = db.execute(conn, """
-SELECT mail_text
-FROM quarantine
-WHERE quarantine.mail_id='%s'
-""" % mail_id)
- content = ""
- for part in cursor.fetchall():
- content += part[0]
- msg = email.message_from_string(content)
- return _render(request, 'amavis_quarantine/viewmail.html', {
- "headers" : msg, "alert" : msg.get("X-Amavis-Alert"),
- "mail_id" : mail_id, "page_id" : request.GET["page"],
- "params" : request.GET
- })
+ args = ""
+ for kw in ["mode", "links"]:
+ if kw in request.GET.keys():
+ args += args != "" and "&" or "?"
+ args += "%s=%s" % (kw, request.GET[kw])
+ content = Template("""
+
+""").render(Context({"url" : reverse(getmailcontent, args=[mail_id]) + args}))
+ menu = viewm_menu("", request.session, mail_id, request.user.get_all_permissions())
+ ctx = getctx("ok", menu=menu, listing=content)
+ return HttpResponse(simplejson.dumps(ctx), mimetype="application/json")
@login_required
def viewheaders(request, mail_id):
@@ -129,7 +181,9 @@ def delete(request, mail_id, count=1):
count) % {"count" : count}
else:
message = error
- return _redirect_to_index(request, message, count)
+ ctx = getctx("ok", url="?page=%s" % request.session["page"], message=message)
+ return HttpResponse(simplejson.dumps(ctx),
+ mimetype="application/json")
@login_required
def release(request, mail_id, count=1):
@@ -152,13 +206,6 @@ WHERE msgrcpt.mail_id=msgs.mail_id AND msgrcpt.rid=maddr.id AND msgs.mail_id IN
error = None
for k, values in emails.iteritems():
result = amr.sendreq(k, values["secret"], *values["rcpts"])
-# cmd = "/tmp/amavisd-release "
-# cmd += "%s %s" % (k, values["secret"])
-# for rcpt in values["rcpts"]:
-# cmd += " %s" % rcpt
-# cmd += "\n"
-# result = os.system(cmd)
-# if re.search("250 [^\s]+ Ok", result):
if result:
count += 1
else:
@@ -170,7 +217,9 @@ WHERE msgrcpt.mail_id=msgs.mail_id AND msgrcpt.rid=maddr.id AND msgs.mail_id IN
count) % {"count" : count}
else:
message = error
- return _redirect_to_index(request, message, count)
+ ctx = getctx("ok", url="?page=%s" % request.session["page"], message=message)
+ return HttpResponse(simplejson.dumps(ctx),
+ mimetype="application/json")
@login_required
def process(request):
@@ -182,19 +231,13 @@ def process(request):
ids += "'%s'" % id
if ids == "":
return HttpResponseRedirect(reverse(index))
+
+ print "Ok c pas vide"
if request.POST["action"] == "release":
- release(request, ids, count)
+ return release(request, ids, count)
if request.POST["action"] == "delete":
- delete(request, ids, count)
-
- try:
- pagenum = int(request.POST.get('pagenum', '1'))
- except ValueError:
- pagenum = 1
- ctx = _ctx_ok(reverse(index) + "?page=%s" % pagenum)
- return HttpResponse(simplejson.dumps(ctx),
- mimetype="application/json")
+ return delete(request, ids, count)
@login_required
def search(request):
@@ -211,19 +254,16 @@ def search(request):
filter += " OR "
filter += "msgs.%s LIKE '%%%s%%'" % (c, pattern)
filter = "&(%s)" % filter
- lst = SQLlisting([filter])
- try:
- pageid = request.GET["page"]
- if pageid == "":
- pageid = 1
- except KeyError:
- pageid = 1
- page = lst.paginator.getpage(pageid)
- if page:
- content = lst.fetch(page.id_start, page.id_stop).render(request)
- navbar = lst.render_navbar(page)
- else:
- content = "Empty quarantine"
- navbar = ""
- ctx = {"status" : "ok", "listing" : content, "navbar" : navbar}
- return HttpResponse(simplejson.dumps(ctx), mimetype="application/json")
+ return _listing(request, filter=filter)
+
+# lst = SQLlisting([filter])
+
+# page = lst.paginator.getpage(1)
+# if page:
+# content = lst.fetch(page.id_start, page.id_stop).render(request)
+# navbar = lst.render_navbar(page)
+# else:
+# content = "Empty quarantine"
+# navbar = ""
+# ctx = {"status" : "ok", "listing" : content, "navbar" : navbar}
+# return HttpResponse(simplejson.dumps(ctx), mimetype="application/json")
diff --git a/extensions/amavis_quarantine/sql_listing.py b/extensions/amavis_quarantine/sql_listing.py
index fe24843a8..d7f83f1d0 100644
--- a/extensions/amavis_quarantine/sql_listing.py
+++ b/extensions/amavis_quarantine/sql_listing.py
@@ -6,6 +6,7 @@ from mailng.lib import tables, db
from mailng.lib.email_listing import MBconnector, EmailListing
class Qtable(tables.Table):
+ tableid = "emails"
idkey = "mailid"
selection = tables.SelectionColumn("selection", first=True)
type = tables.Column("type", label=_("Type"))
@@ -83,6 +84,8 @@ LIMIT %d,%d
class SQLlisting(EmailListing):
tpl = "amavis_quarantine/index.html"
tbltype = Qtable
+ deflocation = "listing/"
+ defcallback = "updatelisting"
def __init__(self, filter, **kwargs):
self.mbc = SQLconnector(filter)
diff --git a/extensions/amavis_quarantine/templates/index.html b/extensions/amavis_quarantine/templates/index.html
index 3d780c5d7..bd95702b6 100644
--- a/extensions/amavis_quarantine/templates/index.html
+++ b/extensions/amavis_quarantine/templates/index.html
@@ -3,9 +3,10 @@
{% load amextras %}
{% block css %}
#searchbox {
- float: left;
+ /*float: left;*/ /* Marche pas ici?! obligé de le faire en JS sous FF */
margin-right: 10px;
- width: 250px;
+ z-index: 2;
+ position: relative;
}
#searchbox img {
@@ -17,87 +18,137 @@
#searchparams {
background: white;
padding: 5px;
- width: 150px;
+ width: 90%;
+ border-bottom: 5px solid #CCCCCC;
+ border-left: 5px solid #CCCCCC;
+ border-right: 5px solid #CCCCCC;
+}
+
+thead tr {
+ position: relative;
+ z-index: 1;
}
{% endblock %}
{% block js %}
-mysubmit = function(event, name) {
- event.stop();
- new Element('input', {
- 'type' : 'hidden', 'name' : "action", style: "display:none", 'value' : name
- }).inject($("listingform"), "top");
- {% url extensions.amavis_quarantine.main.process as actionurl %}
- $("listingform").set("action", "{{ actionurl }}");
- $("listingform").set("send", {
+ mysubmit = function(event, name) {
+ event.stop();
+ new Element('input', {
+ 'type' : 'hidden', 'name' : "action", style: "display:none", 'value' : name
+ }).inject($("listingform"), "top");
+ {% url extensions.amavis_quarantine.main.process as actionurl %}
+ $("listingform").set("action", "{{ actionurl }}");
+ $("listingform").set("send", {
onSuccess : function(res) {
- response = JSON.decode(res);
- location.href = response.url;
+ response = JSON.decode(res);
+ actioncallback(response);
+ }
+ });
+ $("listingform").send();
+ }
+
+ updatehash = function(evt) {
+ evt.stop();
+ current_anchor.parse_string(evt.target.get("href"), true).setparams(navparams);
+ current_anchor.update();
+ }
+
+ appendhash = function(evt) {
+ evt.stop();
+ location.hash += evt.target.get("href");
+ }
+
+ updateparams = function(evt) {
+ evt.stop();
+ current_anchor.updateparams(evt.target.get("href"));
+ current_anchor.update();
+ }
+
+ register_callback("_listing", function(resp) {
+ updatelisting(resp);
+ $$("a[name=release]").addEvent("click", function(event) {
+ if (!checkSelection("selection", "{% trans "Release this selection?" %}")) {
+ event.stop();
+ return;
+ }
+ mysubmit(event, "release");
+ });
+ $$("a[name=delete]").addEvent("click", function(event) {
+ if (!checkSelection("selection", "{% trans "Delete this selection?" %}")) {
+ event.stop();
+ return;
+ }
+ mysubmit(event, "delete");
+ });
+
+ var myFx = new Fx.Slide($("searchparams"));
+ myFx.hide();
+ $("searchopts").addEvent("click", function(event) {
+ myFx.cancel();
+ myFx.toggle();
+ });
+ $$("input[name=scriteria]").addEvent("click", function(event) {
+ myFx.cancel();
+ myFx.toggle();
+ });
+ $("searchfield").addEvent("change", function(event) {
+ var criteria = "";
+ $$("input[name=scriteria]:checked").each(function(obj) {
+ criteria = obj.value;
+ });
+ var url = "search"
+ + "?pattern=" + $("searchfield").value
+ + "&criteria=" + criteria;
+ current_anchor.parse_string(url, true).setparams(navparams);
+ current_anchor.update();
+
+ /*new Request.JSON({url: "{{ s_url }}", onSuccess: function(resp) {
+ $("listing").set("html", resp.listing);
+ $("navbar").set("html", resp.navbar);
+ {% url extensions.amavis_quarantine.main.viewmail as view_url %}
+ bindRows("{{ view_url }}", "{{ current_page }}");
+ }}).get({"pattern" : $("searchfield").value, "criteria" : criteria});*/
+ });
+ $("searchfield").addEvent("click", function(event) {
+ $("searchfield").select();
+ });
+
+ $("searchfield").addEvent("blur", function(event) {
+ if ($("searchfield").value == "") {
+ $("searchfield").set("value", "{% trans "Search..." %}");
+ }
+ });
+ $("searchbox").setStyle("float", "left");
+ $$("tr").addEvent("dblclick", viewmail);
+ });
+
+ actioncallback = function(resp) {
+ $("listing").set("html", "");
+ $("menubar").set("html", "");
+ $("navbar").set("html", "");
+ if (resp.status == "ok") {
+ infobox.show(resp.message, "green", 1);
+ } else {
+ infobox.show(resp.message, "red", 1);
}
+ current_anchor.parse_string(resp.url, true).setparams(navparams);
+ current_anchor.update(1);
+ }
+
+ actionclick = function(evt) {
+ evt.stop();
+ new Request.JSON({
+ url: evt.target.get("href"),
+ onSuccess: actioncallback
+ }).get();
+ }
+
+ register_callback("viewmail", function(resp) {
+ updatelisting(resp);
+ $$("a[name=back]").addEvent("click", updatehash);
+ $$("a[name=delete]").addEvent("click", actionclick);
+ $$("a[name=release]").addEvent("click", actionclick);
+ $$("a[name=viewmode]").addEvent("click", updateparams);
+ setDivHeight("mailcontent", 5, 0);
});
- $("listingform").send();
-}
-
-$$("a[name=delete]").addEvent("click", function(event) {
- if (!checkSelection("selection", "{% trans "Delete this selection?" %}")) {
- event.stop();
- return;
- }
- mysubmit(event, "delete");
-});
-$$("a[name=release]").addEvent("click", function(event) {
- if (!checkSelection("selection", "{% trans "Release this selection?" %}")) {
- event.stop();
- return;
- }
- mysubmit(event, "release");
-});
-
-
-var myFx = new Fx.Slide($("searchparams"));
-myFx.hide();
-$("searchopts").addEvent("click", function(event) {
- myFx.cancel();
- myFx.toggle();
-});
-$$("input[name=scriteria]").addEvent("click", function(event) {
- myFx.cancel();
- myFx.toggle();
-});
-$("searchfield").addEvent("change", function(event) {
- var criteria = "";
- $$("input[name=scriteria]:checked").each(function(obj) {
- criteria = obj.value;
- });
- {% url extensions.amavis_quarantine.main.search as s_url %}
- new Request.JSON({url: "{{ s_url }}", onSuccess: function(resp) {
- $("listing").set("html", resp.listing);
- $("navbar").set("html", resp.navbar);
- {% url extensions.amavis_quarantine.main.viewmail as view_url %}
- bindRows("{{ view_url }}", "{{ current_page }}");
- }}).get({"pattern" : $("searchfield").value, "criteria" : criteria});
-});
-$("searchfield").addEvent("click", function(event) {
- $("searchfield").select();
-});
-
-$("searchfield").addEvent("blur", function(event) {
- if ($("searchfield").value == "") {
- $("searchfield").set("value", "{% trans "Search..." %}");
- }
-});
-{% url extensions.amavis_quarantine.main.viewmail as view_url %}
-bindRows("{{ view_url }}", "{{ current_page }}");
{% endblock %}
{% block middletitle %}{% trans "Quarantine" %}{% endblock %}
-{% block menu %}
- {% quar_menu "" perms %}
-
-{% endblock %}
diff --git a/extensions/amavis_quarantine/templates/viewmail.html b/extensions/amavis_quarantine/templates/viewmail.html
index d1f9c0539..351418ee3 100644
--- a/extensions/amavis_quarantine/templates/viewmail.html
+++ b/extensions/amavis_quarantine/templates/viewmail.html
@@ -26,6 +26,8 @@ window.addEvent("domready", function() {
var iheight = spage.y - stable.y - slogo.y;
$("mailcontent").setStyle("height", iheight + "px");
+ parse_menubar("menubar");
+
});
diff --git a/extensions/amavis_quarantine/templatetags/amextras.py b/extensions/amavis_quarantine/templatetags/amextras.py
index 5a4aaf1f9..62cf4b7e1 100644
--- a/extensions/amavis_quarantine/templatetags/amextras.py
+++ b/extensions/amavis_quarantine/templatetags/amextras.py
@@ -7,25 +7,22 @@ from mailng.extensions import amavis_quarantine
register = template.Library()
@register.simple_tag
-def viewm_menu(selection, mail_id, page_id, perms):
+def viewm_menu(selection, session, mail_id, perms):
options_menu = [
- {"name" : "plain",
+ {"name" : "viewmode",
"label" : _("View as plain text"),
- "url" : reverse(amavis_quarantine.main.viewmail, args=[mail_id])
- + "?page=%s&mode=plain" % page_id},
- {"name" : "html",
+ "url" : "?mode=plain&links=0"},
+ {"name" : "viewmode",
"label" : _("View as HTML"),
- "url" : reverse(amavis_quarantine.main.viewmail, args=[mail_id])
- + "?page=%s&mode=html" % page_id},
- {"name" : "links",
+ "url" : "?mode=html&links=0"},
+ {"name" : "viewmode",
"label" : _("Activate links"),
- "url" : reverse(amavis_quarantine.main.viewmail, args=[mail_id])
- + "?page=%s&mode=html&links=1" % page_id}
+ "url" : "?mode=html&links=1"}
]
entries = [
{"name" : "back",
- "url" : reverse(amavis_quarantine.main.index) + "?page=%s" % page_id,
+ "url" : "?page=%s" % session["page"],
"img" : "/static/pics/back.png",
"label" : _("Back to list")},
{"name" : "headers",
@@ -35,20 +32,19 @@ def viewm_menu(selection, mail_id, page_id, perms):
"class" : "boxed",
"rel" : "{handler:'iframe',size:{x:600,y:500}}"},
{"name" : "release",
- "url" : reverse(amavis_quarantine.main.release, args=[mail_id])
- + "?page=%s" % page_id,
+ "url" : reverse(amavis_quarantine.main.release, args=[mail_id]),
"img" : "/static/pics/release.png",
"label" : _("Release"),
"confirm" : _("Release this message?")},
{"name" : "delete",
- "url" : reverse(amavis_quarantine.main.delete, args=[mail_id])
- + "?page=%s" % page_id,
+ "url" : reverse(amavis_quarantine.main.delete, args=[mail_id]),
"img" : "/static/pics/remove.png",
"label" : _("Delete"),
"confirm" : _("Delete this message?")},
{"name" : "options",
"label" : _("Options"),
"img" : "/static/pics/settings.png",
+ "class" : "menubardropdown",
"menu" : options_menu}
]
@@ -69,6 +65,8 @@ def quar_menu(selection, perms):
"label" : _("Delete")},
]
- return render_to_string('main/menu.html',
+ menu = render_to_string('main/menu.html',
{"selection" : selection, "entries" : entries,
"perms" : perms})
+ searchbar = render_to_string('common/email_searchbar.html', {})
+ return menu + searchbar
diff --git a/extensions/amavis_quarantine/urls.py b/extensions/amavis_quarantine/urls.py
index 06806aa1f..303885bda 100644
--- a/extensions/amavis_quarantine/urls.py
+++ b/extensions/amavis_quarantine/urls.py
@@ -2,13 +2,12 @@ from django.conf.urls.defaults import *
urlpatterns = patterns('mailng.extensions.amavis_quarantine.main',
(r'^$', 'index'),
- url(r'^viewmail/(?P[\w\-\+]+)/$', 'viewmail',
- name="viewmail_std"),
- url(r'^viewmail/$', 'viewmail', name="viewmail_null"),
+ (r'^listing/$', '_listing'),
(r'^getmailcontent/(?P[\w\-\+]+)/$', 'getmailcontent'),
- (r'^viewheaders/(?P[\w\-\+]+)/$', 'viewheaders'),
+ (r'^(?P[\w\-\+]+)/headers/$', 'viewheaders'),
(r'^process/$', 'process'),
(r'^delete/(?P[\w\-\+]+)/$', 'delete'),
(r'^release/(?P[\w\-\+]+)/$', 'release'),
(r'^search/', 'search'),
+ (r'^(?P[\w\-\+]+)/$', 'viewmail'),
)
diff --git a/extensions/webmail/imap_listing.py b/extensions/webmail/imap_listing.py
index a09c55aa8..311c8b47a 100644
--- a/extensions/webmail/imap_listing.py
+++ b/extensions/webmail/imap_listing.py
@@ -248,12 +248,12 @@ class IMAPconnector(object):
class ImapListing(EmailListing):
tpl = "webmail/index.html"
tbltype = WMtable
+ deflocation = "INBOX/"
+ defcallback = "wm_updatelisting"
- def __init__(self, user, password, baseurl=None, **kwargs):
+ def __init__(self, user, password, **kwargs):
self.mbc = IMAPconnector(user=user, password=password)
- EmailListing.__init__(self, **kwargs)
- if baseurl:
- self.paginator.baseurl = baseurl
+ EmailListing.__init__(self, **kwargs)
def getfolders(self):
md_folders = [{"name" : "INBOX", "icon" : "overview.png"},
diff --git a/extensions/webmail/main.py b/extensions/webmail/main.py
index bb1a4158c..4ad2eb26c 100644
--- a/extensions/webmail/main.py
+++ b/extensions/webmail/main.py
@@ -10,7 +10,7 @@ from django.core.urlresolvers import reverse
from django.conf.urls.defaults import include
from django.contrib.auth.decorators import login_required
from mailng.admin.models import Mailbox
-from mailng.lib import events, parameters, _render, _render_error
+from mailng.lib import events, parameters, _render, _render_error, getctx
from imap_listing import *
from forms import *
from templatetags.webextras import *
@@ -51,13 +51,6 @@ def menu(**kwargs):
def userlogin(**kwargs):
kwargs["request"].session["password"] = kwargs["password"]
-def getctx(status, level=1, **kwargs):
- callername = sys._getframe(level).f_code.co_name
- ctx = {"status" : status, "callback" : callername}
- for kw, v in kwargs.iteritems():
- ctx[kw] = v
- return ctx
-
@login_required
def folder(request, name, updatenav=True):
if not name:
@@ -76,7 +69,7 @@ def folder(request, name, updatenav=True):
order = request.session["navparams"]["order"]
lst = ImapListing(request.user.username, request.session["password"],
- name, folder=name, order=order)
+ baseurl=name, folder=name, order=order)
page = lst.paginator.getpage(request.session["page"])
if page:
content = lst.fetch(request, page.id_start, page.id_stop)
@@ -94,10 +87,11 @@ def index(request):
navp = request.session.has_key("navparams") \
and request.session["navparams"] or {}
lst = ImapListing(request.user.username, request.session["password"],
- "INBOX", navparams=navp, folder="INBOX")
+ baseurl="INBOX", navparams=navp, folder="INBOX",
+ empty=True)
except Exception as exp:
return _render_error(request, {"error" : exp})
- return lst.render(request, empty=True)
+ return lst.render(request)
def fetchmail(request, folder, mail_id, all=False):
res = IMAPconnector(request).fetch(start=mail_id, folder=folder, all=all)
@@ -128,7 +122,7 @@ def getmailcontent(request, folder, mail_id):
except KeyError:
pageid = "1"
folder, imapid = msg["imapid"].split("/")
- return _render(request, "webmail/viewmail.html", {
+ return _render(request, "common/viewmail.html", {
"headers" : email.render_headers(folder, mail_id),
"folder" : folder, "imapid" : imapid, "mailbody" : email.body,
"pre" : email.pre
@@ -270,7 +264,7 @@ def reply(request, folder, mail_id):
else:
form.fields["subject"].initial = "Re: %s" % email.Subject
textheader = "%s %s" % (email.From, _("wrote:"))
- return render_compose(request, form, reverse(reply, args[folder, mail_id]),
+ return render_compose(request, form, reverse(reply, args=[folder, mail_id]),
textheader, body)
@login_required
diff --git a/extensions/webmail/templates/index.html b/extensions/webmail/templates/index.html
index 9bbf339a4..3818c77c7 100644
--- a/extensions/webmail/templates/index.html
+++ b/extensions/webmail/templates/index.html
@@ -1,6 +1,20 @@
{% extends "common/email_listing.html" %}
{% load i18n %}
{% block css %}
+#listing {
+ position: absolute;
+ left: 155px;
+ right: 0px;
+ top: 130px;
+ height: expression(document.body.clientHeight - 35 + "px");
+ overflow: auto;
+}
+
+html > body #listing {
+ position: fixed;
+ bottom: 35px;
+}
+
#leftcol {
float: left;
width: 150px;
@@ -97,22 +111,9 @@ tr.selected {
{% endblock %}
{% block js %}
- navparams = new Hash({
- {% for k, v in navparams.items %}
- {{ k }} : "{{ v }}",
- {% endfor %}
- });
+ wm_updatelisting = function(resp) {
+ updatelisting(resp);
- updatelisting = function(resp) {
- if ($defined(resp.menu)) {
- $("menubar").set("html", resp.menu);
- parse_menubar("menubar");
- }
- $("listing").set("html", resp.listing);
- if ($defined(resp.navbar)) {
- $("navbar").set("html", resp.navbar);
- $("navbar").getChildren("a").addEvent("click", navbarcallback);
- }
$$("a[name=compose]").addEvent("click", loadCompose);
$$("a[name=empty]").addEvent("click", empty);
if (!checkSelection()) {
@@ -123,7 +124,7 @@ tr.selected {
empty = function(event) {
event.stop();
new Request.JSON({url : event.target.get("href"), onSuccess : function(resp) {
- updatelisting(resp);
+ wm_updatelisting(resp);
}}).get();
}
@@ -147,17 +148,8 @@ tr.selected {
obj.getParent().addClass("selected");
}
- {% url extensions.webmail.main.folder as view_url %}
- viewmail = function(event) {
- event.stop();
- if (event.target.parentNode.id) {
- var url = event.target.parentNode.id + "/";
- event.target.parentNode.setStyle("background", "#ffffcc");
- current_anchor.baseurl(url).update();
- }
- }
register_callback("viewmail", function(resp) {
- updatelisting(resp, "hidden");
+ wm_updatelisting(resp, "hidden");
$$("a[name=back]").addEvent("click", loadFolder);
$$("a[name=reply]").addEvent("click", reply);
$$("a[name=replyall]").addEvent("click", replyall);
@@ -173,7 +165,7 @@ tr.selected {
});
compose_callback = function(resp) {
- updatelisting(resp);
+ wm_updatelisting(resp);
window.addEvent("resize", function(evt) {
setDivHeight("id_body", $("mailheader").getSize().y, 0);
});
@@ -184,7 +176,7 @@ tr.selected {
onSuccess: function(resp) {
resp = JSON.decode(resp);
if (resp.status == "ko") {
- updatelisting(resp);
+ wm_updatelisting(resp);
window.fireEvent("resize");
return;
}
@@ -228,7 +220,7 @@ tr.selected {
current_anchor.update();
}
register_callback("folder", function(resp) {
- updatelisting(resp);
+ wm_updatelisting(resp);
if (navparams.has("order")) {
src = navparams.get("order").charAt(0) == "-" ? "down_arrow.png" : "up_arrow.png";
th = $$("th[id=" + navparams.get("order").substring(1) + "]");
@@ -341,18 +333,10 @@ tr.selected {
});
});
- navbarcallback = function(event) {
- event.stop();
- current_anchor.setparams(navparams);
- current_anchor.parse_string(event.target.getParent().get("href")).update();
- }
-
foldercallback = function(event) {
select(event.target);
loadFolder(event, event.target);
}
-
- ajaxListener("INBOX/", updatelisting);
$$("a[name=loadfolder]").addEvent("click", foldercallback);
{% endblock %}
{% block middletitle %}{% trans "Webmail" %}{% endblock %}
@@ -374,3 +358,6 @@ tr.selected {
{% endblock %}
+{% block menu %}
+
+{% endblock %}
diff --git a/extensions/webmail/templatetags/webextras.py b/extensions/webmail/templatetags/webextras.py
index f36817730..f15d3488b 100644
--- a/extensions/webmail/templatetags/webextras.py
+++ b/extensions/webmail/templatetags/webextras.py
@@ -75,6 +75,17 @@ def listing_menu(selection, folder, perms):
"url" : reverse(webmail.main.compose),
"img" : "/static/pics/edit.png",
"label" : _("New message")},
+ {"name" : "actions",
+ "img" : "/static/pics/domains.png",
+ "label" : _("Mark messages"),
+ "class" : "menubardropdown",
+ "menu" : [
+ {"name" : "mark-read",
+ "label" : _("As read")},
+ {"name" : "mark-unread",
+ "label" : _("As unread")}
+ ]
+ }
]
if folder in ["Trash"]:
entries += [
diff --git a/lib/__init__.py b/lib/__init__.py
index c2582c4bd..581f964d3 100644
--- a/lib/__init__.py
+++ b/lib/__init__.py
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
import popen2
import os
+import sys
import time
from django.conf import settings
from django.template import RequestContext
@@ -67,6 +68,16 @@ def _ctx_ok(url):
def _ctx_ko(tpl, ctx):
return {"status" : "ko", "content" : render_to_string(tpl, ctx)}
+def getctx(status, level=1, callback=None, **kwargs):
+ if not callback:
+ callername = sys._getframe(level).f_code.co_name
+ else:
+ callername = callback
+ ctx = {"status" : status, "callback" : callername}
+ for kw, v in kwargs.iteritems():
+ ctx[kw] = v
+ return ctx
+
def decode(s, encodings=('utf8', 'latin1', 'windows-1252', 'ascii')):
for encoding in encodings:
try:
diff --git a/lib/email_listing.py b/lib/email_listing.py
index 5d77853f6..0d8b337a0 100644
--- a/lib/email_listing.py
+++ b/lib/email_listing.py
@@ -83,16 +83,23 @@ class Paginator(object):
return p
class EmailListing:
- def __init__(self, folder=None, elems_per_page=40, navparams={}, **kwargs):
+ def __init__(self, baseurl=None, folder=None, elems_per_page=40,
+ navparams={}, **kwargs):
self.folder = folder
self.elems_per_page = elems_per_page
self.navparams = navparams
order = "order" in kwargs.keys() and kwargs["order"] or None
- self.paginator = Paginator(self.mbc.messages_count(folder=self.folder,
- order=order),
- elems_per_page)
+ self.empty = "empty" in kwargs.keys() and kwargs["empty"] or False
+ if not self.empty:
+ self.paginator = Paginator(self.mbc.messages_count(folder=self.folder,
+ order=order),
+ elems_per_page)
+ if baseurl:
+ self.paginator.baseurl = baseurl
def render_navbar(self, page):
+ if page is None:
+ return ""
return render_to_string("common/navbar.html", {
"page" : page
})
@@ -110,9 +117,10 @@ class EmailListing:
return tpl.render(Context({"table" : table.render(request)}))
def render(self, request, pageid=1, **kwargs):
- page = self.paginator.getpage(pageid)
- thead = listing = ""
- if "empty" in kwargs.keys() and not kwargs["empty"]:
+ listing = ""
+ page = None
+ if not self.empty:
+ page = self.paginator.getpage(pageid)
if not page:
listing = "Empty folder"
else:
@@ -125,7 +133,7 @@ class EmailListing:
"folders" : self.getfolders(),
"selection" : self.folder,
"navparams" : self.navparams,
- "current_page" : pageid
+ "deflocation" : self.deflocation, "defcallback" : self.defcallback
})
class Email(object):
diff --git a/lib/tables.py b/lib/tables.py
index 3a3e07f33..6d64b8bb2 100644
--- a/lib/tables.py
+++ b/lib/tables.py
@@ -55,16 +55,21 @@ class Table(object):
for row in rows:
nrow = {"id" : row[self.idkey], "cols" : []}
for c in self.columns:
+ newcol = {}
+ try:
+ newcol["width"] = getattr(c, "width")
+ except AttributeError:
+ pass
if isinstance(c, SelectionColumn):
- nrow["cols"] += [{"value" : c.render(row[self.idkey]), "safe" : True}]
- continue
+ newcol["value"] = c.render(row[self.idkey])
+ newcol["safe"] = True
+
if isinstance(c, ImgColumn):
key = "img_%s" % c.name
if key in row.keys():
- nrow["cols"] += [{"value" : c.render(row[key]), "safe" : True, "width" : c.width}]
- else:
- nrow["cols"] += [{"width" : c.width}]
- continue
+ newcol["value"] = c.render(row[key])
+ newcol["safe"] = True
+
if row.has_key(c.name):
try:
cssclass = getattr(c, "cssclass")
@@ -72,10 +77,9 @@ class Table(object):
cssclass = ""
if "class" in row.keys():
cssclass += (cssclass != "") and ", %s" % row["class"] or row["class"]
-
- nrow["cols"] += [{"value" : self.parse(c.name, row[c.name]),
- "class" : cssclass,
- "width" : c.width}]
+ newcol["value"] = self.parse(c.name, row[c.name])
+ newcol["class"] = cssclass
+ nrow["cols"] += [newcol]
self.rows += [nrow]
def render(self, request):
diff --git a/static/js/common.js b/static/js/common.js
index 2f64d6e4e..4f9be35e5 100644
--- a/static/js/common.js
+++ b/static/js/common.js
@@ -3,6 +3,12 @@ window.addEvent('domready', function(){
SqueezeBox.assign($$('a.boxed'), {
parse: 'rel',
});
+
+
+ infobox = new InfoBox({
+ parent : $("menubar"),
+ message : "Loading"
+ });
});
callbacks = {};
@@ -18,18 +24,23 @@ get_callback = function(name) {
current_anchor = null;
check_anchor = function() {
- if (current_anchor.serialized == location.hash) {
+ if (current_anchor.serialized == location.hash
+ && !$defined(current_anchor.force)) {
return;
}
+ delete(current_anchor.force);
current_anchor.from_string(location.hash);
if (!current_anchor.serialized) {
query = current_anchor.deflocation;
} else {
query = current_anchor.serialized.substring(1);
}
+ infobox.show("Loading...", "gray");
new Request.JSON({url: query, onSuccess: function(resp) {
callback = ($defined(resp.callback)) ? resp.callback : "default";
callbacks[callback](resp);
+ infobox.notice("Done");
+ infobox.hide(1);
}}).get();
}
@@ -96,8 +107,26 @@ function HashWrapper(deflocation) {
return res;
};
- this.update = function() {
+ this.update = function(force) {
location.hash = this.serialize();
+ if ($defined(force)) {
+ this.force = force;
+ }
+ };
+
+ this.updateparams = function(str) {
+ if (str.charAt(0) == '?') {
+ str = str.substring(1);
+ }
+ var elems = str.split('&');
+ for (var i = 0; i < elems.length; i++) {
+ this.setparamfromstring(elems[i]);
+ }
+ };
+
+ this.setparamfromstring = function(str) {
+ var def = str.split('=');
+ this.params.set(def[0], def[1]);
};
this.setparam = function(name, value) {
@@ -158,6 +187,9 @@ parse_menubar = function(id) {
}
});
});
+ SqueezeBox.assign($$('a.boxed'), {
+ parse: 'rel',
+ });
}
}
diff --git a/static/js/infobox.js b/static/js/infobox.js
new file mode 100644
index 000000000..9852af96b
--- /dev/null
+++ b/static/js/infobox.js
@@ -0,0 +1,105 @@
+var InfoBox = new Class({
+ Implements: [Options, Events],
+ options: {
+ parent : null,
+ message : "This is my info box!",
+ width : 200,
+ },
+
+ profiles: {
+ gray : {"background" : "#EEEEEE", "border" : "#CCCCCC"},
+ green : {"background" : "#DAF8DA", "border" : "#166D14"},
+ red : {"background" : "#F9D2D2", "border" : "#FF2A00"},
+ yellow : {"background" : "#FDE6B5", "border" : "#FF7F00"}
+ },
+
+ initialize: function(options) {
+ this.setOptions(options);
+
+ var boxleft = document.body.getSize().x / 2 - this.options.width / 2;
+ this.box = new Element("div", {"id" : "infobox"});
+ this.box.setStyles({
+ "font-size" : "normal",
+ "font-weight" : "bold",
+ "text-align" : "left",
+ "width" : this.options. width + "px",
+ "padding" : "10px",
+ "position" : "absolute",
+ "top" : "0px",
+ "left" : boxleft + "px",
+ "display" : "none"
+ });
+ this.setProfile("gray");
+ this.spinner = new Element("img", {
+ "src" : "/static/stylesheets/spinner.gif"
+ });
+ this.spinner.setStyle("float", "left");
+ this.spinner.inject(this.box);
+
+ this.label = new Element("label").set("html", this.options.message);
+ this.label.setStyles({
+ "margin-left" : "10px"
+ });
+ this.label.inject(this.box);
+ this.box.inject(document.body);
+ },
+
+ setMessage: function(text) {
+ this.label.set("html", text);
+ },
+
+ setProfile: function(color) {
+ this.box.setStyles({
+ "background" : this.profiles[color].background,
+ "border" : "2px solid " + this.profiles[color].border
+ });
+ },
+
+ notice: function(message) {
+ this.setProfile("green");
+ this.setMessage(message);
+ },
+
+ error: function(message) {
+ this.setProfile("red");
+ this.setMessage(message);
+ },
+
+ warning: function(message) {
+ this.setProfile("yellow");
+ this.setMessage(message);
+ },
+
+ show: function(message, prof, delay) {
+ if ($defined(this.start)) {
+ if ($time() - this.start > this.delay) {
+ $clear(this.showtimer);
+ delete(this.start);
+ delete(this.delay);
+ } else {
+ this.showtimer = this.show.delay(100, this, [message, prof]);
+ return;
+ }
+ }
+ if ($defined(message)) {
+ this.setMessage(message);
+ }
+ if ($defined(prof)) {
+ this.setProfile(prof);
+ }
+ if ($defined(delay)) {
+ this.start = $time();
+ this.delay = delay * 1000;
+ }
+ this.box.setStyle("display", "block");
+ },
+
+ hide: function(timer) {
+ if ($defined(timer)) {
+ this.timer = this.hide.periodical(timer * 1000, this);
+ return;
+ }
+ $clear(this.timer);
+ this.box.setStyle("display", "none");
+ },
+});
\ No newline at end of file
diff --git a/static/stylesheets/default.css b/static/stylesheets/default.css
index 809492b69..61e1b46e2 100644
--- a/static/stylesheets/default.css
+++ b/static/stylesheets/default.css
@@ -177,11 +177,11 @@ div#footer {
border-left: 5px solid #ccc;
}
-.left {
+div.left {
float: left;
}
-.right {
+div.right {
float: right;
}
diff --git a/templates/common/email_listing.html b/templates/common/email_listing.html
index e0c19ef14..10f1abd1e 100644
--- a/templates/common/email_listing.html
+++ b/templates/common/email_listing.html
@@ -2,20 +2,6 @@
{% load i18n %}
{% block html_head %}
{% endblock %}
@@ -55,5 +75,5 @@ window.addEvent("domready", function() {
{{ listing }}
{% endblock %}
-{% block footer %}{% endblock %}
+{% block footer %}{{ navbar }}
{% endblock %}
diff --git a/templates/common/email_searchbar.html b/templates/common/email_searchbar.html
new file mode 100644
index 000000000..99b7e9f9f
--- /dev/null
+++ b/templates/common/email_searchbar.html
@@ -0,0 +1,10 @@
+{% load i18n %}
+
diff --git a/extensions/webmail/templates/viewmail.html b/templates/common/viewmail.html
similarity index 100%
rename from extensions/webmail/templates/viewmail.html
rename to templates/common/viewmail.html
diff --git a/templates/nlayout.html b/templates/nlayout.html
index 683576397..ad3092f79 100644
--- a/templates/nlayout.html
+++ b/templates/nlayout.html
@@ -13,6 +13,7 @@
+
{% url django.views.i18n.javascript_catalog as catalog_url %}