From 9ef5df3d26c18bc407918c7c80eca3a0fa09001c Mon Sep 17 00:00:00 2001 From: tonio Date: Fri, 5 Feb 2010 19:07:51 +0100 Subject: [PATCH] Ticket #32 + minor CSS modifications. --- admin/templatetags/admin_extras.py | 21 ++++++++++---- admin/views.py | 4 ++- extensions/webmail/imap_listing.py | 37 +++++++++++++++++++------ extensions/webmail/main.py | 14 ++++++---- extensions/webmail/templates/index.html | 30 +++++++++++++++++--- lib/__init__.py | 4 +++ lib/email_listing.py | 3 +- lib/parameters.py | 2 +- static/js/common.js | 2 +- static/js/domains.js | 1 + static/js/settings.js | 1 + static/stylesheets/default.css | 26 +++++++++++------ templates/common/error.html | 6 ++++ templates/common/tables.html | 2 +- 14 files changed, 117 insertions(+), 36 deletions(-) create mode 100644 templates/common/error.html diff --git a/admin/templatetags/admin_extras.py b/admin/templatetags/admin_extras.py index 5e435c7e1..6eb5fab93 100644 --- a/admin/templatetags/admin_extras.py +++ b/admin/templatetags/admin_extras.py @@ -90,19 +90,30 @@ def loadadminextmenu(perms): @register.simple_tag def param(app, definition): - print definition result = """
""" % definition["name"] + name = "%s.%s" % (app, definition["name"]) if definition["type"] in ["string", "int"]: value = definition.has_key("value") \ and definition["value"] or definition["default"] - name = "%s.%s" % (app, definition["name"]) result += """ """ % (name, name, value) - if definition["type"] in ["list"]: + if definition["type"] in ["list", "list_yesno"]: result += """ -""" % (name, name) + values = [] + if definition["type"] == "list_yesno": + values = [("yes", _("Yes")), ("no", _("No"))] + else: + if definition.has_key("values"): + values = definition["values"] + value = definition.has_key("value") \ + and definition["value"] or definition["default"] + for v in values: + selected = "" + if value == v[0]: + selected = " selected='selected'" + result += "\n" % (v[0], selected, v[1]) result += """ """ diff --git a/admin/views.py b/admin/views.py index be9cf960f..2d8492211 100644 --- a/admin/views.py +++ b/admin/views.py @@ -413,8 +413,10 @@ def viewparameters(request): for app in apps: tmp = {"name" : app, "params" : []} for p in sorted(parameters._params[app]): - tmp["params"] += [{"name" : p, "value" : parameters.get(app, p), + tmp["params"] += [{"name" : p, + "value" : parameters.get(app, p), "help" : parameters._params[app][p]["help"], + "default" : parameters._params[app][p]["default"], "type" : parameters._params[app][p]["type"]}] gparams += [tmp] diff --git a/extensions/webmail/imap_listing.py b/extensions/webmail/imap_listing.py index ca2631468..e525f9430 100644 --- a/extensions/webmail/imap_listing.py +++ b/extensions/webmail/imap_listing.py @@ -3,6 +3,7 @@ import re import time import imaplib +import ssl from datetime import datetime, timedelta from email.header import decode_header import email.utils @@ -69,7 +70,10 @@ class IMAPheader(object): @staticmethod def parse_date(value): - ndate = datetime(*(email.utils.parsedate_tz(value))[:7]) + tmp = email.utils.parsedate_tz(value) + if not tmp: + return value + ndate = datetime(*(tmp)[:7]) now = datetime.now() if now - ndate > timedelta(7): return ndate.strftime("%d.%m.%Y %H:%M") @@ -90,22 +94,30 @@ class IMAPconnector(object): def __init__(self, request=None, user=None, password=None): self.address = parameters.get("webmail", "IMAP_SERVER") + self.port = int(parameters.get("webmail", "IMAP_PORT")) if request: status, msg = self.login(request.user.username, request.session["password"]) else: status, msg = self.login(user, password) if not status: - # Gestion d'erreur - pass + raise Exception(msg) def login(self, user, passwd): import imaplib try: - self.m = imaplib.IMAP4_SSL(self.address) + secured = parameters.get("webmail", "IMAP_SECURED") + if secured == "yes": + self.m = imaplib.IMAP4_SSL(self.address, self.port) + else: + self.m = imaplib.IMAP4(self.address, self.port) + except (imaplib.IMAP4.error, ssl.SSLError), error: + return False, _("Connection to IMAP server failed, check your configuration") + try: self.m.login(user, passwd) - except imaplib.IMAP4.error, test: - return False, test + except (imaplib.IMAP4.error, ssl.SSLError), error: + return False, _("Authentication failed, check your configuration") + return True, None def _encodefolder(self, folder): @@ -113,9 +125,18 @@ class IMAPconnector(object): return "INBOX" return folder.encode("imap4-utf-7") - def messages_count(self, folder=None): + def messages_count(self, folder=None, order=None): + if order: + sign = order[:1] + criterion = order[1:].upper() + if sign == '-': + criterion = "REVERSE %s" % criterion + else: + criterion = "REVERSE DATE" + print criterion + (status, data) = self.m.select(self._encodefolder(folder)) - (status, data) = self.m.sort("(REVERSE DATE)", "UTF-8", "(NOT DELETED)") + (status, data) = self.m.sort("(%s)" % criterion, "UTF-8", "(NOT DELETED)") self.messages = data[0].split() return len(self.messages) diff --git a/extensions/webmail/main.py b/extensions/webmail/main.py index d5fda042a..4ae9a12c6 100644 --- a/extensions/webmail/main.py +++ b/extensions/webmail/main.py @@ -9,7 +9,7 @@ from django.core.urlresolvers import reverse from django.conf.urls.defaults import include from django.contrib.auth.decorators import login_required from mailng.admin.models import Mailbox -from mailng.lib import events, parameters, _render +from mailng.lib import events, parameters, _render, _render_error from mailng.lib.email_listing import Email from imap_listing import * from forms import * @@ -20,7 +20,7 @@ def init(): events.register("UserLogin", userlogin) parameters.register("webmail", "IMAP_SERVER", "string", "127.0.0.1", help=_("Address of your IMAP server")) - parameters.register("webmail", "IMAP_SECURED", "list", "No", + parameters.register("webmail", "IMAP_SECURED", "list_yesno", "no", help=_("Use a secure connexion to access IMAP server")) parameters.register("webmail", "IMAP_PORT", "int", "143", help=_("Listening port of your IMAP server")) @@ -60,8 +60,9 @@ def folder(request, name, updatenav=True): pageid = request.GET.has_key("page") and int(request.GET["page"]) or 1 request.session["folder"] = name request.session["page"] = pageid + order = request.GET.has_key("order") and request.GET["order"] or None lst = ImapListing(request.user.username, request.session["password"], - name, folder=name) + name, folder=name, order=order) page = lst.paginator.getpage(request.session["page"]) if page: content = lst.fetch(request, page.id_start, page.id_stop) @@ -75,8 +76,11 @@ def folder(request, name, updatenav=True): @login_required def index(request): - lst = ImapListing(request.user.username, request.session["password"], - "INBOX", folder="INBOX") + try: + lst = ImapListing(request.user.username, request.session["password"], + "INBOX", folder="INBOX") + except Exception as exp: + return _render_error(request, {"error" : exp}) return lst.render(request, empty=True) def fetchmail(request, folder, mail_id, all=False): diff --git a/extensions/webmail/templates/index.html b/extensions/webmail/templates/index.html index 6e58764a5..9ff2b3f61 100644 --- a/extensions/webmail/templates/index.html +++ b/extensions/webmail/templates/index.html @@ -207,6 +207,32 @@ tr { }); }); $$("tr").addEvent("dblclick", viewmail); + var sortOrder = ""; + $$("th[class=sortable]").addEvent("click", function(evt) { + var tmp = "?"; + + if (sortOrder == "") { + test = /order=([\+\-]\w+$|&)/.exec(location.hash); + if (test) { + sortOrder = test[1]; + } + } + if (sortOrder.substring(1) == evt.target.id) { + var sign = (sortOrder.charAt(0) == '+') ? '-' : '+'; + sortOrder = sign + evt.target.id; + } else { + sortOrder = "-" + 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; + }); }); navbarcallback = function(event) { @@ -224,10 +250,6 @@ tr { $$("a[name=compose]").addEvent("click", loadCompose); {% endblock %} {% block middletitle %}{% trans "Webmail" %}{% endblock %} -{% block menu %} - {% load webextras %} - {% listing_menu "" "INBOX" perms %} -{% endblock %} {% block leftcol %}

{% trans "Folders" %}

diff --git a/lib/__init__.py b/lib/__init__.py index e02f23c13..c2582c4bd 100644 --- a/lib/__init__.py +++ b/lib/__init__.py @@ -50,6 +50,10 @@ def _render(request, tpl, user_context): return render_to_response(tpl, user_context, context_instance=RequestContext(request)) +def _render_error(request, user_context): + return render_to_response("common/error.html", user_context, + context_instance=RequestContext(request)) + def exec_as_vuser(cmd): code, output = exec_pipe("sudo -u %s %s" % (settings.VIRTUAL_UID, cmd)) if code: diff --git a/lib/email_listing.py b/lib/email_listing.py index 9f2cbb875..c39b604ce 100644 --- a/lib/email_listing.py +++ b/lib/email_listing.py @@ -80,7 +80,8 @@ class EmailListing: def __init__(self, folder=None, elems_per_page=40, **kwargs): self.folder = folder self.elems_per_page = elems_per_page - self.paginator = Paginator(self.mbc.messages_count(self.folder), + order = "order" in kwargs.keys() and kwargs["order"] or None + self.paginator = Paginator(self.mbc.messages_count(self.folder, order), elems_per_page) def render_navbar(self, page): diff --git a/lib/parameters.py b/lib/parameters.py index e7b1e484f..cdcfe2ec0 100644 --- a/lib/parameters.py +++ b/lib/parameters.py @@ -24,7 +24,7 @@ class NotDefined(Exception): return "Application '%s' and/or parameter '%s' not defined" % (self.app, self.name) -def register(app, name, type="string", deflt=None, help=None): +def register(app, name, type="string", deflt=None, help=None, **kwargs): """Register a new parameter. app corresponds to a core component (admin, main) or an extension. diff --git a/static/js/common.js b/static/js/common.js index 44c17ef94..0804351c4 100644 --- a/static/js/common.js +++ b/static/js/common.js @@ -23,7 +23,7 @@ check_anchor = function() { query = "INBOX/"; // Default location } else { var splits = current_anchor.substring(1).split('?'); - var section = splits[0]; + var section = (splits[0] != "") ? splits[0] : "INBOX"; delete splits[0]; var params = splits.join('&'); if (section[section.length - 1] != '/') { diff --git a/static/js/domains.js b/static/js/domains.js index 286515bac..5898b43bd 100644 --- a/static/js/domains.js +++ b/static/js/domains.js @@ -66,6 +66,7 @@ window.addEvent('domready', function() { } } }); + setDivHeight("content", 20, 0); }); newdom = function() { diff --git a/static/js/settings.js b/static/js/settings.js index f420da35c..5552a095d 100644 --- a/static/js/settings.js +++ b/static/js/settings.js @@ -3,6 +3,7 @@ window.addEvent('domready', function() { parse: 'rel', }); + setDivHeight("content", 20, 0); if ($$("a[name=deletePerm]")) $$("a[name=deletePerm]").addEvent('click', function(event) { diff --git a/static/stylesheets/default.css b/static/stylesheets/default.css index 610ff9fc0..471cd3109 100644 --- a/static/stylesheets/default.css +++ b/static/stylesheets/default.css @@ -262,16 +262,13 @@ table.hr { } .toggler { - color: #222; - margin: 0; + margin: 5px auto; padding: 2px 5px; - background: #eee; - border-bottom: 1px solid #ddd; - border-right: 1px solid #ddd; - border-top: 1px solid #f5f5f5; - border-left: 1px solid #f5f5f5; - font-size: small; - font-weight: normal; + background: #CEDBEC; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + /*border: 1px solid #CCC;*/ + font-size: 1.1em; } .element { @@ -287,3 +284,14 @@ div.row label { width: 200px; padding: 3px 0; } + +.error { + margin: 0 auto; + padding: 5px; + background: red; + width: 500px; + text-align: center; + background-color: #F9D2D2; + border: 3px solid #FF2A2A; + color: #FF2A00; +} \ No newline at end of file diff --git a/templates/common/error.html b/templates/common/error.html new file mode 100644 index 000000000..11677caf5 --- /dev/null +++ b/templates/common/error.html @@ -0,0 +1,6 @@ +{% extends "nlayout.html" %} +{% load i18n %} +{% block middletitle %}{% trans "Error" %}{% endblock %} +{% block content %} +

{{ error }}

+{% endblock %} diff --git a/templates/common/tables.html b/templates/common/tables.html index efe7808c7..43d065b6a 100644 --- a/templates/common/tables.html +++ b/templates/common/tables.html @@ -2,7 +2,7 @@ {% for c in table.columns %} - {{ c|safe }} + {{ c|safe }} {% endfor %}