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" %}

+
+ + + + + + {% for domain in domains %} + + + + {% endfor %} +
{% trans "Domain" %}{% trans "Identities" %}
{{ domain.name }}{{ domain.identities_count }}
+
+
+ +
+ +{% 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)