242 lines
7.7 KiB
Python
242 lines
7.7 KiB
Python
import graphene
|
|
from graphene import relay
|
|
from graphene_django import DjangoObjectType
|
|
from graphene_django.filter import DjangoFilterConnectionField
|
|
|
|
from api.utils import get_object
|
|
from books.utils import are_solutions_enabled_for
|
|
from notes.models import ContentBlockHighlight
|
|
from rooms.models import ModuleRoomSlug
|
|
from ..models import Book, Topic, Module, Chapter, ContentBlock
|
|
|
|
|
|
def process_module_room_slug_block(content):
|
|
if content['type'] == 'module_room_slug':
|
|
try:
|
|
module_room_slug = ModuleRoomSlug.objects.get(title=content['value']['title'])
|
|
content['value'] = {
|
|
'title': content['value']['title'],
|
|
'slug': module_room_slug.slug
|
|
}
|
|
except ModuleRoomSlug.DoesNotExist:
|
|
pass
|
|
return content
|
|
|
|
|
|
class ContentBlockNode(DjangoObjectType):
|
|
mine = graphene.Boolean()
|
|
highlights = graphene.List(graphene.String)
|
|
|
|
class Meta:
|
|
model = ContentBlock
|
|
only_fields = [
|
|
'slug', 'title', 'type', 'contents', 'hidden_for', 'visible_for', 'user_created'
|
|
]
|
|
filter_fields = [
|
|
'slug', 'title',
|
|
]
|
|
interfaces = (relay.Node,)
|
|
|
|
def resolve_mine(self, info, **kwargs):
|
|
return self.owner is not None and self.owner.pk == info.context.user.pk
|
|
|
|
def resolve_contents(self, info, **kwargs):
|
|
updated_stream_data = []
|
|
for content in self.contents.stream_data:
|
|
if not are_solutions_enabled_for(info.context.user, self.module) and content['type'] == 'solution':
|
|
continue
|
|
|
|
if content['type'] == 'content_list_item':
|
|
for index, list_block in enumerate(content['value']):
|
|
content['value'][index] = process_module_room_slug_block(list_block)
|
|
|
|
content = process_module_room_slug_block(content)
|
|
updated_stream_data.append(content)
|
|
|
|
self.contents.stream_data = updated_stream_data
|
|
return self.contents
|
|
|
|
def resolve_highlights(self, info, **kwargs):
|
|
return [highlight.id for highlight in ContentBlockHighlight.objects.filter(
|
|
user=info.context.user,
|
|
content_block=self
|
|
)]
|
|
|
|
|
|
class ChapterNode(DjangoObjectType):
|
|
content_blocks = DjangoFilterConnectionField(ContentBlockNode)
|
|
|
|
class Meta:
|
|
model = Chapter
|
|
only_fields = [
|
|
'slug', 'title', 'description',
|
|
]
|
|
filter_fields = [
|
|
'slug', 'title',
|
|
]
|
|
interfaces = (relay.Node,)
|
|
|
|
def resolve_content_blocks(self, info, **kwargs):
|
|
user = info.context.user
|
|
school_classes = user.school_classes.values_list('pk')
|
|
|
|
if user.has_perm('users.can_manage_school_class_content'): # teacher
|
|
publisher_content_blocks = ContentBlock.get_by_parent(self).filter(user_created=False)
|
|
user_created_content_blocks = ContentBlock.get_by_parent(self).filter(user_created=True, owner=user)
|
|
else: # student
|
|
publisher_content_blocks = ContentBlock.get_by_parent(self).filter(user_created=False).exclude(
|
|
hidden_for__in=school_classes)
|
|
|
|
self_created_content_blocks = ContentBlock.get_by_parent(self).filter(user_created=True, owner=user)
|
|
|
|
user_created_content_blocks = ContentBlock.get_by_parent(self).filter(user_created=True,
|
|
visible_for__in=school_classes).union(
|
|
self_created_content_blocks)
|
|
|
|
return publisher_content_blocks.union(user_created_content_blocks)
|
|
|
|
|
|
class ModuleNode(DjangoObjectType):
|
|
pk = graphene.Int()
|
|
chapters = DjangoFilterConnectionField(ChapterNode)
|
|
topic = graphene.Field('books.schema.queries.TopicNode')
|
|
hero_image = graphene.String()
|
|
solutions_enabled = graphene.Boolean()
|
|
|
|
class Meta:
|
|
model = Module
|
|
only_fields = [
|
|
'slug', 'title', 'meta_title', 'teaser', 'intro', 'objective_groups', 'assignments', 'hero_image', 'topic'
|
|
]
|
|
filter_fields = {
|
|
'slug': ['exact', 'icontains', 'in'],
|
|
'title': ['exact', 'icontains', 'in'],
|
|
}
|
|
interfaces = (relay.Node,)
|
|
|
|
def resolve_pk(self, info, **kwargs):
|
|
return self.id
|
|
|
|
def resolve_hero_image(self, info, **kwargs):
|
|
if self.hero_image:
|
|
return self.hero_image.file.url
|
|
|
|
def resolve_chapters(self, info, **kwargs):
|
|
return Chapter.get_by_parent(self)
|
|
|
|
def resolve_topic(self, info, **kwargs):
|
|
return self.get_parent().specific
|
|
|
|
def resolve_solutions_enabled(self, info, **kwargs):
|
|
teacher = info.context.user.get_teacher()
|
|
return self.solutions_enabled_by.filter(pk=teacher.pk).exists() if teacher is not None else False
|
|
|
|
|
|
class TopicNode(DjangoObjectType):
|
|
pk = graphene.Int()
|
|
modules = DjangoFilterConnectionField(ModuleNode)
|
|
|
|
class Meta:
|
|
model = Topic
|
|
only_fields = [
|
|
'slug', 'title', 'meta_title', 'teaser', 'description', 'vimeo_id', 'order'
|
|
]
|
|
filter_fields = {
|
|
'slug': ['exact', 'icontains', 'in'],
|
|
'title': ['exact', 'icontains', 'in'],
|
|
}
|
|
interfaces = (relay.Node,)
|
|
|
|
def resolve_pk(self, *args, **kwargs):
|
|
return self.id
|
|
|
|
def resolve_modules(self, *args, **kwargs):
|
|
return Module.get_by_parent(self)
|
|
|
|
|
|
class BookNode(DjangoObjectType):
|
|
pk = graphene.Int()
|
|
topics = DjangoFilterConnectionField(TopicNode)
|
|
|
|
class Meta:
|
|
model = Book
|
|
only_fields = [
|
|
'slug', 'title',
|
|
]
|
|
filter_fields = {
|
|
'slug': ['exact', 'icontains', 'in'],
|
|
'title': ['exact', 'icontains', 'in'],
|
|
}
|
|
interfaces = (relay.Node,)
|
|
|
|
def resolve_pk(self, *args, **kwargs):
|
|
return self.id
|
|
|
|
def resolve_topics(self, *args, **kwargs):
|
|
return Topic.get_by_parent(self)
|
|
|
|
|
|
class FilteredChapterNode(DjangoObjectType):
|
|
content_blocks = DjangoFilterConnectionField(ContentBlockNode)
|
|
|
|
class Meta:
|
|
model = Chapter
|
|
only_fields = [
|
|
'slug', 'title',
|
|
]
|
|
filter_fields = [
|
|
'slug', 'title',
|
|
]
|
|
interfaces = (relay.Node,)
|
|
|
|
def resolve_content_blocks(self, *args, **kwargs):
|
|
return ContentBlock.get_by_parent(self)
|
|
|
|
|
|
class BookQuery(object):
|
|
book = relay.Node.Field(BookNode)
|
|
topic = graphene.Field(TopicNode, slug=graphene.String())
|
|
module = graphene.Field(ModuleNode, slug=graphene.String(), id=graphene.ID())
|
|
chapter = relay.Node.Field(FilteredChapterNode)
|
|
content_block = relay.Node.Field(ContentBlockNode)
|
|
|
|
books = DjangoFilterConnectionField(BookNode)
|
|
topics = DjangoFilterConnectionField(TopicNode)
|
|
modules = DjangoFilterConnectionField(ModuleNode)
|
|
chapters = DjangoFilterConnectionField(FilteredChapterNode)
|
|
|
|
def resolve_books(self, *args, **kwargs):
|
|
return Book.objects.filter(**kwargs).live()
|
|
|
|
def resolve_topics(self, *args, **kwargs):
|
|
return Topic.objects.filter(**kwargs).live()
|
|
|
|
def resolve_modules(self, *args, **kwargs):
|
|
return Module.objects.filter(**kwargs).live()
|
|
|
|
def resolve_chapters(self, *args, **kwargs):
|
|
return Chapter.objects.filter(**kwargs).live()
|
|
|
|
def resolve_module(self, info, **kwargs):
|
|
slug = kwargs.get('slug')
|
|
id = kwargs.get('id')
|
|
module = None
|
|
|
|
if id is not None:
|
|
module = get_object(Module, id)
|
|
|
|
elif slug is not None:
|
|
module = Module.objects.get(slug=slug)
|
|
|
|
return module
|
|
|
|
def resolve_topic(self, info, **kwargs):
|
|
slug = kwargs.get('slug')
|
|
id = kwargs.get('id')
|
|
|
|
if id is not None:
|
|
return get_object(Topic, id)
|
|
if slug is not None:
|
|
return Topic.objects.get(slug=slug)
|
|
return None
|