From 67357e66af166f72eaac306233778f21dd4a00ad Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Thu, 17 Mar 2011 17:41:10 +0100 Subject: [PATCH 1/4] see #55: folders manipulation. Work in progress. This commit adds the following features: * Folder creation, * Folder modification, * Folder removal. There are still issues with subfolders but they should not be too complicated to fix. I've also done some javascript refactoring. --- .../postfix_autoreply/autoreply.html | 6 + extensions/postfix_autoreply/views.py | 16 +-- extensions/webmail/forms.py | 2 + extensions/webmail/lib.py | 14 ++ extensions/webmail/static/css/folders.css | 99 ++++++++++++++ extensions/webmail/static/css/webmail.css | 89 ++++-------- extensions/webmail/static/js/fdmenu.js | 97 +++++++++++++ .../webmail/templates/webmail/folder.html | 56 ++++++++ .../webmail/templates/webmail/folders.html | 9 +- .../webmail/templates/webmail/index.html | 24 +++- extensions/webmail/templatetags/webextras.py | 15 ++- extensions/webmail/urls.py | 3 + extensions/webmail/views.py | 75 ++++++++++- lib/__init__.py | 12 +- static/js/form.js | 127 +++++++++++------- static/pics/go-down.png | Bin 0 -> 325 bytes templates/common/email_listing.html | 1 + 17 files changed, 504 insertions(+), 141 deletions(-) create mode 100644 extensions/webmail/static/css/folders.css create mode 100644 extensions/webmail/static/js/fdmenu.js create mode 100644 extensions/webmail/templates/webmail/folder.html create mode 100644 static/pics/go-down.png diff --git a/extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html b/extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html index edfbd2fab..b402bfc34 100644 --- a/extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html +++ b/extensions/postfix_autoreply/templates/postfix_autoreply/autoreply.html @@ -16,6 +16,12 @@ {% endblock %} diff --git a/extensions/postfix_autoreply/views.py b/extensions/postfix_autoreply/views.py index 0a176e509..580076fc0 100644 --- a/extensions/postfix_autoreply/views.py +++ b/extensions/postfix_autoreply/views.py @@ -7,13 +7,13 @@ from django.contrib.auth.decorators \ from django.contrib import messages from django.core.urlresolvers import reverse from django.utils.translation import ugettext as _ -from modoboa.lib import _render, _ctx_ok, _ctx_ko, is_not_localadmin +from modoboa.lib import _render, ajax_response, is_not_localadmin from forms import * from models import * @login_required @is_not_localadmin('boxerror') -def autoreply(request): +def autoreply(request, tplname="postfix_autoreply/autoreply.html"): mb = Mailbox.objects.get(user=request.user.id) try: arm = ARmessage.objects.get(mbox=mb.id) @@ -34,17 +34,13 @@ def autoreply(request): arm.save() messages.info(request, _("Auto reply message updated successfully."), fail_silently=True) - ctx = _ctx_ok(reverse(userprefs.views.index)) - else: - ctx = _ctx_ko("postfix_autoreply/autoreply.html", { - "form" : form, "error" : error - }) - return HttpResponse(simplejson.dumps(ctx), - mimetype="application/json") + return ajax_response(request, url=reverse(userprefs.views.index)) + return ajax_response(request, status="ko", template=tplname, + form=form, error=error) form = ARmessageForm(instance=arm) if arm is not None: form.fields['untildate'].initial = arm.untildate - return _render(request, "postfix_autoreply/autoreply.html", { + return _render(request, tplname, { "form" : form }) diff --git a/extensions/webmail/forms.py b/extensions/webmail/forms.py index 32c5ede87..1de6598e1 100644 --- a/extensions/webmail/forms.py +++ b/extensions/webmail/forms.py @@ -7,3 +7,5 @@ class ComposeMailForm(forms.Form): cc = forms.CharField(label=_("Cc"), widget=forms.Textarea(), required=False) subject = forms.CharField(label=_("Subject"), max_length=255) +class FolderForm(forms.Form): + name = forms.CharField() diff --git a/extensions/webmail/lib.py b/extensions/webmail/lib.py index 949d4795d..8cbb4d495 100644 --- a/extensions/webmail/lib.py +++ b/extensions/webmail/lib.py @@ -303,6 +303,20 @@ class IMAPconnector(object): self.m.select(self._encodefolder(folder)) self.m.expunge() + def create_folder(self, name, parent=None): + if parent is not None: + name = "%s.%s" % (parent, name) + typ, data = self.m.create(self._encodefolder(name)) + if typ == "NO": + return False + return True + + def delete_folder(self, name): + typ, data = self.m.delete(self._encodefolder(name)) + if typ == "NO": + return False + return True + def getquota(self, folder): status, data = self.m.getquotaroot(self._encodefolder(folder)) if status == "OK": diff --git a/extensions/webmail/static/css/folders.css b/extensions/webmail/static/css/folders.css new file mode 100644 index 000000000..796f50419 --- /dev/null +++ b/extensions/webmail/static/css/folders.css @@ -0,0 +1,99 @@ +#folders { + float: left; + width: 150px; +} + +#folders2 { + border: 1px solid #ccc; + background-color: #eee; + position: absolute; + top: 100px; + left: 20px; + right: 20px; + bottom: 40px; + overflow-x: hidden; + overflow-y: auto; +} + +#fdcreate { + position: absolute; + top: 370px; + left: 20px; + right: 20px; + text-align: center; +} + +.box h3 { + font-size: small; + margin: 2px 0px 2px 0px; + text-align: center; +} + +.box ul { + list-style: none; + padding: 5px 5px; + margin: 0; +} + +.box li { + margin-bottom: 4px; + padding-left: 15px; +} + +.box li.selected { + background-color: #FFFF77; +} + +.box a:link, .box a:visited { + background: transparent; + color: black; + text-decoration: none; + margin-left: 5px; +} + +.box a:hover { + color: #6AB0C5; + text-decoration: none; +} + +.box img { + border: 0; +} + +.box li.dragging { + background-color: #6AB0C5; +} + +img.aligned { + float: left; +} + +img.footer { + float: none; + vertical-align: bottom; +} + +li.inbox { + background: url("/static/pics/overview.png") no-repeat; +} + +li.trash { + background: url("/static/pics/trash.png") no-repeat; +} + +li.folder { + background: url("/static/pics/folder.png") no-repeat; +} + +li.subfolders { + background: url("/static/pics/subfolders.png") no-repeat; +} + +ul.hidden { + display: none; +} + +ul.visible { + display: block; + padding-bottom: 0; +} \ No newline at end of file diff --git a/extensions/webmail/static/css/webmail.css b/extensions/webmail/static/css/webmail.css index b87973c89..1928e05ac 100644 --- a/extensions/webmail/static/css/webmail.css +++ b/extensions/webmail/static/css/webmail.css @@ -12,11 +12,6 @@ html > body #listing { bottom: 35px; } -#folders { - float: left; - width: 150px; -} - /*thead tr { position: relative; top: expression(offsetParent.scrollTop); @@ -50,60 +45,6 @@ html > body #listing { -khtml-user-select: none; /* Webkit (Safari, Chrome) */ } -.box h3 { - font-size: small; - margin: 2px 0px 2px 0px; - text-align: center; -} - -.box ul { - list-style: none; - padding: 5px 5px; - margin: 0; -} - -.box li { - margin-bottom: 4px; - padding-left: 20px; -} - -.box li.selected { - background-color: #FFFF77; -} - -.box a:link, .box a:visited { - background: transparent; - color: black; - text-decoration: none; - margin-left: 5px; -} - -.box a:hover { - color: #6AB0C5; - text-decoration: none; -} - -.box img { - float: left; - border: 0; -} - -li.inbox { - background: url("/static/pics/overview.png") no-repeat; -} - -li.trash { - background: url("/static/pics/trash.png") no-repeat; -} - -li.folder { - background: url("/static/pics/folder.png") no-repeat; -} - -li.subfolders { - background: url("/static/pics/subfolders.png") no-repeat; -} - th[class*=sortable] { cursor: pointer; /*-moz-box-shadow: 0px -15px 10px -10px rgba(0,0,0,0.6) inset; @@ -124,16 +65,11 @@ th.selected { position: static; } -.box li.dragging { - background-color: #6AB0C5; -} - ul.hidden { display: none; } ul.visible { - background-color: white; display: block; padding-bottom: 0; } @@ -219,4 +155,27 @@ textarea:hover { #quotatext { padding: 2px 0 0 2px; float: left; -} \ No newline at end of file +} + +/* context menu specific */ +#fdmenu { border:1px solid #999; padding:0; background:#eee; width:150px; display:none; } +#fdmenu .separator { border-top:1px solid #999; } +#fdmenu ul { list-style-type:none; margin:0; padding:0; } +#fdmenu li { margin:0; padding:0; } +#fdmenu li a { display:block; padding:5px 10px 5px 5px; font-size:12px; text-decoration:none; font-family:tahoma,arial,sans-serif; color:#000; } +#fdmenu li a:hover { background-color:#ddd; } +#fdmenu img { float:left; margin: 0 5px 0 0; } + +.folder_menu { + float: right; + opacity: 0.8; +} + +.folder_btn { + float: right; + margin: 3px; +} + +.folder_menubar { + clear: both; +} diff --git a/extensions/webmail/static/js/fdmenu.js b/extensions/webmail/static/js/fdmenu.js new file mode 100644 index 000000000..2c540cae9 --- /dev/null +++ b/extensions/webmail/static/js/fdmenu.js @@ -0,0 +1,97 @@ +/* + * Simple dropdown menu plugin used for folders manipulation. + * + */ +var FdMenu = new Class({ + Implements: [Options], + + options: { + media_url: "", + modify_url: "", + delete_url: "" + }, + + add_entry: function(name, label, pic, url, onclick) { + var item = new Element("li"); + var picpath = this.options.media_url + "pics/" + pic; + + this[name] = new Element("a") + .set("html", " " + label) + .addEvent("click", onclick) + .inject(item); + item.inject(this.list); + }, + + initialize: function(options) { + this.setOptions(options); + + this.container = new Element("div", {"id" : "fdmenu"}) + .addClass("fdmenu"); + this.list = new Element("ul"); + + this.add_entry("modbutton", gettext("Edit folder"), + "edit.png", this.options.modify_url, function(evt) { + evt.stop(); + SqueezeBox.initialize({ + size: {x: 350, y: 400}, + handler: 'iframe' + }); + SqueezeBox.open(this.get("href")); + }); + this.add_entry("delbutton", gettext("Delete folder"), "remove.png", + this.options.delete_url, function(evt) { + evt.stop(); + if (!confirm(gettext("Delete folder?"))) { + return; + } + new Request.JSON({ + url: this.get("href"), + method: "GET", + onSuccess: function(resp) { + if (resp.status == "ok") { + infobox.info(gettext("Folder deleted.")); + var id = current_anchor.update.delay(500, current_anchor, 1); + } else { + infobox.error(gettext("Failed to delete folder")); + infobox.hide(2); + } + } + }).send(); + }); + this.list.inject(this.container); + this.shown = false; + + $(document.body).addEvent("click", function() { + if (this.shown) { + this.hide(); + } + }.bind(this)); + //this.fx = new Fx.Slide(this.container); + }, + + show: function(origin, folder) { + var position = origin.getPosition(); + + this.container.setStyles({ + position: "absolute", + top: position.y + 5, + left: position.x + 5, + display: "block" + }); + this.container.inject(document.body); + this.shown = true; + this.modbutton.set("href", this.options.modify_url + "?name=" + folder); + }, + + hide: function() { + this.container.setStyles({ + display: "none" + }); + this.container.dispose(); + this.shown = false; + }, + + toggle: function(origin, folder) { + return (!this.shown) ? this.show(origin, folder) : this.hide(); + } +}); \ No newline at end of file diff --git a/extensions/webmail/templates/webmail/folder.html b/extensions/webmail/templates/webmail/folder.html new file mode 100644 index 000000000..59d0f3492 --- /dev/null +++ b/extensions/webmail/templates/webmail/folder.html @@ -0,0 +1,56 @@ +{% extends "layout_simple.html" %} +{% load i18n %} +{% block html_head %} + + + +{% endblock %} +{% block content %} +

{{ title }}

+
+ {% include "common/genericform.html" %} +
+ +
+
+ {% include "webmail/folders.html" %} +
+
+ +
+
+{% endblock %} diff --git a/extensions/webmail/templates/webmail/folders.html b/extensions/webmail/templates/webmail/folders.html index ce21f6cf7..5956654a9 100644 --- a/extensions/webmail/templates/webmail/folders.html +++ b/extensions/webmail/templates/webmail/folders.html @@ -1,6 +1,13 @@ {% load i18n %} {% load webextras %} +{% if titlebar %} + + {% trans 'Add a new folder' %} +

{% trans "Folders" %}

+{% endif %} diff --git a/extensions/webmail/templates/webmail/index.html b/extensions/webmail/templates/webmail/index.html index 9c9443966..d82ac2dd4 100644 --- a/extensions/webmail/templates/webmail/index.html +++ b/extensions/webmail/templates/webmail/index.html @@ -1,8 +1,8 @@ - {% extends "common/email_listing.html" %} {% load i18n %} {% block css %} + {% endblock %} {% block js %} quota_pb = new ProgressBar({ @@ -19,9 +19,29 @@ updatelisting(resp); if ($defined(resp.folders)) { $("folders").set("html", resp.folders); + $$("li[class*=clickable]").removeEvents(); + SqueezeBox.assign($$('a[class=boxed]'), { + parse: 'rel' + }); + + var fdbuttons = $$("img[class*=footer]"); + var fdmenu = new FdMenu({ + media_url: "{{MEDIA_URL}}", + modify_url: "{% url extensions.webmail.views.editfolder %}", + delete_url: "{% url extensions.webmail.views.delfolder %}" + }); + + fdbuttons.addEvents({ + click: function(evt) { + var parent = this.getParent(); + var fdname = parent.getFirst("a[name=loadfolder]").get("href"); + + fdmenu.toggle(this, fdname); + evt.stop(); + } + }); } select($$("a[href=" + current_anchor.getbaseurl() + "]")); - $$("li[class*=clickable]").removeEvents(); $$("li[class*=clickable]").addEvent("click", function(evt) { $$("ul[name=" + evt.target.get("name") + "]").each(function(item) { if (item.hasClass("hidden")) { diff --git a/extensions/webmail/templatetags/webextras.py b/extensions/webmail/templatetags/webextras.py index bfd310c9b..cbeb5bcba 100644 --- a/extensions/webmail/templatetags/webextras.py +++ b/extensions/webmail/templatetags/webextras.py @@ -116,8 +116,14 @@ def listing_menu(selection, folder, user): return menu + searchbar @register.simple_tag -def print_folders(folders, selected=None): +def print_folders(folders, selected=None, withunseen=False, withmenu=False): result = "" + + import pprint + pprint.PrettyPrinter(indent=2).pprint(folders) + print "END" + + for fd in folders: if fd.has_key("class"): cssclass = fd["class"] @@ -131,14 +137,17 @@ def print_folders(folders, selected=None): if selected == label: cssclass += " selected" result += "
  • \n" % (name, cssclass) + if withmenu: + result += "" % settings.MEDIA_URL cssclass = "" - if fd.has_key("unseen"): + if withunseen and fd.has_key("unseen"): label += " (%d)" % fd["unseen"] cssclass = "unseen" result += "%s\n" \ % (fd.has_key("path") and fd["path"] or fd["name"], cssclass, label) if fd.has_key("sub"): - result += "\n" + result += "\n" result += "
  • \n" return result diff --git a/extensions/webmail/urls.py b/extensions/webmail/urls.py index 1799bac60..201341160 100644 --- a/extensions/webmail/urls.py +++ b/extensions/webmail/urls.py @@ -7,6 +7,9 @@ urlpatterns = patterns('modoboa.extensions.webmail.views', (r'^mark/(?P.+)/$', "mark"), (r'^empty/(?P.+)/$', "empty"), (r'^compact/(?P.+)/$', "compact"), + (r'^newfolder/$', "newfolder"), + (r'^editfolder/$', 'editfolder'), + (r'^delfolder/$', 'delfolder'), (r'^(?P.+)/(?P[\w\-\+]+)/part/$', 'getattachment'), (r'^(?P.+)/(?P[\w\-\+]+)/delete/$', 'delete'), (r'^(?P.+)/(?P[\w\-\+]+)/content/$', 'getmailcontent'), diff --git a/extensions/webmail/views.py b/extensions/webmail/views.py index 43e71a95b..9a5eded9a 100644 --- a/extensions/webmail/views.py +++ b/extensions/webmail/views.py @@ -10,7 +10,8 @@ from django.core.urlresolvers import reverse from django.contrib.auth.decorators import login_required from modoboa.admin.models import Mailbox from modoboa.lib import parameters, _render, _render_error, \ - getctx, is_not_localadmin, _render_to_string, split_mailbox + getctx, is_not_localadmin, _render_to_string, split_mailbox, \ + ajax_response from modoboa.lib.email_listing import parse_search_parameters, Paginator from lib import * from forms import * @@ -63,9 +64,12 @@ def __render_common_components(request, folder_name, lst=None, content=None, men % _("This folder contains no messages") ret = { - "folders" : render_to_string("webmail/folders.html", { + "folders" : _render_to_string(request, "webmail/folders.html", { + "titlebar" : True, "selected" : request.session["folder"], - "folders" : mbc.getfolders(request.user) + "folders" : mbc.getfolders(request.user), + "withmenu" : True, + "withunseen" : True }), "menu" : menu, "listing" : content, @@ -423,3 +427,68 @@ def forward(request, folder, mail_id): email = ForwardModifier(msg, request.user, form, addrfull=True, links="1") return render_compose(request, form, reverse(forward, args=[folder, mail_id]), email) + +@login_required +@is_not_localadmin() +def newfolder(request, tplname="webmail/folder.html"): + mbc = IMAPconnector(user=request.user.username, + password=request.session["password"]) + ctx = {"title" : _("Create a new folder"), + "fname" : "newfolder", + "submit_label" : _("Create"), + "withmenu" : False, + "withunseen" : False} + ctx["folders"] = mbc.getfolders(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 + if mbc.create_folder(form.cleaned_data["name"], pf): + return ajax_response(request, ajaxnav=True) + + ctx["form"] = form + ctx["selected"] = None + return ajax_response(request, status="ko", template=tplname, **ctx) + + ctx["form"] = FolderForm() + ctx["selected"] = None + return _render(request, tplname, ctx) + +@login_required +@is_not_localadmin() +def editfolder(request, tplname="webmail/folder.html"): + mbc = IMAPconnector(user=request.user.username, + password=request.session["password"]) + ctx = {"title" : _("Edit folder"), + "fname" : "editfolder", + "submit_label" : _("Update"), + "withmenu" : False, + "withunseen" : False} + ctx["folders"] = mbc.getfolders(request.user) + if not request.GET.has_key("name") or request.GET["name"] == "": + return + name = request.GET["name"] + if name.count("."): + parts = name.split(".") + name = parts[-1] + parent = ".".join(parts[0:len(parts) - 1]) + else: + parent = None + print parent + ctx["form"] = FolderForm() + ctx["form"].fields["name"].initial = name + parts = request + ctx["selected"] = parent + return _render(request, tplname, ctx) + +@login_required +@is_not_localadmin() +def delfolder(request): + if not request.GET.has_key("name") or request.GET["name"] == "": + return + mbc = IMAPconnector(user=request.user.username, + password=request.session["password"]) + if mbc.delete_folder(request.GET["name"]): + return ajax_response(request) + return ajax_response(request, status="ko") diff --git a/lib/__init__.py b/lib/__init__.py index 476e28a3e..0a9586e9c 100644 --- a/lib/__init__.py +++ b/lib/__init__.py @@ -74,7 +74,7 @@ def getctx(status, level=1, callback=None, **kwargs): ctx[kw] = v return ctx -def ajax_response(request, status="ok", url=None, template=None, **kwargs): +def ajax_response(request, status="ok", url="", ajaxnav=False, template=None, **kwargs): """Ajax response shortcut Simple shortcut that sends an JSON response. If a template is @@ -94,10 +94,12 @@ def ajax_response(request, status="ok", url=None, template=None, **kwargs): content = _render_to_string(request, template, ctx) else: content = "" - return HttpResponse(simplejson.dumps({"status" : status, - "content" : content, - "url" : url}), - mimetype="application/json") + jsonctx = {"status" : status, "content" : content} + if ajaxnav: + jsonctx["ajaxnav"] = True + else: + jsonctx["url"] = url + return HttpResponse(simplejson.dumps(jsonctx), mimetype="application/json") def decode(s, encodings=('utf8', 'latin1', 'windows-1252', 'ascii'), charset=None): if charset is not None: diff --git a/static/js/form.js b/static/js/form.js index 15c4af0c3..6c4dab943 100644 --- a/static/js/form.js +++ b/static/js/form.js @@ -1,59 +1,82 @@ -window.addEvent("domready", function() { - ajax_submit = function(event, error_callbacks) { - var form = event.target; - var myid = form.get("id"); +var error_callbacks = { + mbaliasform: function() { + if ($("id_domain").value == 0) { + $("id_mboxes").set("html", ""); + } + mbaliasform_init(); + }, + permform: function() { + if ($defined($("id_domain"))) { + $("id_domain").options[0].setProperty("selected", "selected"); + domadminform_init(); + } + } +}; - event.stop(); - form.set('send', { - onSuccess: function(responseText) { - var response = JSON.decode(responseText); +var extra_data_callbacks = { - if (response.status == "ko") { - $(document.body).set("html", response.content); - $(document.body).addEvent("submit", default_submit); - if ($defined(error_callbacks[myid])) { - error_callbacks[myid](); - } - } else { - if (response.url != "") { - parent.location.href = response.url; - } - parent.SqueezeBox.close(); +}; + +function register_callback(hash, name, callback) { + if ($defined(hash[name])) { + return false; + } + hash[name] = callback; + return true; +} + +function register_error_callback(name, callback) { + return register_callback(error_callbacks, name, callback); +} + +function register_extra_data_callback(name, callback) { + return register_callback(extra_data_callbacks, name, callback); +} + +function ajax_submit(event) { + var form = event.target; + var myid = form.get("id"); + var data = form.toQueryString(); + + event.stop(); + if ($defined(extra_data_callbacks[myid])) { + if (data != "") { + data += "&"; + } + data += extra_data_callbacks[myid](); + } + + new Request({ + method: form.get("method"), + data: data, + onSuccess: function(responseText) { + var response = JSON.decode(responseText); + + if (response.status == "ko") { + $(document.body).set("html", response.content); + $(document.body).addEvent("submit", ajax_submit); + if ($defined(error_callbacks[myid])) { + error_callbacks[myid](); + } + } else { + if ($defined(response.url) && response.url != "") { + parent.location.href = response.url; + } + if ($defined(response.ajaxnav)) { + parent.current_anchor.update(1); } - }, - onFailure: function(xhr) { - parent.document.getElement('iframe').setStyles({width: 800, height: 600}); - $(document.body).set("html", xhr.responseText); - } - }); - form.send(); - }; + parent.SqueezeBox.close(); + } + }, + onFailure: function(xhr) { + parent.document.getElement('iframe').setStyles({width: 800, height: 600}); + $(document.body).set("html", xhr.responseText); + } + }).send(); +} - default_submit = function(event) { - var error_callbacks = { - mbaliasform: function() { - if ($("id_domain").value == 0) { - $("id_mboxes").set("html", ""); - } - mbaliasform_init(); - }, - armform: function() { - new Calendar({id_untildate: "Y-m-d"}, { - tweak: {x: -100, y:-100} - }); - }, - permform: function() { - if ($defined($("id_domain"))) { - $("id_domain").options[0].setProperty("selected", "selected"); - domadminform_init(); - } - } - }; - - ajax_submit(event, error_callbacks); - }; - - $(document.body).addEvent("submit", default_submit); +window.addEvent("domready", function() { + $(document.body).addEvent("submit", ajax_submit); $$("input[type!=submit]", "select").addEvents({ focus: function(evt) { diff --git a/static/pics/go-down.png b/static/pics/go-down.png new file mode 100644 index 0000000000000000000000000000000000000000..adb59b0afe57c9c2b187b7c31da432b5304c37d3 GIT binary patch literal 325 zcmeAS@N?(olHy`uVBq!ia0vp^93afW1|*O0@9PFqjKx9jP7LeL$-D$|*pj^6T^Rm@ z;DWu&Cj&(|3p^r=f!eQwFr$;k>JffI>$-T^vIsE+?ln zFzt>Cb51i;i)3SCYuj&MA7_8%P{Hg*AYff~;Ih(^=db^7_sidJoBHE_@7DhUhg+3^ z3fa_VG{x7~{rmgtweaEg{PmJ`|Ns7#S37s)z<~n+dry_?8?!ebHa{lL!!svdQewyc zw4=V^^SQzcUfxQ(?|(mj{{Q2@8yy2C&2H>&t-rnK%xud7*4fe$`|j4)>2~xxev`VN zKl3sFx|p8SgoK9Z!$3n1oI7wp;pGH9xpndf-X8<98AX+O7?$-rP3Z`H<`47`gQu&X J%Q~loCIDR_fye*= literal 0 HcmV?d00001 diff --git a/templates/common/email_listing.html b/templates/common/email_listing.html index eb23499c1..a4c5c8828 100644 --- a/templates/common/email_listing.html +++ b/templates/common/email_listing.html @@ -5,6 +5,7 @@ + {% block css %}{% endblock %} {% url django.views.i18n.javascript_catalog as catalog_url %} - {%block html_head %}{% endblock %} + + {% block html_head %}{% endblock %} From 0bcaa4cc518ecf6071cdbf5bd6eb682f8acdedde Mon Sep 17 00:00:00 2001 From: Antoine Nguyen Date: Mon, 21 Mar 2011 18:32:07 +0100 Subject: [PATCH 3/4] * New icon and parameter for the 'Drafts' folder, * Fixed a refresh issue when removing a top folder (ie. with no parent) that is the current selection. --- extensions/webmail/lib.py | 3 ++- extensions/webmail/main.py | 3 +++ extensions/webmail/static/css/folders.css | 7 ++++++- extensions/webmail/static/js/fdmenu.js | 3 +++ static/pics/draft.png | Bin 0 -> 317 bytes 5 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 static/pics/draft.png diff --git a/extensions/webmail/lib.py b/extensions/webmail/lib.py index 2f31177f0..85cfcc753 100644 --- a/extensions/webmail/lib.py +++ b/extensions/webmail/lib.py @@ -257,7 +257,8 @@ class IMAPconnector(object): def getfolders(self, user): md_folders = [{"name" : "INBOX", "class" : "inbox"}, - {"name" : 'Drafts'}, + {"name" : parameters.get_user(user, "DRAFTS_FOLDER"), + "class" : "drafts"}, {"name" : 'Junk'}, {"name" : parameters.get_user(user, "SENT_FOLDER")}, {"name" : parameters.get_user(user, "TRASH_FOLDER"), diff --git a/extensions/webmail/main.py b/extensions/webmail/main.py index 0ec493e98..1e1a1cff8 100644 --- a/extensions/webmail/main.py +++ b/extensions/webmail/main.py @@ -43,6 +43,9 @@ def init(): parameters.register_user("SENT_FOLDER", type="string", deflt="Sent", label=_("Sent folder"), help=_("Folder where copies of sent messages go")) + parameters.register_user("DRAFTS_FOLDER", type="string", deflt="Drafts", + label=_("Drafts folder"), + help=_("Folder where drafts go")) parameters.register_user("SIGNATURE", type="text", deflt="", label=_("Signature text"), help=_("User defined email signature")) diff --git a/extensions/webmail/static/css/folders.css b/extensions/webmail/static/css/folders.css index 14511c42f..25400f3ef 100644 --- a/extensions/webmail/static/css/folders.css +++ b/extensions/webmail/static/css/folders.css @@ -74,7 +74,7 @@ a.block { } img.aligned { - float: left; + float: right; } img.footer { @@ -98,6 +98,11 @@ li.folder { background-repeat: no-repeat; } +li.drafts { + background-image: url("/static/pics/draft.png"); + background-repeat: no-repeat; +} + li.subfolders { background-image: url("/static/pics/folder.png"); background-repeat: no-repeat; diff --git a/extensions/webmail/static/js/fdmenu.js b/extensions/webmail/static/js/fdmenu.js index f178aa404..567e3d497 100644 --- a/extensions/webmail/static/js/fdmenu.js +++ b/extensions/webmail/static/js/fdmenu.js @@ -54,6 +54,9 @@ var FdMenu = new Class({ infobox.info(gettext("Folder deleted.")); if (dfolder == current_anchor.base) { var pfolder = ((this.current_folder.split(".")).slice(0, -1)).join("."); + if (pfolder == "") { + pfolder = "INBOX"; + } current_anchor.baseurl(pfolder, 1); } current_anchor.update.delay(500, current_anchor, 1); diff --git a/static/pics/draft.png b/static/pics/draft.png new file mode 100644 index 0000000000000000000000000000000000000000..663cbadddefa3c7f74f35faa702b752eb251f599 GIT binary patch literal 317 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#VfERCM0c#WBR9cj@HUTulxFt>;%oC#+8w zH~lQC^g^)d-50K`+ Date: Fri, 25 Mar 2011 15:30:08 +0100 Subject: [PATCH 4/4] Fixed a double SqueezeBox initialisation. --- extensions/webmail/static/js/fdmenu.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/extensions/webmail/static/js/fdmenu.js b/extensions/webmail/static/js/fdmenu.js index 567e3d497..c70f8dcbe 100644 --- a/extensions/webmail/static/js/fdmenu.js +++ b/extensions/webmail/static/js/fdmenu.js @@ -31,13 +31,13 @@ var FdMenu = new Class({ this.add_entry("modbutton", gettext("Edit folder"), "edit.png", this.options.modify_url, function(evt) { evt.stop(); - SqueezeBox.initialize({ - size: {x: 350, y: 400}, - handler: 'iframe' + SqueezeBox.open(evt.target.get("href"), { + handler: "iframe", + size: {x: 350, y: 400} }); - SqueezeBox.open(evt.target.get("href")); $(document.body).fireEvent("click"); }); + this.add_entry("delbutton", gettext("Delete folder"), "remove.png", this.options.delete_url, function(evt) { evt.stop(); @@ -99,7 +99,7 @@ var FdMenu = new Class({ this.container.setStyles({ display: "none" }); - this.container.dispose(); + this.container = this.container.dispose(); this.shown = false; },