wip: global UI refactoring

* A submailbox can now be moved to the top level
* Code cleanup

see #204
This commit is contained in:
Antoine Nguyen
2012-04-20 12:08:12 +02:00
parent be2d5286ed
commit 1e36158841
5 changed files with 44 additions and 158 deletions
+1 -2
View File
@@ -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")
+1 -6
View File
@@ -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
+37 -21
View File
@@ -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);
}
+1 -14
View File
@@ -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<name>.+)/$', "mark"),
@@ -27,10 +20,4 @@ urlpatterns = patterns(
(r'^delattachment/$', 'delattachment'),
(r'^(?P<folder>.+)/(?P<mail_id>[\w\-\+]+)/part/$', 'getattachment'),
#(r'^(?P<fdname>.+)/(?P<mail_id>[\w\-\+]+)/delete/$', 'delete'),
#(r'^(?P<folder>.+)/(?P<mailid>[\w\-\+]+)/content/$', 'getmailcontent'),
(r'^(?P<folder>.+)/(?P<mail_id>[\w\-\+]+)/forward/$', 'forward'),
# (r'^(?P<folder>.+)/(?P<mail_id>[\w\-\+]+)/reply/$', 'reply'),
# (r'^(?P<folder>.+)/(?P<mail_id>[\w\-\+]+)/$', 'viewmail'),
(r'^(?P<name>.+)/$', "folder"),
)
+4 -115
View File
@@ -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 = "<div class='alert alert-info'>%s</div>" \
% _("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'