diff --git a/admin/templatetags/admin_extras.py b/admin/templatetags/admin_extras.py
index 99ca98f98..4e5cbf15c 100644
--- a/admin/templatetags/admin_extras.py
+++ b/admin/templatetags/admin_extras.py
@@ -39,7 +39,8 @@ def domain_menu(domain_id, selection, perms):
"class" : "boxed",
"rel" : "{handler:'iframe',size:{x:300,y:180}}"}
]
- entries += events.raiseQueryEvent("AdminMenuDisplay", target="admin_menu_bar" , domain=domain_id)
+ entries += events.raiseQueryEvent("AdminMenuDisplay", target="admin_menu_bar",
+ perms=perms, domain=domain_id)
return render_to_string('main/menu.html',
{"selection" : selection, "entries" : entries,
"perms" : perms})
@@ -49,6 +50,13 @@ def settings_menu(selection):
return render_to_string('admin/settings_menu.html',
{"selection" : selection})
+@register.simple_tag
+def loadadminextmenu(perms):
+ menu = events.raiseQueryEvent("AdminMenuDisplay", target="admin_menu_box",
+ perms=perms)
+ return render_to_string('main/menulist.html',
+ {"menu" : menu, "perms" : perms})
+
@register.filter
def gender(value, target):
if genders.has_key(value):
diff --git a/admin/views.py b/admin/views.py
index cbeae3cf2..5c1cfa794 100644
--- a/admin/views.py
+++ b/admin/views.py
@@ -16,6 +16,7 @@ from forms import MailboxForm, DomainForm, AliasForm, PermissionForm
from mailng.lib.authbackends import crypt_password
from mailng.lib import _render, _ctx_ok, _ctx_ko
from mailng.lib import events
+import string
import copy
def is_superuser(user):
@@ -29,9 +30,10 @@ def good_domain(f):
if request.user.is_superuser:
return f(request, dom_id, **kwargs)
mb = Mailbox.objects.get(user=request.user.id)
- domid = isinstance(dom_id, str) and "%d" % dom_id or dom_id
- if domid == mb.domain.id:
- return f(request, domid, **kwargs)
+ if isinstance(dom_id, str) or isinstance(dom_id, unicode):
+ dom_id = string.atoi(dom_id)
+ if dom_id == mb.domain.id:
+ return f(request, dom_id, **kwargs)
from django.conf import settings
path = urlquote(request.get_full_path())
diff --git a/extensions/amavis_quarantine/main.py b/extensions/amavis_quarantine/main.py
index 312c22848..a3fd1fb50 100644
--- a/extensions/amavis_quarantine/main.py
+++ b/extensions/amavis_quarantine/main.py
@@ -43,13 +43,13 @@ def urls():
include('mailng.extensions.amavis_quarantine.urls'))
def menu(**kwargs):
- if kwargs["target"] != "user_menu_box":
- return []
- return [
- {"name" : _("Quarantine"),
- "url" : reverse(index),
- "img" : "/static/pics/quarantine.png"}
- ]
+ if kwargs["target"] == "user_menu_box":
+ return [
+ {"name" : _("Quarantine"),
+ "url" : reverse(index),
+ "img" : "/static/pics/quarantine.png"}
+ ]
+ return []
def lookup(*args):
filter = ""
diff --git a/extensions/stats/grapher.py b/extensions/stats/grapher.py
index 4f33e817c..ea493de20 100644
--- a/extensions/stats/grapher.py
+++ b/extensions/stats/grapher.py
@@ -4,19 +4,48 @@ import os
import time
import datetime
import rrdtool
+from django.utils.translation import ugettext as _
from mailng.lib import getoption
-default_avg_template = {
+traffic_avg_template = {
+ 'name' : 'traffic',
'width' : '540',
'height' : '100',
- 'title' : 'average message flow per minute',
'vertlabel' : 'msgs/min',
'cf' : 'AVERAGE',
'vars' : {
- 'sent' : { "type" : "AREA", "color" : "#00FF00", "legend" : "sent messages" },
- 'recv' : { "type" : "AREA", "color" : "#0000FF", "legend" : "received messages" },
-# 'bounced' : { "color" : "#FFFF00", "legend" : "bounced messages" },
-# 'reject' : { "color" : "#FF0000", "legend" : "rejected messages" },
+ 'sent' : { "type" : "AREA", "color" : "#00FF00",
+ "legend" : _("sent messages") },
+ 'recv' : { "type" : "AREA", "color" : "#0000FF",
+ "legend" : _("received messages") },
+ }
+}
+
+badtraffic_avg_template = {
+ 'name' : 'badtraffic',
+ 'width' : '540',
+ 'height' : '100',
+ 'vertlabel' : _('msgs/min'),
+ 'cf' : 'AVERAGE',
+ 'vars' : {
+ 'bounced' : { "type" : "AREA", "color" : "#FFFF00",
+ "legend" : _("bounced messages") },
+ 'reject' : { "type" : "AREA", "color" : "#FF0000",
+ "legend" : _("rejected messages") },
+ }
+}
+
+size_avg_template = {
+ 'name' : 'size',
+ 'width' : '540',
+ 'height' : '100',
+ 'vertlabel' : _('bytes/min'),
+ 'cf' : 'AVERAGE',
+ 'vars' : {
+ 'size_recv' : { "type" : "AREA", "color" : "#FF9900",
+ "legend" : _("received size") },
+ 'size_sent' : { "type" : "AREA", "color" : "#339999",
+ "legend" : _("sent size") },
}
}
@@ -25,12 +54,13 @@ class Grapher(object):
self.rrd_rootdir = getoption("RRD_ROOTDIR", "/tmp")
self.img_rootdir = getoption("IMG_ROOTDIR", "/tmp")
- def process(self, target, suffix, start, end, tpl=default_avg_template):
+ def process(self, target, suffix, start, end, tpl=traffic_avg_template):
rrdfile = "%s/%s.rrd" % (self.rrd_rootdir, target)
if not os.path.exists(rrdfile):
return
ext = "png"
- path = "%s/%s_%s_%s.%s" % (self.img_rootdir, target, tpl['cf'], suffix, ext)
+ path = "%s/%s_%s_%s_%s.%s" % (self.img_rootdir, tpl['name'],
+ target, tpl['cf'], suffix, ext)
start = str(start)
end = str(end)
defs = []
@@ -39,7 +69,8 @@ class Grapher(object):
defs += ['DEF:%s=%s:%s:%s' % (v, rrdfile, v, tpl['cf']),
'CDEF:%spm=%s,60,*' % (v, v)]
type = d.has_key("type") and d["type"] or "LINE"
- lines += ["%s:%spm%s:%s" % (type, v, d["color"], d["legend"])]
+ lines += ["%s:%spm%s:%s" % (type, v, d["color"],
+ d["legend"].encode("utf-8"))]
params = defs + lines
rrdtool.graph(path,
"--imgformat", "PNG",
@@ -47,30 +78,16 @@ class Grapher(object):
"--height", tpl["height"],
"--start", start,
"--end", end,
- "--vertical-label", tpl["vertlabel"],
- "--title", tpl["title"],
+ "--vertical-label", tpl["vertlabel"].encode("utf-8"),
"--lower-limit", "0",
"--slope-mode",
*params)
- def make_defaults(self, target):
- #now = int(time.time())
- #start = now - (now % 86400)
- #end = start + 86400
+ def make_defaults(self, target, tpl=traffic_avg_template):
end = "now"
- self.process(target, "day", "-1day", end)
-
- #today = datetime.date.today()
- #day = today.day - today.weekday()
- #weekbegin = datetime.date(today.year, today.month, day)
- #start = weekbegin.strftime("%Y%m%d")
- #end = "+1week"
- self.process(target, "week", "-1week", end)
-
-# monthbegin = datetime.date(today.year, today.month, 1)
-# start = monthbegin.strftime("%Y%m%d")
-# end = "+1month"
- self.process(target, "month", "-1month", end)
- self.process(target, "year", "-1year", end)
+ self.process(target, "day", "-1day", end, tpl)
+ self.process(target, "week", "-1week", end, tpl)
+ self.process(target, "month", "-1month", end, tpl)
+ self.process(target, "year", "-1year", end, tpl)
diff --git a/extensions/stats/logparser.py b/extensions/stats/logparser.py
index 40b656fba..07674f2f4 100755
--- a/extensions/stats/logparser.py
+++ b/extensions/stats/logparser.py
@@ -5,6 +5,7 @@ import sys
import os
import re
import rrdtool
+import string
from optparse import OptionParser
from mailng.lib import getoption
from mailng.admin.models import Domain
@@ -19,6 +20,8 @@ Postfix log parser.
rrdstep = 60
xpoints = 540
points_per_sample = 3
+variables = ["sent", "recv", "bounced", "reject", "spam", "virus",
+ "size_sent", "size_recv"]
class LogParser(object):
def __init__(self, logfile, workdir,
@@ -86,7 +89,7 @@ class LogParser(object):
# Set up data sources for our RRD
params = []
- for v in ["sent", "recv", "bounced", "reject"]:
+ for v in variables:
params += ['DS:%s:%s:%s:0:U' % (v, ds_type, rrdstep * 2)]
# Set up RRD to archive data
@@ -125,39 +128,54 @@ class LogParser(object):
print "[rrd] VERBOSE events at %s already recorded in RRD" %m
return False
+ tpl = ""
+ for v in variables:
+ if tpl != "":
+ tpl += ":"
+ tpl += v
# Missing some RRD steps
# Est ce vraiment nécessaire... ?
if m > self.lupdates[fname] + rrdstep:
+ values = ""
+ for v in variables:
+ if values != "": values += ":"
+ values += "0"
for p in range(self.lupdates[fname] + rrdstep, m, rrdstep):
if self.verbose:
print "[rrd] VERBOSE update %s:%s:%s:%s:%s (SKIP)" \
%(p,'0','0','0','0')
- rrdtool.update(fname, "%s:%s:%s:%s:%s" \
- % (p, '0', '0', '0', '0'))
+ rrdtool.update(fname, "-t", tpl, "%s:%s" % (p, values))
if self.verbose:
print "[rrd] VERBOSE update %s:%s:%s:%s:%s" \
%(m, self.data[dom][m]['sent'], self.data[dom][m]['recv'],\
self.data[dom][m]['bounced'], self.data[dom][m]['reject'])
- rrdtool.update(fname, "%s:%s:%s:%s:%s" \
- % (m, self.data[dom][m]['sent'],
- self.data[dom][m]['recv'],
- self.data[dom][m]['bounced'],
- self.data[dom][m]['reject']))
+ values = "%s" % m
+ tpl = ""
+ for v in variables:
+ values += ":"
+ values += str(self.data[dom][m][v])
+ if tpl != "":
+ tpl += ":"
+ tpl += v
+ rrdtool.update(fname, "-t", tpl, values)
self.lupdates[fname] = m
return True
- def inc_counter(self, dom, cur_t, counter):
+ def initcounters(self, dom, cur_t):
+ init = {}
+ for v in variables: init[v] = 0
+ self.data[dom][cur_t] = init
+
+ def inc_counter(self, dom, cur_t, counter, val=1):
if not self.data[dom].has_key(cur_t):
- self.data[dom][cur_t] = \
- {'sent' : 0, 'recv' : 0, 'bounced' : 0, 'reject' : 0}
- self.data[dom][cur_t][counter] += 1
+ self.initcounters(dom, cur_t)
+ self.data[dom][cur_t][counter] += val
if not self.data["global"].has_key(cur_t):
- self.data["global"][cur_t] = \
- {'sent' : 0, 'recv' : 0, 'bounced' : 0, 'reject' : 0}
- self.data["global"][cur_t][counter] += 1
+ self.initcounters("global", cur_t)
+ self.data["global"][cur_t][counter] += val
def process(self):
for line in self.f.readlines():
@@ -170,9 +188,10 @@ class LogParser(object):
cur_t = self.str2Time(self.year, mo, da, ho, mi, se)
cur_t = cur_t - cur_t % rrdstep
- m = re.search("(\w{10}): from=<(.*)>", log)
+ m = re.search("(\w{10}): from=<(.*)>, size=(\d+)", log)
if m:
- self.workdict[m.group(1)] = {'from' : m.group(2)}
+ self.workdict[m.group(1)] = {'from' : m.group(2),
+ 'size' : string.atoi(m.group(3))}
continue
m = re.search("(\w{10}): to=<(.*)>.*status=(\S+)", log)
@@ -183,10 +202,14 @@ class LogParser(object):
addrfrom = re.match("([^@]+)@(.+)", self.workdict[m.group(1)]['from'])
if addrfrom and addrfrom.group(2) in self.domains:
self.inc_counter(addrfrom.group(2), cur_t, 'sent')
+ self.inc_counter(addrfrom.group(2), cur_t, 'size_sent',
+ self.workdict[m.group(1)]['size'])
addrto = re.match("([^@]+)@(.+)", m.group(2))
if addrto.group(2) in self.domains:
if m.group(3) == "sent":
self.inc_counter(addrto.group(2), cur_t, 'recv')
+ self.inc_counter(addrto.group(2), cur_t, 'size_recv',
+ self.workdict[m.group(1)]['size'])
else:
self.inc_counter(addrto.group(2), cur_t, m.group(3))
continue
@@ -205,7 +228,10 @@ class LogParser(object):
sortedData = [ (i, data[i]) for i in sorted(data.keys()) ]
for t, dict in sortedData:
self.update_rrd(dom, t)
- G.make_defaults(dom)
+
+ G.make_defaults(dom, tpl=grapher.traffic_avg_template)
+ G.make_defaults(dom, tpl=grapher.badtraffic_avg_template)
+ G.make_defaults(dom, tpl=grapher.size_avg_template)
if __name__ == "__main__":
log_file = getoption("LOGFILE", "/var/log/maillog")
diff --git a/extensions/stats/main.py b/extensions/stats/main.py
index 75ceb9dda..808bf18ba 100644
--- a/extensions/stats/main.py
+++ b/extensions/stats/main.py
@@ -11,38 +11,36 @@ from django.core.urlresolvers import reverse
from django.utils.translation import ugettext as _
from django.conf.urls.defaults import *
from mailng.lib import events, _render
-from mailng.admin.views import is_superuser
+from mailng.admin.views import good_domain
from mailng.admin.models import Domain, Mailbox
-#from mailng.extensions.stats.mailrrd import parser
from django.contrib.auth.decorators \
- import login_required
-import pdb
+ import login_required, user_passes_test, permission_required
-graph_nature = ["sent_recv","boun_reje"]
-graph_types = ["AVERAGE","MAX"]
-tmp_path = "static/tmp"
+graph_types = ['AVERAGE', 'MAX']
def init():
- events.register("AdminMenuDisplay", menu)
+ events.register("AdminMenuDisplay", menu)
def urls():
return (r'^mailng/stats/',
include('mailng.extensions.stats.urls'))
-
def menu(**kwargs):
- print kwargs
- domain_id = kwargs['domain']
if kwargs["target"] == "admin_menu_bar":
+ domain_id = kwargs['domain']
return [
{"label" : _("Statistics"),
"name" : "stats",
"url" : reverse('domindex', args=[domain_id]),
"img" : "/static/pics/graph.png"}
]
- else:
- return []
-
+ if kwargs["target"] == "admin_menu_box":
+ return [
+ {"name" : _("Statistics"),
+ "url" : reverse('fullindex'),
+ "img" : "/static/pics/graph.png"}
+ ]
+ return []
@login_required
def domain(request,dom_id):
@@ -82,26 +80,38 @@ def graph_display(request,dom_id,graph_t=graph_types):
"domain":domain,"domains" : domains, "messages" : errors ,
"types" : graph_type, "tmp_path" : tmp_path})
+@login_required
+@user_passes_test(lambda u: u.is_superuser)
+def adminindex(request):
+ period = request.GET.has_key("period") and request.GET["period"] or "day"
+ domain = request.GET.has_key("domain") and request.GET["domain"] or "global"
+ if domain != "global":
+ domain = Domain.objects.get(pk=domain)
+ domain = domain.name
+ domains = Domain.objects.all()
+ return _render(request, 'stats/adminindex.html', {
+ "domains" : domains, "domain" : domain,
+ "graphs" : {"traffic" : _("Average normal traffic"),
+ "badtraffic" : _("Average bad traffic"),
+ "size" : _("Average normal traffic size")},
+ "periods" : ["day", "week", "month", "year"],
+ "period" : period
+ })
@login_required
+@good_domain
+@permission_required("admin.view_mailboxes")
def index(request, dom_id=None):
- domains = []
- errors = []
domain = None
- if dom_id:
- if request.user.has_perm("admin.view_mailboxes"):
- domain = Domain.objects.get(pk=dom_id)
- if domain:
- domains.append(domain)
- else:
- print "pas de dom"
- else:
- domains = Domain.objects.all()
+ period = request.GET.has_key("period") and request.GET["period"] or "day"
+ if request.user.has_perm("admin.view_mailboxes"):
+ domain = Domain.objects.get(pk=dom_id)
- if domains == []:
- errors.append(_("No Domain defined"))
return _render(request, 'stats/index.html', {
- "page" : "Statistics",
- "domain" : domain, "domains": domains, "messages" : errors ,
- "periods" : ["day", "week", "month", "year"]
- })
+ "domain" : domain,
+ "graphs" : {"traffic" : _("Average normal traffic"),
+ "badtraffic" : _("Average bad traffic"),
+ "size" : _("Average normal traffic size")},
+ "periods" : ["day", "week", "month", "year"],
+ "period" : period
+ })
diff --git a/extensions/stats/templates/adminindex.html b/extensions/stats/templates/adminindex.html
new file mode 100644
index 000000000..25cf9ff8e
--- /dev/null
+++ b/extensions/stats/templates/adminindex.html
@@ -0,0 +1,52 @@
+{% extends "layout.html" %}
+{% load i18n %}
+{% load stats_extra %}
+{% block html_head %}
+
+
+
+
+
+{% endblock %}
+{% block middletitle %}{% trans "Global statistics" %}{% endblock %}
+{% block content %}
+
+
+
+
+
+
+
+
+ {% include "stats/graphs.html" %}
+
+{% endblock %}
diff --git a/extensions/stats/templates/graphs.html b/extensions/stats/templates/graphs.html
new file mode 100644
index 000000000..5c1709303
--- /dev/null
+++ b/extensions/stats/templates/graphs.html
@@ -0,0 +1,6 @@
+{% load i18n %}
+{% for g, title in graphs.items %}
+{{ title }}
+
+{% endfor %}
diff --git a/extensions/stats/templates/index.html b/extensions/stats/templates/index.html
index 90f43880b..374e780cb 100644
--- a/extensions/stats/templates/index.html
+++ b/extensions/stats/templates/index.html
@@ -1,34 +1,21 @@
-{% extends "layout.html" %}
+{% extends "admin/domain_header.html" %}
{% load i18n %}
{% block html_head %}
{% endblock %}
@@ -38,45 +25,15 @@
{% domain_menu domain.id "stats" perms %}
{% endif %}
{% endblock %}
-{% block middletitle %}
-{% if domain %}
- {% trans "Statistics for" %} {{ domain.name }}
-{% else %}
- {% trans "Global statistics" %}
-{% endif %}
-{% endblock %}
-{% block content %}
-
-
- {% if domain %}
- {% for p in periods %}
-
-
-
- |
-
- {% endfor %}
- {% else %}
- {% if domains %}
-
- | {% trans "Graph type" %} |
- {% trans "Domain name" %} |
-
-
- {% for dom in domains %}
-
- |
- {% for t in types %}
- {% url extensions.stats.main.graph_display dom.id,t as graphurl %}
- {{ t|lower }}
- {% endfor %}
- |
- {% url extensions.stats.main.domain dom.id as domurl %}
- {{ dom.name }} |
-
- {% endfor %}
- {% endif %}
- {% endif %}
-
+{% block domcontent %}
+
+
+
+
+ {% include "stats/graphs.html" %}
{% endblock %}
diff --git a/extensions/stats/templatetags/__init__.py b/extensions/stats/templatetags/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/extensions/stats/templatetags/stats_extra.py b/extensions/stats/templatetags/stats_extra.py
new file mode 100644
index 000000000..3f4222c73
--- /dev/null
+++ b/extensions/stats/templatetags/stats_extra.py
@@ -0,0 +1,14 @@
+from django import template
+from django.utils.translation import ugettext as _
+
+register = template.Library()
+
+@register.simple_tag
+def getLabel(var):
+ labels = {
+ "day" : _("Day"),
+ "week" : _("Week"),
+ "month" : _("Month"),
+ "year" : _("Year")
+ }
+ return labels.has_key(var) and labels[var] or var
diff --git a/extensions/stats/urls.py b/extensions/stats/urls.py
index bb2ee66dd..904b014c4 100644
--- a/extensions/stats/urls.py
+++ b/extensions/stats/urls.py
@@ -1,7 +1,7 @@
from django.conf.urls.defaults import *
urlpatterns = patterns('mailng.extensions.stats.main',
- url(r'^$', 'index', name='fullindex'),
+ url(r'^$', 'adminindex', name='fullindex'),
url(r'^(?P\d+)/$', 'index', name='domindex'),
(r'^display/(?P\d+)/(?P\w+)/$', 'graph_display'),
(r'^domain/(?P\d+)/$', 'domain'),
diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po
index 864e8c9ee..8c1760074 100644
--- a/locale/fr/LC_MESSAGES/django.po
+++ b/locale/fr/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2009-10-30 11:19+0100\n"
+"POT-Creation-Date: 2009-11-03 15:22+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Antoine Nguyen \n"
"Language-Team: LANGUAGE \n"
@@ -17,64 +17,69 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
#: admin/forms.py:16 templates/admin/domains.html:17
-#: templates/admin/mailboxes.html:18
+#: templates/admin/mailboxes.html:17
msgid "Quota"
msgstr ""
#: admin/forms.py:17
+msgid "Mailbox quota in MB (default to domain quota if blank)"
+msgstr ""
+"Quota en Mo de la boite aux lettres (par défaut celui du domaine si vide)"
+
+#: admin/forms.py:18
msgid "Password"
msgstr "Mot de passe"
-#: admin/forms.py:18
+#: admin/forms.py:19
msgid "Password used to log in"
msgstr "Mot de passe utilisé pour se connecter"
-#: admin/forms.py:19 main/forms.py:21
+#: admin/forms.py:20 main/forms.py:21
msgid "Confirmation"
msgstr ""
-#: admin/forms.py:20
+#: admin/forms.py:21
msgid "Password confirmation"
msgstr "Confirmation du mot de passe"
-#: admin/forms.py:23
+#: admin/forms.py:24
msgid "Check to activate this mailbox"
msgstr "Cocher pour activer cette boite aux lettres"
-#: admin/forms.py:36 main/forms.py:36
+#: admin/forms.py:37 main/forms.py:36
msgid "Passwords mismatch"
msgstr "Les mots de passe diffèrent"
-#: admin/forms.py:55 templates/admin/domain_header.html:7
+#: admin/forms.py:56 templates/admin/domain_header.html:6
#: templates/admin/editdomain.html:7 templates/admin/permissions.html:42
msgid "Domain"
msgstr "Domaine"
-#: admin/forms.py:57
+#: admin/forms.py:58
msgid "Select a domain in the list"
msgstr "Sélectionner un domaine dans la liste"
-#: admin/forms.py:58
+#: admin/forms.py:59
msgid "User"
msgstr "Utilisateur"
-#: admin/forms.py:59
+#: admin/forms.py:60
msgid "Select a user in the list"
msgstr "Sélectionner un utilisateur dans la liste"
-#: admin/forms.py:60
+#: admin/forms.py:61
msgid "Role"
msgstr "Rôle"
-#: admin/forms.py:61
+#: admin/forms.py:62
msgid "Super administrator"
msgstr "Super administrateur"
-#: admin/forms.py:62
+#: admin/forms.py:63
msgid "Domain administrator"
msgstr "Admin. de domaine"
-#: admin/forms.py:63
+#: admin/forms.py:64
msgid "Select the role you want this user to have"
msgstr "Sélectionner le rôle souhaité pour cet utilisateur"
@@ -114,11 +119,6 @@ msgstr "Adresse de la boite aux lettres (sans la partie @domain.tld)"
msgid "password"
msgstr "Mot de passe"
-#: admin/models.py:44
-msgid "Mailbox quota in MB (default to domain quota if blank)"
-msgstr ""
-"Quota en Mo de la boite aux lettres (par défaut celui du domaine si vide)"
-
#: admin/models.py:107
msgid "The alias address (without the domain part)"
msgstr "L'adresse de l'alias (sans la partie domaine)"
@@ -135,44 +135,44 @@ msgstr "La boite aux lettres sur laquelle pointe cet alias"
msgid "Check to activate this alias"
msgstr "Cocher pour activer cet alias"
-#: admin/views.py:23
+#: admin/views.py:24
msgid "Permission denied."
msgstr "Permission refusée."
-#: admin/views.py:67 admin/views.py:97
+#: admin/views.py:69 admin/views.py:99
msgid "Domain with this name already defined"
msgstr "Un domaine avec ce nom existe déjà"
-#: admin/views.py:76
+#: admin/views.py:78
msgid "Failed to initialise domain, check permissions"
msgstr "Impossible d'initialiser le domaine, vérifier les permissions"
-#: admin/views.py:100
+#: admin/views.py:102
msgid "Failed to rename domain, check permissions"
msgstr "Impossible de renommer le domaine, vérifier les permissions"
-#: admin/views.py:154 admin/views.py:213
+#: admin/views.py:156 admin/views.py:215
msgid "Mailbox with this address already exists"
msgstr "Une boite aux lettres pour cette adresse existe déjà"
-#: admin/views.py:185
+#: admin/views.py:187
msgid "Mailbox created."
msgstr "Boite aux lettres créé."
-#: admin/views.py:189
+#: admin/views.py:191
msgid "Failed to initialise mailbox, check permissions"
msgstr ""
"Impossible d'initialiser la boite aux lettres, vérifier les permissions"
-#: admin/views.py:216
+#: admin/views.py:218
msgid "Failed to rename mailbox, check permissions"
msgstr "Impossible de renommer la boite aux lettres, vérifier les permissions."
-#: admin/views.py:292 admin/views.py:322
+#: admin/views.py:294 admin/views.py:324
msgid "Alias with this address already exists"
msgstr "Un alias avec cette adresse existe déjà"
-#: admin/views.py:395
+#: admin/views.py:397
msgid "admin is intouchable!!"
msgstr "admin est intouchable!!"
@@ -200,8 +200,8 @@ msgstr "Alias"
msgid "Properties"
msgstr "Propriétés"
-#: extensions/amavis_quarantine/main.py:49
-#: extensions/amavis_quarantine/templates/index.html:153
+#: extensions/amavis_quarantine/main.py:48
+#: extensions/amavis_quarantine/templates/index.html:152
msgid "Quarantine"
msgstr "Quarantaine"
@@ -215,29 +215,29 @@ msgstr "%(count)d message%(plural)s supprimé correctement"
msgid "%(count)d message%(plural)s released successfully"
msgstr "%(count)d messages relâché correctement"
-#: extensions/amavis_quarantine/templates/index.html:95
+#: extensions/amavis_quarantine/templates/index.html:94
msgid "Delete this selection?"
msgstr "Supprimer cette sélection?"
-#: extensions/amavis_quarantine/templates/index.html:102
+#: extensions/amavis_quarantine/templates/index.html:101
msgid "Release this selection?"
msgstr "Relâcher cette sélection?"
-#: extensions/amavis_quarantine/templates/index.html:136
-#: extensions/amavis_quarantine/templates/index.html:158
+#: extensions/amavis_quarantine/templates/index.html:135
+#: extensions/amavis_quarantine/templates/index.html:157
msgid "Search..."
msgstr "Chercher..."
-#: extensions/amavis_quarantine/templates/index.html:160
+#: extensions/amavis_quarantine/templates/index.html:159
msgid "From address"
msgstr "Emetteur"
-#: extensions/amavis_quarantine/templates/index.html:161
+#: extensions/amavis_quarantine/templates/index.html:160
#: extensions/amavis_quarantine/templates/listing.html:35
msgid "Subject"
msgstr "Sujet"
-#: extensions/amavis_quarantine/templates/index.html:162
+#: extensions/amavis_quarantine/templates/index.html:161
msgid "Both"
msgstr "Tous"
@@ -277,11 +277,11 @@ msgstr ""
msgid "Message headers"
msgstr "Entêtes du message"
-#: extensions/amavis_quarantine/templates/viewmail.html:32
+#: extensions/amavis_quarantine/templates/viewmail.html:22
msgid "Mail content"
msgstr "Contenu du message"
-#: extensions/amavis_quarantine/templates/viewmail.html:41
+#: extensions/amavis_quarantine/templates/viewmail.html:31
msgid "Message"
msgstr ""
@@ -327,29 +327,98 @@ msgstr "Supprimer ce message?"
msgid "Options"
msgstr ""
-#: extensions/dummy_plugin/main.py:17
-msgid "Dummy"
-msgstr ""
-
#: extensions/postfix_autoreply/main.py:35
msgid "Auto-reply message"
msgstr "Message de réponse automatique"
-#: extensions/stats/main.py:39
+#: extensions/stats/grapher.py:18
+msgid "sent messages"
+msgstr "messages envoyés"
+
+#: extensions/stats/grapher.py:20
+msgid "received messages"
+msgstr "messages reçus"
+
+#: extensions/stats/grapher.py:28
+msgid "msgs/min"
+msgstr ""
+
+#: extensions/stats/grapher.py:32
+msgid "bounced messages"
+msgstr "messages ?"
+
+#: extensions/stats/grapher.py:34
+msgid "rejected messages"
+msgstr "messages rejetés"
+
+#: extensions/stats/grapher.py:42
+msgid "bytes/min"
+msgstr "octes/min"
+
+#: extensions/stats/grapher.py:46
+msgid "received size"
+msgstr "taille reçue"
+
+#: extensions/stats/grapher.py:48
+msgid "sent size"
+msgstr "taille envoyée"
+
+#: extensions/stats/main.py:32 extensions/stats/main.py:39
msgid "Statistics"
msgstr "Statistiques"
-#: extensions/stats/main.py:66 extensions/stats/main.py:95
+#: extensions/stats/main.py:68
msgid "No Domain defined"
msgstr "Aucun domaine défini."
-#: extensions/stats/templates/index.html:62
-msgid "Graph type"
+#: extensions/stats/main.py:94 extensions/stats/main.py:112
+msgid "Average normal traffic"
+msgstr "Trafic normal moyen"
+
+#: extensions/stats/main.py:95 extensions/stats/main.py:113
+msgid "Average bad traffic"
+msgstr "Mauvais trafic moyen"
+
+#: extensions/stats/main.py:96 extensions/stats/main.py:114
+msgid "Average normal traffic size"
+msgstr "Taille moyenne du trafic moyen"
+
+#: extensions/stats/templates/adminindex.html:31
+msgid "Global statistics"
+msgstr "Statistiques globales"
+
+#: extensions/stats/templates/adminindex.html:35
+msgid "Domain:"
+msgstr "Domaine :"
+
+#: extensions/stats/templates/adminindex.html:37
+msgid "Global"
msgstr ""
-#: extensions/stats/templates/index.html:63
-msgid "Domain name"
-msgstr "Nom du domaine"
+#: extensions/stats/templates/adminindex.html:43
+#: extensions/stats/templates/index.html:30
+msgid "Period:"
+msgstr "Période :"
+
+#: extensions/stats/templates/graphs.html:5
+msgid "No statistics available"
+msgstr "Aucune statistique disponible"
+
+#: extensions/stats/templatetags/stats_extra.py:9
+msgid "Day"
+msgstr "Jour"
+
+#: extensions/stats/templatetags/stats_extra.py:10
+msgid "Week"
+msgstr "Semaine"
+
+#: extensions/stats/templatetags/stats_extra.py:11
+msgid "Month"
+msgstr "Mois"
+
+#: extensions/stats/templatetags/stats_extra.py:12
+msgid "Year"
+msgstr "Année"
#: main/forms.py:17
msgid "Old password"
@@ -371,10 +440,6 @@ msgstr "sujet"
msgid "content"
msgstr "contenu"
-#: main/models.py:10
-msgid "until"
-msgstr ""
-
#: main/views.py:45
msgid "Auto reply message updated successfully."
msgstr "Message de réponse auto. mis à jour."
@@ -383,27 +448,27 @@ msgstr "Message de réponse auto. mis à jour."
msgid "Change password"
msgstr "Changer de mot de passe"
-#: templates/layout.html:42
+#: templates/layout.html:44
msgid "Admin"
msgstr ""
-#: templates/layout.html:49
+#: templates/layout.html:51
msgid "Preferences"
msgstr "Préférences"
-#: templates/layout.html:56
+#: templates/layout.html:58
msgid "Logout"
msgstr "Déconnexion"
-#: templates/layout.html:69 templates/admin/newdomain.html:7
+#: templates/layout.html:72 templates/admin/newdomain.html:7
msgid "New domain"
msgstr "Nouveau domaine"
-#: templates/layout.html:76
+#: templates/layout.html:79
msgid "Domains"
msgstr "Domaines"
-#: templates/layout.html:83 templates/admin/settings_header.html:6
+#: templates/layout.html:86 templates/admin/settings_header.html:6
msgid "Settings"
msgstr "Paramètres"
@@ -416,34 +481,34 @@ msgstr "Ajouter une permission"
msgid "Create"
msgstr "Créer"
-#: templates/admin/aliases.html:10
+#: templates/admin/aliases.html:9
msgid "No alias defined."
msgstr "Aucun alias défini."
-#: templates/admin/aliases.html:14 templates/admin/domains.html:14
-#: templates/admin/mailboxes.html:15 templates/admin/permissions.html:14
+#: templates/admin/aliases.html:13 templates/admin/domains.html:14
+#: templates/admin/mailboxes.html:14 templates/admin/permissions.html:14
#: templates/admin/permissions.html:41
msgid "Actions"
msgstr ""
-#: templates/admin/aliases.html:15 templates/admin/mailboxes.html:17
+#: templates/admin/aliases.html:14 templates/admin/mailboxes.html:16
msgid "Address"
msgstr "Adresse"
-#: templates/admin/aliases.html:16 templates/admin/editmailbox.html:7
+#: templates/admin/aliases.html:15 templates/admin/editmailbox.html:7
msgid "Mailbox"
msgstr "Boite aux lettres"
-#: templates/admin/aliases.html:17 templates/admin/domains.html:18
+#: templates/admin/aliases.html:16 templates/admin/domains.html:18
#: templates/admin/permissions.html:17 templates/admin/permissions.html:44
msgid "Enabled"
msgstr "Activé"
-#: templates/admin/aliases.html:25
+#: templates/admin/aliases.html:24
msgid "Edit alias"
msgstr "Editer cet alias"
-#: templates/admin/aliases.html:29
+#: templates/admin/aliases.html:28
msgid "Delete alias"
msgstr "Supprimer cet alias"
@@ -455,7 +520,7 @@ msgstr "Domaines disponibles"
msgid "No domain defined."
msgstr "Aucun domaine défini."
-#: templates/admin/domains.html:15 templates/admin/mailboxes.html:16
+#: templates/admin/domains.html:15 templates/admin/mailboxes.html:15
#: templates/admin/permissions.html:43
msgid "Name"
msgstr "Nom"
@@ -468,37 +533,37 @@ msgstr "Editer le domaine"
msgid "Delete domain"
msgstr "Supprimer le domaine"
-#: templates/admin/domains.html:36 templates/admin/mailboxes.html:46
+#: templates/admin/domains.html:36 templates/admin/mailboxes.html:45
msgid "MB"
msgstr "Mo"
-#: templates/admin/domains.html:37 templates/admin/mailboxes.html:47
+#: templates/admin/domains.html:37 templates/admin/mailboxes.html:46
msgid "yes,no"
msgstr "oui,non"
#: templates/admin/editalias.html:14 templates/admin/editdomain.html:15
-#: templates/admin/editmailbox.html:16 templates/main/autoreply.html:19
+#: templates/admin/editmailbox.html:16 templates/main/autoreply.html:17
#: templates/main/chpassword.html:15
msgid "Update"
msgstr "Mettre à jour"
-#: templates/admin/mailboxes.html:11
+#: templates/admin/mailboxes.html:10
msgid "No mailbox defined."
msgstr "Aucune boite aux lettres définie."
-#: templates/admin/mailboxes.html:27
+#: templates/admin/mailboxes.html:26
msgid "Edit mailbox"
msgstr "Editer la boite aux lettres"
-#: templates/admin/mailboxes.html:32
+#: templates/admin/mailboxes.html:31
msgid "Delete mailbox"
msgstr "Supprimer la boite aux lettres"
-#: templates/admin/mailboxes.html:37
+#: templates/admin/mailboxes.html:36
msgid "Add new alias"
msgstr "Ajouter un alias"
-#: templates/admin/mailboxes.html:41
+#: templates/admin/mailboxes.html:40
msgid "Mailbox aliases"
msgstr "Alias de cette boite aux lettres"
@@ -538,11 +603,11 @@ msgstr "Aucun admin de domaine défini."
msgid "Permissions"
msgstr ""
-#: templates/main/confirm.html:26
+#: templates/main/confirm.html:25
msgid "Do not delete mailbox directory"
msgstr "Ne pas supprimer le répertoire de la boite aux lettres"
-#: templates/main/header.html:8
+#: templates/main/header.html:6
msgid "General"
msgstr "Général"
@@ -563,3 +628,6 @@ msgid "Your username and password didn't match. Please try again."
msgstr ""
"Votre nom d'utilisateur et mot de passe ne correspondent pas. Veuillez "
"réessayer."
+
+#~ msgid "Domain name"
+#~ msgstr "Nom du domaine"
diff --git a/main/templatetags/main_extras.py b/main/templatetags/main_extras.py
index 152623139..774ac99b5 100644
--- a/main/templatetags/main_extras.py
+++ b/main/templatetags/main_extras.py
@@ -25,6 +25,7 @@ def menu(selection, perms):
@register.simple_tag
def loadextmenu(perms):
- menu = events.raiseQueryEvent("UserMenuDisplay", target="user_menu_box")
+ menu = events.raiseQueryEvent("UserMenuDisplay", target="user_menu_box",
+ perms=perms)
return render_to_string('main/menulist.html',
{"menu" : menu, "perms" : perms})
diff --git a/templates/layout.html b/templates/layout.html
index d64dd6ec1..a9e384ecf 100644
--- a/templates/layout.html
+++ b/templates/layout.html
@@ -61,6 +61,7 @@
{% if user.is_superuser %}
+ {% load admin_extras %}
{% endif %}