diff --git a/server/books/models/contentblock.py b/server/books/models/contentblock.py index f8392647..1698ca23 100644 --- a/server/books/models/contentblock.py +++ b/server/books/models/contentblock.py @@ -41,30 +41,30 @@ def duplicate_entities_generator(new_module): def duplicate_entities(block): content_type = block.block_type value = block.value - logger.debug(block) + # logger.debug(block) if content_type == "assignment": assignment = value.get("assignment_id") # copy the assignment assignment.pk = None assignment.title = f"{assignment.title} (Kopie)" assignment.module = new_module - logger.debug(f"setting new module {new_module}, {assignment.module}") + # logger.debug(f"setting new module {new_module}, {assignment.module}") assignment.save() data = {"assignment_id": assignment} new_block = ("assignment", data) return new_block if content_type == "survey": - logger.debug(value) + # logger.debug(value) survey = value.get("survey_id") # copy the survey survey.pk = None survey.title = f"{survey.title} (Kopie)" survey.module = new_module - logger.debug(f"setting new module {new_module}, {survey.module}") + # logger.debug(f"setting new module {new_module}, {survey.module}") survey.save() data = {"survey_id": survey} new_block = ("survey", data) - logger.debug(new_block) + # logger.debug(new_block) return new_block return block @@ -159,19 +159,19 @@ class ContentBlock(StrictHierarchyPage, GraphqlNodeMixin): # duplicate all attached Surveys and Assignments def duplicate_attached_entities(self): - logger.debug("starting to duplicate inside the content block") + # logger.debug("starting to duplicate inside the content block") duplicate_entities = duplicate_entities_generator(self.module) - logger.debug(f"new module: {self.module}") + # logger.debug(f"new module: {self.module}") iterator = map(duplicate_entities, self.contents) - logger.debug("here is the iterator") + # logger.debug("here is the iterator") new_contents = list(iterator) - logger.debug(new_contents) + # logger.debug(new_contents) # we can't just insert a list here, we need a StreamValue data type # so we need to clear the list, then add each element in turn self.contents.clear() # like this, the internal methods of the SteamValue data type can work on the single elements for content in new_contents: - logger.debug(content) + # logger.debug(content) self.contents.append(content) # as an illustration @@ -180,8 +180,8 @@ class ContentBlock(StrictHierarchyPage, GraphqlNodeMixin): # value = block.to_python(data) # clean_value = block.clean(value) # self.contents.append(('solution', clean_value)) - logger.debug("self.contents") - logger.debug(self.contents) + # logger.debug("self.contents") + # logger.debug(self.contents) self.save() def is_hidden_for_class(self, school_class): @@ -193,6 +193,23 @@ class ContentBlock(StrictHierarchyPage, GraphqlNodeMixin): and not self.visible_for.filter(id=school_class.id).exists() ) + def reassign_entities(self): + module = self.module + logger.debug("reassigning entities") + for content in self.contents: + if content.block_type == "assignment": + assignment = content.value.get("assignment_id") + logger.debug(assignment.module) + if assignment.module != module: + assignment.module = module + assignment.save() + if content.block_type == "survey": + survey = content.value.get("survey_id") + logger.debug(survey.module) + if survey.module != module: + survey.module = module + survey.save() + # def save(self, *args, **kwargs): # todo: move this to the after_create_page and after_edit_page hooks, and remove from here. # for data in self.contents.raw_data: diff --git a/server/core/tests/test_core_hooks.py b/server/core/tests/test_core_hooks.py index 75232d66..e3bac915 100644 --- a/server/core/tests/test_core_hooks.py +++ b/server/core/tests/test_core_hooks.py @@ -1,6 +1,7 @@ import json from django.test import TestCase from django.urls import reverse +from wagtail.models import Page from wagtail.test.utils import WagtailTestUtils from assignments.factories import AssignmentFactory from assignments.models import Assignment @@ -45,6 +46,7 @@ class CoreHooksTestCase(WagtailTestUtils, TestCase): # create content blocks assignment = AssignmentFactory() + self.assignment_id = assignment.id assignment_block = AssignmentBlock() assignment_value = assignment_block.to_python({"assignment_id": assignment.id}) cleaned_assignment_value = assignment_block.clean(assignment_value) @@ -66,7 +68,7 @@ class CoreHooksTestCase(WagtailTestUtils, TestCase): self.assertEqual(self.content_block.contents[1].value["survey_id"], survey) self.assertEqual(Assignment.objects.count(), 1) self.assertEqual(Survey.objects.count(), 1) - logger.debug(f"assignment: {assignment.id}") + # logger.debug(f"assignment: {assignment.id}") self.new_topic = TopicFactory.create( parent=self.book, title="A second Topic", order=2 @@ -111,12 +113,11 @@ class CoreHooksTestCase(WagtailTestUtils, TestCase): "wagtailadmin_pages:add", args=("books", "topic", self.book.id), ) - logger.debug(url) - response = self.client.post( + # logger.debug(url) + self.client.post( url, post_data, ) - logger.debug(response) self.assertEqual(Topic.objects.count(), 3) def _check_copied_content_block(self, module=None): @@ -127,7 +128,6 @@ class CoreHooksTestCase(WagtailTestUtils, TestCase): self.assertEqual(Assignment.objects.count(), 2) self.assertEqual(Survey.objects.count(), 2) new_content_block = ContentBlock.objects.latest("-latest_revision_created_at") - logger.debug(f"new content block {new_content_block}") new_assignment = Assignment.objects.latest("pk") new_survey = Survey.objects.latest("pk") self.assertEqual( @@ -147,9 +147,7 @@ class CoreHooksTestCase(WagtailTestUtils, TestCase): post_data = get_copy_payload( "Neuer Titel (Kopie)", "new-slug", self.new_chapter ) - logger.debug(post_data) - response = self.client.post(url, post_data) - logger.debug(response) + self.client.post(url, post_data) self._check_copied_content_block() def test_chapter_after_copy_hook(self): @@ -158,8 +156,7 @@ class CoreHooksTestCase(WagtailTestUtils, TestCase): """ url = get_copy_url(self.chapter) post_data = get_copy_payload("Neuer Titel (Kopie)", "new-slug", self.new_module) - response = self.client.post(url, post_data) - logger.debug(response) + self.client.post(url, post_data) self._check_copied_content_block() def test_module_after_copy_hook(self): @@ -168,8 +165,7 @@ class CoreHooksTestCase(WagtailTestUtils, TestCase): """ url = get_copy_url(self.module) post_data = get_copy_payload("Neuer Titel (Kopie)", "new-slug", self.new_topic) - response = self.client.post(url, post_data) - logger.debug(response) + self.client.post(url, post_data) module = Module.objects.latest("-latest_revision_created_at") self._check_copied_content_block(module) @@ -179,8 +175,90 @@ class CoreHooksTestCase(WagtailTestUtils, TestCase): """ url = get_copy_url(self.topic) post_data = get_copy_payload("Neuer Titel (Kopie)", "new-slug", self.book) - response = self.client.post(url, post_data) - logger.debug(response) + self.client.post(url, post_data) topic = Topic.objects.latest("-latest_revision_created_at") module = topic.get_children().first().specific self._check_copied_content_block(module) + + def test_chapter_after_move_hook(self): + """ + should move the chapter, and set all entities' module to the new parent's parent module + """ + + assignment = self.content_block.contents[0].value["assignment_id"] + survey = self.content_block.contents[1].value["survey_id"] + self.assertEqual(self.chapter.pk, self.content_block.get_parent().pk) + + logger.debug("content blocks") + logger.debug(self.chapter.get_content_blocks()) + + url = reverse( + "wagtailadmin_pages:move_confirm", + args=(self.chapter.id, self.new_module.id), + ) + logger.debug(url) + response = self.client.post(url) + logger.debug(response) + chapter = Page.objects.get(id=self.chapter.id) + logger.debug("new content blocks") + logger.debug(chapter.specific.get_content_blocks()) + self.assertEqual(chapter.get_parent().id, self.new_module.id) + # reload the assignment from the DB + assignment = Assignment.objects.get(id=assignment.id) + self.assertEqual(assignment.module, self.new_module) + survey = Survey.objects.get(id=survey.id) + self.assertEqual(survey.module, self.new_module) + + def test_content_block_after_move_hook(self): + """ + should move the content block, and set all entities' module to the new parent's parent module + """ + + url = reverse( + "wagtailadmin_pages:move_confirm", + args=(self.content_block.id, self.new_chapter.id), + ) + self.client.post(url) + assignment = self.content_block.contents[0].value["assignment_id"] + self.assertEqual(assignment.module, self.new_module) + + def test_content_block_after_create_hook(self): + """ + should save the content block and set all new entites' module to the correct module + """ + assignment = AssignmentFactory(module=self.module) + survey = SurveyFactory(module=None) + self.assertEqual(assignment.module, assignment.module) + self.assertIsNone(survey.module) + self.assertEqual(ContentBlock.objects.count(), 1) + url = reverse( + "wagtailadmin_pages:add", + args=("books", "contentblock", self.new_chapter.id), + ) + post_data = { + "title": "New Content Block", + "order": 1, + "slug": "hello-world", + "contents-count": 2, + "contents-0-deleted": "", + "contents-0-order": "0", + "contents-0-type": "assignment", + "contents-0-id": "", + "contents-0-value-assignment_id": f"{assignment.id}", + "contents-1-deleted": "", + "contents-1-order": "1", + "contents-1-type": "survey", + "contents-1-id": "", + "contents-1-value-survey_id": f"{survey.id}", + "type": "normal", + } + response = self.client.post( + url, + post_data, + ) + self.assertEqual(ContentBlock.objects.count(), 2) + # reload assignment + assignment = Assignment.objects.get(id=assignment.id) + self.assertEqual(assignment.module, self.new_module) + survey = Survey.objects.get(id=survey.id) + self.assertEqual(survey.module, self.new_module) diff --git a/server/core/wagtail_hooks.py b/server/core/wagtail_hooks.py index 8522efc2..2d85789a 100644 --- a/server/core/wagtail_hooks.py +++ b/server/core/wagtail_hooks.py @@ -6,6 +6,7 @@ from wagtail import hooks from basicknowledge.models import BasicKnowledge from books.models import ContentBlockSnapshot +from books.models.chapter import Chapter from books.models.contentblock import ContentBlock from core.logger import get_logger @@ -102,20 +103,32 @@ def remove_page_types_from_menu(parent_page, pages, request): def after_copy_hook(request, page, new_page): # todo: find every ContentBlock further down in the tree, see if there are any Surveys or Assignments and copy them and reassign them if type(page.specific) == ContentBlock: - logger.debug("It's a content block") + # logger.debug("It's a content block") content_block: ContentBlock = new_page.specific - logger.debug(f"duplicatin {content_block.title, content_block.pk}") + # logger.debug(f"duplicatin {content_block.title, content_block.pk}") content_block.duplicate_attached_entities() else: - logger.debug(f"It's something else {type(page.specific)}, {ContentBlock}") + # logger.debug(f"It's something else {type(page.specific)}, {ContentBlock}") content_blocks = new_page.specific.get_content_blocks() for content_block in content_blocks: content_block.duplicate_attached_entities() - logger.debug( - f"After copy page old: {page.title} {page.pk}, {new_page.title} {new_page.pk}" - ) + +@hooks.register("after_move_page") +def after_move_hook(request, page): + logger.debug(f"after moving the page {page.title}") + if type(page.specific) == ContentBlock: + logger.debug("it's a content block") + page.specific.reassign_entities() + if type(page.specific) == Chapter: + logger.debug("it's a chapter") + content_blocks = page.specific.get_content_blocks() + logger.debug(page.id) + logger.debug(page.specific.get_content_blocks()) + logger.debug(page.get_children()) + for content_block in content_blocks: + content_block.reassign_entities() @hooks.register("after_edit_page") @@ -125,4 +138,7 @@ def after_edit_hook(request, page): @hooks.register("after_create_page") def after_create_hook(request, page): - logger.debug(f"After create page {page.title}") + # reassign assignment and survey module + if type(page.specific) == ContentBlock: + content_block = page.specific + content_block.reassign_entities()