diff --git a/client/src/views/MediaLibraryCategoryOverview.vue b/client/src/views/MediaLibraryCategoryOverview.vue index a018330a..98faba2a 100644 --- a/client/src/views/MediaLibraryCategoryOverview.vue +++ b/client/src/views/MediaLibraryCategoryOverview.vue @@ -5,57 +5,6 @@ import { ref, watch } from "vue"; log.debug("HandlungsfelderOverview created"); -const fields = [ - { - name: "Fahrzeug", - icon: "icon-hf-fahrzeug", - }, - { - name: "Reisen", - icon: "icon-hf-reisen", - }, - { - name: "Einkommenssicherung", - icon: "icon-hf-einkommenssicherung", - }, - { - name: "Gesundheit", - icon: "icon-hf-fahrzeug", - }, - { - name: "Haushalt", - icon: "icon-hf-reisen", - }, - { - name: "Sparen", - icon: "icon-hf-einkommenssicherung", - }, - { - name: "Pensionierung", - icon: "icon-hf-fahrzeug", - }, - { - name: "KMU", - icon: "icon-hf-reisen", - }, - { - name: "Wohneigentum", - icon: "icon-hf-einkommenssicherung", - }, - { - name: "Rechtsstreitigkeiten", - icon: "icon-hf-fahrzeug", - }, - { - name: "Erben / Vererben", - icon: "icon-hf-reisen", - }, - { - name: "Selbstständigkeit", - icon: "icon-hf-einkommenssicherung", - }, -]; - const mediaStore = useMediaLibraryStore(); const dropdownSelected = ref(mediaStore.selectedLearningPath); diff --git a/format_code.sh b/format_code.sh index 0c0e7ddd..7ae11c7a 100755 --- a/format_code.sh +++ b/format_code.sh @@ -3,6 +3,9 @@ # script should fail when any process returns non zero code set -e +# set location to script directory +cd "${0%/*}" + echo 'format client code' npm run prettier diff --git a/git-pre-commit.sh b/git-pre-commit.sh index c81f387c..3e58d215 100755 --- a/git-pre-commit.sh +++ b/git-pre-commit.sh @@ -3,11 +3,3 @@ # script should fail when any process returns non zero code set -e -echo 'prettier:check' -(cd client && npm run prettier:check) - -echo 'lint' -(cd client && npm run lint) - -echo 'python ufmt check' -ufmt check server diff --git a/git-pre-push.sh b/git-pre-push.sh index 0cb1fccd..d7f93556 100755 --- a/git-pre-push.sh +++ b/git-pre-push.sh @@ -3,6 +3,15 @@ # script should fail when any process returns non zero code set -e +echo 'prettier:check' +(cd client && npm run prettier:check) + +echo 'lint' +(cd client && npm run lint) + +echo 'python ufmt check' +ufmt check server + echo 'check git-crypt files diff' git-crypt status -e | sort > git-crypt-encrypted-files-check.txt && diff git-crypt-encrypted-files.txt git-crypt-encrypted-files-check.txt diff --git a/server/.pylintrc b/server/.pylintrc index 4b032120..0b9643b9 100644 --- a/server/.pylintrc +++ b/server/.pylintrc @@ -1,5 +1,5 @@ [MASTER] -load-plugins=pylint_django +# load-plugins=pylint_django django-settings-module=config.settings.base [FORMAT] max-line-length=120 @@ -84,4 +84,4 @@ disable= # R0915: Too many statements too-many-statements, duplicate-code, - cyclic-impor + cyclic-import diff --git a/server/config/settings/base.py b/server/config/settings/base.py index cfb29b4a..b40cf862 100644 --- a/server/config/settings/base.py +++ b/server/config/settings/base.py @@ -213,7 +213,6 @@ LANGUAGES = [ WAGTAILDOCS_DOCUMENT_MODEL = "media_library.LibraryDocument" - WAGTAIL_CONTENT_LANGUAGES = [ ("fr-CH", "Swiss French"), ("de-CH", "Swiss German"), @@ -424,7 +423,6 @@ else: cache_logger_on_first_use=True, ) - # django-rest-framework # ------------------------------------------------------------------------------- # django-rest-framework - https://www.django-rest-framework.org/api-guide/settings/ @@ -464,8 +462,6 @@ CSP_DEFAULT_SRC = [ ] CSP_FRAME_ANCESTORS = ("'self'",) -# By Default swagger ui is available only to admin user. You can change permission classs to change that -# See more configuration options at https://drf-spectacular.readthedocs.io/en/latest/settings.html#settings SPECTACULAR_SETTINGS = { "TITLE": "VBV Lernwelt API", "DESCRIPTION": "Documentation of API endpoints of VBV Lernwelt", @@ -492,7 +488,6 @@ ALLOWED_HOSTS = env.list( "IT_DJANGO_ALLOWED_HOSTS", default=["localhost", "0.0.0.0", "127.0.0.1"] ) - # CACHES CACHES = { "default": { @@ -533,8 +528,6 @@ OAUTH = { "client_name": env("IT_OAUTH_CLIENT_NAME", default="lernetz"), "client_id": env("IT_OAUTH_CLIENT_ID", default="iterativ"), "client_secret": env("IT_OAUTH_CLIENT_SECRET", default=""), - # "access_token_url": env("IT_OAUTH_ACCESS_TOKEN_URL", default="https://sso.test.b.lernetz.host/auth/realms/vbv/protocol/openid-connect/token"), - # "authorize_url": env("IT_OAUTH_AUTHORIZE_URL", default="https://sso.test.b.lernetz.host/auth/realms/vbv/protocol/openid-connect/auth"), "authorize_params": IT_OAUTH_AUTHORIZE_PARAMS, "access_token_params": IT_OAUTH_AUTHORIZE_PARAMS, "api_base_url": env( diff --git a/server/config/urls.py b/server/config/urls.py index 7cc07c28..fb7685d4 100644 --- a/server/config/urls.py +++ b/server/config/urls.py @@ -50,19 +50,25 @@ urlpatterns = [ # user management path("sso/", include("vbv_lernwelt.sso.urls")), re_path(r'api/core/me/$', me_user_view, name='me_user_view'), - re_path(r'api/core/login/$', django_view_authentication_exempt(vue_login), name='vue_login'), + re_path(r'api/core/login/$', django_view_authentication_exempt(vue_login), + name='vue_login'), re_path(r'api/core/logout/$', vue_logout, name='vue_logout'), # core - re_path(r"server/core/icons/$", generate_web_component_icons, name="generate_web_component_icons"), + re_path(r"server/core/icons/$", generate_web_component_icons, + name="generate_web_component_icons"), # course path(r"api/course/page//", page_api_view, name="page_api_view"), - path(r"api/course/completion/mark/", mark_course_completion, name="mark_course_completion"), - path(r"api/course/completion//", request_course_completion, name="request_course_completion"), + path(r"api/course/completion/mark/", mark_course_completion, + name="mark_course_completion"), + path(r"api/course/completion//", request_course_completion, + name="request_course_completion"), # testing and debug - path('server/raise_error/', user_passes_test(lambda u: u.is_superuser, login_url='/login/')(raise_example_error), ), + path('server/raise_error/', + user_passes_test(lambda u: u.is_superuser, login_url='/login/')( + raise_example_error), ), path("server/checkratelimit/", check_rate_limit), ] urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) @@ -73,8 +79,11 @@ if settings.DEBUG: if settings.APP_ENVIRONMENT != 'production': urlpatterns += [ - re_path(r'api/core/cypressreset/$', cypress_reset_view, name='cypress_reset_view'), + re_path(r'api/core/cypressreset/$', cypress_reset_view, + name='cypress_reset_view'), ] + + # fmt: on @@ -88,7 +97,6 @@ def handler403(request, exception=None): handler500 = "vbv_lernwelt.core.views.server_json_error" - if settings.DEBUG: # This allows the error pages to be debugged during development, just visit # these url in browser to see how these error pages look like. @@ -115,6 +123,5 @@ if settings.DEBUG: urlpatterns = [path("__debug__/", include(debug_toolbar.urls))] + urlpatterns - # serve everything else via the vue app urlpatterns += [re_path(r"^(?!.*(server/|api/|sso/)).*$", vue_home, name="home")] diff --git a/server/vbv_lernwelt/course/creators/test_course.py b/server/vbv_lernwelt/course/creators/test_course.py index 6a8bdeb2..ba8b197a 100644 --- a/server/vbv_lernwelt/course/creators/test_course.py +++ b/server/vbv_lernwelt/course/creators/test_course.py @@ -28,10 +28,11 @@ from vbv_lernwelt.learnpath.tests.learning_path_factories import ( TopicFactory, ) from vbv_lernwelt.media_library.tests.media_library_factories import ( - create_document_collection, - create_link_collection, - create_media_content_link, - LinkBlockFactory, + create_external_link_block, + create_learn_media_block, + create_media_collection, + ExternalLinkBlockFactory, + LearnMediaBlockFactory, MediaCategoryPageFactory, MediaLibraryPageFactory, ) @@ -321,22 +322,31 @@ welche Aspekte du bei einer Offerte beachten musst und wie du dem Kunden die Lö ] body_data = json.dumps( [ - create_document_collection(), - create_link_collection( - links_dict=[ - create_media_content_link( - LinkBlockFactory( + create_media_collection( + title="Lernmedien", + contents=[ + create_learn_media_block(LearnMediaBlockFactory()), + create_learn_media_block(LearnMediaBlockFactory()), + create_learn_media_block(LearnMediaBlockFactory()), + create_learn_media_block(LearnMediaBlockFactory()), + ], + ), + create_media_collection( + title="Links", + contents=[ + create_external_link_block( + ExternalLinkBlockFactory( title="Nationales Versicherungsbüro", url="https://www.vbv.ch/", ) ), - create_media_content_link( - LinkBlockFactory( + create_external_link_block( + ExternalLinkBlockFactory( title="Adressen der Strassenverkehrsämter", url="https://www.vbv.ch/", ) ), - ] + ], ), ] ) diff --git a/server/vbv_lernwelt/media_library/content_blocks.py b/server/vbv_lernwelt/media_library/content_blocks.py index 5e250259..88dfb9f7 100644 --- a/server/vbv_lernwelt/media_library/content_blocks.py +++ b/server/vbv_lernwelt/media_library/content_blocks.py @@ -1,49 +1,32 @@ -from django.db import models from wagtail import blocks -from wagtail.admin.panels import FieldPanel -from wagtail.documents.blocks import DocumentChooserBlock -from wagtail.snippets.models import register_snippet -@register_snippet -class MediaLibraryContent(models.Model): - title = models.TextField() - description = models.TextField() - link_display_text = models.CharField(max_length=255) - # TODO: Revisions only work with wagtail 4.0, can not migrate since wagtail localize is not ready yet. - # _revisions = GenericRelation("wagtailcore.Revision", related_query_name="media_library_content") - - panels = [ - FieldPanel("title"), - FieldPanel("description"), - FieldPanel("link_display_text"), - ] - - @property - def revisions(self): - return self._revisions - - -class AnchorBlock(blocks.PageChooserBlock): - """ - Verankerung im Lernpfad. Link to a Learning Content. - """ - - page_type = "learnpath.LearningUnit" - - -class LinkBlock(blocks.StructBlock): +class MediaLibraryContentBlock(blocks.StructBlock): title = blocks.TextBlock(blank=False, null=False) - description = blocks.TextBlock(default="") + description = blocks.TextBlock(default="", required=False) + icon_url = blocks.TextBlock(default="", required=False) link_display_text = blocks.CharBlock(max_length=255, default="Link öffnen") - url = blocks.URLBlock() + url = blocks.TextBlock(default="", required=False) + open_window = blocks.BooleanBlock(default=False) + page = blocks.PageChooserBlock( + page_type=["learnpath.LearningContent"], required=False + ) -class CrossReferenceBlock(blocks.StructBlock): - title = models.TextField(blank=False, null=False) - description = blocks.TextBlock(default="") - link_display_text = blocks.CharBlock(max_length=255, default="Link öffnen") - category = blocks.PageChooserBlock(page_type="media_library.MediaCategoryPage") +class ExternalLinkBlock(MediaLibraryContentBlock): + pass + + +class InternalLinkBlock(MediaLibraryContentBlock): + pass + + +class RelativeLinkBlock(MediaLibraryContentBlock): + pass + + +class LearnMediaBlock(MediaLibraryContentBlock): + pass class MediaContentCollection(blocks.StructBlock): @@ -54,10 +37,10 @@ class MediaContentCollection(blocks.StructBlock): title = blocks.TextBlock() contents = blocks.StreamBlock( [ - ("Links", LinkBlock()), - ("Documents", DocumentChooserBlock()), - ("Ankers", AnchorBlock()), - ("CrossReference", CrossReferenceBlock()), + ("learn_media", MediaLibraryContentBlock()), + ("external_link", ExternalLinkBlock()), + ("internal_link", InternalLinkBlock()), + ("relative_link", RelativeLinkBlock()), ] ) diff --git a/server/vbv_lernwelt/media_library/create_default_media_library.py b/server/vbv_lernwelt/media_library/create_default_media_library.py index 5c74443e..dc672a30 100644 --- a/server/vbv_lernwelt/media_library/create_default_media_library.py +++ b/server/vbv_lernwelt/media_library/create_default_media_library.py @@ -3,12 +3,17 @@ import json from vbv_lernwelt.course.consts import COURSE_VERSICHERUNGSVERMITTLERIN_ID from vbv_lernwelt.course.models import Course, CoursePage from vbv_lernwelt.media_library.tests.media_library_factories import ( - create_document_collection, - create_link_collection, - create_media_content_link, - LinkBlockFactory, + create_external_link_block, + create_learn_media_block, + create_media_collection, + ExternalLinkBlockFactory, + LearnMediaBlockFactory, MediaCategoryPageFactory, MediaLibraryPageFactory, + create_internal_link_block, + InternalLinkBlockFactory, + create_relative_link_block, + RelativeLinkBlockFactory, ) @@ -44,22 +49,71 @@ welche Aspekte du bei einer Offerte beachten musst und wie du dem Kunden die Lö ] body_data = json.dumps( [ - create_document_collection(), - create_link_collection( - links_dict=[ - create_media_content_link( - LinkBlockFactory( + create_media_collection( + title="Lernmedien", + contents=[ + create_learn_media_block(LearnMediaBlockFactory()), + create_learn_media_block(LearnMediaBlockFactory()), + create_learn_media_block(LearnMediaBlockFactory()), + create_learn_media_block(LearnMediaBlockFactory()), + ], + ), + create_media_collection( + title="Links", + contents=[ + create_external_link_block( + ExternalLinkBlockFactory( title="Nationales Versicherungsbüro", url="https://www.vbv.ch/", ) ), - create_media_content_link( - LinkBlockFactory( + create_external_link_block( + ExternalLinkBlockFactory( title="Adressen der Strassenverkehrsämter", url="https://www.vbv.ch/", ) ), - ] + ], + ), + create_media_collection( + title="Links", + contents=[ + create_internal_link_block( + InternalLinkBlockFactory( + title="Nora kauft sich ein neues Auto", + url="/learn/versicherungsvermittlerin-lp/analyse/nora-kauft-sich-ein-neues-auto", + ) + ), + create_internal_link_block( + InternalLinkBlockFactory( + title="Nora kauft sich ein neues Auto", + url="/learn/versicherungsvermittlerin-lp/analyse/nora-kauft-sich-ein-neues-auto", + ) + ), + create_internal_link_block( + InternalLinkBlockFactory( + title="Nora kauft sich ein neues Auto", + url="/learn/versicherungsvermittlerin-lp/analyse/nora-kauft-sich-ein-neues-auto", + ) + ), + ], + ), + create_media_collection( + title="Querverweise", + contents=[ + create_relative_link_block( + RelativeLinkBlockFactory( + title="Rechtsstreigkeiten", + url="", + ), + ), + create_relative_link_block( + RelativeLinkBlockFactory( + title="Rechtsstreigkeiten", + url="", + ), + ), + ], ), ] ) diff --git a/server/vbv_lernwelt/media_library/migrations/0001_initial.py b/server/vbv_lernwelt/media_library/migrations/0001_initial.py index 9f567f5b..1cf58ff9 100644 --- a/server/vbv_lernwelt/media_library/migrations/0001_initial.py +++ b/server/vbv_lernwelt/media_library/migrations/0001_initial.py @@ -1,16 +1,13 @@ -# Generated by Django 3.2.13 on 2022-09-28 12:51 +# Generated by Django 3.2.13 on 2022-10-03 14:18 +from django.conf import settings +from django.db import migrations, models import django.db.models.deletion import taggit.managers import wagtail.blocks -import wagtail.documents.blocks import wagtail.fields import wagtail.models.collections import wagtail.search.index -from django.conf import settings -from django.db import migrations, models - -import vbv_lernwelt.media_library.content_blocks class Migration(migrations.Migration): @@ -18,251 +15,61 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ("course", "0001_initial"), - ("wagtailcore", "0069_log_entry_jsonfield"), + ('course', '0001_initial'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ("taggit", "0004_alter_taggeditem_content_type_alter_taggeditem_tag"), + ('taggit', '0004_alter_taggeditem_content_type_alter_taggeditem_tag'), + ('wagtailcore', '0069_log_entry_jsonfield'), ] operations = [ migrations.CreateModel( - name="MediaLibraryContent", + name='MediaLibraryPage', fields=[ - ( - "id", - models.BigAutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("title", models.TextField()), - ("description", models.TextField()), - ("link_display_text", models.CharField(max_length=255)), - ], - ), - migrations.CreateModel( - name="MediaLibraryPage", - fields=[ - ( - "page_ptr", - models.OneToOneField( - auto_created=True, - on_delete=django.db.models.deletion.CASCADE, - parent_link=True, - primary_key=True, - serialize=False, - to="wagtailcore.page", - ), - ), + ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')), ], options={ - "abstract": False, + 'abstract': False, }, - bases=("wagtailcore.page",), + bases=('wagtailcore.page',), ), migrations.CreateModel( - name="MediaCategoryPage", + name='MediaCategoryPage', fields=[ - ( - "page_ptr", - models.OneToOneField( - auto_created=True, - on_delete=django.db.models.deletion.CASCADE, - parent_link=True, - primary_key=True, - serialize=False, - to="wagtailcore.page", - ), - ), - ("introduction_text", models.TextField(default="")), - ( - "description_title", - models.TextField( - default="Das erwartet dich in diesem Handlungsfeld" - ), - ), - ("description_text", models.TextField(default="")), - ( - "items", - wagtail.fields.StreamField( - [("item", wagtail.blocks.TextBlock())], use_json_field=True - ), - ), - ( - "overview_icon", - models.CharField(default="icon-hf-fahrzeug", max_length=255), - ), - ( - "body", - wagtail.fields.StreamField( - [ - ( - "content_collection", - wagtail.blocks.StructBlock( - [ - ("title", wagtail.blocks.TextBlock()), - ( - "contents", - wagtail.blocks.StreamBlock( - [ - ( - "Links", - wagtail.blocks.StructBlock( - [ - ( - "title", - wagtail.blocks.TextBlock( - blank=False, - null=False, - ), - ), - ( - "description", - wagtail.blocks.TextBlock( - default="" - ), - ), - ( - "link_display_text", - wagtail.blocks.CharBlock( - default="Link öffnen", - max_length=255, - ), - ), - ( - "url", - wagtail.blocks.URLBlock(), - ), - ] - ), - ), - ( - "Documents", - wagtail.documents.blocks.DocumentChooserBlock(), - ), - ( - "Ankers", - vbv_lernwelt.media_library.content_blocks.AnchorBlock(), - ), - ( - "CrossReference", - wagtail.blocks.StructBlock( - [ - ( - "description", - wagtail.blocks.TextBlock( - default="" - ), - ), - ( - "link_display_text", - wagtail.blocks.CharBlock( - default="Link öffnen", - max_length=255, - ), - ), - ( - "category", - wagtail.blocks.PageChooserBlock( - page_type=[ - "media_library.MediaCategoryPage" - ] - ), - ), - ] - ), - ), - ] - ), - ), - ] - ), - ) - ], - null=True, - use_json_field=True, - ), - ), - ( - "course_category", - models.ForeignKey( - blank=True, - null=True, - on_delete=django.db.models.deletion.SET_NULL, - to="course.coursecategory", - ), - ), + ('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.page')), + ('introduction_text', models.TextField(default='')), + ('description_title', models.TextField(default='Das erwartet dich in diesem Handlungsfeld')), + ('description_text', models.TextField(default='')), + ('items', wagtail.fields.StreamField([('item', wagtail.blocks.TextBlock())], use_json_field=True)), + ('overview_icon', models.CharField(default='icon-hf-fahrzeug', max_length=255)), + ('body', wagtail.fields.StreamField([('content_collection', wagtail.blocks.StructBlock([('title', wagtail.blocks.TextBlock()), ('contents', wagtail.blocks.StreamBlock([('learn_media', wagtail.blocks.StructBlock([('title', wagtail.blocks.TextBlock(blank=False, null=False)), ('description', wagtail.blocks.TextBlock(default='', required=False)), ('icon_url', wagtail.blocks.TextBlock(default='', required=False)), ('link_display_text', wagtail.blocks.CharBlock(default='Link öffnen', max_length=255)), ('url', wagtail.blocks.TextBlock(default='', required=False)), ('open_window', wagtail.blocks.BooleanBlock(default=False)), ('page', wagtail.blocks.PageChooserBlock(page_type=['learnpath.LearningContent'], required=False))])), ('external_link', wagtail.blocks.StructBlock([('title', wagtail.blocks.TextBlock(blank=False, null=False)), ('description', wagtail.blocks.TextBlock(default='', required=False)), ('icon_url', wagtail.blocks.TextBlock(default='', required=False)), ('link_display_text', wagtail.blocks.CharBlock(default='Link öffnen', max_length=255)), ('url', wagtail.blocks.TextBlock(default='', required=False)), ('open_window', wagtail.blocks.BooleanBlock(default=False)), ('page', wagtail.blocks.PageChooserBlock(page_type=['learnpath.LearningContent'], required=False))])), ('internal_link', wagtail.blocks.StructBlock([('title', wagtail.blocks.TextBlock(blank=False, null=False)), ('description', wagtail.blocks.TextBlock(default='', required=False)), ('icon_url', wagtail.blocks.TextBlock(default='', required=False)), ('link_display_text', wagtail.blocks.CharBlock(default='Link öffnen', max_length=255)), ('url', wagtail.blocks.TextBlock(default='', required=False)), ('open_window', wagtail.blocks.BooleanBlock(default=False)), ('page', wagtail.blocks.PageChooserBlock(page_type=['learnpath.LearningContent'], required=False))])), ('relative_link', wagtail.blocks.StructBlock([('title', wagtail.blocks.TextBlock(blank=False, null=False)), ('description', wagtail.blocks.TextBlock(default='', required=False)), ('icon_url', wagtail.blocks.TextBlock(default='', required=False)), ('link_display_text', wagtail.blocks.CharBlock(default='Link öffnen', max_length=255)), ('url', wagtail.blocks.TextBlock(default='', required=False)), ('open_window', wagtail.blocks.BooleanBlock(default=False)), ('page', wagtail.blocks.PageChooserBlock(page_type=['learnpath.LearningContent'], required=False))]))]))]))], null=True, use_json_field=True)), + ('course_category', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='course.coursecategory')), ], options={ - "abstract": False, + 'abstract': False, }, - bases=("wagtailcore.page",), + bases=('wagtailcore.page',), ), migrations.CreateModel( - name="LibraryDocument", + name='LibraryDocument', fields=[ - ( - "id", - models.BigAutoField( - auto_created=True, - primary_key=True, - serialize=False, - verbose_name="ID", - ), - ), - ("title", models.CharField(max_length=255, verbose_name="title")), - ("file", models.FileField(upload_to="documents", verbose_name="file")), - ( - "created_at", - models.DateTimeField(auto_now_add=True, verbose_name="created at"), - ), - ("file_size", models.PositiveIntegerField(editable=False, null=True)), - ( - "file_hash", - models.CharField(blank=True, editable=False, max_length=40), - ), - ("display_text", models.CharField(default="", max_length=1024)), - ("description", models.TextField(default="")), - ("link_display_text", models.CharField(default="", max_length=1024)), - ("thumbnail", models.URLField()), - ( - "collection", - models.ForeignKey( - default=wagtail.models.collections.get_root_collection_id, - on_delete=django.db.models.deletion.CASCADE, - related_name="+", - to="wagtailcore.collection", - verbose_name="collection", - ), - ), - ( - "tags", - taggit.managers.TaggableManager( - blank=True, - help_text=None, - through="taggit.TaggedItem", - to="taggit.Tag", - verbose_name="tags", - ), - ), - ( - "uploaded_by_user", - models.ForeignKey( - blank=True, - editable=False, - null=True, - on_delete=django.db.models.deletion.SET_NULL, - to=settings.AUTH_USER_MODEL, - verbose_name="uploaded by user", - ), - ), + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=255, verbose_name='title')), + ('file', models.FileField(upload_to='documents', verbose_name='file')), + ('created_at', models.DateTimeField(auto_now_add=True, verbose_name='created at')), + ('file_size', models.PositiveIntegerField(editable=False, null=True)), + ('file_hash', models.CharField(blank=True, editable=False, max_length=40)), + ('display_text', models.CharField(default='', max_length=1024)), + ('description', models.TextField(default='')), + ('link_display_text', models.CharField(default='', max_length=1024)), + ('thumbnail', models.URLField()), + ('collection', models.ForeignKey(default=wagtail.models.collections.get_root_collection_id, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='wagtailcore.collection', verbose_name='collection')), + ('tags', taggit.managers.TaggableManager(blank=True, help_text=None, through='taggit.TaggedItem', to='taggit.Tag', verbose_name='tags')), + ('uploaded_by_user', models.ForeignKey(blank=True, editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='uploaded by user')), ], options={ - "verbose_name": "document", - "verbose_name_plural": "documents", - "abstract": False, + 'verbose_name': 'document', + 'verbose_name_plural': 'documents', + 'abstract': False, }, bases=(wagtail.search.index.Indexed, models.Model), ), diff --git a/server/vbv_lernwelt/media_library/tests/media_library_factories.py b/server/vbv_lernwelt/media_library/tests/media_library_factories.py index 7819b6cb..101c2ab0 100644 --- a/server/vbv_lernwelt/media_library/tests/media_library_factories.py +++ b/server/vbv_lernwelt/media_library/tests/media_library_factories.py @@ -3,10 +3,10 @@ import uuid import wagtail_factories from vbv_lernwelt.media_library.content_blocks import ( - AnchorBlock, - CrossReferenceBlock, - LinkBlock, - MediaContentCollection, + ExternalLinkBlock, + LearnMediaBlock, + InternalLinkBlock, + RelativeLinkBlock, ) from vbv_lernwelt.media_library.models import ( LibraryDocument, @@ -30,35 +30,6 @@ class MediaLibraryPageFactory(wagtail_factories.PageFactory): model = MediaLibraryPage -class AnchorBlockFactory(wagtail_factories.StructBlockFactory): - class Meta: - model = AnchorBlock - - -class LinkBlockFactory(wagtail_factories.StructBlockFactory): - title = "Interesting link" - description = "This link is really interesting..." - url = "https://www.vbv.ch/" - - class Meta: - model = LinkBlock - - -class CrossReferenceBlockFactory(wagtail_factories.StructBlockFactory): - class Meta: - model = CrossReferenceBlock - - -class MediaContentCollectionFactory(wagtail_factories.StructBlockFactory): - title = "Links" - contents = wagtail_factories.StreamFieldFactory( - {"Links": LinkBlockFactory, "Documents": LibraryDocumentFactory} - ) - - class Meta: - model = MediaContentCollection - - class MediaCategoryPageFactory(wagtail_factories.PageFactory): title = "Fahrzeug" introduction_text = "Das Auto ist für viele der grösste Stolz! Es birgt aber ..." @@ -68,19 +39,99 @@ class MediaCategoryPageFactory(wagtail_factories.PageFactory): model = MediaCategoryPage -def create_media_content_link(link_block=None): +class LearnMediaBlockFactory(wagtail_factories.StructBlockFactory): + class Meta: + model = LearnMediaBlock + + title = "Die Motorfahrzeughaftpflicht" + icon_url = "/static/icons/demo/icon-hf-book.png" + description = "Buch «Sach- und Vermögensversicherungen» – Kapitel 16" + link_display_text = "PDF anzeigen" + url = "/static/media/documents/01a_Motorfahrzeughaftpflicht.pdf" + open_window = True + + +def create_learn_media_block(link_block=None): if link_block is None: - link_block = LinkBlockFactory() - return {"id": str(uuid.uuid4()), "type": "Links", "value": dict(link_block.items())} + link_block = LearnMediaBlockFactory() + return { + "id": str(uuid.uuid4()), + "type": "learn_media", + "value": dict(link_block.items()), + } -def create_link_collection(links_dict=None): +class ExternalLinkBlockFactory(wagtail_factories.StructBlockFactory): + class Meta: + model = ExternalLinkBlock + + title = "Nationales Versicherungsbüro" + description = "This link is really interesting..." + url = "https://www.vbv.ch/" + open_window = True + link_display_text = "Link öffnen" + + +def create_external_link_block(link_block=None): + if link_block is None: + link_block = ExternalLinkBlockFactory() + return { + "id": str(uuid.uuid4()), + "type": "external_link", + "value": dict(link_block.items()), + } + + +class InternalLinkBlockFactory(wagtail_factories.StructBlockFactory): + class Meta: + model = InternalLinkBlock + + title = "Rafael Fasel wechselt sein Auto" + description = "Link to a Learning Content" + link_display_text = "Lerneinheit anzeigen" + # TODO: page = blocks.PageChooserBlock mit Titel etc + + +def create_internal_link_block(link_block=None): + if link_block is None: + link_block = InternalLinkBlockFactory() + return { + "id": str(uuid.uuid4()), + "type": "internal_link", + "value": dict(link_block.items()), + } + + +class RelativeLinkBlockFactory(wagtail_factories.StructBlockFactory): + class Meta: + model = RelativeLinkBlock + + title = "Rechtsstreigkeiten" + description = "Lernmedium: Verkehrsrechtsschutz – Buch «Sach- und Vermögensversicherungen/Kapitel 12.3»" + link_display_text = "Handlungsfeld anzeigen" + # TODO: page = blocks.PageChooserBlock zu Handlungsfeld + + +def create_relative_link_block(link_block=None): + if link_block is None: + link_block = RelativeLinkBlockFactory() + return { + "id": str(uuid.uuid4()), + "type": "relative_link", + "value": dict(link_block.items()), + } + + +def create_media_collection(title, contents=None): + if contents is None: + contents = [] + return { "id": str(uuid.uuid4()), "type": "content_collection", "value": { - "title": "Links", - "contents": [link_dict for link_dict in links_dict], + "title": title, + "contents": [content_dict for content_dict in contents], }, }