diff --git a/extensions/webmail/imap_listing.py b/extensions/webmail/imap_listing.py index e525f9430..310017911 100644 --- a/extensions/webmail/imap_listing.py +++ b/extensions/webmail/imap_listing.py @@ -209,8 +209,9 @@ class ImapListing(EmailListing): tpl = "webmail/index.html" tbltype = WMtable - def __init__(self, user, password, baseurl=None, **kwargs): + def __init__(self, user, password, baseurl=None, navparams={}, **kwargs): self.mbc = IMAPconnector(user=user, password=password) + self.navparams = navparams EmailListing.__init__(self, **kwargs) if baseurl: self.paginator.baseurl = baseurl diff --git a/extensions/webmail/main.py b/extensions/webmail/main.py index 4ae9a12c6..2f5a3c058 100644 --- a/extensions/webmail/main.py +++ b/extensions/webmail/main.py @@ -56,11 +56,16 @@ def getctx(status, level=1, **kwargs): def folder(request, name, updatenav=True): if not name: name = "INBOX" + order = request.GET.has_key("order") and request.GET["order"] or None 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 - order = request.GET.has_key("order") and request.GET["order"] or None + if order: + request.session["navparams"]["order"] = order + lst = ImapListing(request.user.username, request.session["password"], name, folder=name, order=order) page = lst.paginator.getpage(request.session["page"]) @@ -77,8 +82,10 @@ def folder(request, name, updatenav=True): @login_required def index(request): try: + navp = request.session.has_key("navparams") \ + and request.session["navparams"] or {} lst = ImapListing(request.user.username, request.session["password"], - "INBOX", folder="INBOX") + "INBOX", navparams=navp, folder="INBOX") except Exception as exp: return _render_error(request, {"error" : exp}) return lst.render(request, empty=True) @@ -94,8 +101,11 @@ def viewmail(request, folder, mail_id=None): header = fetchmail(request, folder, mail_id) if header: from templatetags.webextras import viewm_menu - pageid = request.session.has_key("page") and request.session["page"] or "1" - menu = viewm_menu("", folder, mail_id, pageid, + try: + pageid = request.session["page"] + except KeyError: + pageid = "1" + menu = viewm_menu("", request.session, mail_id, request.user.get_all_permissions()) folder, imapid = header["imapid"].split("/") mailcontent = render_to_string("webmail/viewmail.html", { @@ -132,8 +142,7 @@ def empty(request, name): return folder(request, name, False) def render_compose(request, form, bodyheader=None, body=None): - menu = compose_menu("", request.session["folder"], request.session["page"], - request.user.get_all_permissions()) + menu = compose_menu("", request.session, request.user.get_all_permissions()) content = render_to_string("webmail/compose.html", { "form" : form, "bodyheader" : bodyheader, "body" : body }) @@ -156,7 +165,7 @@ def compose(request): s = smtplib.SMTP(parameters.get("webmail", "SMTP_SERVER")) s.sendmail(msg['From'], [msg['To']], msg.as_string()) s.quit() - return folder(request, request.session["folder"], False) + return folder(request, request.session["navparams"]["folder"], False) form = ComposeMailForm() form.fields["from_"].initial = request.user.username diff --git a/extensions/webmail/templates/index.html b/extensions/webmail/templates/index.html index 9ff2b3f61..c55de985e 100644 --- a/extensions/webmail/templates/index.html +++ b/extensions/webmail/templates/index.html @@ -49,6 +49,15 @@ td { position: relative; } +th { + -moz-box-shadow: 0px -15px 10px -10px rgba(0,0,0,0.6) inset; + -webkit-box-shadow: 0px -15px 10px -10px rgba(0,0,0,0.6) inset; +} + +th.selected { + background: #EEEEEE; +} + .draggable { cursor: move; } @@ -62,6 +71,12 @@ tr { } {% endblock %} {% block js %} + navparams = new Hash({ + {% for k, v in navparams.items %} + {{ k }} : "{{ v }}", + {% endfor %} + }); + updatelisting = function(resp, overflow) { if (!$defined(overflow)) { overflow = "auto"; @@ -100,7 +115,7 @@ tr { if (event.target.parentNode.id) { var url = event.target.parentNode.id + "/"; event.target.parentNode.setStyle("background", "#ffffcc"); - location.hash = url; + current_anchor.baseurl(url).update(); } } register_callback("viewmail", function(resp) { @@ -128,7 +143,7 @@ tr { loadCompose = function(event) { event.stop(); - location.hash = "compose/"; + current_anchor.baseurl("compose/").update(); } register_callback("compose", compose_callback); @@ -143,22 +158,17 @@ tr { obj = event.target; } event.stop(); - location.hash = obj.get("href"); + current_anchor.parse_string(obj.get("href"), true).setparams(navparams); + current_anchor.update(); } register_callback("folder", function(resp) { updatelisting(resp, "auto"); - /*var drag_group = new Drag.Group({ - filter: function(item) { return item.hasClass("active"); }, - drag: { - onComplete: function(item) { - item.dispose(); - delete(item); - }, - onEnter: function(item, droppable) { - alert(droppable); - } - } - });*/ + if (navparams.has("order")) { + src = navparams.get("order").charAt(0) == "-" ? "down_arrow.png" : "up_arrow.png"; + th = $$("th[id=" + navparams.get("order").substring(1) + "]"); + th.getElement("img").set("src", "/static/pics/" + src); + th.addClass("selected"); + } $$("td[class*=draggable]").each(function(item) { item.makeDraggable({ droppables: ".droppable", @@ -207,36 +217,28 @@ tr { }); }); $$("tr").addEvent("dblclick", viewmail); - var sortOrder = ""; - $$("th[class=sortable]").addEvent("click", function(evt) { + $$("th[class*=sortable]").addEvent("click", function(evt) { var tmp = "?"; - - if (sortOrder == "") { - test = /order=([\+\-]\w+$|&)/.exec(location.hash); - if (test) { - sortOrder = test[1]; - } + var order = (navparams.has("order")) ? navparams.get("order") : ""; + + if (order == "") { + order = current_anchor.getparam("order"); } - if (sortOrder.substring(1) == evt.target.id) { - var sign = (sortOrder.charAt(0) == '+') ? '-' : '+'; - sortOrder = sign + evt.target.id; + if (order.substring(1) == evt.target.id) { + var sign = (order.charAt(0) == '+') ? '-' : '+'; + order = sign + evt.target.id; } else { - sortOrder = "-" + evt.target.id; + order = "-" + evt.target.id; } - if (location.hash.indexOf("?") != -1) { - if (location.hash.indexOf("order") != -1) { - location.hash = location.hash.replace(/order=[\+\-]\w+$|&/, - "order=" + sortOrder); - return; - } - tmp = "&"; - } - location.hash += tmp + "order=" + sortOrder; + navparams.set("order", order); + current_anchor.setparams(navparams).update(); }); }); navbarcallback = function(event) { - loadFolder(event, event.target.getParent()); + event.stop(); + current_anchor.setparams(navparams); + current_anchor.parse_string(event.target.getParent().get("href")).update(); } foldercallback = function(event) { @@ -244,10 +246,9 @@ tr { loadFolder(event, event.target); } - ajaxListener(updatelisting); + ajaxListener("INBOX", updatelisting); $$("a[name=loadfolder]").addEvent("click", foldercallback); $("navbar").getChildren("a").addEvent("click", navbarcallback); - $$("a[name=compose]").addEvent("click", loadCompose); {% endblock %} {% block middletitle %}{% trans "Webmail" %}{% endblock %} {% block leftcol %} diff --git a/extensions/webmail/templatetags/webextras.py b/extensions/webmail/templatetags/webextras.py index 5d2d2578b..826424f01 100644 --- a/extensions/webmail/templatetags/webextras.py +++ b/extensions/webmail/templatetags/webextras.py @@ -7,11 +7,27 @@ from mailng.extensions.webmail.imap_listing import IMAPheader register = template.Library() +def backurl(session, **kwargs): + res = session["folder"] + params = "" + for key in ["page"]: + if key in session.keys(): + if params != "": + params += "&" + params += "%s=%s" % (key, session[key]) + for k, v in kwargs.iteritems(): + if params != "": + params += "&" + params += "%s=%s" % (k, v) + if params != "": + res += "?%s" % params + return res + @register.simple_tag -def viewm_menu(selection, folder, mail_id, page_id, perms): +def viewm_menu(selection, session, mail_id, perms): entries = [ {"name" : "back", - "url" : folder + "?page=%s" % page_id + "&menu=1", + "url" : "%s?page=%s" % (session["folder"], session["page"]), "img" : "/static/pics/back.png", "label" : _("Back")}, {"name" : "reply", @@ -33,10 +49,10 @@ def viewm_menu(selection, folder, mail_id, page_id, perms): "perms" : perms}) @register.simple_tag -def compose_menu(selection, folder, page_id, perms): +def compose_menu(selection, session, perms): entries = [ {"name" : "back", - "url" : folder + "?page=%s" % page_id + "&menu=1", + "url" : "%s?page=%s" % (session["folder"], session["page"]), "img" : "/static/pics/back.png", "label" : _("Back")}, {"name" : "sendmail", diff --git a/lib/email_listing.py b/lib/email_listing.py index c39b604ce..a2d36e11d 100644 --- a/lib/email_listing.py +++ b/lib/email_listing.py @@ -116,6 +116,7 @@ class EmailListing: "navbar" : self.render_navbar(page), "folders" : self.getfolders(), "selection" : self.folder, + "navparams" : self.navparams, "current_page" : pageid }) diff --git a/static/js/common.js b/static/js/common.js index 0804351c4..d2bd80afb 100644 --- a/static/js/common.js +++ b/static/js/common.js @@ -15,24 +15,14 @@ register_callback = function(name, callback) { current_anchor = null; check_anchor = function() { - if (current_anchor == document.location.hash) { + if (current_anchor.serialized == document.location.hash) { return; } - current_anchor = document.location.hash; - if (!current_anchor) { - query = "INBOX/"; // Default location + current_anchor.from_string(document.location.hash); + if (!current_anchor.serialized) { + query = current_anchor.deflocation; } else { - var splits = current_anchor.substring(1).split('?'); - var section = (splits[0] != "") ? splits[0] : "INBOX"; - delete splits[0]; - var params = splits.join('&'); - if (section[section.length - 1] != '/') { - section += "/"; - } - var query = section; - if (params != "") { - query += "?" + params; - } + query = current_anchor.serialized.substring(1); } new Request.JSON({url: query, onSuccess: function(resp) { callback = ($defined(resp.callback)) ? resp.callback : "default"; @@ -40,11 +30,108 @@ check_anchor = function() { }}).get(); } -ajaxListener = function(defcallback) { +ajaxListener = function(deflocation, defcallback) { + current_anchor = new HashWrapper(deflocation); register_callback("default", defcallback); check_anchor.periodical(300); } +/* +* +*/ +function HashWrapper(deflocation) { + this.deflocation = deflocation; + this.params = $H(); + this.base = ''; + this.serialized = null; + + this.reset = function() { + this.base = null; + this.params.empty(); + return this; + }; + + this.parse_string = function(value, reset) { + var splits = (value.charAt(0) == '#') + ? value.substring(1).split('?') : value.split('?'); + + if (splits.length == 0) { + return this; + } + if (!$defined(reset)) { + reset = false; + } + if (reset) { + this.reset(); + } + this.base = (splits[0] == "") ? this.deflocation : splits[0]; + if (this.base[this.base.length - 1] != '/') { + this.base += '/'; + } + if (splits.length > 1) { + params = splits[1].split('&'); + for (var i = 0; i < params.length; i++) { + tmp = params[i].split('='); + this.setparam(tmp[0], tmp[1]); + } + } + return this; + }; + + this.from_string = function(value, reset) { + this.parse_string(value); + this.serialized = value; + return this; + }; + + this.serialize = function() { + var res = this.base; + + if (this.params.getLength() != 0) { + res += "?" + this.params.toQueryString(); + } + return res; + }; + + this.update = function() { + location.hash = this.serialize(); + }; + + this.setparam = function(name, value) { + this.params.set(name, value); + return this; + }; + + this.setparams = function(params) { + this.params.extend(params); + return this; + }; + + this.getparam = function(name) { + if (!this.params.has(name)) { + return ""; + } + return this.params.get(name); + } + + this.baseurl = function(value) { + this.reset(); + this.base = value; + if (this.base[this.base.length - 1] != '/') { + this.base += '/'; + } + return this; + }; + + this.delparam = function(name) { + if (!this.params.has(name)) { + return false; + } + this.params.erase(name); + return this; + }; +}; + parse_menubar = function(id) { if ($(id)) { $(id).getElements('li.dropdown').each( function( elem ){ diff --git a/static/pics/down_arrow.png b/static/pics/down_arrow.png new file mode 100644 index 000000000..f5f128b26 Binary files /dev/null and b/static/pics/down_arrow.png differ diff --git a/static/pics/up_arrow.png b/static/pics/up_arrow.png new file mode 100644 index 000000000..524fb5ebd Binary files /dev/null and b/static/pics/up_arrow.png differ diff --git a/templates/common/tables.html b/templates/common/tables.html index 43d065b6a..51624c85e 100644 --- a/templates/common/tables.html +++ b/templates/common/tables.html @@ -2,7 +2,10 @@ {% for c in table.columns %} - {{ c|safe }} + + {{ c|safe }} + + {% endfor %}