wip: webmail big refactoring and performance improvment

*On demand* mailboxes loading.
This commit is contained in:
Antoine Nguyen
2011-11-17 15:34:59 +01:00
parent f04862b28f
commit 5730d66979
5 changed files with 103 additions and 25 deletions
+19 -12
View File
@@ -43,6 +43,7 @@ class IMAPconnector(object):
list_response_pattern = re.compile(list_base_pattern)
listextended_response_pattern = \
re.compile(list_base_pattern + r'\s*(?P<childinfo>.*)')
unseen_pattern = re.compile(r'[^\(]+\(UNSEEN (\d+)\)')
def __init__(self, user=None, password=None):
self.criterions = []
@@ -175,8 +176,10 @@ class IMAPconnector(object):
# data = self._cmd("SEARCH", "UTF-8", "(NOT DELETED UNSEEN)")
# return len(data[0].split())
data = self._cmd("STATUS", mailbox.encode("imap4-utf-7"), "(UNSEEN)")
print data
return 0
m = self.unseen_pattern.match(data[0])
if m is None:
return 0
return int(m.group(1))
def _encodefolder(self, folder):
if not folder:
@@ -227,7 +230,8 @@ class IMAPconnector(object):
@capability('LIST-EXTENDED', '_listfolders_simple')
def _listfolders(self, topmailbox='', md_mailboxes=[]):
resp = self._cmd("LSUB", topmailbox, "%", "RETURN", "(CHILDREN)")
pattern = ("%s.%%" % topmailbox) if len(topmailbox) else "%"
resp = self._cmd("LSUB", "", pattern, "RETURN", "(CHILDREN)")
result = []
for mb in resp:
flags, delimiter, name, childinfo = \
@@ -250,15 +254,18 @@ class IMAPconnector(object):
from operator import itemgetter
return sorted(result, key=itemgetter("name"))
def getfolders(self, user, unseen_messages=True):
md_mailboxes = [{"name" : "INBOX", "class" : "inbox"},
{"name" : parameters.get_user(user, "DRAFTS_FOLDER"),
"class" : "drafts"},
{"name" : 'Junk'},
{"name" : parameters.get_user(user, "SENT_FOLDER")},
{"name" : parameters.get_user(user, "TRASH_FOLDER"),
"class" : "trash"}]
md_mailboxes += self._listfolders(md_mailboxes=md_mailboxes)
def getfolders(self, user, topmailbox='', unseen_messages=True):
if len(topmailbox):
md_mailboxes = []
else:
md_mailboxes = [{"name" : "INBOX", "class" : "inbox"},
{"name" : parameters.get_user(user, "DRAFTS_FOLDER"),
"class" : "drafts"},
{"name" : 'Junk'},
{"name" : parameters.get_user(user, "SENT_FOLDER")},
{"name" : parameters.get_user(user, "TRASH_FOLDER"),
"class" : "trash"}]
md_mailboxes += self._listfolders(topmailbox, md_mailboxes)
if unseen_messages:
for fd in md_mailboxes:
key = fd.has_key("path") and "path" or "name"
+74 -12
View File
@@ -8,7 +8,8 @@ var Webmail = new Class({
refreshRate: 0,
modify_url: "",
delete_url: "",
move_url: ""
move_url: "",
submboxes_url: ""
},
/*
@@ -23,7 +24,7 @@ var Webmail = new Class({
this.init_menubar();
this.init_folders_buttons();
this.init_folders_browsing();
/* FIXME: à faire uniquement pour le mode pushState */
/*this.init_emails_table();*/
@@ -93,6 +94,71 @@ var Webmail = new Class({
});
},
/*
* Open/Close a mailbox with children
*/
toggle_mbox_state: function(div, ul) {
if (ul.hasClass("hidden")) {
div.removeClass("collapsed").addClass("expanded");
ul.removeClass("hidden").addClass("visible");
} else {
div.removeClass("expanded").addClass("collapsed");
ul.removeClass("visible").addClass("hidden");
}
},
/*
* Inject new mailboxes under a given parent in the tree.
*/
inject_mailboxes: function(parent, mboxes) {
var ul = new Element("ul", {
name: parent.get("name"),
'class': "hidden"
}).inject(parent);
for (var i = 0; i < mboxes.length; i++) {
var mbname = mboxes[i].name;
var li = new Element("li", {
name: mbname,
'class': "droppable folder"
}).inject(ul);
var img = new Element("img", {
'class': "footer",
src: static_url("pics/go-down.png")
}).inject(li);
var link = new Element("a", {
name: "loadfolder",
'class': "block",
href: mbname
}).inject(li);
var parts = mbname.split(".");
var displayname = parts[parts.length - 1];
if (mboxes[i].unseen != undefined) {
link.addClass("unseen");
link.set("html", displayname + " (" + mboxes[i].unseen + ")");
} else {
link.set("html", displayname);
}
}
this.toggle_mbox_state(parent.getFirst("div"), ul);
},
/*
* Download sub-mailboxes from the server
*/
get_mailboxes: function(parent) {
new Request.JSON({
url: this.options.submboxes_url,
onSuccess: function(resp) {
if (resp.status == "ko") {
return;
}
this.inject_mailboxes(parent, resp.mboxes);
}.bind(this)
}).get({topmailbox: parent.get("name")});
},
/*
* Enables folders opening/closing
*
@@ -100,21 +166,17 @@ var Webmail = new Class({
*/
init_folders_browsing: function() {
$$("div[class*=clickbox]").addEvent("click", function(evt) {
var parent = this.getParent();
var div = evt.target;
var parent = div.getParent();
var ul = parent.getFirst("ul[name=" + parent.get("name") + "]");
if (!$defined(ul)) {
if (ul == undefined) {
this.get_mailboxes(parent);
return;
}
if (ul.hasClass("hidden")) {
this.removeClass("collapsed").addClass("expanded");
ul.removeClass("hidden").addClass("visible");
} else {
this.removeClass("expanded").addClass("collapsed");
ul.removeClass("visible").addClass("hidden");
}
this.toggle_mbox_state(div, ul);
evt.stop();
});
}.bind(this));
},
/*
@@ -75,7 +75,8 @@ function wm_updatelisting(resp) {
refreshRate: {{ refreshrate }},
modify_url: "{% url extensions.webmail.views.editfolder %}",
delete_url: "{% url extensions.webmail.views.delfolder %}",
move_url: "{% url extensions.webmail.views.move as moveurl %}"
move_url: "{% url extensions.webmail.views.move %}",
submboxes_url: "{% url extensions.webmail.views.submailboxes %}"
});
current_anchor.register_callback("folder", function(resp) {
+1
View File
@@ -8,6 +8,7 @@ from django.conf.urls.defaults import *
urlpatterns = patterns('modoboa.extensions.webmail.views',
#(r'^$', "index"),
(r'^$', "newindex"),
(r'^submailboxes', "submailboxes"),
(r'^compose/$', "compose"),
(r'^move/$', "move"),
+7
View File
@@ -518,6 +518,13 @@ def listmailbox(request):
return lst.render(request)
@login_required
@is_not_localadmin()
def submailboxes(request):
topmailbox = request.GET.get('topmailbox', '')
mboxes = get_imapconnector(request).getfolders(request.user, topmailbox)
return ajax_simple_response(dict(status="ok", mboxes=mboxes))
@login_required
@is_not_localadmin()
def newindex(request):