diff --git a/modoboa/extensions/admin/models/domain.py b/modoboa/extensions/admin/models/domain.py
index c0a13d459..02e50731e 100644
--- a/modoboa/extensions/admin/models/domain.py
+++ b/modoboa/extensions/admin/models/domain.py
@@ -56,6 +56,11 @@ class Domain(AdminObject):
def mbalias_count(self):
return self.alias_set.count()
+ @property
+ def identities_count(self):
+ """Total number of identities in this domain."""
+ return self.mailbox_set.count() + self.alias_set.count()
+
@property
def tags(self):
return [{"name": "domain", "label": _("Domain"), "type": "dom"}]
diff --git a/modoboa/extensions/admin/templates/admin/domain_statistics.html b/modoboa/extensions/admin/templates/admin/domain_statistics.html
new file mode 100644
index 000000000..2be458dab
--- /dev/null
+++ b/modoboa/extensions/admin/templates/admin/domain_statistics.html
@@ -0,0 +1,63 @@
+{% extends "admin/header.html" %}
+
+{% load i18n %}
+{% load admin_tags %}
+
+{% block leftcol %}
+
+
+{% get_extra_admin_content user "leftcol" selection %}
+{% endblock %}
+
+{% block apparea %}
+{% trans "Statistics" %} {% trans "Domains and identities" %}
+
+
+
+ {% if user.group == "SuperAdmins" %}
+
+
+
{% trans "Global counters" %}
+
+
+
+ | {% trans "Type" %} |
+ {% trans "Quantity" %} |
+
+
+ | {% trans "Domains" %} | {{ domains_counter }} |
+
+
+ | {% trans "Domain aliases" %} | {{ domain_aliases_counter }} |
+
+
+ | {% trans "Identities" %} | {{ identities_counter }} |
+
+
+
+
+ {% endif %}
+
+
+
+
{% trans "Per-domain counters" %}
+
+
+
+ | {% trans "Domain" %} |
+ {% trans "Identities" %} |
+
+ {% for domain in domains %}
+
+ | {{ domain.name }} | {{ domain.identities_count }} |
+
+ {% endfor %}
+
+
+
+
+
+
+{% endblock %}
diff --git a/modoboa/extensions/admin/templatetags/admin_tags.py b/modoboa/extensions/admin/templatetags/admin_tags.py
index e8e504ed5..2d1060b61 100644
--- a/modoboa/extensions/admin/templatetags/admin_tags.py
+++ b/modoboa/extensions/admin/templatetags/admin_tags.py
@@ -1,10 +1,15 @@
+"""
+Admin extension tags.
+"""
+
from django import template
+from django.core.urlresolvers import reverse
from django.template.loader import render_to_string
from django.utils.translation import ugettext as _, ugettext_lazy
-from django.core.urlresolvers import reverse
+
from modoboa.lib import events
-from modoboa.lib.webutils import render_actions
from modoboa.lib.templatetags.lib_tags import render_link
+from modoboa.lib.webutils import render_actions
register = template.Library()
@@ -18,39 +23,52 @@ def domains_menu(selection, user):
"""Specific menu for domain related operations.
Corresponds to the menu visible on the left column when you go to
- Domains.
+ *Domains*.
:param str selection: menu entry currently selected
:param ``User`` user: connected user
:rtype: str
:return: rendered menu (as HTML)
"""
- if not user.has_perm("admin.add_domain"):
- return ""
-
+ domain_list_url = (
+ "list/" if selection != "statistics" else reverse("admin:domain_list")
+ )
entries = [
- {"name": "newdomain",
- "label": _("Add domain"),
- "img": "fa fa-plus",
- "modal": True,
- "modalcb": "admin.newdomain_cb",
- "url": reverse("admin:domain_add")},
- ]
- entries += events.raiseQueryEvent("ExtraDomainMenuEntries", user)
- entries += [
- {"name": "import",
- "label": _("Import"),
- "img": "fa fa-folder-open",
- "url": reverse("admin:domain_import"),
- "modal": True,
- "modalcb": "admin.importform_cb"},
- {"name": "export",
- "label": _("Export"),
- "img": "fa fa-share-alt",
- "url": reverse("admin:domain_export"),
- "modal": True,
- "modalcb": "admin.exportform_cb"}
+ {"name": "domains",
+ "label": _("List domains"),
+ "img": "fa fa-user",
+ "class": "ajaxlink navigation",
+ "url": domain_list_url},
+ {"name": "statistics",
+ "label": _("Statistics"),
+ "img": "fa fa-line-chart",
+ "class": "navigation",
+ "url": reverse("admin:domain_statistics")}
]
+ if user.has_perm("admin.add_domain"):
+ entries += [
+ {"name": "newdomain",
+ "label": _("Add domain"),
+ "img": "fa fa-plus",
+ "modal": True,
+ "modalcb": "admin.newdomain_cb",
+ "url": reverse("admin:domain_add")},
+ ]
+ entries += events.raiseQueryEvent("ExtraDomainMenuEntries", user)
+ entries += [
+ {"name": "import",
+ "label": _("Import"),
+ "img": "fa fa-folder-open",
+ "url": reverse("admin:domain_import"),
+ "modal": True,
+ "modalcb": "admin.importform_cb"},
+ {"name": "export",
+ "label": _("Export"),
+ "img": "fa fa-share-alt",
+ "url": reverse("admin:domain_export"),
+ "modal": True,
+ "modalcb": "admin.exportform_cb"}
+ ]
return render_to_string('common/menulist.html', {
"entries": entries,
diff --git a/modoboa/extensions/admin/urls.py b/modoboa/extensions/admin/urls.py
index a75852cec..e601c45d1 100644
--- a/modoboa/extensions/admin/urls.py
+++ b/modoboa/extensions/admin/urls.py
@@ -8,6 +8,7 @@ urlpatterns = patterns(
url(r'^domains/$', 'domains', name="domain_list"),
url(r'^domains/list/$', '_domains', name="_domain_list"),
url(r'^domains/flatlist/$', 'domains_list', name="domain_flat_list"),
+ url(r'^domains/stats/$', 'domain_statistics', name="domain_statistics"),
url(r'^domains/new/', 'newdomain', name='domain_add'),
url(r'^domains/(?P\d+)/edit/$', 'editdomain', name="domain_change"),
url(r'^domains/(?P\d+)/delete/$', 'deldomain',
diff --git a/modoboa/extensions/admin/views/domain.py b/modoboa/extensions/admin/views/domain.py
index f64a2737f..3cabdf935 100644
--- a/modoboa/extensions/admin/views/domain.py
+++ b/modoboa/extensions/admin/views/domain.py
@@ -13,6 +13,7 @@ from django.contrib.auth.decorators import (
import reversion
+from modoboa.core.models import User
from modoboa.lib import parameters, events
from modoboa.lib.webutils import (
_render_to_string, render_to_json_response
@@ -21,7 +22,9 @@ from modoboa.lib.exceptions import (
PermDeniedException
)
from modoboa.lib.listing import get_sort_order, get_listing_page
-from modoboa.extensions.admin.models import Domain, Mailbox
+from modoboa.extensions.admin.models import (
+ Domain, DomainAlias, Mailbox, Alias
+)
from modoboa.extensions.admin.forms import (
DomainForm
)
@@ -134,3 +137,18 @@ def deldomain(request, dom_id):
msg = ungettext("Domain deleted", "Domains deleted", 1)
return render_to_json_response(msg)
+
+
+@login_required
+@permission_required("admin.view_domains")
+def domain_statistics(request):
+ """A simple page to present domain statistics."""
+ context = {}
+ if request.user.group == "SuperAdmins":
+ context.update({
+ "domains_counter": Domain.objects.count(),
+ "domain_aliases_counter": DomainAlias.objects.count(),
+ "identities_counter": User.objects.count() + Alias.objects.count(),
+ })
+ context.update({"domains": Domain.objects.get_for_admin(request.user)})
+ return render(request, "admin/domain_statistics.html", context)