From 5730d669790fc23f76b73c6c00d1f898e175edd5 Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Thu, 17 Nov 2011 15:34:59 +0100 Subject: [PATCH] wip: webmail big refactoring and performance improvment *On demand* mailboxes loading. --- extensions/webmail/imaputils.py | 31 ++++--- extensions/webmail/static/js/webmail.js | 86 ++++++++++++++++--- .../webmail/templates/webmail/index.html | 3 +- extensions/webmail/urls.py | 1 + extensions/webmail/views.py | 7 ++ 5 files changed, 103 insertions(+), 25 deletions(-) diff --git a/extensions/webmail/imaputils.py b/extensions/webmail/imaputils.py index 49dc4f093..dd6ba51c0 100644 --- a/extensions/webmail/imaputils.py +++ b/extensions/webmail/imaputils.py @@ -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.*)') + 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" diff --git a/extensions/webmail/static/js/webmail.js b/extensions/webmail/static/js/webmail.js index c78c1065e..3880b610f 100644 --- a/extensions/webmail/static/js/webmail.js +++ b/extensions/webmail/static/js/webmail.js @@ -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)); }, /* diff --git a/extensions/webmail/templates/webmail/index.html b/extensions/webmail/templates/webmail/index.html index 1e86ea09c..7c23f9e27 100644 --- a/extensions/webmail/templates/webmail/index.html +++ b/extensions/webmail/templates/webmail/index.html @@ -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) { diff --git a/extensions/webmail/urls.py b/extensions/webmail/urls.py index f083f7612..cf6996121 100644 --- a/extensions/webmail/urls.py +++ b/extensions/webmail/urls.py @@ -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"), diff --git a/extensions/webmail/views.py b/extensions/webmail/views.py index c6a0cf673..419c27f51 100644 --- a/extensions/webmail/views.py +++ b/extensions/webmail/views.py @@ -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):