<NME> admin_tags.py
<BEF> """Admin extension tags."""

from functools import reduce

from django import template
from django.template.loader import render_to_string
from django.urls import reverse
from django.utils.safestring import mark_safe
from django.utils.translation import ugettext as _, ugettext_lazy

from modoboa.core import signals as core_signals
from modoboa.lib.templatetags.lib_tags import render_link
from modoboa.lib.web_utils import render_actions
from .. import signals

register = template.Library()

genders = {
    "Enabled": (ugettext_lazy("enabled_m"), ugettext_lazy("enabled_f"))
}


@register.simple_tag
def domains_menu(selection, user, ajax_mode=True):
    """Specific menu for domain related operations.

    Corresponds to the menu visible on the left column when you go to
    *Domains*.

    :param str selection: menu entry currently selected
    :param ``User`` user: connected user
    :rtype: str
    :return: rendered menu (as HTML)
    """
    nav_classes = "navigation"
    if ajax_mode:
        domain_list_url = "list/"
        quota_list_url = "quotas/"
        logs_url = "logs/"
        nav_classes += " ajaxnav"
    else:
        domain_list_url = reverse("admin:domain_list")
        quota_list_url = domain_list_url + "#quotas/"
        logs_url = domain_list_url + "#logs/"
    entries = [
        {"name": "domains",
         "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",
         "img": "fa fa-hdd-o",
         "class": "ajaxnav navigation",
         "url": quota_list_url},
        {"name": "logs",
         "label": _("Message logs"),
         "img": "fa fa-list",
         "class": "ajaxnav navigation",
         "url": logs_url},
    ]
    if user.has_perm("admin.add_domain"):
        extra_entries = signals.extra_domain_menu_entries.send(
            sender="domains_menu", user=user)
        for entry in extra_entries:
            entries += entry[1]
        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,
        "selection": selection,
        "user": user
    })


@register.simple_tag
def identities_menu(user, selection=None, ajax_mode=True):
    """Menu specific to the Identities page.

    :param ``User`` user: the connecter user
    :rtype: str
    :return: the rendered menu
    """
    nav_classes = "navigation"
    if ajax_mode:
        identity_list_url = "list/"
        quota_list_url = "quotas/"
        nav_classes += " ajaxnav"
    else:
        identity_list_url = reverse("admin:identity_list")
        quota_list_url = identity_list_url + "#quotas/"
    entries = [
        {"name": "identities",
         "label": _("List identities"),
         "img": "fa fa-user",
         "class": nav_classes,
         "url": identity_list_url},
        {"name": "quotas",
         "label": _("List quotas"),
         "img": "fa fa-hdd-o",
         "class": nav_classes,
         "url": quota_list_url},
        {"name": "import",
         "label": _("Import"),
         "img": "fa fa-folder-open",
         "url": reverse("admin:identity_import"),
         "modal": True,
         "modalcb": "admin.importform_cb"},
        {"name": "export",
         "label": _("Export"),
         "img": "fa fa-share-alt",
         "url": reverse("admin:identity_export"),
         "modal": True,
         "modalcb": "admin.exportform_cb"}
    ]

    return render_to_string("common/menulist.html", {
        "entries": entries,
        "user": user
    })


@register.simple_tag
def domain_actions(user, domain):
    actions = [
        {"name": "listidentities",
         "url": u"{0}#list/?searchquery=@{1}".format(
             reverse("admin:identity_list"), domain.name),
         "title": _("View the domain's identities"),
         "img": "fa fa-user"},
    ]
    if domain.alarms.opened().exists():
        actions.append({
            "name": "listalarms",
            "url": reverse("admin:domain_alarms", args=[domain.pk]),
            "title": _("View domain's alarms"),
            "img": "fa fa-bell"
        })
    if user.has_perm("admin.change_domain"):
        actions.append({
            "name": "editdomain",
            "title": _("Edit {}").format(domain),
            "url": reverse("admin:domain_change", args=[domain.pk]),
            "modal": True,
            "modalcb": "admin.domainform_cb",
            "img": "fa fa-edit"
        })
    if user.has_perm("admin.delete_domain"):
        actions.append({
            "name": "deldomain",
            "url": reverse("admin:domain_delete", args=[domain.id]),
            "title": _("Delete %s?") % domain.name,
            "img": "fa fa-trash"
        })

    responses = signals.extra_domain_actions.send(
        sender=None, user=user, domain=domain)
    for _receiver, response in responses:
        if response:
            actions += response

    return render_actions(actions)


@register.simple_tag
def identity_actions(user, ident):
    name = ident.__class__.__name__
    objid = ident.id
    if name == "User":
        actions = []
        result = core_signals.extra_account_actions.send(
            sender="identity_actions", account=ident)
        for action in result:
            actions += action[1]
        url = (
            reverse("admin:account_change", args=[objid]) +
            "?active_tab=default"
        )
        actions += [
            {"name": "changeaccount",
             "url": url,
             "img": "fa fa-edit",
             "modal": True,
             "modalcb": "admin.editaccount_cb",
             "title": _("Edit {}").format(ident.username)},
            {"name": "delaccount",
             "url": reverse("admin:account_delete", args=[objid]),
             "img": "fa fa-trash",
             "title": _("Delete %s?") % ident.username},
        ]
    else:
        actions = [
            {"name": "changealias",
             "url": reverse("admin:alias_change", args=[objid]),
             "img": "fa fa-edit",
             "modal": True,
             "modalcb": "admin.aliasform_cb",
             "title": _("Edit {}").format(ident)},
            {"name": "delalias",
             "url": "{}?selection={}".format(
                 reverse("admin:alias_delete"), objid),
             "img": "fa fa-trash",
             "title": _("Delete %s?") % ident.address},
        ]
    return render_actions(actions)


@register.simple_tag
def check_identity_status(identity):
    """Check if identity is enabled or not."""
    if identity.__class__.__name__ == "User":
        if hasattr(identity, "mailbox") \
           and not identity.mailbox.domain.enabled:
            return False
        elif not identity.is_active:
            return False
    elif not identity.enabled or not identity.domain.enabled:
        return False
    return True


@register.simple_tag
def domain_aliases(domain):
    """Display domain aliases of this domain.

    :param domain:
    :rtype: str
    """
    if not domain.aliases.count():
        return "---"
    res = ""
    for alias in domain.aliases.all():
        res += "%s<br/>" % alias.name
    return mark_safe(res)


@register.simple_tag
def identity_modify_link(identity, active_tab="default"):
    """Return the appropriate modification link.

    According to the identity type, a specific modification link (URL)
    must be used.

    :param identity: a ``User`` or ``Alias`` instance
    :param str active_tab: the tab to display
    :rtype: str
    """
    linkdef = {"label": identity.identity, "modal": True}
    if identity.__class__.__name__ == "User":
        linkdef["url"] = reverse("admin:account_change", args=[identity.id])
        linkdef["url"] += "?active_tab=%s" % active_tab
        linkdef["modalcb"] = "admin.editaccount_cb"
    else:
        linkdef["url"] = reverse("admin:alias_change", args=[identity.id])
        linkdef["modalcb"] = "admin.aliasform_cb"
    return render_link(linkdef)


@register.simple_tag
def domadmin_actions(daid, domid):
    actions = [{
        "name": "removeperm",
        "url": "{0}?domid={1}&daid={2}".format(
            reverse("admin:permission_remove"), domid, daid),
        "img": "fa fa-trash",
        "title": _("Remove this permission")
    }]
    return render_actions(actions)


@register.filter
def gender(value, target):
    if value in genders:
        trans = target == "m" and genders[value][0] or genders[value][1]
        if trans.find("_") == -1:
            return trans
    return value


@register.simple_tag
def get_extra_admin_content(user, target, currentpage):
    results = signals.extra_admin_content.send(
        sender="get_extra_admin_content",
        user=user, location=target, currentpage=currentpage)
    if not results:
        return ""
    results = reduce(lambda a, b: a + b, [result[1] for result in results])
    return mark_safe("".join(results))

<MSG> Move domain add button.

<DFF> @@ -47,14 +47,6 @@ def domains_menu(selection, user, ajax_mode=True):
          "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",

Move domain add button.