diff --git a/docs/reference/hooks.rst b/docs/reference/hooks.rst
index 9eb9b750f..b281efac1 100644
--- a/docs/reference/hooks.rst
+++ b/docs/reference/hooks.rst
@@ -120,6 +120,33 @@ Hooks for building new areas of the admin interface (alongside pages, images, do
``url`` (optional)
A URL to an index page that lists the objects being described.
+.. _register_account_menu_item:
+
+``register_account_menu_item``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Add an item to the My Account page within the Wagtail admin. The callable
+ for this hook should return a dict with values for the keys ``url``,
+ ``label`` and ``help_text``. For example:
+
+ .. code-block:: python
+
+ from django.utils.translation import ugettext_lazy as _
+ from wagtail.core import hooks
+
+ @hooks.register('register_account_menu_item')
+ def register_account_set_gravatar(request):
+ return {
+ 'url': 'https://gravatar.com/emails/',
+ 'label': _('Set gravatar'),
+ 'help_text': _(
+ "Your avatar image is provided by Gravatar and is connected to "
+ "your email address. With a Gravatar account you can set an "
+ "avatar for any number of other email addresses you use."
+ )
+ }
+
+
.. _register_admin_menu_item:
diff --git a/wagtail/admin/templates/wagtailadmin/account/account.html b/wagtail/admin/templates/wagtailadmin/account/account.html
index 4527f8902..28a8f34f0 100644
--- a/wagtail/admin/templates/wagtailadmin/account/account.html
+++ b/wagtail/admin/templates/wagtailadmin/account/account.html
@@ -8,50 +8,14 @@
- -
-
-
-
- {% trans "Your avatar image is provided by Gravatar and is connected to your email address. With a Gravatar account you can set an avatar for any number of other email addresses you use." %}
-
-
-
- {% if show_change_password %}
+ {% for item in items %}
-
-
-
- {% trans "Change the password you use to log in." %}
-
+ {{ item.help_text }}
- {% endif %}
- {% if show_notification_preferences %}
- -
-
-
-
- {% trans "Choose which email notifications to receive." %}
-
-
- {% endif %}
- {% if show_preferred_language_preferences %}
- -
-
-
-
- {% trans "Choose the language you want to use here." %}
-
-
- {% endif %}
-
+ {% endfor %}
{% endblock %}
diff --git a/wagtail/admin/tests/test_account_management.py b/wagtail/admin/tests/test_account_management.py
index 9ea6955a2..1a24c60ac 100644
--- a/wagtail/admin/tests/test_account_management.py
+++ b/wagtail/admin/tests/test_account_management.py
@@ -413,9 +413,12 @@ class TestAccountManagementForAdminOnlyUser(TestCase, WagtailTestUtils):
Test that the user is not even shown the link to the notification
preferences view
"""
+ expected_url = reverse('wagtailadmin_account_notification_preferences')
+
response = self.client.get(reverse('wagtailadmin_account'))
- self.assertEqual(response.context['show_notification_preferences'], False)
- self.assertNotContains(response, reverse('wagtailadmin_account_notification_preferences'))
+ account_urls = [item['url'] for item in response.context['items']]
+ self.assertFalse(expected_url in account_urls)
+ self.assertNotContains(response, expected_url)
# safety check that checking for absence/presence of urls works
self.assertContains(response, reverse('wagtailadmin_home'))
diff --git a/wagtail/admin/views/account.py b/wagtail/admin/views/account.py
index 76ee72598..122286f7c 100644
--- a/wagtail/admin/views/account.py
+++ b/wagtail/admin/views/account.py
@@ -13,8 +13,7 @@ from django.views.decorators.cache import never_cache
from django.views.decorators.debug import sensitive_post_parameters
from wagtail.admin import forms
-from wagtail.admin.utils import get_available_admin_languages
-from wagtail.core.models import UserPagePermissionsProxy
+from wagtail.core import hooks
from wagtail.users.forms import NotificationPreferencesForm, PreferredLanguageForm
from wagtail.users.models import UserProfile
from wagtail.utils.loading import get_custom_form
@@ -43,13 +42,15 @@ def password_reset_enabled():
# Views
def account(request):
- user_perms = UserPagePermissionsProxy(request.user)
- show_notification_preferences = user_perms.can_edit_pages() or user_perms.can_publish_pages()
+ items = []
+
+ for fn in hooks.get_hooks('register_account_menu_item'):
+ item = fn(request)
+ if item:
+ items.append(item)
return render(request, 'wagtailadmin/account/account.html', {
- 'show_change_password': password_management_enabled() and request.user.has_usable_password(),
- 'show_notification_preferences': show_notification_preferences,
- 'show_preferred_language_preferences': len(get_available_admin_languages()) > 1
+ 'items': items,
})
diff --git a/wagtail/admin/wagtail_hooks.py b/wagtail/admin/wagtail_hooks.py
index dc26c9c81..5829173db 100644
--- a/wagtail/admin/wagtail_hooks.py
+++ b/wagtail/admin/wagtail_hooks.py
@@ -15,10 +15,12 @@ from wagtail.admin.rich_text.converters.html_to_contentstate import (
BlockElementHandler, ExternalLinkElementHandler, HorizontalRuleHandler,
InlineStyleElementHandler, ListElementHandler, ListItemElementHandler, PageLinkElementHandler)
from wagtail.admin.search import SearchArea
-from wagtail.admin.utils import user_has_any_page_permission
+from wagtail.admin.utils import get_available_admin_languages, user_has_any_page_permission
+from wagtail.admin.views.account import password_management_enabled
from wagtail.admin.viewsets import viewsets
from wagtail.admin.widgets import Button, ButtonWithDropdownFromHook, PageListingButton
from wagtail.core import hooks
+from wagtail.core.models import UserPagePermissionsProxy
from wagtail.core.permissions import collection_permission_policy
from wagtail.core.rich_text.pages import PageLinkHandler
from wagtail.core.whitelist import allow_without_attributes, attribute_rule, check_url
@@ -189,6 +191,50 @@ def register_viewsets_urls():
return viewsets.get_urlpatterns()
+@hooks.register('register_account_menu_item')
+def register_account_set_gravatar(request):
+ return {
+ 'url': 'https://gravatar.com/emails/',
+ 'label': _('Set gravatar'),
+ 'help_text': _(
+ "Your avatar image is provided by Gravatar and is connected to "
+ "your email address. With a Gravatar account you can set an "
+ "avatar for any number of other email addresses you use."
+ )
+ }
+
+
+@hooks.register('register_account_menu_item')
+def register_account_change_password(request):
+ if password_management_enabled() and request.user.has_usable_password():
+ return {
+ 'url': reverse('wagtailadmin_account_change_password'),
+ 'label': _('Change password'),
+ 'help_text': _('Change the password you use to log in.'),
+ }
+
+
+@hooks.register('register_account_menu_item')
+def register_account_notification_preferences(request):
+ user_perms = UserPagePermissionsProxy(request.user)
+ if user_perms.can_edit_pages() or user_perms.can_publish_pages():
+ return {
+ 'url': reverse('wagtailadmin_account_notification_preferences'),
+ 'label': _('Notification preferences'),
+ 'help_text': _('Choose which email notifications to receive.'),
+ }
+
+
+@hooks.register('register_account_menu_item')
+def register_account_preferred_language_preferences(request):
+ if len(get_available_admin_languages()) > 1:
+ return {
+ 'url': reverse('wagtailadmin_account_language_preferences'),
+ 'label': _('Language preferences'),
+ 'help_text': _('Choose the language you want to use here.'),
+ }
+
+
@hooks.register('register_rich_text_features')
def register_core_features(features):
# Hallo.js