mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-17 05:41:25 +02:00
wip: global UI refactoring
I'm almost done with the webmail :p Mailboxes manipulation is working pretty well now. see #204
This commit is contained in:
@@ -356,7 +356,7 @@ class IMAPconnector(object):
|
||||
return sorted(result, key=itemgetter("name"))
|
||||
|
||||
@capability('LIST-EXTENDED', '_listfolders_simple')
|
||||
def _listmboxes(self, topmailbox='', mailboxes=[]):
|
||||
def _listmboxes(self, topmailbox='', mailboxes=[], until_mailbox=None):
|
||||
pattern = ("%s.%%" % topmailbox.encode("imap4-utf-7")) if len(topmailbox) else "%"
|
||||
resp = self._cmd("LIST", "", pattern, "RETURN", "(CHILDREN)")
|
||||
newmboxes = []
|
||||
@@ -381,10 +381,25 @@ class IMAPconnector(object):
|
||||
if r'\HasChildren' in flags:
|
||||
descr["path"] = name
|
||||
descr["sub"] = []
|
||||
if until_mailbox and until_mailbox.startswith(name):
|
||||
self._listmboxes(name, descr["sub"], until_mailbox)
|
||||
|
||||
from operator import itemgetter
|
||||
mailboxes += sorted(newmboxes, key=itemgetter("name"))
|
||||
|
||||
def getmboxes(self, user, topmailbox='', unseen_messages=True):
|
||||
def getmboxes(self, user, topmailbox='', until_mailbox=None, unseen_messages=True):
|
||||
"""Returns a list of mailboxes for a particular user
|
||||
|
||||
By default, only the first level of mailboxes under
|
||||
``topmailbox`` is returned. If ``until_mailbox`` is specified,
|
||||
all levels needed to access this mailbox will be returned.
|
||||
|
||||
:param user: a ``User`` instance
|
||||
:param topmailbox: the mailbox where to start in the tree
|
||||
:param until_mailbox: the deepest needed mailbox
|
||||
:param unseen_messages: include unseen messages counters or not
|
||||
:return: a list
|
||||
"""
|
||||
if len(topmailbox):
|
||||
md_mailboxes = []
|
||||
else:
|
||||
@@ -395,7 +410,11 @@ class IMAPconnector(object):
|
||||
{"name" : parameters.get_user(user, "SENT_FOLDER")},
|
||||
{"name" : parameters.get_user(user, "TRASH_FOLDER"),
|
||||
"class" : "icon-trash"}]
|
||||
self._listmboxes(topmailbox, md_mailboxes)
|
||||
if until_mailbox:
|
||||
name, parent = separate_mailbox(until_mailbox)
|
||||
if parent:
|
||||
until_mailbox = parent
|
||||
self._listmboxes(topmailbox, md_mailboxes, until_mailbox)
|
||||
|
||||
if unseen_messages:
|
||||
for mb in md_mailboxes:
|
||||
@@ -577,6 +596,19 @@ class IMAPconnector(object):
|
||||
)
|
||||
return data[int(mailid)]
|
||||
|
||||
def separate_mailbox(fullname, sep="."):
|
||||
"""Split a mailbox name
|
||||
|
||||
If a separator is found in ``fullname``, this function returns the
|
||||
corresponding name and parent mailbox name.
|
||||
"""
|
||||
if fullname.count("."):
|
||||
parts = fullname.split(sep)
|
||||
name = parts[-1]
|
||||
parent = sep.join(parts[0:len(parts) - 1])
|
||||
return name, parent
|
||||
return fullname, None
|
||||
|
||||
def get_imapconnector(request):
|
||||
"""Simple shortcut to create a connector
|
||||
|
||||
|
||||
@@ -84,6 +84,8 @@ Webmail.prototype = {
|
||||
this.select_parent_mailbox),
|
||||
$(document).on("click", "div[class*=clickbox]",
|
||||
$.proxy(this.mbox_state_callback, this));
|
||||
$(document).on("click", "a[name=newmbox]",
|
||||
$.proxy(this.new_mailbox, this));
|
||||
$(document).on("click", "a[name=editmbox]",
|
||||
$.proxy(this.edit_mbox, this));
|
||||
$(document).on("click", "a[name=removembox]",
|
||||
@@ -133,11 +135,10 @@ Webmail.prototype = {
|
||||
* Simple helper to retrieve the currently selected mailbox.
|
||||
*/
|
||||
get_current_mailbox: function() {
|
||||
if (this.navobject.params.action != "listmailbox") {
|
||||
return null;
|
||||
if (this.navobject.getparam("action") != "listmailbox") {
|
||||
return undefined;
|
||||
}
|
||||
return (this.navobject.params.name)
|
||||
? this.navobject.params.name : "INBOX";
|
||||
return this.navobject.getparam("name", "INBOX");
|
||||
},
|
||||
|
||||
/*
|
||||
@@ -256,6 +257,42 @@ Webmail.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* Inject a new *clickbox* somewhere in the tree
|
||||
*/
|
||||
inject_clickbox: function($container) {
|
||||
$container.prepend($("<div />", {'class' : 'clickbox collapsed'}));
|
||||
},
|
||||
|
||||
/*
|
||||
* Injects a single mailbox somewhere in the tree
|
||||
*/
|
||||
inject_mailbox: function($parent, mailbox, linkname, unseen) {
|
||||
var $li = $("<li />", {
|
||||
name: mailbox,
|
||||
'class': "droppable"
|
||||
});
|
||||
var $link = $("<a />", {
|
||||
name: linkname,
|
||||
'class': "block",
|
||||
href: mailbox
|
||||
});
|
||||
var parts = mailbox.split(".");
|
||||
var linkcontent = "<i class='icon-folder-close'></i> ";
|
||||
var displayname = linkcontent + parts[parts.length - 1];
|
||||
|
||||
$li.append($link);
|
||||
$parent.append($li);
|
||||
|
||||
if (unseen != undefined) {
|
||||
$link.addClass("unseen");
|
||||
$link.html(displayname + " (" + unseen + ")");
|
||||
this.unseen_counters[$link.attr("href")] = unseen;
|
||||
} else {
|
||||
$link.html(displayname);
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* Inject new mailboxes under a given parent in the tree.
|
||||
*/
|
||||
@@ -267,30 +304,16 @@ Webmail.prototype = {
|
||||
var $plink = $parent.children("a");
|
||||
|
||||
$parent.append($ul);
|
||||
if (!$parent.children("div").length) {
|
||||
this.inject_clickbox($parent);
|
||||
}
|
||||
for (var i = 0; i < mboxes.length; i++) {
|
||||
var mbname = mboxes[i].name;
|
||||
var $li = $("<li />", {
|
||||
name: mbname,
|
||||
'class': "droppable"
|
||||
});
|
||||
var $link = $("<a />", {
|
||||
name: $plink.attr("name"),
|
||||
'class': "block",
|
||||
href: mbname
|
||||
});
|
||||
var parts = mbname.split(".");
|
||||
var linkcontent = "<i class='icon-folder-close'></i> ";
|
||||
var displayname = linkcontent + parts[parts.length - 1];
|
||||
|
||||
$li.append($link);
|
||||
$ul.append($li);
|
||||
|
||||
if (mboxes[i].unseen != undefined) {
|
||||
$link.addClass("unseen");
|
||||
$link.html(displayname + " (" + mboxes[i].unseen + ")");
|
||||
this.unseen_counters[$link.attr("href")] = mboxes[i].unseen;
|
||||
} else {
|
||||
$link.html(displayname);
|
||||
if ($parent.find('li[name="' + mboxes[i].name + '"]').length) {
|
||||
continue;
|
||||
}
|
||||
this.inject_mailbox($ul, mboxes[i].name, $plink.attr("name"), mboxes[i].unseen);
|
||||
if (mboxes[i].sub != undefined) {
|
||||
this.inject_clickbox($('li[name="' + mboxes[i].name + '"]'));
|
||||
}
|
||||
}
|
||||
this.init_droppables($ul.find(".droppable"), true);
|
||||
@@ -300,10 +323,14 @@ Webmail.prototype = {
|
||||
/*
|
||||
* Download sub-mailboxes from the server
|
||||
*/
|
||||
get_mailboxes: function(parent) {
|
||||
get_mailboxes: function(parent, async) {
|
||||
if (async === undefined) {
|
||||
async = true;
|
||||
}
|
||||
$.ajax({
|
||||
url: this.options.submboxes_url,
|
||||
dataType: 'json',
|
||||
async: async,
|
||||
data: "topmailbox=" + parent.attr("name"),
|
||||
success: $.proxy(function(data) {
|
||||
if (data.status == "ko") {
|
||||
@@ -341,29 +368,58 @@ Webmail.prototype = {
|
||||
},
|
||||
|
||||
/*
|
||||
* Select a particular mailbox
|
||||
* Unselect every selected mailbox
|
||||
*/
|
||||
reset_mb_selection: function() {
|
||||
$("a[name=loadfolder]").parent().removeClass("active").addClass("droppable");
|
||||
},
|
||||
|
||||
/*
|
||||
* Select a particular mailbox (one already present in the DOM)
|
||||
*/
|
||||
select_mailbox: function(obj) {
|
||||
var $obj = $(obj);
|
||||
var $obj = (typeof obj != "string") ? $(obj) : $('a[href="' + obj + '"]');
|
||||
|
||||
$("a[name=loadfolder]").each(function() {
|
||||
var $this = $(this);
|
||||
$this.parent().removeClass("active");
|
||||
$this.parent().addClass("droppable");
|
||||
});
|
||||
this.reset_mb_selection();
|
||||
$obj.parents("ul").addClass("visible");
|
||||
$obj.parent().removeClass("droppable");
|
||||
$obj.parent().addClass("active");
|
||||
},
|
||||
|
||||
// $$(obj.getParents("ul[class*=hidden]")).each(function(item) {
|
||||
// item.removeClass("hidden");
|
||||
// item.addClass("visible");
|
||||
// $$("li[name=" + item.get("name") + "]").each(function(item) {
|
||||
// item.setStyle(
|
||||
// "background",
|
||||
// "url('" + static_url("pics/folder-open.png") + "') no-repeat"
|
||||
// );
|
||||
// });
|
||||
// });
|
||||
/*
|
||||
* Tries to select a particular sub-mailbox and loads it from the
|
||||
* server if it's not present in the DOM. (nb: all parents needed
|
||||
* to access this mailbox are also loaded)
|
||||
*/
|
||||
load_and_select_mailbox: function(mailbox) {
|
||||
if (mailbox.indexOf(".") == -1) {
|
||||
this.select_mailbox(mailbox);
|
||||
return;
|
||||
}
|
||||
this.reset_mb_selection();
|
||||
|
||||
var parts = mailbox.split(".");
|
||||
var curmb = parts[0], lastmb = "";
|
||||
|
||||
for (var i = 1; i < parts.length; i++) {
|
||||
lastmb = curmb;
|
||||
curmb += "." + parts[i];
|
||||
|
||||
var $link = $('a[href="' + curmb + '"]');
|
||||
var $container = $('li[name="' + lastmb + '"]');
|
||||
|
||||
if ($link.length) {
|
||||
if ($container.children("div").hasClass("collapsed")) {
|
||||
this.toggle_mbox_state($container.children("div"), $container.children("ul"));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
this.get_mailboxes($container, false);
|
||||
$container.children("div").addClass("expanded");
|
||||
$container.children("ul").addClass("visible");
|
||||
}
|
||||
$('li[name="' + mailbox + '"]').addClass("active");
|
||||
},
|
||||
|
||||
select_parent_mailbox: function(e) {
|
||||
@@ -372,11 +428,17 @@ Webmail.prototype = {
|
||||
$(this).parent().addClass("active");
|
||||
},
|
||||
|
||||
new_mailbox: function(e) {
|
||||
this.poller.pause();
|
||||
},
|
||||
|
||||
/*
|
||||
* Edit the currently selected mailbox. Opens a modal box that
|
||||
* permits to change mailbox's name and more.
|
||||
*/
|
||||
edit_mbox: function(e) {
|
||||
this.poller.pause();
|
||||
|
||||
var $link = get_target(e, "a");
|
||||
if ($link.hasClass("disabled")) {
|
||||
e.preventDefault();
|
||||
@@ -385,7 +447,7 @@ Webmail.prototype = {
|
||||
var $selected = $("#folders li.active").children("a");
|
||||
|
||||
modalbox(e, undefined, $link.attr("href") + "?name=" + $selected.attr("href"),
|
||||
$.proxy(this.mboxform_cb, this));
|
||||
$.proxy(this.mboxform_cb, this), $.proxy(this.mboxform_close, this));
|
||||
},
|
||||
|
||||
/*
|
||||
@@ -393,13 +455,13 @@ Webmail.prototype = {
|
||||
*/
|
||||
remove_mbox: function(e) {
|
||||
var $link = get_target(e, "a");
|
||||
|
||||
e.preventDefault();
|
||||
if ($link.hasClass("disabled")) return;
|
||||
if (!confirm(gettext("Remove the selected mailbox?"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.poller.pause();
|
||||
var $selected = $("#folders li.active").children("a");
|
||||
|
||||
$.ajax({
|
||||
@@ -407,12 +469,9 @@ Webmail.prototype = {
|
||||
dataType: 'json',
|
||||
success: $.proxy(function(data) {
|
||||
if (data.status == "ok") {
|
||||
this.remove_mbox_from_tree(this.navobject.getparam("name"));
|
||||
this.poller.resume();
|
||||
$("body").notify("success", gettext("Mailbox removed"), 2000);
|
||||
if (this.navobject.getparam("action") == "listmailbox") {
|
||||
$('li[name="' + this.navobject.getparam("name") + '"]').remove();
|
||||
this.select_mailbox($("a[href=INBOX]"));
|
||||
this.navobject.setparam("name", "INBOX").update();
|
||||
}
|
||||
} else {
|
||||
$("body").notify("error", data.respmsg);
|
||||
}
|
||||
@@ -420,6 +479,54 @@ Webmail.prototype = {
|
||||
});
|
||||
},
|
||||
|
||||
/*
|
||||
* Remove a mailbox from the tree.
|
||||
*
|
||||
* It is a client-side action, no request is sent to the server.
|
||||
*/
|
||||
remove_mbox_from_tree: function(mailbox) {
|
||||
var $container = (typeof mailbox === "string") ? $('li[name="' + mailbox + '"]') : mailbox;
|
||||
var $parent = $container.parent("ul");
|
||||
|
||||
if ($parent.children("li").length == 1) {
|
||||
$parent.siblings("div").remove();
|
||||
$parent.remove();
|
||||
} else {
|
||||
$container.remove();
|
||||
}
|
||||
if (this.navobject.getparam("action") == "listmailbox") {
|
||||
this.select_mailbox($("a[href=INBOX]"));
|
||||
this.navobject.setparam("name", "INBOX").update();
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* Rename a mailbox (client-side)
|
||||
* If needed, the mailbox will be moved to its new location.
|
||||
*/
|
||||
rename_mailbox: function(oldname, newname, oldparent, newparent) {
|
||||
var pattern = (oldparent) ? oldparent + "." + oldname : oldname;
|
||||
var $link = $("#folders").find('a[href="' + pattern + '"]');
|
||||
|
||||
if (oldname != newname) {
|
||||
var $i = $link.children("i");
|
||||
|
||||
$link.html(newname);
|
||||
$link.parent("li").attr("name", pattern);
|
||||
$link.prepend($i);
|
||||
$link.attr("href", pattern);
|
||||
}
|
||||
if (oldparent != newparent) {
|
||||
var newlocation = (newparent != "") ? newparent + "." + newname : newname;
|
||||
this.remove_mbox_from_tree($link.parent("li"));
|
||||
if (this.navobject.getparam("action") == "listmailbox") {
|
||||
this.navobject.setparam("name", newlocation).update();
|
||||
} else {
|
||||
this.select_mailbox("INBOX");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
send_mark_request: function(e) {
|
||||
e.preventDefault();
|
||||
if (!this.htmltable.current_selection().length) {
|
||||
@@ -487,13 +594,15 @@ Webmail.prototype = {
|
||||
* mailbox. (activated when clicking on a mailbox's name)
|
||||
*/
|
||||
_listmailbox_loader: function(event, obj) {
|
||||
event.preventDefault();
|
||||
if (event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
if (obj === undefined) {
|
||||
obj = $(event.target);
|
||||
}
|
||||
this.navobject.reset().setparams({
|
||||
action: "listmailbox",
|
||||
name: gethref(obj)
|
||||
name: obj.attr("href")
|
||||
}).update();
|
||||
},
|
||||
|
||||
@@ -573,6 +682,9 @@ Webmail.prototype = {
|
||||
//window.removeEvents("resize");
|
||||
var curmb = this.get_current_mailbox();
|
||||
|
||||
if (!$('li[name="' + curmb + '"]').hasClass("active")) {
|
||||
this.load_and_select_mailbox(curmb);
|
||||
}
|
||||
this.enable_mb_actions();
|
||||
for (var idx in this.options.ro_mboxes) {
|
||||
if (curmb == this.options.ro_mboxes[idx]) {
|
||||
@@ -617,7 +729,7 @@ Webmail.prototype = {
|
||||
$("a[name=sendmail]").attr("disabled", null);
|
||||
return;
|
||||
}
|
||||
history.go(-2);
|
||||
this._listmailbox_loader(null, $("#folders").find("li[class*=active]").children("a"));
|
||||
$("body").notify("success", gettext("Message sent"), 2000);
|
||||
},
|
||||
|
||||
@@ -654,20 +766,62 @@ Webmail.prototype = {
|
||||
},
|
||||
|
||||
/*
|
||||
* Mailbox form
|
||||
* Mailbox form initialization
|
||||
*/
|
||||
mboxform_cb: function() {
|
||||
$("#mboxform").find("input").keypress(function(e) {
|
||||
if (e.which == 13) e.preventDefault();
|
||||
});
|
||||
$(".submit").one('click', $.proxy(function(e) {
|
||||
var $link = $("#folders2 li.active").children("a");
|
||||
|
||||
simple_ajax_form_post(e, {
|
||||
formid: "mboxform",
|
||||
error_cb: this.mboxform_cb,
|
||||
extradata: ($link.length) ? "parent_folder=" + $link.attr("href") : ""
|
||||
reload_on_success: false,
|
||||
formid: "mboxform",
|
||||
error_cb: this.mboxform_cb,
|
||||
extradata: ($link.length) ? "parent_folder=" + $link.attr("href") : "",
|
||||
success_cb: $.proxy(this.mboxform_success, this)
|
||||
});
|
||||
}, this));
|
||||
},
|
||||
|
||||
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");
|
||||
} else if (data.newmb) {
|
||||
this.rename_mailbox(data.oldmb, data.newmb, data.oldparent, data.newparent);
|
||||
}
|
||||
this.poller.resume();
|
||||
},
|
||||
|
||||
/*
|
||||
* Just a simple 'onclose' callback to check if the poller has
|
||||
* been resumed (useful when the user has cancelled the action)
|
||||
*/
|
||||
mboxform_close: function() {
|
||||
if (this.poller.paused) {
|
||||
this.poller.resume();
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
* Attachments form
|
||||
*/
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div id="folders2" class="well">
|
||||
<ul class="nav nav-list">
|
||||
<li class="nav-header">{% trans "Parent mailbox" %}</li>
|
||||
{% print_folders folders selected withunseen selectonly %}
|
||||
{% print_mailboxes mboxes selected withunseen selectonly %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{% load i18n webextras %}
|
||||
<div id="mboxes_container">
|
||||
<ul class="nav nav-list">
|
||||
<li class="nav-header">{% trans "Folders" %}</li>
|
||||
{% print_folders folders selected withunseen %}
|
||||
<li class="nav-header">{% trans "Mailboxes" %}</li>
|
||||
{% print_mailboxes mboxes selected withunseen %}
|
||||
</ul>
|
||||
</div>
|
||||
<div id="mboxactions">{% mboxes_menu %}</div>
|
||||
|
||||
@@ -5,6 +5,7 @@ from django.core.urlresolvers import reverse
|
||||
from django.conf import settings
|
||||
from modoboa.extensions import webmail
|
||||
from modoboa.extensions.webmail.lib import IMAPheader
|
||||
from modoboa.extensions.webmail.imaputils import separate_mailbox
|
||||
from modoboa.lib import parameters
|
||||
from modoboa.lib.webutils import static_url
|
||||
|
||||
@@ -118,22 +119,23 @@ def listmailbox_menu(selection, folder, user):
|
||||
))
|
||||
|
||||
@register.simple_tag
|
||||
def print_folders(folders, selected=None, withunseen=False, selectonly=False):
|
||||
def print_mailboxes(tree, selected=None, withunseen=False, selectonly=False):
|
||||
"""Display a tree of mailboxes and sub-mailboxes
|
||||
|
||||
|
||||
:param tree: the mailboxes to display
|
||||
"""
|
||||
result = ""
|
||||
|
||||
for fd in folders:
|
||||
for mbox in tree:
|
||||
cssclass = ""
|
||||
name = fd["path"] if fd.has_key("sub") else fd["name"]
|
||||
label = fd["name"]
|
||||
name = mbox["path"] if mbox.has_key("sub") else mbox["name"]
|
||||
label = separate_mailbox(mbox["name"])[0]
|
||||
if selected == name:
|
||||
cssclass = "active"
|
||||
result += "<li name='%s' class='droppable %s'>\n" % (name, cssclass)
|
||||
if fd.has_key("sub"):
|
||||
if mbox.has_key("sub"):
|
||||
if selected is not None and selected != name and selected.count(name):
|
||||
print "%s is visible" % name
|
||||
ul_state = "visible"
|
||||
div_state = "expanded"
|
||||
else:
|
||||
@@ -143,20 +145,20 @@ def print_folders(folders, selected=None, withunseen=False, selectonly=False):
|
||||
|
||||
cssclass = "block"
|
||||
extra_attrs = ""
|
||||
if withunseen and fd.has_key("unseen"):
|
||||
label += " (%d)" % fd["unseen"]
|
||||
if withunseen and mbox.has_key("unseen"):
|
||||
label += " (%d)" % mbox["unseen"]
|
||||
cssclass += " unseen"
|
||||
extra_attrs = ' data-toggle="%d"' % fd["unseen"]
|
||||
iclass = fd["class"] if fd.has_key("class") else "icon-folder-close"
|
||||
extra_attrs = ' data-toggle="%d"' % mbox["unseen"]
|
||||
iclass = mbox["class"] if mbox.has_key("class") else "icon-folder-close"
|
||||
result += """<a href='%s' class='%s' name='%s'%s>
|
||||
<i class="%s"></i>
|
||||
%s
|
||||
</a>
|
||||
""" % (fd.has_key("path") and fd["path"] or fd["name"], cssclass,
|
||||
""" % (mbox.has_key("path") and mbox["path"] or mbox["name"], cssclass,
|
||||
'selectfolder' if selectonly else 'loadfolder', extra_attrs, iclass, label)
|
||||
if fd.has_key("sub") and len(fd["sub"]):
|
||||
result += "<ul name='%s' class='%s'>" % (fd["path"], ul_state) \
|
||||
+ print_folders(fd["sub"], selected, withunseen, selectonly) + "</ul>\n"
|
||||
if mbox.has_key("sub") and len(mbox["sub"]):
|
||||
result += "<ul name='%s' class='nav nav-list %s'>" % (mbox["path"], ul_state) \
|
||||
+ print_mailboxes(mbox["sub"], selected, withunseen, selectonly) + "</ul>\n"
|
||||
result += "</li>\n"
|
||||
return result
|
||||
|
||||
@@ -169,6 +171,7 @@ def mboxes_menu():
|
||||
"title" : _("Create a new mailbox"),
|
||||
"modal" : True,
|
||||
"modalcb" : "webmail.mboxform_cb",
|
||||
"closecb" : "webmail.mboxform_close",
|
||||
"class" : "btn btn-mini"},
|
||||
{"name" : "editmbox",
|
||||
"url" : reverse(webmail.views.editfolder),
|
||||
|
||||
+24
-30
@@ -229,39 +229,28 @@ def compact(request, name):
|
||||
imapc.compact(name)
|
||||
return ajax_simple_response(dict(status="ok"))
|
||||
|
||||
def separate_folder(fullname, sep="."):
|
||||
"""Split a folder name
|
||||
|
||||
If a separator is found in fullname, this function returns the
|
||||
corresponding name and parent folder name.
|
||||
"""
|
||||
if fullname.count("."):
|
||||
parts = fullname.split(sep)
|
||||
name = parts[-1]
|
||||
parent = sep.join(parts[0:len(parts) - 1])
|
||||
return name, parent
|
||||
return fullname, None
|
||||
|
||||
@login_required
|
||||
@needs_mailbox()
|
||||
def newfolder(request, tplname="webmail/folder.html"):
|
||||
mbc = IMAPconnector(user=request.user.username,
|
||||
password=request.session["password"])
|
||||
ctx = {"title" : _("Create a new folder"),
|
||||
ctx = {"title" : _("Create a new mailbox"),
|
||||
"formid" : "mboxform",
|
||||
"action" : reverse(newfolder),
|
||||
"action" : reverse(newfolder),
|
||||
"action_label" : _("Create"),
|
||||
"action_classes" : "submit",
|
||||
"withunseen" : False,
|
||||
"selectonly" : True}
|
||||
|
||||
ctx["folders"] = mbc.getmboxes(request.user)
|
||||
ctx["mboxes"] = mbc.getmboxes(request.user)
|
||||
if request.method == "POST":
|
||||
form = FolderForm(request.POST)
|
||||
if form.is_valid():
|
||||
pf = request.POST.get("parent_folder", None)
|
||||
mbc.create_folder(form.cleaned_data["name"], pf)
|
||||
return ajax_response(request, ajaxnav=True, respmsg=_("Folder created"))
|
||||
return ajax_simple_response(dict(
|
||||
status="ok", respmsg=_("Mailbox created"), newmb=form.cleaned_data["name"], parent=pf
|
||||
))
|
||||
|
||||
ctx["form"] = form
|
||||
ctx["selected"] = None
|
||||
@@ -283,34 +272,39 @@ def editfolder(request, tplname="webmail/folder.html"):
|
||||
"action_classes" : "submit",
|
||||
"withunseen" : False,
|
||||
"selectonly" : True}
|
||||
ctx["folders"] = mbc.getmboxes(request.user)
|
||||
|
||||
if request.method == "POST":
|
||||
form = FolderForm(request.POST)
|
||||
if form.is_valid():
|
||||
pf = request.POST.has_key("parent_folder") \
|
||||
and request.POST["parent_folder"] or None
|
||||
ctx["selected"] = pf
|
||||
oldname, oldparent = separate_folder(request.POST["oldname"])
|
||||
extra = {}
|
||||
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):
|
||||
newname = form.cleaned_data["name"] if pf is None \
|
||||
else "%s.%s" % (pf, form.cleaned_data["name"])
|
||||
mbc.rename_folder(request.POST["oldname"], newname)
|
||||
extra["url"] = newname
|
||||
return ajax_response(request, ajaxnav=True,
|
||||
respmsg=_("Folder modified"), **extra)
|
||||
res["oldmb"] = oldname
|
||||
res["newmb"] = form.cleaned_data["name"]
|
||||
res["oldparent"] = oldparent
|
||||
res["newparent"] = pf
|
||||
del request.session["mbox"]
|
||||
return ajax_simple_response(res)
|
||||
|
||||
ctx["mboxes"] = mbc.getmboxes(request.user)
|
||||
ctx["form"] = form
|
||||
return ajax_response(request, status="ko", template=tplname, **ctx)
|
||||
|
||||
name = request.GET.get("name", None)
|
||||
if name is None:
|
||||
raise WebmailError(_("Invalid request"))
|
||||
shortname, parent = separate_folder(name)
|
||||
shortname, parent = separate_mailbox(name)
|
||||
ctx["mboxes"] = mbc.getmboxes(request.user, until_mailbox=parent)
|
||||
ctx["form"] = FolderForm()
|
||||
ctx["form"].fields["oldname"].initial = shortname
|
||||
ctx["form"].fields["name"].initial = name
|
||||
ctx["form"].fields["oldname"].initial = name
|
||||
ctx["form"].fields["name"].initial = shortname
|
||||
ctx["selected"] = parent
|
||||
return _render(request, tplname, ctx)
|
||||
|
||||
@@ -323,6 +317,8 @@ def delfolder(request):
|
||||
mbc = IMAPconnector(user=request.user.username,
|
||||
password=request.session["password"])
|
||||
mbc.delete_folder(name)
|
||||
if request.session.has_key("mbox"):
|
||||
del request.session["mbox"]
|
||||
return ajax_response(request)
|
||||
|
||||
@login_required
|
||||
@@ -404,7 +400,7 @@ def render_mboxes_list(request, imapc):
|
||||
curmbox = request.session.get("mbox", "INBOX")
|
||||
return _render_to_string(request, "webmail/folders.html", {
|
||||
"selected" : curmbox,
|
||||
"folders" : imapc.getmboxes(request.user),
|
||||
"mboxes" : imapc.getmboxes(request.user),
|
||||
"withunseen" : True
|
||||
})
|
||||
|
||||
@@ -438,13 +434,11 @@ def listmailbox(request, defmailbox="INBOX"):
|
||||
:return: a dictionnary
|
||||
"""
|
||||
mbox = request.GET.get("name", defmailbox)
|
||||
request.session["mbox"] = mbox
|
||||
set_nav_params(request)
|
||||
|
||||
lst = ImapListing(request.user, request.session["password"],
|
||||
baseurl="?action=listmailbox&name=%s&" % mbox,
|
||||
folder=mbox, **request.session["navparams"])
|
||||
|
||||
request.session["mbox"] = mbox
|
||||
return lst.render(request, request.session["pageid"])
|
||||
|
||||
def render_compose(request, form, posturl, email=None, insert_signature=False):
|
||||
|
||||
@@ -140,6 +140,7 @@ def render_link(linkdef, mdclass=None):
|
||||
t = Template("""<a href="{{ link.url }}" name="{{ link.name }}" title="{{ link.title }}"
|
||||
{% if link.modal %}data-toggle="ajaxmodal{% if link.autowidth %}-autowidth{% endif %}"{% endif %}
|
||||
{% if link.modalcb %}modalcb="{{ link.modalcb }}"{% endif %}
|
||||
{% if link.closecb %}closecb="{{ link.closecb }}"{% endif %}
|
||||
class="{{ mdclass }}{% if link.class %} {{ link.class }}{% endif %}"
|
||||
{% if link.confirm %} onclick="return confirm('{{ link.confirm }}')"{% endif %}>
|
||||
{% if link.img %}<i class="{{ link.img }}"></i>{% endif %}
|
||||
|
||||
@@ -3,30 +3,6 @@ $(document).ready(function() {
|
||||
$(document).on('click', 'a[data-toggle="ajaxmodal-autowidth"]', modalbox_autowidth);
|
||||
$(document).on('click', 'a[name=sendspam]', simple_ajax_request);
|
||||
$(document).on('click', 'a[name=sendvirus]', simple_ajax_request);
|
||||
|
||||
//parse_menubar('#topmenubar');
|
||||
//parse_menubar('#menubar');
|
||||
|
||||
/*infobox = new InfoBox({
|
||||
parent : $("menubar"),
|
||||
message : "Loading"
|
||||
});*/
|
||||
|
||||
/* Specific javascript code for the demo... not the best place */
|
||||
/*$$("a[name=sendspam], a[name=sendvirus]").addEvent("click", function(evt) {
|
||||
evt.stop();
|
||||
new Request.JSON({
|
||||
url: this.get("href"),
|
||||
onSuccess: function(response) {
|
||||
if (response.status == "ok") {
|
||||
infobox.info(gettext("Message sent"));
|
||||
infobox.hide(1);
|
||||
} else {
|
||||
infobox.error(response.respmsg);
|
||||
}
|
||||
}
|
||||
}).get();
|
||||
});*/
|
||||
});
|
||||
|
||||
var media_url = "";
|
||||
|
||||
+14
-4
@@ -97,7 +97,13 @@ History.prototype = {
|
||||
var res = this.base;
|
||||
|
||||
if (this.paramslength() != 0) {
|
||||
res += "?" + $.param(this.params);
|
||||
res += "?";
|
||||
$.each(this.params, function(key, value) {
|
||||
if (res != "?") {
|
||||
res += "&";
|
||||
}
|
||||
res += key + "=" + encodeURIComponent(value);
|
||||
});
|
||||
}
|
||||
return res;
|
||||
},
|
||||
@@ -144,9 +150,9 @@ History.prototype = {
|
||||
return this;
|
||||
},
|
||||
|
||||
getparam: function(name) {
|
||||
getparam: function(name, defvalue) {
|
||||
if (this.params[name] === undefined) {
|
||||
return "";
|
||||
return (defvalue != undefined) ? defvalue : undefined;
|
||||
}
|
||||
return this.params[name];
|
||||
},
|
||||
@@ -201,7 +207,7 @@ History.prototype = {
|
||||
return;
|
||||
}
|
||||
delete(this.force);
|
||||
this.from_string(location.hash);
|
||||
this.from_string(decodeURIComponent(location.hash));
|
||||
if (!this.serialized) {
|
||||
location.hash = this.options.deflocation;
|
||||
return;
|
||||
@@ -222,6 +228,10 @@ History.prototype = {
|
||||
} catch (e) {
|
||||
resp = { status: 'ko', respmsg: gettext('Internal Error') };
|
||||
}
|
||||
if (resp.status == "ko") {
|
||||
$("body").notify("error", resp.respmsg);
|
||||
return;
|
||||
}
|
||||
var callback = (resp.callback != undefined) ? resp.callback : "default";
|
||||
this.callbacks[callback](resp);
|
||||
}, this)
|
||||
|
||||
+20
-1
@@ -20,11 +20,30 @@ Poller.prototype = {
|
||||
this.url = url;
|
||||
this.options = $.extend({}, this.defaults, options);
|
||||
this.running_request = false;
|
||||
this.paused = false;
|
||||
this.reset();
|
||||
},
|
||||
|
||||
reset: function() {
|
||||
setTimeout($.proxy(this.send_request, this), this.options.interval);
|
||||
if (!this.paused) {
|
||||
this.tid = setTimeout($.proxy(this.send_request, this), this.options.interval);
|
||||
}
|
||||
},
|
||||
|
||||
pause: function() {
|
||||
this.paused = true;
|
||||
if (!this.tid) {
|
||||
return;
|
||||
}
|
||||
clearTimeout(this.tid);
|
||||
},
|
||||
|
||||
resume: function() {
|
||||
if (!this.paused) {
|
||||
return;
|
||||
}
|
||||
this.paused = false;
|
||||
this.reset();
|
||||
},
|
||||
|
||||
send_request: function() {
|
||||
|
||||
+9
-8
@@ -2,10 +2,12 @@
|
||||
* Collection of functions that are accessible to every page.
|
||||
*/
|
||||
|
||||
function modalbox(e, css, defhref, defcb) {
|
||||
function modalbox(e, css, defhref, defcb, defclosecb) {
|
||||
e.preventDefault();
|
||||
var href = (defhref != undefined) ? defhref : $(this).attr('href');
|
||||
var modalcb = (defcb != undefined) ? defcb : $(this).attr('modalcb');
|
||||
var $this = $(this);
|
||||
var href = (defhref != undefined) ? defhref : $this.attr('href');
|
||||
var modalcb = (defcb != undefined) ? defcb : $this.attr('modalcb');
|
||||
var closecb = (defclosecb != undefined) ? defclosecb : $this.attr("closecb");
|
||||
|
||||
if (href.indexOf('#') == 0) {
|
||||
$(href).modal('open');
|
||||
@@ -21,15 +23,14 @@ function modalbox(e, css, defhref, defcb) {
|
||||
var $div = $('<div id="modalbox" class="modal" >' + data + '</div>')
|
||||
.one('shown', function() {
|
||||
if (modalcb != undefined) {
|
||||
if (typeof modalcb === "function") {
|
||||
modalcb();
|
||||
} else {
|
||||
eval(modalcb + '()');
|
||||
}
|
||||
if (typeof modalcb === "function") modalcb(); else eval(modalcb + '()');
|
||||
}
|
||||
})
|
||||
.on('hidden', function() {
|
||||
$("#modalbox").remove();
|
||||
if (closecb != undefined) {
|
||||
if (typeof closecb === "function") closecb(); else eval(closecb + '()');
|
||||
}
|
||||
})
|
||||
.modal();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user