From c5d21a76d973c97a112dc37e99a7761d20348891 Mon Sep 17 00:00:00 2001 From: Michael van Tellingen Date: Thu, 29 Mar 2018 20:48:23 +0200 Subject: [PATCH] Add a new hook 'register_account_menu_item' (#4421) * Add a new hook 'register_account_menu_item' This new hook makes it easier for third party apps to add new buttons on the 'my account' page in the Wagtail admin. Existing buttons are converted to the new hooks to make the code consistent. * Add documentation for the new register_account_menu_item hook --- docs/reference/hooks.rst | 27 +++++++++++ .../wagtailadmin/account/account.html | 44 ++--------------- .../admin/tests/test_account_management.py | 7 ++- wagtail/admin/views/account.py | 15 +++--- wagtail/admin/wagtail_hooks.py | 48 ++++++++++++++++++- 5 files changed, 91 insertions(+), 50 deletions(-) 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 @@
{% 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