mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-18 05:51:26 +02:00
wip: global UI refactoring
* A submailbox can now be moved to the top level * Code cleanup see #204
This commit is contained in:
@@ -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,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
|
||||
|
||||
|
||||
@@ -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,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
@@ -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'
|
||||
|
||||
Reference in New Issue
Block a user