From f3ed9db4376e731bfc0e370c737b1ad1c5d8f984 Mon Sep 17 00:00:00 2001 From: Daniel Egger Date: Fri, 21 Jul 2023 08:06:28 +0200 Subject: [PATCH 1/3] Change some settings for Wagtail --- server/config/settings/base.py | 40 +++++++++++++------ .../course/creators/test_course.py | 3 +- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/server/config/settings/base.py b/server/config/settings/base.py index 4cafd708..10a80e6e 100644 --- a/server/config/settings/base.py +++ b/server/config/settings/base.py @@ -7,6 +7,7 @@ from pathlib import Path import structlog from environs import Env +from vbv_lernwelt.core.constants import DEFAULT_RICH_TEXT_FEATURES from vbv_lernwelt.core.utils import structlog_add_app_info SERVER_ROOT_DIR = Path(__file__).resolve(strict=True).parent.parent.parent @@ -226,26 +227,41 @@ else: IT_SERVE_VUE = env.bool("IT_SERVE_VUE", DEBUG) IT_SERVE_VUE_URL = env("IT_SERVE_VUE_URL", "http://localhost:5173") +LANGUAGES = [ + ("de", "German"), + ("fr", "French"), + ("it", "Italian"), +] # WAGTAIL # ------------------------------------------------------------------------------ WAGTAIL_SITE_NAME = "VBV Lernwelt" -WAGTAIL_I18N_ENABLED = True +WAGTAIL_I18N_ENABLED = False WAGTAILADMIN_BASE_URL = "/server/cms/" -LANGUAGES = [ - ("en-US", "English (American)"), - ("fr-CH", "Swiss French"), - ("de-CH", "Swiss German"), - ("it-CH", "Swiss Italian"), -] +WAGTAILREDIRECTS_AUTO_CREATE = False +WAGTAIL_PASSWORD_MANAGEMENT_ENABLED = False +WAGTAIL_PASSWORD_RESET_ENABLED = False +WAGTAILUSERS_PASSWORD_ENABLED = False +WAGTAIL_ENABLE_UPDATE_CHECK = False +WAGTAIL_ENABLE_WHATS_NEW_BANNER = False WAGTAILDOCS_DOCUMENT_MODEL = "media_library.LibraryDocument" -WAGTAIL_CONTENT_LANGUAGES = [ - ("fr-CH", "Swiss French"), - ("de-CH", "Swiss German"), - ("it-CH", "Swiss Italian"), -] +WAGTAILADMIN_RICH_TEXT_EDITORS = { + "default": { + "WIDGET": "wagtail.admin.rich_text.DraftailRichTextArea", + "OPTIONS": {"features": DEFAULT_RICH_TEXT_FEATURES}, + }, + "secondary": { + "WIDGET": "some.external.RichTextEditor", + }, +} + +# WAGTAIL_CONTENT_LANGUAGES = [ +# ("fr-CH", "Swiss French"), +# ("de-CH", "Swiss German"), +# ("it-CH", "Swiss Italian"), +# ] WAGTAILSEARCH_BACKENDS = { "default": { diff --git a/server/vbv_lernwelt/course/creators/test_course.py b/server/vbv_lernwelt/course/creators/test_course.py index bb70aa38..8a2696fa 100644 --- a/server/vbv_lernwelt/course/creators/test_course.py +++ b/server/vbv_lernwelt/course/creators/test_course.py @@ -27,7 +27,6 @@ from vbv_lernwelt.core.constants import ( TEST_COURSE_SESSION_ZURICH_ID, ) from vbv_lernwelt.core.models import User -from vbv_lernwelt.core.tests.helpers import create_locales_for_wagtail from vbv_lernwelt.course.consts import COURSE_TEST_ID from vbv_lernwelt.course.factories import CoursePageFactory from vbv_lernwelt.course.models import ( @@ -70,7 +69,7 @@ from vbv_lernwelt.media_library.tests.media_library_factories import ( def create_test_course(include_uk=True, include_vv=True, with_sessions=False): - create_locales_for_wagtail() + # create_locales_for_wagtail() course = create_test_course_with_categories() create_test_competence_profile() From 6654d61761e1a8bbb5c140c0f0a366d38d7bc114 Mon Sep 17 00:00:00 2001 From: Daniel Egger Date: Mon, 24 Jul 2023 10:18:12 +0200 Subject: [PATCH 2/3] Refactor some course creation stuff --- .../course/creators/test_course.py | 13 +------- .../vbv_lernwelt/course/creators/uk_course.py | 31 +------------------ .../course/creators/uk_training_course.py | 13 +------- .../creators/versicherungsvermittlerin.py | 13 +------- .../commands/create_default_courses.py | 31 ++++++++++++------- server/vbv_lernwelt/course/views.py | 2 +- .../learnpath/create_vv_new_learning_path.py | 13 +------- 7 files changed, 26 insertions(+), 90 deletions(-) diff --git a/server/vbv_lernwelt/course/creators/test_course.py b/server/vbv_lernwelt/course/creators/test_course.py index 8a2696fa..a790bd09 100644 --- a/server/vbv_lernwelt/course/creators/test_course.py +++ b/server/vbv_lernwelt/course/creators/test_course.py @@ -1,8 +1,6 @@ from datetime import datetime -import wagtail_factories from dateutil.relativedelta import MO, relativedelta, TH, TU -from django.conf import settings from django.utils import timezone from slugify import slugify from wagtail.models import Site @@ -231,18 +229,9 @@ def create_test_course_with_categories(apps=None, schema_editor=None): ]: CourseCategory.objects.get_or_create(course=course, title=cat) - # create default course page - site = Site.objects.filter(is_default_site=True).first() - if not site: - site = wagtail_factories.SiteFactory(is_default_site=True) - - if settings.APP_ENVIRONMENT == "development": - site.port = 8000 - site.save() - course_page = CoursePageFactory( title="Test Lehrgang", - parent=site.root_page, + parent=Site.objects.get(is_default_site=True).root_page, course=course, ) course.slug = course_page.slug diff --git a/server/vbv_lernwelt/course/creators/uk_course.py b/server/vbv_lernwelt/course/creators/uk_course.py index 5b63b706..58a75ead 100644 --- a/server/vbv_lernwelt/course/creators/uk_course.py +++ b/server/vbv_lernwelt/course/creators/uk_course.py @@ -1,8 +1,6 @@ -import wagtail_factories -from django.conf import settings from django.core.management import call_command from slugify import slugify -from wagtail.models import Locale, Page, Site +from wagtail.models import Locale, Page from wagtail.rich_text import RichText from wagtail_localize.models import LocaleSynchronization @@ -36,15 +34,6 @@ def create_uk_learning_path(course_id=COURSE_UK, user=None, skip_locales=True): if user is None: user = User.objects.get(username="info@iterativ.ch") - site = Site.objects.filter(is_default_site=True).first() - - if not site: - site = wagtail_factories.SiteFactory(is_default_site=True) - - if settings.APP_ENVIRONMENT == "development": - site.port = 8000 - site.save() - course_page = CoursePage.objects.get(course_id=course_id) lp = LearningPathFactory( title="Lernpfad", @@ -93,15 +82,6 @@ def create_uk_fr_learning_path(course_id=COURSE_UK_FR, user=None, skip_locales=T if user is None: user = User.objects.get(username="info@iterativ.ch") - site = Site.objects.filter(is_default_site=True).first() - - if not site: - site = wagtail_factories.SiteFactory(is_default_site=True) - - if settings.APP_ENVIRONMENT == "development": - site.port = 8000 - site.save() - course_page = CoursePage.objects.get(course_id=course_id) lp = LearningPathFactory( title="Lernpfad", @@ -149,15 +129,6 @@ def create_uk_it_learning_path(course_id=COURSE_UK_IT, user=None, skip_locales=T if user is None: user = User.objects.get(username="info@iterativ.ch") - site = Site.objects.filter(is_default_site=True).first() - - if not site: - site = wagtail_factories.SiteFactory(is_default_site=True) - - if settings.APP_ENVIRONMENT == "development": - site.port = 8000 - site.save() - course_page = CoursePage.objects.get(course_id=course_id) lp = LearningPathFactory( title="Lernpfad", diff --git a/server/vbv_lernwelt/course/creators/uk_training_course.py b/server/vbv_lernwelt/course/creators/uk_training_course.py index ef4449fb..dc013b11 100644 --- a/server/vbv_lernwelt/course/creators/uk_training_course.py +++ b/server/vbv_lernwelt/course/creators/uk_training_course.py @@ -1,7 +1,5 @@ -import wagtail_factories -from django.conf import settings from django.core.management import call_command -from wagtail.models import Locale, Page, Site +from wagtail.models import Locale, Page from wagtail_localize.models import LocaleSynchronization from vbv_lernwelt.core.admin import User @@ -28,15 +26,6 @@ def create_uk_training_learning_path( if user is None: user = User.objects.get(username="info@iterativ.ch") - site = Site.objects.filter(is_default_site=True).first() - - if not site: - site = wagtail_factories.SiteFactory(is_default_site=True) - - if settings.APP_ENVIRONMENT == "development": - site.port = 8000 - site.save() - course_page = CoursePage.objects.get(course_id=course_id) lp = LearningPathFactory( title="Lernpfad", diff --git a/server/vbv_lernwelt/course/creators/versicherungsvermittlerin.py b/server/vbv_lernwelt/course/creators/versicherungsvermittlerin.py index a0e72b47..77f9f2b8 100644 --- a/server/vbv_lernwelt/course/creators/versicherungsvermittlerin.py +++ b/server/vbv_lernwelt/course/creators/versicherungsvermittlerin.py @@ -1,5 +1,3 @@ -import wagtail_factories -from django.conf import settings from wagtail.models import Site from vbv_lernwelt.course.consts import COURSE_VERSICHERUNGSVERMITTLERIN_ID @@ -43,18 +41,9 @@ def create_versicherungsvermittlerin_with_categories( ]: CourseCategory.objects.get_or_create(course=course, title=cat) - # create default course page - site = Site.objects.filter(is_default_site=True).first() - if not site: - site = wagtail_factories.SiteFactory(is_default_site=True) - - if settings.APP_ENVIRONMENT == "development": - site.port = 8000 - site.save() - course_page = CoursePageFactory( title=title, - parent=site.root_page, + parent=Site.objects.get(is_default_site=True).root_page, course=course, ) course.slug = course_page.slug diff --git a/server/vbv_lernwelt/course/management/commands/create_default_courses.py b/server/vbv_lernwelt/course/management/commands/create_default_courses.py index 7b836e78..d8b09b63 100644 --- a/server/vbv_lernwelt/course/management/commands/create_default_courses.py +++ b/server/vbv_lernwelt/course/management/commands/create_default_courses.py @@ -121,6 +121,7 @@ def command(course): if COURSE_UK in course: create_course_uk_de() + create_course_uk_de_course_sessions() create_course_uk_de_completion_data( CourseSession.objects.get(title="Bern 2023 a") ) @@ -220,26 +221,34 @@ def create_versicherungsvermittlerin_course(): ) -def create_course_uk_de(): - # Überbetriebliche Kurse DE +def create_course_uk_de(course_id=COURSE_UK, lang="de"): + names = { + "de": "Überbetriebliche Kurse", + "fr": "Cours interentreprises", + "it": "Corsi interaziendali", + } course = create_versicherungsvermittlerin_with_categories( - course_id=COURSE_UK, title="Überbetriebliche Kurse" + course_id=course_id, title=names[lang] ) # assignments create assignments parent page _assignment_list_page = AssignmentListPageFactory( parent=course.coursepage, ) - create_uk_kickoff_prep_assignment(course_id=COURSE_UK) - create_uk_basis_prep_assignment(course_id=COURSE_UK) - create_uk_fahrzeug_casework(course_id=COURSE_UK) - create_uk_fahrzeug_prep_assignment(course_id=COURSE_UK) - create_uk_reflection(course_id=COURSE_UK) + create_uk_kickoff_prep_assignment(course_id=course_id) + create_uk_basis_prep_assignment(course_id=course_id) + create_uk_fahrzeug_casework(course_id=course_id) + create_uk_fahrzeug_prep_assignment(course_id=course_id) + create_uk_reflection(course_id=course_id) # learning path - create_uk_learning_path(course_id=COURSE_UK) - create_uk_competence_profile(course_id=COURSE_UK) - create_default_media_library(course_id=COURSE_UK) + create_uk_learning_path(course_id=course_id) + create_uk_competence_profile(course_id=course_id) + create_default_media_library(course_id=course_id) + + +def create_course_uk_de_course_sessions(): + course = Course.objects.get(id=COURSE_UK) cs = CourseSession.objects.create( course_id=COURSE_UK, diff --git a/server/vbv_lernwelt/course/views.py b/server/vbv_lernwelt/course/views.py index fb4dcadc..9a6b511f 100644 --- a/server/vbv_lernwelt/course/views.py +++ b/server/vbv_lernwelt/course/views.py @@ -39,7 +39,7 @@ def course_page_api_view(request, slug_or_id): if slug_or_id.isdigit(): page = Page.objects.get(id=slug_or_id) else: - page = Page.objects.get(slug=slug_or_id, locale__language_code="de-CH") + page = Page.objects.get(slug=slug_or_id) if not has_course_access_by_page_request(request, page): raise PermissionDenied() diff --git a/server/vbv_lernwelt/learnpath/create_vv_new_learning_path.py b/server/vbv_lernwelt/learnpath/create_vv_new_learning_path.py index 472ecc54..3b530440 100644 --- a/server/vbv_lernwelt/learnpath/create_vv_new_learning_path.py +++ b/server/vbv_lernwelt/learnpath/create_vv_new_learning_path.py @@ -1,8 +1,6 @@ -import wagtail_factories -from django.conf import settings from django.core.management import call_command from slugify import slugify -from wagtail.models import Locale, Page, Site +from wagtail.models import Locale, Page from wagtail.rich_text import RichText from wagtail_localize.models import LocaleSynchronization @@ -39,15 +37,6 @@ def create_vv_new_learning_path( if user is None: user = User.objects.get(username="info@iterativ.ch") - site = Site.objects.filter(is_default_site=True).first() - - if not site: - site = wagtail_factories.SiteFactory(is_default_site=True) - - if settings.APP_ENVIRONMENT == "development": - site.port = 8000 - site.save() - course_page = CoursePage.objects.get(course_id=course_id) lp = LearningPathFactory( title="Lernpfad", From a999375f23c9104d7f887d250f4322d1234b8fd9 Mon Sep 17 00:00:00 2001 From: Daniel Egger Date: Mon, 24 Jul 2023 13:34:08 +0200 Subject: [PATCH 3/3] Update slugs when parent changes slug due to title change --- server/config/settings/base.py | 1 + .../course/creators/test_course.py | 4 +- .../creators/versicherungsvermittlerin.py | 5 +-- server/vbv_lernwelt/course/models.py | 27 ++++++++++++- .../course/tests/test_model_save.py | 38 +++++++++++++++++++ server/vbv_lernwelt/course/utils.py | 15 ++++++++ 6 files changed, 84 insertions(+), 6 deletions(-) create mode 100644 server/vbv_lernwelt/course/tests/test_model_save.py create mode 100644 server/vbv_lernwelt/course/utils.py diff --git a/server/config/settings/base.py b/server/config/settings/base.py index 10a80e6e..2136e4fd 100644 --- a/server/config/settings/base.py +++ b/server/config/settings/base.py @@ -244,6 +244,7 @@ WAGTAIL_PASSWORD_RESET_ENABLED = False WAGTAILUSERS_PASSWORD_ENABLED = False WAGTAIL_ENABLE_UPDATE_CHECK = False WAGTAIL_ENABLE_WHATS_NEW_BANNER = False +WAGTAIL_CONTENT_LANGUAGES = LANGUAGES WAGTAILDOCS_DOCUMENT_MODEL = "media_library.LibraryDocument" diff --git a/server/vbv_lernwelt/course/creators/test_course.py b/server/vbv_lernwelt/course/creators/test_course.py index a790bd09..2eaaae2d 100644 --- a/server/vbv_lernwelt/course/creators/test_course.py +++ b/server/vbv_lernwelt/course/creators/test_course.py @@ -3,7 +3,6 @@ from datetime import datetime from dateutil.relativedelta import MO, relativedelta, TH, TU from django.utils import timezone from slugify import slugify -from wagtail.models import Site from wagtail.rich_text import RichText from vbv_lernwelt.assignment.creators.create_assignments import ( @@ -34,6 +33,7 @@ from vbv_lernwelt.course.models import ( CourseSession, CourseSessionUser, ) +from vbv_lernwelt.course.utils import get_wagtail_default_site from vbv_lernwelt.course_session.models import ( CourseSessionAssignment, CourseSessionAttendanceCourse, @@ -231,7 +231,7 @@ def create_test_course_with_categories(apps=None, schema_editor=None): course_page = CoursePageFactory( title="Test Lehrgang", - parent=Site.objects.get(is_default_site=True).root_page, + parent=get_wagtail_default_site().root_page, course=course, ) course.slug = course_page.slug diff --git a/server/vbv_lernwelt/course/creators/versicherungsvermittlerin.py b/server/vbv_lernwelt/course/creators/versicherungsvermittlerin.py index 77f9f2b8..48fa0bc6 100644 --- a/server/vbv_lernwelt/course/creators/versicherungsvermittlerin.py +++ b/server/vbv_lernwelt/course/creators/versicherungsvermittlerin.py @@ -1,7 +1,6 @@ -from wagtail.models import Site - from vbv_lernwelt.course.consts import COURSE_VERSICHERUNGSVERMITTLERIN_ID from vbv_lernwelt.course.factories import CoursePageFactory +from vbv_lernwelt.course.utils import get_wagtail_default_site def create_versicherungsvermittlerin_with_categories( @@ -43,7 +42,7 @@ def create_versicherungsvermittlerin_with_categories( course_page = CoursePageFactory( title=title, - parent=Site.objects.get(is_default_site=True).root_page, + parent=get_wagtail_default_site().root_page, course=course, ) course.slug = course_page.slug diff --git a/server/vbv_lernwelt/course/models.py b/server/vbv_lernwelt/course/models.py index 12721ca9..f5e77d67 100644 --- a/server/vbv_lernwelt/course/models.py +++ b/server/vbv_lernwelt/course/models.py @@ -2,7 +2,8 @@ import enum import uuid from django.db import models -from django.db.models import UniqueConstraint +from django.db.models import UniqueConstraint, Value +from django.db.models.functions import Replace from django.utils.text import slugify from django.utils.translation import gettext_lazy as _ from grapple.models import GraphQLString @@ -131,6 +132,30 @@ class CourseBasePage(Page): def __str__(self): return f"{self.title}" + def _update_descendant_slugs(self, old_slug, new_slug): + """ + this method is inspired by `_update_descendant_url_paths` from wagtail Page + """ + Page.objects.filter(path__startswith=self.path).exclude(pk=self.pk).update( + slug=Replace("slug", Value(old_slug), Value(new_slug)) + ) + + def save(self, clean=True, user=None, log_action=False, **kwargs): + slug_changed = False + + if not self.id is None: + old_record = Page.objects.get(id=self.id).specific + if old_record.slug != self.slug: + self.set_url_path(self.get_parent()) + slug_changed = True + old_slug = old_record.slug + new_slug = self.slug + + super().save(**kwargs) + + if slug_changed: + self._update_descendant_slugs(old_slug, new_slug) + class CoursePage(CourseBasePage): content_panels = Page.content_panels diff --git a/server/vbv_lernwelt/course/tests/test_model_save.py b/server/vbv_lernwelt/course/tests/test_model_save.py new file mode 100644 index 00000000..45710866 --- /dev/null +++ b/server/vbv_lernwelt/course/tests/test_model_save.py @@ -0,0 +1,38 @@ +from rest_framework.test import APITestCase + +from vbv_lernwelt.core.create_default_users import create_default_users +from vbv_lernwelt.course.creators.test_course import create_test_course +from vbv_lernwelt.learnpath.models import Circle, LearningContentAttendanceCourse + + +class CourseBasePageSaveTestCase(APITestCase): + def setUp(self) -> None: + create_default_users() + create_test_course() + + def test_save_willRenameSlugsOfChildren(self): + circle_fahrzeug = Circle.objects.get(title="Fahrzeug") + self.assertEqual(circle_fahrzeug.slug, "test-lehrgang-lp-circle-fahrzeug") + + lc_attendance_course = LearningContentAttendanceCourse.objects.descendant_of( + circle_fahrzeug + ).first() + self.assertEqual( + lc_attendance_course.slug, + "test-lehrgang-lp-circle-fahrzeug-lc-präsenzkurs-fahrzeug", + ) + + # title update should also update the slugs of the descendants + circle_fahrzeug.title = "Foobar" + circle_fahrzeug.save() + + circle_fahrzeug = Circle.objects.get(id=circle_fahrzeug.id) + self.assertEqual(circle_fahrzeug.slug, "test-lehrgang-lp-circle-foobar") + + lc_attendance_course = LearningContentAttendanceCourse.objects.descendant_of( + circle_fahrzeug + ).first() + self.assertEqual( + lc_attendance_course.slug, + "test-lehrgang-lp-circle-foobar-lc-präsenzkurs-fahrzeug", + ) diff --git a/server/vbv_lernwelt/course/utils.py b/server/vbv_lernwelt/course/utils.py new file mode 100644 index 00000000..57cb333a --- /dev/null +++ b/server/vbv_lernwelt/course/utils.py @@ -0,0 +1,15 @@ +import wagtail_factories +from django.conf import settings +from wagtail.models import Locale, Site + + +def get_wagtail_default_site(): + for language in settings.WAGTAIL_CONTENT_LANGUAGES: + Locale.objects.get_or_create(language_code=language[0]) + + site = Site.objects.filter(is_default_site=True).first() + + if not site: + site = wagtail_factories.SiteFactory(is_default_site=True) + + return site