Merged in feature/wagtail (pull request #170)

Feature/wagtail
This commit is contained in:
Daniel Egger 2023-07-28 14:48:12 +00:00
commit 8cee1346c5
11 changed files with 137 additions and 108 deletions

View File

@ -7,6 +7,7 @@ from pathlib import Path
import structlog import structlog
from environs import Env from environs import Env
from vbv_lernwelt.core.constants import DEFAULT_RICH_TEXT_FEATURES
from vbv_lernwelt.core.utils import structlog_add_app_info from vbv_lernwelt.core.utils import structlog_add_app_info
SERVER_ROOT_DIR = Path(__file__).resolve(strict=True).parent.parent.parent SERVER_ROOT_DIR = Path(__file__).resolve(strict=True).parent.parent.parent
@ -226,26 +227,42 @@ else:
IT_SERVE_VUE = env.bool("IT_SERVE_VUE", DEBUG) IT_SERVE_VUE = env.bool("IT_SERVE_VUE", DEBUG)
IT_SERVE_VUE_URL = env("IT_SERVE_VUE_URL", "http://localhost:5173") IT_SERVE_VUE_URL = env("IT_SERVE_VUE_URL", "http://localhost:5173")
LANGUAGES = [
("de", "German"),
("fr", "French"),
("it", "Italian"),
]
# WAGTAIL # WAGTAIL
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
WAGTAIL_SITE_NAME = "VBV Lernwelt" WAGTAIL_SITE_NAME = "VBV Lernwelt"
WAGTAIL_I18N_ENABLED = True WAGTAIL_I18N_ENABLED = False
WAGTAILADMIN_BASE_URL = "/server/cms/" WAGTAILADMIN_BASE_URL = "/server/cms/"
LANGUAGES = [ WAGTAILREDIRECTS_AUTO_CREATE = False
("en-US", "English (American)"), WAGTAIL_PASSWORD_MANAGEMENT_ENABLED = False
("fr-CH", "Swiss French"), WAGTAIL_PASSWORD_RESET_ENABLED = False
("de-CH", "Swiss German"), WAGTAILUSERS_PASSWORD_ENABLED = False
("it-CH", "Swiss Italian"), WAGTAIL_ENABLE_UPDATE_CHECK = False
] WAGTAIL_ENABLE_WHATS_NEW_BANNER = False
WAGTAIL_CONTENT_LANGUAGES = LANGUAGES
WAGTAILDOCS_DOCUMENT_MODEL = "media_library.LibraryDocument" WAGTAILDOCS_DOCUMENT_MODEL = "media_library.LibraryDocument"
WAGTAIL_CONTENT_LANGUAGES = [ WAGTAILADMIN_RICH_TEXT_EDITORS = {
("fr-CH", "Swiss French"), "default": {
("de-CH", "Swiss German"), "WIDGET": "wagtail.admin.rich_text.DraftailRichTextArea",
("it-CH", "Swiss Italian"), "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 = { WAGTAILSEARCH_BACKENDS = {
"default": { "default": {

View File

@ -1,11 +1,8 @@
from datetime import datetime from datetime import datetime
import wagtail_factories
from dateutil.relativedelta import MO, relativedelta, TH, TU from dateutil.relativedelta import MO, relativedelta, TH, TU
from django.conf import settings
from django.utils import timezone from django.utils import timezone
from slugify import slugify from slugify import slugify
from wagtail.models import Site
from wagtail.rich_text import RichText from wagtail.rich_text import RichText
from vbv_lernwelt.assignment.creators.create_assignments import ( from vbv_lernwelt.assignment.creators.create_assignments import (
@ -27,7 +24,6 @@ from vbv_lernwelt.core.constants import (
TEST_COURSE_SESSION_ZURICH_ID, TEST_COURSE_SESSION_ZURICH_ID,
) )
from vbv_lernwelt.core.models import User 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.consts import COURSE_TEST_ID
from vbv_lernwelt.course.factories import CoursePageFactory from vbv_lernwelt.course.factories import CoursePageFactory
from vbv_lernwelt.course.models import ( from vbv_lernwelt.course.models import (
@ -37,6 +33,7 @@ from vbv_lernwelt.course.models import (
CourseSession, CourseSession,
CourseSessionUser, CourseSessionUser,
) )
from vbv_lernwelt.course.utils import get_wagtail_default_site
from vbv_lernwelt.course_session.models import ( from vbv_lernwelt.course_session.models import (
CourseSessionAssignment, CourseSessionAssignment,
CourseSessionAttendanceCourse, CourseSessionAttendanceCourse,
@ -70,7 +67,7 @@ from vbv_lernwelt.media_library.tests.media_library_factories import (
def create_test_course(include_uk=True, include_vv=True, with_sessions=False): 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() course = create_test_course_with_categories()
create_test_competence_profile() create_test_competence_profile()
@ -232,18 +229,9 @@ def create_test_course_with_categories(apps=None, schema_editor=None):
]: ]:
CourseCategory.objects.get_or_create(course=course, title=cat) 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( course_page = CoursePageFactory(
title="Test Lehrgang", title="Test Lehrgang",
parent=site.root_page, parent=get_wagtail_default_site().root_page,
course=course, course=course,
) )
course.slug = course_page.slug course.slug = course_page.slug

View File

@ -1,8 +1,6 @@
import wagtail_factories
from django.conf import settings
from django.core.management import call_command from django.core.management import call_command
from slugify import slugify 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.rich_text import RichText
from wagtail_localize.models import LocaleSynchronization 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: if user is None:
user = User.objects.get(username="info@iterativ.ch") 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) course_page = CoursePage.objects.get(course_id=course_id)
lp = LearningPathFactory( lp = LearningPathFactory(
title="Lernpfad", 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: if user is None:
user = User.objects.get(username="info@iterativ.ch") 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) course_page = CoursePage.objects.get(course_id=course_id)
lp = LearningPathFactory( lp = LearningPathFactory(
title="Lernpfad", 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: if user is None:
user = User.objects.get(username="info@iterativ.ch") 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) course_page = CoursePage.objects.get(course_id=course_id)
lp = LearningPathFactory( lp = LearningPathFactory(
title="Lernpfad", title="Lernpfad",

View File

@ -1,7 +1,5 @@
import wagtail_factories
from django.conf import settings
from django.core.management import call_command 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 wagtail_localize.models import LocaleSynchronization
from vbv_lernwelt.core.admin import User from vbv_lernwelt.core.admin import User
@ -28,15 +26,6 @@ def create_uk_training_learning_path(
if user is None: if user is None:
user = User.objects.get(username="info@iterativ.ch") 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) course_page = CoursePage.objects.get(course_id=course_id)
lp = LearningPathFactory( lp = LearningPathFactory(
title="Lernpfad", title="Lernpfad",

View File

@ -1,9 +1,6 @@
import wagtail_factories
from django.conf import settings
from wagtail.models import Site
from vbv_lernwelt.course.consts import COURSE_VERSICHERUNGSVERMITTLERIN_ID from vbv_lernwelt.course.consts import COURSE_VERSICHERUNGSVERMITTLERIN_ID
from vbv_lernwelt.course.factories import CoursePageFactory from vbv_lernwelt.course.factories import CoursePageFactory
from vbv_lernwelt.course.utils import get_wagtail_default_site
def create_versicherungsvermittlerin_with_categories( def create_versicherungsvermittlerin_with_categories(
@ -43,18 +40,9 @@ def create_versicherungsvermittlerin_with_categories(
]: ]:
CourseCategory.objects.get_or_create(course=course, title=cat) 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( course_page = CoursePageFactory(
title=title, title=title,
parent=site.root_page, parent=get_wagtail_default_site().root_page,
course=course, course=course,
) )
course.slug = course_page.slug course.slug = course_page.slug

View File

@ -121,6 +121,7 @@ def command(course):
if COURSE_UK in course: if COURSE_UK in course:
create_course_uk_de() create_course_uk_de()
create_course_uk_de_course_sessions()
create_course_uk_de_completion_data( create_course_uk_de_completion_data(
CourseSession.objects.get(title="Bern 2023 a") CourseSession.objects.get(title="Bern 2023 a")
) )
@ -220,26 +221,34 @@ def create_versicherungsvermittlerin_course():
) )
def create_course_uk_de(): def create_course_uk_de(course_id=COURSE_UK, lang="de"):
# Überbetriebliche Kurse DE names = {
"de": "Überbetriebliche Kurse",
"fr": "Cours interentreprises",
"it": "Corsi interaziendali",
}
course = create_versicherungsvermittlerin_with_categories( course = create_versicherungsvermittlerin_with_categories(
course_id=COURSE_UK, title="Überbetriebliche Kurse" course_id=course_id, title=names[lang]
) )
# assignments create assignments parent page # assignments create assignments parent page
_assignment_list_page = AssignmentListPageFactory( _assignment_list_page = AssignmentListPageFactory(
parent=course.coursepage, parent=course.coursepage,
) )
create_uk_kickoff_prep_assignment(course_id=COURSE_UK) create_uk_kickoff_prep_assignment(course_id=course_id)
create_uk_basis_prep_assignment(course_id=COURSE_UK) create_uk_basis_prep_assignment(course_id=course_id)
create_uk_fahrzeug_casework(course_id=COURSE_UK) create_uk_fahrzeug_casework(course_id=course_id)
create_uk_fahrzeug_prep_assignment(course_id=COURSE_UK) create_uk_fahrzeug_prep_assignment(course_id=course_id)
create_uk_reflection(course_id=COURSE_UK) create_uk_reflection(course_id=course_id)
# learning path # learning path
create_uk_learning_path(course_id=COURSE_UK) create_uk_learning_path(course_id=course_id)
create_uk_competence_profile(course_id=COURSE_UK) create_uk_competence_profile(course_id=course_id)
create_default_media_library(course_id=COURSE_UK) 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( cs = CourseSession.objects.create(
course_id=COURSE_UK, course_id=COURSE_UK,

View File

@ -2,7 +2,8 @@ import enum
import uuid import uuid
from django.db import models 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.text import slugify
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from grapple.models import GraphQLString from grapple.models import GraphQLString
@ -131,6 +132,30 @@ class CourseBasePage(Page):
def __str__(self): def __str__(self):
return f"{self.title}" 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): class CoursePage(CourseBasePage):
content_panels = Page.content_panels content_panels = Page.content_panels

View File

@ -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",
)

View File

@ -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

View File

@ -39,7 +39,7 @@ def course_page_api_view(request, slug_or_id):
if slug_or_id.isdigit(): if slug_or_id.isdigit():
page = Page.objects.get(id=slug_or_id) page = Page.objects.get(id=slug_or_id)
else: 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): if not has_course_access_by_page_request(request, page):
raise PermissionDenied() raise PermissionDenied()

View File

@ -1,8 +1,6 @@
import wagtail_factories
from django.conf import settings
from django.core.management import call_command from django.core.management import call_command
from slugify import slugify 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.rich_text import RichText
from wagtail_localize.models import LocaleSynchronization from wagtail_localize.models import LocaleSynchronization
@ -39,15 +37,6 @@ def create_vv_new_learning_path(
if user is None: if user is None:
user = User.objects.get(username="info@iterativ.ch") 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) course_page = CoursePage.objects.get(course_id=course_id)
lp = LearningPathFactory( lp = LearningPathFactory(
title="Lernpfad", title="Lernpfad",