mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-18 05:51:26 +02:00
Quarantine plugin refactoring. It is now working like the webmail plugin, ie with an anchor based ajax navigation. What is broken for the moment:
* search functionality, * headers do not appear while displaying a mail. New message system. (see infobox.js)
This commit is contained in:
@@ -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("""
|
||||
<iframe width="100%" frameBorder="0" src="{{ url }}" id="mailcontent"></iframe>
|
||||
""").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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 %}
|
||||
<div id="searchbox">
|
||||
<img src="/static/pics/search.png" id="searchopts" />
|
||||
<input type="text" name="searchfield" id="searchfield" value="{% trans "Search..." %}" />
|
||||
<div id="searchparams">
|
||||
<input type="radio" name="scriteria" value="from_addr" checked>{% trans "From address" %}<br/>
|
||||
<input type="radio" name="scriteria" value="subject">{% trans "Subject" %}<br/>
|
||||
<input type="radio" name="scriteria" value="from_addr,subject">{% trans "Both" %}<br/>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -26,6 +26,8 @@ window.addEvent("domready", function() {
|
||||
var iheight = spage.y - stable.y - slogo.y;
|
||||
|
||||
$("mailcontent").setStyle("height", iheight + "px");
|
||||
parse_menubar("menubar");
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -2,13 +2,12 @@ from django.conf.urls.defaults import *
|
||||
|
||||
urlpatterns = patterns('mailng.extensions.amavis_quarantine.main',
|
||||
(r'^$', 'index'),
|
||||
url(r'^viewmail/(?P<mail_id>[\w\-\+]+)/$', 'viewmail',
|
||||
name="viewmail_std"),
|
||||
url(r'^viewmail/$', 'viewmail', name="viewmail_null"),
|
||||
(r'^listing/$', '_listing'),
|
||||
(r'^getmailcontent/(?P<mail_id>[\w\-\+]+)/$', 'getmailcontent'),
|
||||
(r'^viewheaders/(?P<mail_id>[\w\-\+]+)/$', 'viewheaders'),
|
||||
(r'^(?P<mail_id>[\w\-\+]+)/headers/$', 'viewheaders'),
|
||||
(r'^process/$', 'process'),
|
||||
(r'^delete/(?P<mail_id>[\w\-\+]+)/$', 'delete'),
|
||||
(r'^release/(?P<mail_id>[\w\-\+]+)/$', 'release'),
|
||||
(r'^search/', 'search'),
|
||||
(r'^(?P<mail_id>[\w\-\+]+)/$', 'viewmail'),
|
||||
)
|
||||
|
||||
@@ -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"},
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
</ul>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block menu %}
|
||||
|
||||
{% endblock %}
|
||||
|
||||
@@ -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 += [
|
||||
|
||||
@@ -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:
|
||||
|
||||
+16
-8
@@ -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):
|
||||
|
||||
+14
-10
@@ -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):
|
||||
|
||||
+34
-2
@@ -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',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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");
|
||||
},
|
||||
});
|
||||
@@ -177,11 +177,11 @@ div#footer {
|
||||
border-left: 5px solid #ccc;
|
||||
}
|
||||
|
||||
.left {
|
||||
div.left {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.right {
|
||||
div.right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,20 +2,6 @@
|
||||
{% load i18n %}
|
||||
{% block html_head %}
|
||||
<style type="text/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;
|
||||
}
|
||||
|
||||
#navbar {
|
||||
float: right;
|
||||
padding: 0;
|
||||
@@ -37,6 +23,39 @@ html > body #listing {
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
window.addEvent("domready", function() {
|
||||
navparams = new Hash({
|
||||
{% for k, v in navparams.items %}
|
||||
{{ k }} : "{{ v }}",
|
||||
{% endfor %}
|
||||
});
|
||||
|
||||
navbarcallback = function(event) {
|
||||
event.stop();
|
||||
current_anchor.setparams(navparams);
|
||||
current_anchor.parse_string(event.target.getParent().get("href")).update();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if ($("selectall")) {
|
||||
$("selectall").addEvent("click", function(event) {
|
||||
if ($("selectall").checked) {
|
||||
@@ -47,6 +66,7 @@ window.addEvent("domready", function() {
|
||||
});
|
||||
}
|
||||
{% block js %}{% endblock %}
|
||||
ajaxListener("{{ deflocation }}", {{ defcallback }});
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
@@ -55,5 +75,5 @@ window.addEvent("domready", function() {
|
||||
<div id="listing">{{ listing }}</div>
|
||||
<div class="spacer"></div>
|
||||
{% endblock %}
|
||||
{% block footer %}<div id="navbar"></div>{% endblock %}
|
||||
{% block footer %}<div id="navbar">{{ navbar }}</div>{% endblock %}
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
{% load i18n %}
|
||||
<div id="searchbox">
|
||||
<img src="/static/pics/search.png" id="searchopts" />
|
||||
<input type="text" name="searchfield" id="searchfield" value="{% trans "Search..." %}" />
|
||||
<div id="searchparams">
|
||||
<input type="radio" name="scriteria" value="from_addr" checked>{% trans "From address" %}<br/>
|
||||
<input type="radio" name="scriteria" value="subject">{% trans "Subject" %}<br/>
|
||||
<input type="radio" name="scriteria" value="from_addr,subject">{% trans "Both" %}<br/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -13,6 +13,7 @@
|
||||
<script src="/static/js/mootools-more.js" type="text/javascript"></script>
|
||||
<script src="/static/js/drag.group.js" type="text/javascript"></script>
|
||||
<script src="/static/js/SqueezeBox.js" type="text/javascript"></script>
|
||||
<script src="/static/js/infobox.js" type="text/javascript"></script>
|
||||
<script src="/static/js/common.js" type="text/javascript"></script>
|
||||
{% url django.views.i18n.javascript_catalog as catalog_url %}
|
||||
<script type="text/javascript" src="{{ catalog_url }}"></script>
|
||||
|
||||
Reference in New Issue
Block a user