From 1e36158841e084b161d11308f9004e5fab89d16d Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Fri, 20 Apr 2012 12:08:12 +0200 Subject: [PATCH] wip: global UI refactoring * A submailbox can now be moved to the top level * Code cleanup see #204 --- extensions/webmail/__init__.py | 3 +- extensions/webmail/lib.py | 7 +- extensions/webmail/static/js/webmail.js | 58 +++++++----- extensions/webmail/urls.py | 15 +-- extensions/webmail/views.py | 119 +----------------------- 5 files changed, 44 insertions(+), 158 deletions(-) diff --git a/extensions/webmail/__init__.py b/extensions/webmail/__init__.py index c044e3824..83d0c4eb7 100644 --- a/extensions/webmail/__init__.py +++ b/extensions/webmail/__init__.py @@ -83,8 +83,7 @@ def menu(target, user): return [ {"name" : "webmail", "label" : _("Webmail"), - "url" : reverse("modoboa.extensions.webmail.views.newindex"), - "img" : static_url("pics/webmail.png")} + "url" : reverse("modoboa.extensions.webmail.views.index")}, ] @events.observe("Userlogout") diff --git a/extensions/webmail/lib.py b/extensions/webmail/lib.py index c7d0f523d..6e734fd17 100644 --- a/extensions/webmail/lib.py +++ b/extensions/webmail/lib.py @@ -1,13 +1,8 @@ # coding: utf-8 import sys, os -reload(sys) -sys.setdefaultencoding("utf-8") - import re import time -import socket -import ssl from datetime import datetime, timedelta import email import lxml @@ -102,7 +97,7 @@ class IMAPheader(object): @staticmethod def parse_subject(value, **kwargs): try: - return decode(u2u_decode.u2u_decode(value)) + return u2u_decode.u2u_decode(value) except UnicodeDecodeError: return value diff --git a/extensions/webmail/static/js/webmail.js b/extensions/webmail/static/js/webmail.js index e2236b000..c5260ce6e 100644 --- a/extensions/webmail/static/js/webmail.js +++ b/extensions/webmail/static/js/webmail.js @@ -424,8 +424,14 @@ Webmail.prototype = { select_parent_mailbox: function(e) { e.preventDefault(); + var $this = $(this); + var $parent = $this.parent(); + var is_selected = $parent.hasClass("active"); + $("a[name=selectfolder]").parent().removeClass("active"); - $(this).parent().addClass("active"); + if (!is_selected) { + $parent.addClass("active"); + } }, new_mailbox: function(e) { @@ -500,6 +506,33 @@ Webmail.prototype = { } }, + /* + * Add a new mailbox into the tree. We check if the parent is + * present before adding. If it's not present, we do nothing. + */ + add_mailbox_to_tree: function(parent, mailbox) { + var $parent; + + if (parent) { + $parent = $("#folders").find('li[name="' + parent + '"]'); + if (!$parent.length) { + return; + } + if (!$parent.children("div").length) { + this.inject_clickbox($parent); + } + var $ul = $parent.children("ul"); + if (!$ul.length) { + return; + } + $parent = $ul; + mailbox = $parent.attr("name") + "." + mailbox; + } else { + $parent = $("#mboxes_container").children("ul"); + } + this.inject_mailbox($parent, mailbox, "loadfolder"); + }, + /* * Rename a mailbox (client-side) * If needed, the mailbox will be moved to its new location. @@ -517,8 +550,9 @@ Webmail.prototype = { $link.attr("href", pattern); } if (oldparent != newparent) { - var newlocation = (newparent != "") ? newparent + "." + newname : newname; + var newlocation = (newparent) ? newparent + "." + newname : newname; this.remove_mbox_from_tree($link.parent("li")); + this.add_mailbox_to_tree(newparent, newname); if (this.navobject.getparam("action") == "listmailbox") { this.navobject.setparam("name", newlocation).update(); } else { @@ -787,25 +821,7 @@ Webmail.prototype = { mboxform_success: function(data) { if (data.oldmb === undefined) { - var $parent; - - if (data.parent) { - $parent = $("#folders").find('li[name="' + data.parent + '"]'); - if (!$parent.length) { - return; - } - if (!$parent.children("div").length) { - this.inject_clickbox($parent); - } - var $ul = $parent.children("ul"); - if (!$ul.length) { - return; - } - $parent = $ul; - } else { - $parent = $("#mboxes_container").children("ul"); - } - this.inject_mailbox($parent, data.newmb, "loadfolder"); + this.add_mailbox_to_tree(data.parent, data.newmb); } else if (data.newmb) { this.rename_mailbox(data.oldmb, data.newmb, data.oldparent, data.newparent); } diff --git a/extensions/webmail/urls.py b/extensions/webmail/urls.py index 9e31054d7..2149baa05 100644 --- a/extensions/webmail/urls.py +++ b/extensions/webmail/urls.py @@ -1,19 +1,12 @@ from django.conf.urls.defaults import * -# -# FIXME: there is a big issue with this url mapping. If a folder's -# name matches one of the first entries (from "compose" to -# "attachments"), the associated folder will not be accessible. -# urlpatterns = patterns( 'modoboa.extensions.webmail.views', - #(r'^$', "index"), - (r'^$', "newindex"), + (r'^$', "index"), (r'^submailboxes', "submailboxes"), (r'^getmailcontent', 'getmailcontent'), (r'^unseenmsgs', 'check_unseen_messages'), - # (r'^compose/$', "compose"), (r'^delete/$', 'delete'), (r'^move/$', "move"), (r'^mark/(?P.+)/$', "mark"), @@ -27,10 +20,4 @@ urlpatterns = patterns( (r'^delattachment/$', 'delattachment'), (r'^(?P.+)/(?P[\w\-\+]+)/part/$', 'getattachment'), - #(r'^(?P.+)/(?P[\w\-\+]+)/delete/$', 'delete'), - #(r'^(?P.+)/(?P[\w\-\+]+)/content/$', 'getmailcontent'), - (r'^(?P.+)/(?P[\w\-\+]+)/forward/$', 'forward'), -# (r'^(?P.+)/(?P[\w\-\+]+)/reply/$', 'reply'), - # (r'^(?P.+)/(?P[\w\-\+]+)/$', 'viewmail'), - (r'^(?P.+)/$', "folder"), ) diff --git a/extensions/webmail/views.py b/extensions/webmail/views.py index e85cc11a2..a1409ba01 100644 --- a/extensions/webmail/views.py +++ b/extensions/webmail/views.py @@ -1,127 +1,19 @@ # coding: utf-8 -import time -import sys -from django.http import HttpResponse, Http404, HttpResponseRedirect +from django.http import HttpResponse, Http404 from django.template import Template, Context -from django.template.loader import render_to_string -from django.utils import simplejson from django.utils.translation import ugettext as _ from django.core.urlresolvers import reverse from django.contrib.auth.decorators import login_required -from django.contrib import messages from modoboa.lib import parameters from modoboa.lib.webutils import _render, _render_error, \ getctx, _render_to_string, ajax_response, ajax_simple_response -from modoboa.lib.emailutils import split_mailbox -from modoboa.lib.email_listing import parse_search_parameters, Paginator +from modoboa.lib.email_listing import parse_search_parameters from modoboa.lib.decorators import needs_mailbox from modoboa.auth.lib import * from lib import * from forms import * from templatetags import webextras -def __render_common_components(request, folder_name, lst=None, content=None, menu=None): - """Render all components that are common to all pages in the webmail - - It concerns the main listing, the viewmail and the compose - pages. Components are : main content, folders list, pagination - bar, quota bar. - - Two modes are available : - * If lst is provided, do not use content, - * If lst is not provided, do not use content, nor menu. - - :param request: a Request object - :param folder: the current folder - :param lst: an ImapListing object - :param content: the HTML that will go into the 'listing' div - :param menu: the current page menu - """ - if lst is not None: - paginator = lst.paginator - mbc = lst.mbc - menu = listing_menu("", folder_name, request.user) - else: - mbc = IMAPconnector(user=request.user.username, - password=request.session["password"]) - paginator = Paginator(mbc.messages_count(folder=folder_name, - order=request.session["navparams"]["order"]), - int(parameters.get_user(request.user, "MESSAGES_PER_PAGE"))) - - page = paginator.getpage(request.session["page"]) - if page: - navbar = EmailListing.render_navbar(page) - if lst: - content = lst.fetch(request, page.id_start, page.id_stop) - else: - navbar = "" - if lst: - content = "
%s
" \ - % _("This folder contains no messages") - - ret = { - "folders" : _render_to_string(request, "webmail/folders.html", { - "titlebar" : True, - "selected" : request.session["folder"], - "folders" : mbc.getmboxes(request.user), - "withunseen" : True - }), - "menu" : menu, - "listing" : content, - "navbar" : navbar, - "quota" : ImapListing.computequota(mbc) - } - - return ret - - -@login_required -@needs_mailbox() -def folder(request, name, updatenav=True): - if not name: - name = "INBOX" - order = request.GET.has_key("order") and request.GET["order"] or "-date" - if updatenav: - pageid = request.GET.has_key("page") and int(request.GET["page"]) or 1 - if not "navparams" in request.session.keys(): - request.session["navparams"] = {} - request.session["folder"] = name - request.session["page"] = pageid - if order: - request.session["navparams"]["order"] = order - parse_search_parameters(request) - else: - # Internal usage - order = request.session["navparams"]["order"] - - optparams = {} - if request.session.has_key("pattern"): - optparams["pattern"] = request.session["pattern"] - optparams["criteria"] = request.session["criteria"] - else: - optparams["reset"] = True - optparams["elems_per_page"] = \ - int(parameters.get_user(request.user, "MESSAGES_PER_PAGE")) - lst = ImapListing(request.user, request.session["password"], - baseurl=name, folder=name, order=order, - **optparams) - dico = __render_common_components(request, name, lst) - ctx = getctx("ok", **dico) - return HttpResponse(simplejson.dumps(ctx), mimetype="application/json") - -@login_required -@needs_mailbox() -def index(request): - try: - navp = request.session.has_key("navparams") \ - and request.session["navparams"] or {} - lst = ImapListing(request.user, request.session["password"], - baseurl="INBOX", navparams=navp, folder="INBOX", - empty=True) - except Exception, exp: - return _render_error(request, user_context={"error" : exp}) - return lst.render(request) - @login_required @needs_mailbox() def getattachment(request, folder, mail_id): @@ -282,7 +174,7 @@ def editfolder(request, tplname="webmail/folder.html"): oldname, oldparent = separate_mailbox(request.POST["oldname"]) res = dict(status="ok", respmsg=_("Mailbox updated")) if form.cleaned_data["name"] != oldname \ - or (pf is not None and pf != oldparent): + or (pf != oldparent): newname = form.cleaned_data["name"] if pf is None \ else "%s.%s" % (pf, form.cleaned_data["name"]) mbc.rename_folder(request.POST["oldname"], newname) @@ -387,9 +279,6 @@ def delattachment(request): error = _("Unknown attachment") return ajax_response(request, "ko", respmsg=error) -# -# NEW CODE STARTS HERE -# def render_mboxes_list(request, imapc): """Return the HTML representation of a mailboxes list @@ -572,7 +461,7 @@ def check_unseen_messages(request): @login_required @needs_mailbox() -def newindex(request): +def index(request): """Webmail actions handler Problèmes liés à la navigation 'anchor based'