Monkey Patch list ordering in wagtail

This commit is contained in:
Lorenz Padberg 2023-07-17 13:09:32 +02:00
parent 1de888b5cd
commit 2e826f81d5
2 changed files with 33 additions and 12 deletions

View File

@ -1,3 +1,4 @@
import wagtail.admin.views.pages.ordering
from django.db.models import ProtectedError from django.db.models import ProtectedError
from django.shortcuts import redirect from django.shortcuts import redirect
from wagtail.admin import messages from wagtail.admin import messages
@ -14,6 +15,7 @@ from books.models.chapter import Chapter
from books.models.contentblock import ContentBlock from books.models.contentblock import ContentBlock
from core.logger import get_logger from core.logger import get_logger
from django.conf import settings from django.conf import settings
from .wagtail_patch import set_page_position
logger = get_logger(__name__) logger = get_logger(__name__)
@ -31,6 +33,11 @@ else:
primary = "#17A887" primary = "#17A887"
secondary = "#078CC6" secondary = "#078CC6"
# Monkey patching wagtail.admin.views.pages.ordering.set_page_position because there is a bug in the original code
# github issue:
wagtail.admin.views.pages.ordering.set_page_position = set_page_position
# 1. Use the register_rich_text_features hook. # 1. Use the register_rich_text_features hook.
@hooks.register("register_rich_text_features") @hooks.register("register_rich_text_features")
@ -111,6 +118,8 @@ def register_secondary_feature(features):
@hooks.register("construct_explorer_page_queryset") @hooks.register("construct_explorer_page_queryset")
def remove_page_types_from_menu(parent_page, pages, request): def remove_page_types_from_menu(parent_page, pages, request):
# Modify the queryset used to populate the explorer menu, to exclude content that is created by the teachers.
# or: Show only content that is created by the content team.
return ( return (
pages.not_type(ContentBlockSnapshot) pages.not_type(ContentBlockSnapshot)
.not_type(BasicKnowledge) .not_type(BasicKnowledge)

View File

@ -1,35 +1,45 @@
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.http import HttpResponse from django.http import HttpResponse
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from wagtail.models import Page from wagtail import hooks
from wagtail.models import Page
def set_page_position(request, page_to_move_id): def set_page_position(request, page_to_move_id):
page_to_move = get_object_or_404(Page, id=page_to_move_id) page_to_move = get_object_or_404(Page, id=page_to_move_id)
parent_page = page_to_move.get_parent() parent_page = page_to_move.get_parent()
if not parent_page.permissions_for_user(request.user).can_reorder_children(): if not parent_page.permissions_for_user(request.user).can_reorder_children():
raise PermissionDenied raise PermissionDenied
if request.method == "POST": if request.method == "POST":
# Get position parameter # Get position parameter
visible_target_position = request.GET.get("position", None) visible_target_position = request.GET.get("position", None)
# Get position within all children, the frontend does not count the unpublished pages # Get position within all children, the frontend does not count the unpublished pages
if visible_target_position is not None: if visible_target_position is not None:
visible_target_position = int(visible_target_position) visible_target_position = int(visible_target_position)
position = list(parent_page.get_children()).index( position = list(parent_page.get_children()).index(get_visible_children(parent_page, request)[visible_target_position])
get_visible_children(parent_page)[visible_target_position])
print(f"Visible target position: {visible_target_position} -> {position}") print(f"Visible target position: {visible_target_position} -> {position}")
# Find page that's already in this position # Find page that's already in this position
position_page = None position_page = None
if position is not None: if position is not None:
# position = int(position) + 1 #position = int(position) + 1
try: try:
position_page = parent_page.get_children()[int(position)] position_page = parent_page.get_children()[int(position)]
except IndexError: except IndexError:
pass # No page in this position pass # No page in this position
# Move page # Move page
# any invalid moves *should* be caught by the permission check above, # any invalid moves *should* be caught by the permission check above,
# so don't bother to catch InvalidMoveToDescendant # so don't bother to catch InvalidMoveToDescendant
if position_page: if position_page:
# If the page has been moved to the right, insert it to the # If the page has been moved to the right, insert it to the
# right. If left, then left. # right. If left, then left.
@ -39,18 +49,20 @@ def set_page_position(request, page_to_move_id):
elif int(position) > old_position: elif int(position) > old_position:
page_to_move.move(position_page, pos="right", user=request.user) page_to_move.move(position_page, pos="right", user=request.user)
print(f"Moved {old_position} to {position}") print(f"Moved {old_position} to {position}")
else: else:
# Move page to end # Move page to end
page_to_move.move(parent_page, pos="last-child", user=request.user) page_to_move.move(parent_page, pos="last-child", user=request.user)
return HttpResponse("") return HttpResponse("")
def get_visible_children(parent_page, request):
"""
Get the pages of parent which are visible to the user. If a hook is used the visible pages are returned by the hook.
"""
pages = parent_page.get_children()
def get_visible_children(parent_page): for hook in hooks.get_hooks("construct_explorer_page_queryset"):
visible_children = parent_page.get_children().exclude(has_unpublished_changes=True) pages = hook(parent_page, pages, request)
print_children(visible_children) return pages
return visible_children
def print_children(children, level=0):
for ii, sibling in enumerate(children):
print(ii, sibling.has_unpublished_changes, sibling)