import graphene from django.db.models import Q from graphene import relay from graphene_django import DjangoObjectType from graphene_django.filter import DjangoFilterConnectionField from graphql_relay import to_global_id from books.models import Chapter, ContentBlock from books.models.snapshot import ChapterSnapshot from books.schema.interfaces import ChapterInterface from notes.models import ChapterBookmark from notes.schema import ChapterBookmarkNode class ChapterNode(DjangoObjectType): bookmark = graphene.Field(ChapterBookmarkNode) content_blocks = graphene.List('books.schema.nodes.ContentBlockNode') class Meta: model = Chapter only_fields = [ 'slug', 'title', 'description', 'title_hidden_for', 'description_hidden_for' ] filter_fields = [ 'slug', 'title', ] interfaces = (ChapterInterface,) def resolve_content_blocks(self, info, **kwargs): user = info.context.user school_classes = user.school_classes.values_list('pk', flat=True) by_parent = ContentBlock.get_by_parent(self) \ .filter(contentblocksnapshot__isnull=True) # exclude snapshot # .prefetch_related('visible_for') \ # .prefetch_related('hidden_for') # don't filter the hidden blocks on the server any more, we do this on the client now, as they are not secret default_blocks = Q(user_created=False) owned_by_user = Q(user_created=True, owner=user) teacher_created_and_visible = Q(Q(user_created=True) & Q(visible_for__pk__in=school_classes)) if user.can_manage_school_class_content: # teacher return by_parent.filter(default_blocks | owned_by_user | teacher_created_and_visible).distinct() else: # student return by_parent.filter(default_blocks | teacher_created_and_visible).distinct() def resolve_bookmark(self, info, **kwargs): return ChapterBookmark.objects.filter( user=info.context.user, chapter=self ).first() class ChapterInSnapshotNode(DjangoObjectType): title_hidden = graphene.Boolean() description_hidden = graphene.Boolean() title = graphene.String() description = graphene.String() id = graphene.ID(required=True) class Meta: model = ChapterSnapshot only_fields = '__all__' filter_fields = [ 'id', ] interfaces = (ChapterInterface,) @staticmethod def resolve_title_hidden(parent, info): return parent.title_hidden @staticmethod def resolve_description_hidden(parent, info): return parent.description_hidden @staticmethod def resolve_title(parent, info): return parent.chapter.title @staticmethod def resolve_description(parent, info): return parent.chapter.description @staticmethod def resolve_content_blocks(parent, info, **kwargs): snapshot = parent.snapshot user_created = Q(user_created=True) hidden_for_snapshot = Q(hidden_for_snapshots=snapshot) custom_hidden = Q(contentblocksnapshot__hidden=True) qs = ContentBlock.get_by_parent(parent.chapter) \ .exclude(user_created) \ .exclude(hidden_for_snapshot) \ .exclude(custom_hidden) return qs def resolve_id(self, *args): return to_global_id('SnapshotChapterNode', self.chapter.pk)