Search code examples
pythonhookwagtailwagtail-admin

Customizing Pages Awaiting Moderation panel on the wagtail admin home page


I'm trying to figure out a way to override what shows up in the "Pages Awaiting Moderation" panel on the wagtail admin home page. My content structure on the site's front end looks like this:

Home

  • Organizations
    • Org A
    • Org B
    • etc.
  • People
    • Profile Page 1
    • Profile Page 2
    • etc.

I have three types of users - your regular admin/super-user, moderators for each individual organization, and regular employees.

The regular employees all have profiles in the People section, and can login and edit their own, but not publish them. They just submit them for moderation.

Moderators can edit/publish anything within their org. For example, if you belong to the Org A Moderators group, you have permissions on the Org A page and anything below it in the site tree, and also any Profile in the People section. You can't edit anything belonging to the other orgs.

Since the people Profiles can belong to multiple Orgs (this is handled via a ParentalManyToMany relationship), I wasn't able to nest all of the people under their orgs in the navigation. So I haven't figured out a way to grant edit access ONLY to people under a moderator's org. But I figured I could get around this elegantly enough by restricting the moderator's "Pages Awaiting Moderation" queue so that the query only returns items relevant to their org.

What I can't figure out is whether I need to remove the PagesForModerationPanel that wagtailadmin's home.py sets up and replace it with my own panel that has custom query logic, or whether I can somehow override that class without removing and replacing the panel.

https://docs.wagtail.io/en/latest/reference/hooks.html gives a simple example of how to add a welcome panel to the admin home page. I was able to get that to work. I also figured out how to remove the existing moderation panel in wagtail_hooks.py:

@hooks.register('construct_homepage_panels')
def remove_moderation_panel(request, panels):
for panel in panels:
  if panel.name == 'pages_for_moderation':
    panels.remove(panel)

But when I try to define my own panel class in wagtail_hooks.py and then add it to the home page, it doesn't work. The following code (which for now has the same query logic as wagtailadmin's home.py; I haven't changed it yet) results in an error:

class OrgPagesForModerationPanel:
    name = 'pages_for_moderation'
    order = 200

    def __init__(self, request):
        self.request = request
        user_perms = UserPagePermissionsProxy(request.user)
        self.page_revisions_for_moderation = (user_perms.revisions_for_moderation()
                                              .select_related('page', 'user').order_by('-created_at'))

    def render(self):
        return render_to_string('wagtailadmin/home/pages_for_moderation.html', {
            'page_revisions_for_moderation': self.page_revisions_for_moderation,
        }, request=self.request)

@hooks.register('construct_homepage_panels')
def add_org_moderation_panel(request, panels):
    panels.append(OrgPagesForModerationPanel())

Am I doing something wrong syntax-wise, or am I trying to do this in the wrong file? I've tried some other tricks such as rearranging which order my 'home' app and 'wagtail.admin' are included in my INSTALLED_APPS, but that doesn't seem to make a difference.

This is my first time trying to customize the wagtail admin to account for a more complex user workflow, so I suppose it's possible I could be barking up the wrong tree entirely and there's a way to handle this without overriding the moderation queue.


Solution

  • Since you've defined an __init__ method that accepts a request argument, you need to pass the request when constructing the panel.

    @hooks.register('construct_homepage_panels')
    def add_org_moderation_panel(request, panels):
        panels.append(OrgPagesForModerationPanel(request))