Add GraphQL server code for learning path
This commit is contained in:
parent
8e16daa525
commit
da03b407bb
|
|
@ -24,7 +24,7 @@ def main():
|
|||
reset_queries()
|
||||
|
||||
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)
|
||||
|
||||
|
|
@ -32,6 +32,13 @@ def main():
|
|||
print(len(json.dumps(serializer.data)))
|
||||
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__":
|
||||
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.core.graphql.types import JSONStreamField
|
||||
from vbv_lernwelt.course.schema import CoursePageInterface
|
||||
from vbv_lernwelt.course.graphql.interfaces import CoursePageInterface
|
||||
|
||||
|
||||
class AssignmentObjectType(DjangoObjectType):
|
||||
|
|
|
|||
|
|
@ -2,13 +2,16 @@ import graphene
|
|||
|
||||
from vbv_lernwelt.assignment.graphql.mutations import AssignmentMutation
|
||||
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.queries import CourseSessionQuery
|
||||
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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import wagtail.api.v2.serializers as wagtail_serializers
|
||||
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(
|
||||
|
|
@ -33,7 +33,7 @@ def get_it_serializer_class(
|
|||
|
||||
class ItWagtailTypeField(wagtail_serializers.TypeField):
|
||||
def to_representation(self, obj):
|
||||
name = get_wagtail_type(obj)
|
||||
name = get_django_content_type(obj)
|
||||
return name
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -39,19 +39,17 @@ class DayUserRateThrottle(UserRateThrottle):
|
|||
scope = "day-throttle"
|
||||
|
||||
|
||||
def find_first(iterable, default=False, pred=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
|
||||
def find_first(iterable, pred=None, default=None):
|
||||
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=" "):
|
||||
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
|
||||
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.permissions import has_course_access
|
||||
|
||||
|
||||
class CourseQuery:
|
||||
course = graphene.Field(CourseType, id=graphene.Int())
|
||||
class CourseQuery(graphene.ObjectType):
|
||||
course = graphene.Field(CourseObjectType, 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
|
||||
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.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__)
|
||||
|
||||
|
|
@ -39,12 +39,12 @@ def resolve_course_page(
|
|||
raise e
|
||||
|
||||
|
||||
class CourseType(DjangoObjectType):
|
||||
learning_path = graphene.Field(CoursePageInterface)
|
||||
class CourseObjectType(DjangoObjectType):
|
||||
learning_path = graphene.Field(LearningPathObjectType)
|
||||
|
||||
class Meta:
|
||||
model = Course
|
||||
fields = ("id", "title", "category_name", "slug")
|
||||
fields = ("id", "title", "category_name", "slug", "learning_path")
|
||||
|
||||
def resolve_learning_path(self, info):
|
||||
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.learnpath.utils import get_wagtail_type
|
||||
|
||||
|
||||
def mark_course_completion(
|
||||
|
|
@ -15,7 +15,7 @@ def mark_course_completion(
|
|||
and page.specific.has_course_completion_status
|
||||
):
|
||||
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"
|
||||
)
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ def mark_course_completion(
|
|||
course_session_id=course_session.id,
|
||||
)
|
||||
cc.completion_status = completion_status
|
||||
cc.page_type = get_wagtail_type(page.specific)
|
||||
cc.page_type = get_django_content_type(page.specific)
|
||||
|
||||
cc.save()
|
||||
return cc
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ from rest_framework.exceptions import PermissionDenied
|
|||
from rest_framework.response import Response
|
||||
from wagtail.models import Page
|
||||
|
||||
from vbv_lernwelt.core.utils import get_django_content_type
|
||||
|
||||
from vbv_lernwelt.course.models import (
|
||||
CircleDocument,
|
||||
CourseCompletion,
|
||||
|
|
@ -27,7 +29,6 @@ from vbv_lernwelt.course.serializers import (
|
|||
from vbv_lernwelt.course.services import mark_course_completion
|
||||
from vbv_lernwelt.files.models import UploadFile
|
||||
from vbv_lernwelt.files.services import FileDirectUploadService
|
||||
from vbv_lernwelt.learnpath.utils import get_wagtail_type
|
||||
|
||||
logger = structlog.get_logger(__name__)
|
||||
|
||||
|
|
@ -115,7 +116,7 @@ def mark_course_completion_view(request):
|
|||
"mark_course_completion successful",
|
||||
label="completion_api",
|
||||
page_id=page_id,
|
||||
page_type=get_wagtail_type(page.specific),
|
||||
page_type=get_django_content_type(page.specific),
|
||||
page_slug=page.slug,
|
||||
page_title=page.title,
|
||||
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