Add GraphQL server code for learning path
This commit is contained in:
parent
8e16daa525
commit
da03b407bb
|
|
@ -24,7 +24,7 @@ def main():
|
||||||
reset_queries()
|
reset_queries()
|
||||||
|
|
||||||
page = Page.objects.get(
|
page = Page.objects.get(
|
||||||
slug="versicherungsvermittlerin", locale__language_code="de-CH"
|
slug="überbetriebliche-kurse-lp", locale__language_code="de-CH"
|
||||||
)
|
)
|
||||||
serializer = page.specific.get_serializer_class()(page.specific)
|
serializer = page.specific.get_serializer_class()(page.specific)
|
||||||
|
|
||||||
|
|
@ -32,6 +32,13 @@ def main():
|
||||||
print(len(json.dumps(serializer.data)))
|
print(len(json.dumps(serializer.data)))
|
||||||
print(len(connection.queries))
|
print(len(connection.queries))
|
||||||
|
|
||||||
|
# reference
|
||||||
|
page = Page.objects.get(
|
||||||
|
slug="überbetriebliche-kurse-lp", locale__language_code="de-CH"
|
||||||
|
)
|
||||||
|
list(page.get_descendants().specific())
|
||||||
|
print(len(connection.queries))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import django
|
||||||
|
import graphene
|
||||||
|
from graphene import Context
|
||||||
|
|
||||||
|
sys.path.append("../server")
|
||||||
|
|
||||||
|
os.environ.setdefault("IT_APP_ENVIRONMENT", "local")
|
||||||
|
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings.base")
|
||||||
|
django.setup()
|
||||||
|
|
||||||
|
from vbv_lernwelt.core.schema import Query
|
||||||
|
from vbv_lernwelt.core.models import User
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
settings.DEBUG = True
|
||||||
|
from django.db import connection
|
||||||
|
from django.db import reset_queries
|
||||||
|
|
||||||
|
reset_queries()
|
||||||
|
|
||||||
|
schema = graphene.Schema(query=Query, auto_camelcase=False)
|
||||||
|
context = Context()
|
||||||
|
context.user = User.objects.get(username="admin")
|
||||||
|
result = schema.execute(
|
||||||
|
"""
|
||||||
|
{
|
||||||
|
learning_path(slug: "überbetriebliche-kurse-lp") {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
content_type
|
||||||
|
topics {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
content_type
|
||||||
|
circles {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
content_type
|
||||||
|
learning_sequences {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
icon
|
||||||
|
learning_units {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
learning_contents {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
context=context,
|
||||||
|
)
|
||||||
|
|
||||||
|
print(result)
|
||||||
|
print(len(connection.queries))
|
||||||
|
|
||||||
|
# reference
|
||||||
|
reset_queries()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
@ -4,7 +4,7 @@ from graphene_django import DjangoObjectType
|
||||||
|
|
||||||
from vbv_lernwelt.assignment.models import Assignment, AssignmentCompletion
|
from vbv_lernwelt.assignment.models import Assignment, AssignmentCompletion
|
||||||
from vbv_lernwelt.core.graphql.types import JSONStreamField
|
from vbv_lernwelt.core.graphql.types import JSONStreamField
|
||||||
from vbv_lernwelt.course.schema import CoursePageInterface
|
from vbv_lernwelt.course.graphql.interfaces import CoursePageInterface
|
||||||
|
|
||||||
|
|
||||||
class AssignmentObjectType(DjangoObjectType):
|
class AssignmentObjectType(DjangoObjectType):
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,16 @@ import graphene
|
||||||
|
|
||||||
from vbv_lernwelt.assignment.graphql.mutations import AssignmentMutation
|
from vbv_lernwelt.assignment.graphql.mutations import AssignmentMutation
|
||||||
from vbv_lernwelt.assignment.graphql.queries import AssignmentQuery
|
from vbv_lernwelt.assignment.graphql.queries import AssignmentQuery
|
||||||
from vbv_lernwelt.course.schema import CourseQuery
|
from vbv_lernwelt.course.graphql.queries import CourseQuery
|
||||||
from vbv_lernwelt.course_session.graphql.mutations import CourseSessionMutation
|
from vbv_lernwelt.course_session.graphql.mutations import CourseSessionMutation
|
||||||
from vbv_lernwelt.course_session.graphql.queries import CourseSessionQuery
|
from vbv_lernwelt.course_session.graphql.queries import CourseSessionQuery
|
||||||
from vbv_lernwelt.feedback.graphql.mutations import FeedbackMutation
|
from vbv_lernwelt.feedback.graphql.mutations import FeedbackMutation
|
||||||
|
from vbv_lernwelt.learnpath.graphql.queries import CircleQuery
|
||||||
|
|
||||||
|
|
||||||
class Query(AssignmentQuery, CourseQuery, CourseSessionQuery, graphene.ObjectType):
|
class Query(
|
||||||
|
AssignmentQuery, CourseQuery, CourseSessionQuery, CircleQuery, graphene.ObjectType
|
||||||
|
):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import wagtail.api.v2.serializers as wagtail_serializers
|
import wagtail.api.v2.serializers as wagtail_serializers
|
||||||
from rest_framework.fields import SerializerMethodField
|
from rest_framework.fields import SerializerMethodField
|
||||||
|
|
||||||
from vbv_lernwelt.learnpath.utils import get_wagtail_type
|
from vbv_lernwelt.core.utils import get_django_content_type
|
||||||
|
|
||||||
|
|
||||||
def get_it_serializer_class(
|
def get_it_serializer_class(
|
||||||
|
|
@ -33,7 +33,7 @@ def get_it_serializer_class(
|
||||||
|
|
||||||
class ItWagtailTypeField(wagtail_serializers.TypeField):
|
class ItWagtailTypeField(wagtail_serializers.TypeField):
|
||||||
def to_representation(self, obj):
|
def to_representation(self, obj):
|
||||||
name = get_wagtail_type(obj)
|
name = get_django_content_type(obj)
|
||||||
return name
|
return name
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,19 +39,17 @@ class DayUserRateThrottle(UserRateThrottle):
|
||||||
scope = "day-throttle"
|
scope = "day-throttle"
|
||||||
|
|
||||||
|
|
||||||
def find_first(iterable, default=False, pred=None):
|
def find_first(iterable, pred=None, default=None):
|
||||||
"""Returns the first true value in the iterable.
|
|
||||||
|
|
||||||
If no true value is found, returns *default*
|
|
||||||
|
|
||||||
If *pred* is not None, returns the first item
|
|
||||||
for which pred(item) is true.
|
|
||||||
|
|
||||||
"""
|
|
||||||
# first_true([a,b,c], x) --> a or b or c or x
|
|
||||||
# first_true([a,b], x, f) --> a if f(a) else b if f(b) else x
|
|
||||||
return next(filter(pred, iterable), default)
|
return next(filter(pred, iterable), default)
|
||||||
|
|
||||||
|
|
||||||
|
def find_first_index(iterable, pred, default=None):
|
||||||
|
return next((i for i, x in enumerate(iterable) if pred(x)), default)
|
||||||
|
|
||||||
|
|
||||||
def replace_whitespace(text, replacement=" "):
|
def replace_whitespace(text, replacement=" "):
|
||||||
return re.sub(r"\s+", replacement, text).strip()
|
return re.sub(r"\s+", replacement, text).strip()
|
||||||
|
|
||||||
|
|
||||||
|
def get_django_content_type(obj):
|
||||||
|
return obj._meta.app_label + "." + type(obj).__name__
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
import graphene
|
||||||
|
|
||||||
|
from vbv_lernwelt.core.utils import get_django_content_type
|
||||||
|
|
||||||
|
|
||||||
|
class CoursePageInterface(graphene.Interface):
|
||||||
|
id = graphene.ID()
|
||||||
|
title = graphene.String()
|
||||||
|
slug = graphene.String()
|
||||||
|
content_type = graphene.String()
|
||||||
|
live = graphene.Boolean()
|
||||||
|
translation_key = graphene.String()
|
||||||
|
frontend_url = graphene.String()
|
||||||
|
|
||||||
|
def resolve_frontend_url(self, info):
|
||||||
|
return self.get_frontend_url()
|
||||||
|
|
||||||
|
def resolve_content_type(self, info):
|
||||||
|
return get_django_content_type(self)
|
||||||
|
|
@ -1,16 +1,15 @@
|
||||||
import graphene
|
import graphene
|
||||||
from graphql import GraphQLError
|
|
||||||
|
|
||||||
from vbv_lernwelt.course.graphql.types import CourseType
|
from vbv_lernwelt.course.graphql.types import CourseObjectType
|
||||||
from vbv_lernwelt.course.models import Course
|
from vbv_lernwelt.course.models import Course
|
||||||
from vbv_lernwelt.course.permissions import has_course_access
|
from vbv_lernwelt.course.permissions import has_course_access
|
||||||
|
|
||||||
|
|
||||||
class CourseQuery:
|
class CourseQuery(graphene.ObjectType):
|
||||||
course = graphene.Field(CourseType, id=graphene.Int())
|
course = graphene.Field(CourseObjectType, id=graphene.Int())
|
||||||
|
|
||||||
def resolve_course(root, info, id):
|
def resolve_course(root, info, id):
|
||||||
course = Course.objects.get(pk=id)
|
course = Course.objects.get(pk=id)
|
||||||
if has_course_access(info.context.user, course):
|
if has_course_access(info.context.user, course):
|
||||||
return course
|
return course
|
||||||
return GraphQLError("You do not have access to this course")
|
raise PermissionError("You do not have access to this course")
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ from rest_framework.exceptions import PermissionDenied
|
||||||
|
|
||||||
from vbv_lernwelt.course.models import Course, CourseBasePage
|
from vbv_lernwelt.course.models import Course, CourseBasePage
|
||||||
from vbv_lernwelt.course.permissions import has_course_access
|
from vbv_lernwelt.course.permissions import has_course_access
|
||||||
from vbv_lernwelt.course.schema import CoursePageInterface
|
from vbv_lernwelt.learnpath.graphql.types import LearningPathObjectType
|
||||||
|
|
||||||
logger = structlog.get_logger(__name__)
|
logger = structlog.get_logger(__name__)
|
||||||
|
|
||||||
|
|
@ -39,12 +39,12 @@ def resolve_course_page(
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
|
|
||||||
class CourseType(DjangoObjectType):
|
class CourseObjectType(DjangoObjectType):
|
||||||
learning_path = graphene.Field(CoursePageInterface)
|
learning_path = graphene.Field(LearningPathObjectType)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Course
|
model = Course
|
||||||
fields = ("id", "title", "category_name", "slug")
|
fields = ("id", "title", "category_name", "slug", "learning_path")
|
||||||
|
|
||||||
def resolve_learning_path(self, info):
|
def resolve_learning_path(self, info):
|
||||||
return self.get_learning_path()
|
return self.get_learning_path()
|
||||||
|
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
import graphene
|
|
||||||
from graphene_django import DjangoObjectType
|
|
||||||
|
|
||||||
from vbv_lernwelt.course.models import Course
|
|
||||||
from vbv_lernwelt.course.permissions import has_course_access
|
|
||||||
from vbv_lernwelt.learnpath.models import LearningPath
|
|
||||||
|
|
||||||
|
|
||||||
class CoursePageInterface(graphene.Interface):
|
|
||||||
id = graphene.ID()
|
|
||||||
title = graphene.String()
|
|
||||||
slug = graphene.String()
|
|
||||||
content_type = graphene.String()
|
|
||||||
live = graphene.Boolean()
|
|
||||||
translation_key = graphene.String()
|
|
||||||
frontend_url = graphene.String()
|
|
||||||
|
|
||||||
def resolve_frontend_url(self, info):
|
|
||||||
return self.get_frontend_url()
|
|
||||||
|
|
||||||
|
|
||||||
class LearningPathType(DjangoObjectType):
|
|
||||||
class Meta:
|
|
||||||
model = LearningPath
|
|
||||||
interfaces = (CoursePageInterface,)
|
|
||||||
|
|
||||||
|
|
||||||
class CourseType(DjangoObjectType):
|
|
||||||
learning_path = graphene.Field(LearningPathType)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = Course
|
|
||||||
fields = ("id", "title", "category_name", "slug", "learning_path")
|
|
||||||
|
|
||||||
def resolve_learning_path(self, info):
|
|
||||||
return self.get_learning_path()
|
|
||||||
|
|
||||||
|
|
||||||
class CourseQuery(graphene.ObjectType):
|
|
||||||
course = graphene.Field(CourseType, id=graphene.Int())
|
|
||||||
|
|
||||||
def resolve_course(root, info, id):
|
|
||||||
course = Course.objects.get(pk=id)
|
|
||||||
if has_course_access(info.context.user, course):
|
|
||||||
return course
|
|
||||||
raise PermissionError("You do not have access to this course")
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
from vbv_lernwelt.core.utils import get_django_content_type
|
||||||
from vbv_lernwelt.course.models import CourseCompletion, CourseCompletionStatus
|
from vbv_lernwelt.course.models import CourseCompletion, CourseCompletionStatus
|
||||||
from vbv_lernwelt.learnpath.utils import get_wagtail_type
|
|
||||||
|
|
||||||
|
|
||||||
def mark_course_completion(
|
def mark_course_completion(
|
||||||
|
|
@ -15,7 +15,7 @@ def mark_course_completion(
|
||||||
and page.specific.has_course_completion_status
|
and page.specific.has_course_completion_status
|
||||||
):
|
):
|
||||||
return ValueError(
|
return ValueError(
|
||||||
f"Page {page.id} of type {get_wagtail_type(page)}"
|
f"Page {page.id} of type {get_django_content_type(page)}"
|
||||||
f" cannot be marked as completed"
|
f" cannot be marked as completed"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -25,7 +25,7 @@ def mark_course_completion(
|
||||||
course_session_id=course_session.id,
|
course_session_id=course_session.id,
|
||||||
)
|
)
|
||||||
cc.completion_status = completion_status
|
cc.completion_status = completion_status
|
||||||
cc.page_type = get_wagtail_type(page.specific)
|
cc.page_type = get_django_content_type(page.specific)
|
||||||
|
|
||||||
cc.save()
|
cc.save()
|
||||||
return cc
|
return cc
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,8 @@ from rest_framework.exceptions import PermissionDenied
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from wagtail.models import Page
|
from wagtail.models import Page
|
||||||
|
|
||||||
|
from vbv_lernwelt.core.utils import get_django_content_type
|
||||||
|
|
||||||
from vbv_lernwelt.course.models import (
|
from vbv_lernwelt.course.models import (
|
||||||
CircleDocument,
|
CircleDocument,
|
||||||
CourseCompletion,
|
CourseCompletion,
|
||||||
|
|
@ -27,7 +29,6 @@ from vbv_lernwelt.course.serializers import (
|
||||||
from vbv_lernwelt.course.services import mark_course_completion
|
from vbv_lernwelt.course.services import mark_course_completion
|
||||||
from vbv_lernwelt.files.models import UploadFile
|
from vbv_lernwelt.files.models import UploadFile
|
||||||
from vbv_lernwelt.files.services import FileDirectUploadService
|
from vbv_lernwelt.files.services import FileDirectUploadService
|
||||||
from vbv_lernwelt.learnpath.utils import get_wagtail_type
|
|
||||||
|
|
||||||
logger = structlog.get_logger(__name__)
|
logger = structlog.get_logger(__name__)
|
||||||
|
|
||||||
|
|
@ -115,7 +116,7 @@ def mark_course_completion_view(request):
|
||||||
"mark_course_completion successful",
|
"mark_course_completion successful",
|
||||||
label="completion_api",
|
label="completion_api",
|
||||||
page_id=page_id,
|
page_id=page_id,
|
||||||
page_type=get_wagtail_type(page.specific),
|
page_type=get_django_content_type(page.specific),
|
||||||
page_slug=page.slug,
|
page_slug=page.slug,
|
||||||
page_title=page.title,
|
page_title=page.title,
|
||||||
user_id=request.user.id,
|
user_id=request.user.id,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
import graphene
|
||||||
|
|
||||||
|
from vbv_lernwelt.course.graphql.types import resolve_course_page
|
||||||
|
from vbv_lernwelt.learnpath.graphql.types import (
|
||||||
|
CircleObjectType,
|
||||||
|
LearningContentAssignmentObjectType,
|
||||||
|
LearningContentAttendanceCourseObjectType,
|
||||||
|
LearningContentDocumentListObjectType,
|
||||||
|
LearningContentFeedbackObjectType,
|
||||||
|
LearningContentLearningModuleObjectType,
|
||||||
|
LearningContentMediaLibraryObjectType,
|
||||||
|
LearningContentPlaceholderObjectType,
|
||||||
|
LearningContentRichTextObjectType,
|
||||||
|
LearningContentTestObjectType,
|
||||||
|
LearningContentVideoObjectType,
|
||||||
|
LearningPathObjectType,
|
||||||
|
)
|
||||||
|
from vbv_lernwelt.learnpath.models import Circle, LearningPath
|
||||||
|
|
||||||
|
|
||||||
|
class CircleQuery:
|
||||||
|
circle = graphene.Field(CircleObjectType, id=graphene.Int(), slug=graphene.String())
|
||||||
|
learning_path = graphene.Field(
|
||||||
|
LearningPathObjectType, id=graphene.Int(), slug=graphene.String()
|
||||||
|
)
|
||||||
|
|
||||||
|
def resolve_circle(root, info, id=None, slug=None):
|
||||||
|
return resolve_course_page(Circle, root, info, id=id, slug=slug)
|
||||||
|
|
||||||
|
def resolve_learning_path(root, info, id=None, slug=None):
|
||||||
|
return resolve_course_page(LearningPath, root, info, id=id, slug=slug)
|
||||||
|
|
||||||
|
# dummy import, so that graphene recognizes the types
|
||||||
|
learning_content_media_library = graphene.Field(
|
||||||
|
LearningContentMediaLibraryObjectType
|
||||||
|
)
|
||||||
|
learning_content_assignment = graphene.Field(LearningContentAssignmentObjectType)
|
||||||
|
learning_content_attendance_course = graphene.Field(
|
||||||
|
LearningContentAttendanceCourseObjectType
|
||||||
|
)
|
||||||
|
learning_content_feedback = graphene.Field(LearningContentFeedbackObjectType)
|
||||||
|
learning_content_learning_module = graphene.Field(
|
||||||
|
LearningContentLearningModuleObjectType
|
||||||
|
)
|
||||||
|
learning_content_placeholder = graphene.Field(LearningContentPlaceholderObjectType)
|
||||||
|
learning_content_rich_text = graphene.Field(LearningContentRichTextObjectType)
|
||||||
|
learning_content_test = graphene.Field(LearningContentTestObjectType)
|
||||||
|
learning_content_video = graphene.Field(LearningContentVideoObjectType)
|
||||||
|
learning_content_document_list = graphene.Field(
|
||||||
|
LearningContentDocumentListObjectType
|
||||||
|
)
|
||||||
|
|
||||||
|
def resolve_learning_content_media_library(self, info):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def resolve_learning_content_assignment(self, info):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def resolve_learning_content_attendance_course(self, info):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def resolve_learning_content_feedback(self, info):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def resolve_learning_content_learning_module(self, info):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def resolve_learning_content_placeholder(self, info):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def resolve_learning_content_rich_text(self, info):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def resolve_learning_content_test(self, info):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def resolve_learning_content_video(self, info):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def resolve_learning_content_document_list(self, info):
|
||||||
|
return None
|
||||||
|
|
@ -0,0 +1,282 @@
|
||||||
|
import graphene
|
||||||
|
import structlog
|
||||||
|
from graphene_django import DjangoObjectType
|
||||||
|
|
||||||
|
from vbv_lernwelt.core.utils import find_first_index
|
||||||
|
from vbv_lernwelt.course.graphql.interfaces import CoursePageInterface
|
||||||
|
from vbv_lernwelt.learnpath.models import (
|
||||||
|
Circle,
|
||||||
|
LearningContentAssignment,
|
||||||
|
LearningContentAttendanceCourse,
|
||||||
|
LearningContentDocumentList,
|
||||||
|
LearningContentFeedback,
|
||||||
|
LearningContentLearningModule,
|
||||||
|
LearningContentMediaLibrary,
|
||||||
|
LearningContentPlaceholder,
|
||||||
|
LearningContentRichText,
|
||||||
|
LearningContentTest,
|
||||||
|
LearningContentVideo,
|
||||||
|
LearningPath,
|
||||||
|
LearningSequence,
|
||||||
|
LearningUnit,
|
||||||
|
Topic,
|
||||||
|
)
|
||||||
|
|
||||||
|
logger = structlog.get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class LearningContentInterface(CoursePageInterface):
|
||||||
|
minutes = graphene.Int()
|
||||||
|
description = graphene.String()
|
||||||
|
content = graphene.String()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def resolve_type(cls, instance, info):
|
||||||
|
if isinstance(instance, LearningContentAssignment):
|
||||||
|
return LearningContentAssignmentObjectType
|
||||||
|
elif isinstance(instance, LearningContentAttendanceCourse):
|
||||||
|
return LearningContentAttendanceCourseObjectType
|
||||||
|
elif isinstance(instance, LearningContentFeedback):
|
||||||
|
return LearningContentFeedbackObjectType
|
||||||
|
elif isinstance(instance, LearningContentLearningModule):
|
||||||
|
return LearningContentLearningModuleObjectType
|
||||||
|
elif isinstance(instance, LearningContentMediaLibrary):
|
||||||
|
return LearningContentMediaLibraryObjectType
|
||||||
|
elif isinstance(instance, LearningContentPlaceholder):
|
||||||
|
return LearningContentPlaceholderObjectType
|
||||||
|
elif isinstance(instance, LearningContentRichText):
|
||||||
|
return LearningContentRichTextObjectType
|
||||||
|
elif isinstance(instance, LearningContentTest):
|
||||||
|
return LearningContentTestObjectType
|
||||||
|
elif isinstance(instance, LearningContentVideo):
|
||||||
|
return LearningContentVideoObjectType
|
||||||
|
elif isinstance(instance, LearningContentDocumentList):
|
||||||
|
return LearningContentDocumentListObjectType
|
||||||
|
else:
|
||||||
|
logger.error(
|
||||||
|
"Could not resolve type for LearningContentInterface",
|
||||||
|
django_instance=instance,
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class LearningContentAttendanceCourseObjectType(DjangoObjectType):
|
||||||
|
class Meta:
|
||||||
|
model = LearningContentAttendanceCourse
|
||||||
|
interfaces = (LearningContentInterface,)
|
||||||
|
fields = []
|
||||||
|
|
||||||
|
|
||||||
|
class LearningContentVideoObjectType(DjangoObjectType):
|
||||||
|
class Meta:
|
||||||
|
model = LearningContentVideo
|
||||||
|
interfaces = (LearningContentInterface,)
|
||||||
|
fields = []
|
||||||
|
|
||||||
|
|
||||||
|
class LearningContentPlaceholderObjectType(DjangoObjectType):
|
||||||
|
class Meta:
|
||||||
|
model = LearningContentPlaceholder
|
||||||
|
interfaces = (LearningContentInterface,)
|
||||||
|
fields = []
|
||||||
|
|
||||||
|
|
||||||
|
class LearningContentFeedbackObjectType(DjangoObjectType):
|
||||||
|
class Meta:
|
||||||
|
model = LearningContentFeedback
|
||||||
|
interfaces = (LearningContentInterface,)
|
||||||
|
fields = []
|
||||||
|
|
||||||
|
|
||||||
|
class LearningContentLearningModuleObjectType(DjangoObjectType):
|
||||||
|
class Meta:
|
||||||
|
model = LearningContentLearningModule
|
||||||
|
interfaces = (LearningContentInterface,)
|
||||||
|
fields = []
|
||||||
|
|
||||||
|
|
||||||
|
class LearningContentMediaLibraryObjectType(DjangoObjectType):
|
||||||
|
class Meta:
|
||||||
|
model = LearningContentMediaLibrary
|
||||||
|
interfaces = (LearningContentInterface,)
|
||||||
|
fields = []
|
||||||
|
|
||||||
|
|
||||||
|
class LearningContentTestObjectType(DjangoObjectType):
|
||||||
|
class Meta:
|
||||||
|
model = LearningContentTest
|
||||||
|
interfaces = (LearningContentInterface,)
|
||||||
|
fields = []
|
||||||
|
|
||||||
|
|
||||||
|
class LearningContentRichTextObjectType(DjangoObjectType):
|
||||||
|
class Meta:
|
||||||
|
model = LearningContentRichText
|
||||||
|
interfaces = (LearningContentInterface,)
|
||||||
|
fields = []
|
||||||
|
|
||||||
|
|
||||||
|
class LearningContentAssignmentObjectType(DjangoObjectType):
|
||||||
|
class Meta:
|
||||||
|
model = LearningContentAssignment
|
||||||
|
interfaces = (LearningContentInterface,)
|
||||||
|
fields = [
|
||||||
|
"content_assignment",
|
||||||
|
"assignment_type",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class LearningContentDocumentListObjectType(DjangoObjectType):
|
||||||
|
class Meta:
|
||||||
|
model = LearningContentDocumentList
|
||||||
|
interfaces = (LearningContentInterface,)
|
||||||
|
fields = []
|
||||||
|
|
||||||
|
|
||||||
|
class LearningUnitObjectType(DjangoObjectType):
|
||||||
|
learning_contents = graphene.List(LearningContentInterface)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = LearningUnit
|
||||||
|
interfaces = (CoursePageInterface,)
|
||||||
|
fields = []
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_learning_contents(root: LearningUnit, info, **kwargs):
|
||||||
|
siblings = None
|
||||||
|
if hasattr(info.context, "circle_descendants"):
|
||||||
|
circle_descendants = info.context.circle_descendants
|
||||||
|
index = circle_descendants.index(root)
|
||||||
|
siblings = circle_descendants[index + 1 :]
|
||||||
|
|
||||||
|
if not siblings:
|
||||||
|
siblings = root.get_siblings().live().specific()
|
||||||
|
|
||||||
|
learning_contents = []
|
||||||
|
for sibling in siblings:
|
||||||
|
if (
|
||||||
|
sibling.specific_class == LearningUnit
|
||||||
|
or sibling.specific_class == LearningSequence
|
||||||
|
):
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
learning_contents.append(sibling.specific)
|
||||||
|
return learning_contents
|
||||||
|
|
||||||
|
|
||||||
|
class LearningSequenceObjectType(DjangoObjectType):
|
||||||
|
learning_units = graphene.List(LearningUnitObjectType)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = LearningSequence
|
||||||
|
interfaces = (CoursePageInterface,)
|
||||||
|
fields = ["icon"]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_learning_units(root: LearningSequence, info, **kwargs):
|
||||||
|
siblings = None
|
||||||
|
if hasattr(info.context, "circle_descendants"):
|
||||||
|
circle_descendants = info.context.circle_descendants
|
||||||
|
index = circle_descendants.index(root)
|
||||||
|
siblings = circle_descendants[index + 1 :]
|
||||||
|
|
||||||
|
if not siblings:
|
||||||
|
siblings = root.get_siblings().live().specific()
|
||||||
|
|
||||||
|
learning_units = []
|
||||||
|
for sibling in siblings:
|
||||||
|
if sibling.specific_class == LearningSequence:
|
||||||
|
# finished with this sequence
|
||||||
|
break
|
||||||
|
if sibling.specific_class == LearningUnit:
|
||||||
|
learning_units.append(sibling.specific)
|
||||||
|
return learning_units
|
||||||
|
|
||||||
|
|
||||||
|
class CircleObjectType(DjangoObjectType):
|
||||||
|
learning_sequences = graphene.List(LearningSequenceObjectType)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Circle
|
||||||
|
interfaces = (CoursePageInterface,)
|
||||||
|
fields = [
|
||||||
|
"description",
|
||||||
|
"goals",
|
||||||
|
]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_learning_sequences(root: Circle, info, **kwargs):
|
||||||
|
circle_descendants = None
|
||||||
|
|
||||||
|
if hasattr(info.context, "learning_path_descendants"):
|
||||||
|
children = info.context.learning_path_descendants
|
||||||
|
circle_start_index = children.index(root)
|
||||||
|
next_circle_index = find_first_index(
|
||||||
|
children[circle_start_index + 1 :],
|
||||||
|
pred=lambda child: child.specific_class == Circle,
|
||||||
|
)
|
||||||
|
circle_descendants = children[circle_start_index + 1 : next_circle_index]
|
||||||
|
|
||||||
|
if not circle_descendants:
|
||||||
|
circle_descendants = list(root.get_descendants().live().specific())
|
||||||
|
|
||||||
|
# store flattened descendents to improve performance (no need for db queries)
|
||||||
|
info.context.circle_descendants = list(circle_descendants)
|
||||||
|
|
||||||
|
return [
|
||||||
|
descendant.specific
|
||||||
|
for descendant in circle_descendants
|
||||||
|
if descendant.specific_class == LearningSequence
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class TopicObjectType(DjangoObjectType):
|
||||||
|
circles = graphene.List(CircleObjectType)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Topic
|
||||||
|
interfaces = (CoursePageInterface,)
|
||||||
|
fields = [
|
||||||
|
"is_visible",
|
||||||
|
]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_circles(root: LearningPath, info, **kwargs):
|
||||||
|
siblings = None
|
||||||
|
|
||||||
|
if hasattr(info.context, "learning_path_descendants"):
|
||||||
|
learning_path_descendants = info.context.learning_path_descendants
|
||||||
|
index = learning_path_descendants.index(root)
|
||||||
|
siblings = learning_path_descendants[index + 1 :]
|
||||||
|
|
||||||
|
if not siblings:
|
||||||
|
siblings = root.get_next_siblings().live().specific()
|
||||||
|
|
||||||
|
circles = []
|
||||||
|
for sibling in siblings:
|
||||||
|
if sibling.specific_class == Topic:
|
||||||
|
# finished with this topic
|
||||||
|
break
|
||||||
|
if sibling.specific_class == Circle:
|
||||||
|
circles.append(sibling.specific)
|
||||||
|
return circles
|
||||||
|
|
||||||
|
|
||||||
|
class LearningPathObjectType(DjangoObjectType):
|
||||||
|
topics = graphene.List(TopicObjectType)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = LearningPath
|
||||||
|
interfaces = (CoursePageInterface,)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def resolve_topics(root: LearningPath, info, **kwargs):
|
||||||
|
learning_path_descendants_qs = root.get_descendants().live().specific()
|
||||||
|
|
||||||
|
# store flattened descendents to improve performance (no need for db queries)
|
||||||
|
info.context.learning_path_descendants = list(learning_path_descendants_qs)
|
||||||
|
return [
|
||||||
|
descendant.specific
|
||||||
|
for descendant in learning_path_descendants_qs
|
||||||
|
if descendant.specific_class == Topic
|
||||||
|
]
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
def get_wagtail_type(obj):
|
|
||||||
return obj._meta.app_label + "." + type(obj).__name__
|
|
||||||
Loading…
Reference in New Issue