From 1de888b5cda0bb2bede75555d77eaabb6c5b8052 Mon Sep 17 00:00:00 2001 From: Lorenz Padberg Date: Mon, 17 Jul 2023 10:41:12 +0200 Subject: [PATCH 1/3] Add Idea for the wagtail fix --- .../wagtailadmin/pages/listing/_list.html | 1 + server/core/wagtail_patch.py | 56 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 server/core/wagtail_patch.py diff --git a/server/core/templates/wagtailadmin/pages/listing/_list.html b/server/core/templates/wagtailadmin/pages/listing/_list.html index 49ad3173..69d831d0 100644 --- a/server/core/templates/wagtailadmin/pages/listing/_list.html +++ b/server/core/templates/wagtailadmin/pages/listing/_list.html @@ -64,6 +64,7 @@ {% elif show_bulk_actions %} {% include "wagtailadmin/bulk_actions/listing_checkbox_cell.html" with obj_type="page" obj=page aria_labelledby_prefix="page_" aria_labelledby=page.pk|unlocalize aria_labelledby_suffix="_title" %} {% endif %} + {% block page_title %} diff --git a/server/core/wagtail_patch.py b/server/core/wagtail_patch.py new file mode 100644 index 00000000..a0b8e29e --- /dev/null +++ b/server/core/wagtail_patch.py @@ -0,0 +1,56 @@ +from django.core.exceptions import PermissionDenied +from django.http import HttpResponse +from django.shortcuts import get_object_or_404 +from wagtail.models import Page + + + +def set_page_position(request, page_to_move_id): + page_to_move = get_object_or_404(Page, id=page_to_move_id) + parent_page = page_to_move.get_parent() + if not parent_page.permissions_for_user(request.user).can_reorder_children(): + raise PermissionDenied + if request.method == "POST": + # Get position parameter + visible_target_position = request.GET.get("position", None) + # Get position within all children, the frontend does not count the unpublished pages + if visible_target_position is not None: + visible_target_position = int(visible_target_position) + position = list(parent_page.get_children()).index( + get_visible_children(parent_page)[visible_target_position]) + print(f"Visible target position: {visible_target_position} -> {position}") + # Find page that's already in this position + position_page = None + if position is not None: + # position = int(position) + 1 + try: + position_page = parent_page.get_children()[int(position)] + except IndexError: + pass # No page in this position + # Move page + # any invalid moves *should* be caught by the permission check above, + # so don't bother to catch InvalidMoveToDescendant + if position_page: + # If the page has been moved to the right, insert it to the + # right. If left, then left. + old_position = list(parent_page.get_children()).index(page_to_move) + if int(position) < old_position: + page_to_move.move(position_page, pos="left", user=request.user) + elif int(position) > old_position: + page_to_move.move(position_page, pos="right", user=request.user) + print(f"Moved {old_position} to {position}") + else: + # Move page to end + page_to_move.move(parent_page, pos="last-child", user=request.user) + return HttpResponse("") + + +def get_visible_children(parent_page): + visible_children = parent_page.get_children().exclude(has_unpublished_changes=True) + print_children(visible_children) + return visible_children + + +def print_children(children, level=0): + for ii, sibling in enumerate(children): + print(ii, sibling.has_unpublished_changes, sibling) From 2e826f81d59e6a3f8e5744ede07892a271a02e24 Mon Sep 17 00:00:00 2001 From: Lorenz Padberg Date: Mon, 17 Jul 2023 13:09:32 +0200 Subject: [PATCH 2/3] Monkey Patch list ordering in wagtail --- server/core/wagtail_hooks.py | 9 +++++++++ server/core/wagtail_patch.py | 36 ++++++++++++++++++++++++------------ 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/server/core/wagtail_hooks.py b/server/core/wagtail_hooks.py index 0c82c954..7c9dbf14 100644 --- a/server/core/wagtail_hooks.py +++ b/server/core/wagtail_hooks.py @@ -1,3 +1,4 @@ +import wagtail.admin.views.pages.ordering from django.db.models import ProtectedError from django.shortcuts import redirect from wagtail.admin import messages @@ -14,6 +15,7 @@ from books.models.chapter import Chapter from books.models.contentblock import ContentBlock from core.logger import get_logger from django.conf import settings +from .wagtail_patch import set_page_position logger = get_logger(__name__) @@ -31,6 +33,11 @@ else: primary = "#17A887" 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. @hooks.register("register_rich_text_features") @@ -111,6 +118,8 @@ def register_secondary_feature(features): @hooks.register("construct_explorer_page_queryset") 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 ( pages.not_type(ContentBlockSnapshot) .not_type(BasicKnowledge) diff --git a/server/core/wagtail_patch.py b/server/core/wagtail_patch.py index a0b8e29e..2ac4ec1b 100644 --- a/server/core/wagtail_patch.py +++ b/server/core/wagtail_patch.py @@ -1,35 +1,45 @@ from django.core.exceptions import PermissionDenied from django.http import HttpResponse 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): page_to_move = get_object_or_404(Page, id=page_to_move_id) parent_page = page_to_move.get_parent() + if not parent_page.permissions_for_user(request.user).can_reorder_children(): raise PermissionDenied + if request.method == "POST": # Get position parameter visible_target_position = request.GET.get("position", None) + # Get position within all children, the frontend does not count the unpublished pages if visible_target_position is not None: visible_target_position = int(visible_target_position) - position = list(parent_page.get_children()).index( - get_visible_children(parent_page)[visible_target_position]) + position = list(parent_page.get_children()).index(get_visible_children(parent_page, request)[visible_target_position]) print(f"Visible target position: {visible_target_position} -> {position}") + + # Find page that's already in this position position_page = None + + if position is not None: - # position = int(position) + 1 + #position = int(position) + 1 try: position_page = parent_page.get_children()[int(position)] except IndexError: pass # No page in this position + # Move page + # any invalid moves *should* be caught by the permission check above, # so don't bother to catch InvalidMoveToDescendant + if position_page: # If the page has been moved to the right, insert it to the # right. If left, then left. @@ -39,18 +49,20 @@ def set_page_position(request, page_to_move_id): elif int(position) > old_position: page_to_move.move(position_page, pos="right", user=request.user) print(f"Moved {old_position} to {position}") + else: # Move page to end page_to_move.move(parent_page, pos="last-child", user=request.user) + 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): - visible_children = parent_page.get_children().exclude(has_unpublished_changes=True) - print_children(visible_children) - return visible_children + for hook in hooks.get_hooks("construct_explorer_page_queryset"): + pages = hook(parent_page, pages, request) + return pages - -def print_children(children, level=0): - for ii, sibling in enumerate(children): - print(ii, sibling.has_unpublished_changes, sibling) From 13239ef27e21a7969d61fec91c466ca43e414a79 Mon Sep 17 00:00:00 2001 From: Lorenz Padberg Date: Mon, 17 Jul 2023 14:58:40 +0200 Subject: [PATCH 3/3] Apply inputs from pullrequest --- server/core/wagtail_patch.py | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/server/core/wagtail_patch.py b/server/core/wagtail_patch.py index 2ac4ec1b..f0b36cc6 100644 --- a/server/core/wagtail_patch.py +++ b/server/core/wagtail_patch.py @@ -9,34 +9,30 @@ from wagtail.models import Page def set_page_position(request, page_to_move_id): page_to_move = get_object_or_404(Page, id=page_to_move_id) parent_page = page_to_move.get_parent() + position = None if not parent_page.permissions_for_user(request.user).can_reorder_children(): raise PermissionDenied if request.method == "POST": - # Get position parameter + # Get target_position parameter 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 position is determined explorer_page queryset. if visible_target_position is not None: - visible_target_position = int(visible_target_position) - position = list(parent_page.get_children()).index(get_visible_children(parent_page, request)[visible_target_position]) - print(f"Visible target position: {visible_target_position} -> {position}") - + current_page = get_visible_children(parent_page, request)[int(visible_target_position)] + position = list(parent_page.get_children()).index(current_page) # Find page that's already in this position position_page = None - if position is not None: - #position = int(position) + 1 try: - position_page = parent_page.get_children()[int(position)] + position_page = parent_page.get_children()[position] except IndexError: pass # No page in this position # Move page - # any invalid moves *should* be caught by the permission check above, # so don't bother to catch InvalidMoveToDescendant @@ -44,12 +40,10 @@ def set_page_position(request, page_to_move_id): # If the page has been moved to the right, insert it to the # right. If left, then left. old_position = list(parent_page.get_children()).index(page_to_move) - if int(position) < old_position: + if position < old_position: page_to_move.move(position_page, pos="left", user=request.user) - elif int(position) > old_position: + elif position > old_position: page_to_move.move(position_page, pos="right", user=request.user) - print(f"Moved {old_position} to {position}") - else: # Move page to end page_to_move.move(parent_page, pos="last-child", user=request.user) @@ -65,4 +59,3 @@ def get_visible_children(parent_page, request): for hook in hooks.get_hooks("construct_explorer_page_queryset"): pages = hook(parent_page, pages, request) return pages -