diff --git a/client/src/gql/graphql.ts b/client/src/gql/graphql.ts index 7f5d80c1..4a73e013 100644 --- a/client/src/gql/graphql.ts +++ b/client/src/gql/graphql.ts @@ -615,6 +615,23 @@ export type LearningContentInterface = { translation_key: Scalars['String']['output']; }; +export type LearningContentKnowledgeAssessmentObjectType = CoursePageInterface & LearningContentInterface & { + __typename?: 'LearningContentKnowledgeAssessmentObjectType'; + can_user_self_toggle_course_completion: Scalars['Boolean']['output']; + circle?: Maybe; + content_type: Scalars['String']['output']; + content_url: Scalars['String']['output']; + course?: Maybe; + description: Scalars['String']['output']; + frontend_url: Scalars['String']['output']; + id: Scalars['ID']['output']; + live: Scalars['Boolean']['output']; + minutes?: Maybe; + slug: Scalars['String']['output']; + title: Scalars['String']['output']; + translation_key: Scalars['String']['output']; +}; + export type LearningContentLearningModuleObjectType = CoursePageInterface & LearningContentInterface & { __typename?: 'LearningContentLearningModuleObjectType'; can_user_self_toggle_course_completion: Scalars['Boolean']['output']; @@ -849,6 +866,7 @@ export type Query = { learning_content_attendance_course?: Maybe; learning_content_document_list?: Maybe; learning_content_feedback?: Maybe; + learning_content_knowledge_assessment?: Maybe; learning_content_learning_module?: Maybe; learning_content_media_library?: Maybe; learning_content_placeholder?: Maybe; @@ -1024,6 +1042,8 @@ type CoursePageFieldsLearningContentEdoniqTestObjectTypeFragment = { __typename? type CoursePageFieldsLearningContentFeedbackObjectTypeFragment = { __typename?: 'LearningContentFeedbackObjectType', title: string, id: string, slug: string, content_type: string, frontend_url: string } & { ' $fragmentName'?: 'CoursePageFieldsLearningContentFeedbackObjectTypeFragment' }; +type CoursePageFieldsLearningContentKnowledgeAssessmentObjectTypeFragment = { __typename?: 'LearningContentKnowledgeAssessmentObjectType', title: string, id: string, slug: string, content_type: string, frontend_url: string } & { ' $fragmentName'?: 'CoursePageFieldsLearningContentKnowledgeAssessmentObjectTypeFragment' }; + type CoursePageFieldsLearningContentLearningModuleObjectTypeFragment = { __typename?: 'LearningContentLearningModuleObjectType', title: string, id: string, slug: string, content_type: string, frontend_url: string } & { ' $fragmentName'?: 'CoursePageFieldsLearningContentLearningModuleObjectTypeFragment' }; type CoursePageFieldsLearningContentMediaLibraryObjectTypeFragment = { __typename?: 'LearningContentMediaLibraryObjectType', title: string, id: string, slug: string, content_type: string, frontend_url: string } & { ' $fragmentName'?: 'CoursePageFieldsLearningContentMediaLibraryObjectTypeFragment' }; @@ -1044,7 +1064,7 @@ type CoursePageFieldsPerformanceCriteriaObjectTypeFragment = { __typename?: 'Per type CoursePageFieldsTopicObjectTypeFragment = { __typename?: 'TopicObjectType', title: string, id: string, slug: string, content_type: string, frontend_url: string } & { ' $fragmentName'?: 'CoursePageFieldsTopicObjectTypeFragment' }; -export type CoursePageFieldsFragment = CoursePageFieldsActionCompetenceObjectTypeFragment | CoursePageFieldsAssignmentObjectTypeFragment | CoursePageFieldsCircleObjectTypeFragment | CoursePageFieldsCompetenceCertificateListObjectTypeFragment | CoursePageFieldsCompetenceCertificateObjectTypeFragment | CoursePageFieldsLearningContentAssignmentObjectTypeFragment | CoursePageFieldsLearningContentAttendanceCourseObjectTypeFragment | CoursePageFieldsLearningContentDocumentListObjectTypeFragment | CoursePageFieldsLearningContentEdoniqTestObjectTypeFragment | CoursePageFieldsLearningContentFeedbackObjectTypeFragment | CoursePageFieldsLearningContentLearningModuleObjectTypeFragment | CoursePageFieldsLearningContentMediaLibraryObjectTypeFragment | CoursePageFieldsLearningContentPlaceholderObjectTypeFragment | CoursePageFieldsLearningContentRichTextObjectTypeFragment | CoursePageFieldsLearningContentVideoObjectTypeFragment | CoursePageFieldsLearningPathObjectTypeFragment | CoursePageFieldsLearningSequenceObjectTypeFragment | CoursePageFieldsLearningUnitObjectTypeFragment | CoursePageFieldsPerformanceCriteriaObjectTypeFragment | CoursePageFieldsTopicObjectTypeFragment; +export type CoursePageFieldsFragment = CoursePageFieldsActionCompetenceObjectTypeFragment | CoursePageFieldsAssignmentObjectTypeFragment | CoursePageFieldsCircleObjectTypeFragment | CoursePageFieldsCompetenceCertificateListObjectTypeFragment | CoursePageFieldsCompetenceCertificateObjectTypeFragment | CoursePageFieldsLearningContentAssignmentObjectTypeFragment | CoursePageFieldsLearningContentAttendanceCourseObjectTypeFragment | CoursePageFieldsLearningContentDocumentListObjectTypeFragment | CoursePageFieldsLearningContentEdoniqTestObjectTypeFragment | CoursePageFieldsLearningContentFeedbackObjectTypeFragment | CoursePageFieldsLearningContentKnowledgeAssessmentObjectTypeFragment | CoursePageFieldsLearningContentLearningModuleObjectTypeFragment | CoursePageFieldsLearningContentMediaLibraryObjectTypeFragment | CoursePageFieldsLearningContentPlaceholderObjectTypeFragment | CoursePageFieldsLearningContentRichTextObjectTypeFragment | CoursePageFieldsLearningContentVideoObjectTypeFragment | CoursePageFieldsLearningPathObjectTypeFragment | CoursePageFieldsLearningSequenceObjectTypeFragment | CoursePageFieldsLearningUnitObjectTypeFragment | CoursePageFieldsPerformanceCriteriaObjectTypeFragment | CoursePageFieldsTopicObjectTypeFragment; export type AttendanceCheckQueryQueryVariables = Exact<{ courseSessionId: Scalars['ID']['input']; @@ -1090,6 +1110,9 @@ export type CompetenceCertificateQueryQuery = { __typename?: 'Query', competence ) | ( { __typename?: 'LearningContentFeedbackObjectType', circle?: { __typename?: 'CircleLightObjectType', id: string, title: string, slug: string } | null } & { ' $fragmentRefs'?: { 'CoursePageFieldsLearningContentFeedbackObjectTypeFragment': CoursePageFieldsLearningContentFeedbackObjectTypeFragment } } + ) | ( + { __typename?: 'LearningContentKnowledgeAssessmentObjectType', circle?: { __typename?: 'CircleLightObjectType', id: string, title: string, slug: string } | null } + & { ' $fragmentRefs'?: { 'CoursePageFieldsLearningContentKnowledgeAssessmentObjectTypeFragment': CoursePageFieldsLearningContentKnowledgeAssessmentObjectTypeFragment } } ) | ( { __typename?: 'LearningContentLearningModuleObjectType', circle?: { __typename?: 'CircleLightObjectType', id: string, title: string, slug: string } | null } & { ' $fragmentRefs'?: { 'CoursePageFieldsLearningContentLearningModuleObjectTypeFragment': CoursePageFieldsLearningContentLearningModuleObjectTypeFragment } } @@ -1160,6 +1183,9 @@ export type CourseQueryQuery = { __typename?: 'Query', course?: { __typename?: ' ) | ( { __typename?: 'LearningContentFeedbackObjectType', can_user_self_toggle_course_completion: boolean, content_url: string, minutes?: number | null, description: string } & { ' $fragmentRefs'?: { 'CoursePageFieldsLearningContentFeedbackObjectTypeFragment': CoursePageFieldsLearningContentFeedbackObjectTypeFragment } } + ) | ( + { __typename?: 'LearningContentKnowledgeAssessmentObjectType', can_user_self_toggle_course_completion: boolean, content_url: string, minutes?: number | null, description: string } + & { ' $fragmentRefs'?: { 'CoursePageFieldsLearningContentKnowledgeAssessmentObjectTypeFragment': CoursePageFieldsLearningContentKnowledgeAssessmentObjectTypeFragment } } ) | ( { __typename?: 'LearningContentLearningModuleObjectType', can_user_self_toggle_course_completion: boolean, content_url: string, minutes?: number | null, description: string } & { ' $fragmentRefs'?: { 'CoursePageFieldsLearningContentLearningModuleObjectTypeFragment': CoursePageFieldsLearningContentLearningModuleObjectTypeFragment } } diff --git a/client/src/gql/schema.graphql b/client/src/gql/schema.graphql index d3ee2b9a..fb8a5881 100644 --- a/client/src/gql/schema.graphql +++ b/client/src/gql/schema.graphql @@ -11,6 +11,7 @@ type Query { learning_content_attendance_course: LearningContentAttendanceCourseObjectType learning_content_feedback: LearningContentFeedbackObjectType learning_content_learning_module: LearningContentLearningModuleObjectType + learning_content_knowledge_assessment: LearningContentKnowledgeAssessmentObjectType learning_content_placeholder: LearningContentPlaceholderObjectType learning_content_rich_text: LearningContentRichTextObjectType learning_content_test: LearningContentEdoniqTestObjectType @@ -732,6 +733,22 @@ type LearningContentLearningModuleObjectType implements CoursePageInterface & Le circle: CircleLightObjectType } +type LearningContentKnowledgeAssessmentObjectType implements CoursePageInterface & LearningContentInterface { + id: ID! + title: String! + slug: String! + content_type: String! + live: Boolean! + translation_key: String! + frontend_url: String! + course: CourseObjectType + minutes: Int + description: String! + content_url: String! + can_user_self_toggle_course_completion: Boolean! + circle: CircleLightObjectType +} + type LearningContentPlaceholderObjectType implements CoursePageInterface & LearningContentInterface { id: ID! title: String! diff --git a/client/src/gql/typenames.ts b/client/src/gql/typenames.ts index b057f7d2..84bf9ca1 100644 --- a/client/src/gql/typenames.ts +++ b/client/src/gql/typenames.ts @@ -56,6 +56,7 @@ export const LearningContentDocumentListObjectType = "LearningContentDocumentLis export const LearningContentEdoniqTestObjectType = "LearningContentEdoniqTestObjectType"; export const LearningContentFeedbackObjectType = "LearningContentFeedbackObjectType"; export const LearningContentInterface = "LearningContentInterface"; +export const LearningContentKnowledgeAssessmentObjectType = "LearningContentKnowledgeAssessmentObjectType"; export const LearningContentLearningModuleObjectType = "LearningContentLearningModuleObjectType"; export const LearningContentMediaLibraryObjectType = "LearningContentMediaLibraryObjectType"; export const LearningContentPlaceholderObjectType = "LearningContentPlaceholderObjectType"; diff --git a/client/src/pages/learningPath/learningContentPage/LearningContentParent.vue b/client/src/pages/learningPath/learningContentPage/LearningContentParent.vue index dc7d8a15..8b5cd193 100644 --- a/client/src/pages/learningPath/learningContentPage/LearningContentParent.vue +++ b/client/src/pages/learningPath/learningContentPage/LearningContentParent.vue @@ -44,6 +44,7 @@ const COMPONENTS: Record = { "learnpath.LearningContentDocumentList": DocumentListBlock, "learnpath.LearningContentFeedback": FeedbackBlock, "learnpath.LearningContentLearningModule": IframeBlock, + "learnpath.LearningContentKnowledgeAssessment": IframeBlock, "learnpath.LearningContentMediaLibrary": MediaLibraryBlock, "learnpath.LearningContentPlaceholder": PlaceholderBlock, "learnpath.LearningContentRichText": RichTextBlock, diff --git a/client/src/types.ts b/client/src/types.ts index 16b39089..4cd1a76a 100644 --- a/client/src/types.ts +++ b/client/src/types.ts @@ -12,6 +12,7 @@ import type { LearningContentDocumentListObjectType, LearningContentEdoniqTestObjectType, LearningContentFeedbackObjectType, + LearningContentKnowledgeAssessmentObjectType, LearningContentLearningModuleObjectType, LearningContentMediaLibraryObjectType, LearningContentPlaceholderObjectType, @@ -75,6 +76,11 @@ export type LearningContentLearningModule = LearningContentLearningModuleObjectT readonly content_type: "learnpath.LearningContentLearningModule"; }; +export type LearningContentKnowledgeAssessment = + LearningContentKnowledgeAssessmentObjectType & { + readonly content_type: "learnpath.LearningContentKnowledgeAssessment"; + }; + export type LearningContentMediaLibrary = LearningContentMediaLibraryObjectType & { readonly content_type: "learnpath.LearningContentMediaLibrary"; }; @@ -98,6 +104,7 @@ export type LearningContent = | LearningContentEdoniqTest | LearningContentFeedback | LearningContentLearningModule + | LearningContentKnowledgeAssessment | LearningContentMediaLibrary | LearningContentPlaceholder | LearningContentRichText diff --git a/client/src/utils/typeMaps.ts b/client/src/utils/typeMaps.ts index f0b43168..b0858fe7 100644 --- a/client/src/utils/typeMaps.ts +++ b/client/src/utils/typeMaps.ts @@ -33,6 +33,11 @@ export function learningContentTypeData( title: t("learningContentTypes.learningModule"), icon: "it-icon-lc-learning-module", }; + case "learnpath.LearningContentKnowledgeAssessment": + return { + title: t("learningContentTypes.knowledgeAssessment"), + icon: "it-icon-lc-test", + }; case "learnpath.LearningContentMediaLibrary": return { title: t("a.Mediathek"), icon: "it-icon-lc-media-library" }; case "learnpath.LearningContentVideo": diff --git a/server/vbv_lernwelt/course/graphql/queries.py b/server/vbv_lernwelt/course/graphql/queries.py index c81e0567..cbe377e1 100644 --- a/server/vbv_lernwelt/course/graphql/queries.py +++ b/server/vbv_lernwelt/course/graphql/queries.py @@ -11,6 +11,7 @@ from vbv_lernwelt.learnpath.graphql.types import ( LearningContentDocumentListObjectType, LearningContentEdoniqTestObjectType, LearningContentFeedbackObjectType, + LearningContentKnowledgeAssessmentObjectType, LearningContentLearningModuleObjectType, LearningContentMediaLibraryObjectType, LearningContentPlaceholderObjectType, @@ -53,6 +54,9 @@ class CourseQuery(graphene.ObjectType): learning_content_learning_module = graphene.Field( LearningContentLearningModuleObjectType ) + learning_content_knowledge_assessment = graphene.Field( + LearningContentKnowledgeAssessmentObjectType + ) learning_content_placeholder = graphene.Field(LearningContentPlaceholderObjectType) learning_content_rich_text = graphene.Field(LearningContentRichTextObjectType) learning_content_test = graphene.Field(LearningContentEdoniqTestObjectType) diff --git a/server/vbv_lernwelt/learnpath/graphql/types.py b/server/vbv_lernwelt/learnpath/graphql/types.py index 6958a3f0..a1eb723a 100644 --- a/server/vbv_lernwelt/learnpath/graphql/types.py +++ b/server/vbv_lernwelt/learnpath/graphql/types.py @@ -11,6 +11,7 @@ from vbv_lernwelt.learnpath.models import ( LearningContentDocumentList, LearningContentEdoniqTest, LearningContentFeedback, + LearningContentKnowledgeAssessment, LearningContentLearningModule, LearningContentMediaLibrary, LearningContentPlaceholder, @@ -52,6 +53,8 @@ class LearningContentInterface(CoursePageInterface): return LearningContentFeedbackObjectType elif isinstance(instance, LearningContentLearningModule): return LearningContentLearningModuleObjectType + elif isinstance(instance, LearningContentKnowledgeAssessment): + return LearningContentKnowledgeAssessmentObjectType elif isinstance(instance, LearningContentMediaLibrary): return LearningContentMediaLibraryObjectType elif isinstance(instance, LearningContentPlaceholder): @@ -122,6 +125,16 @@ class LearningContentLearningModuleObjectType(DjangoObjectType): fields = [] +class LearningContentKnowledgeAssessmentObjectType(DjangoObjectType): + class Meta: + model = LearningContentKnowledgeAssessment + interfaces = ( + CoursePageInterface, + LearningContentInterface, + ) + fields = [] + + class LearningContentMediaLibraryObjectType(DjangoObjectType): class Meta: model = LearningContentMediaLibrary diff --git a/server/vbv_lernwelt/learnpath/migrations/0011_learningcontentknowledgeassessment.py b/server/vbv_lernwelt/learnpath/migrations/0011_learningcontentknowledgeassessment.py new file mode 100644 index 00000000..a153621a --- /dev/null +++ b/server/vbv_lernwelt/learnpath/migrations/0011_learningcontentknowledgeassessment.py @@ -0,0 +1,43 @@ +# Generated by Django 3.2.20 on 2023-11-16 09:47 + +import django.db.models.deletion +import wagtail.fields +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("wagtailcore", "0089_log_entry_data_json_null_to_object"), + ("learnpath", "0010_alter_learningcontentedoniqtest_content_assignment"), + ] + + operations = [ + migrations.CreateModel( + name="LearningContentKnowledgeAssessment", + 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", + ), + ), + ("minutes", models.PositiveIntegerField(default=15)), + ("description", wagtail.fields.RichTextField(blank=True)), + ("content_url", models.TextField(blank=True)), + ("has_course_completion_status", models.BooleanField(default=True)), + ( + "can_user_self_toggle_course_completion", + models.BooleanField(default=True), + ), + ], + options={ + "abstract": False, + }, + bases=("wagtailcore.page",), + ), + ] diff --git a/server/vbv_lernwelt/learnpath/models.py b/server/vbv_lernwelt/learnpath/models.py index 3c54b4b2..ac30d325 100644 --- a/server/vbv_lernwelt/learnpath/models.py +++ b/server/vbv_lernwelt/learnpath/models.py @@ -74,6 +74,7 @@ class Circle(CourseBasePage): "learnpath.LearningContentAttendanceCourse", "learnpath.LearningContentFeedback", "learnpath.LearningContentLearningModule", + "learnpath.LearningContentKnowledgeAssessment", "learnpath.LearningContentMediaLibrary", "learnpath.LearningContentPlaceholder", "learnpath.LearningContentRichText", @@ -329,6 +330,12 @@ class LearningContentLearningModule(LearningContent): can_user_self_toggle_course_completion = models.BooleanField(default=True) +class LearningContentKnowledgeAssessment(LearningContent): + parent_page_types = ["learnpath.Circle"] + subpage_types = [] + can_user_self_toggle_course_completion = models.BooleanField(default=True) + + class LearningContentMediaLibrary(LearningContent): parent_page_types = ["learnpath.Circle"] subpage_types = []