import graphene from django.db.models import Prefetch, Value, CharField, Q from django.db.models.functions import Concat from graphene import relay, ObjectType from graphene_django import DjangoObjectType from graphene_django.filter import DjangoFilterConnectionField from graphql_relay import to_global_id from basicknowledge.models import BasicKnowledge from basicknowledge.queries import InstrumentNode from books.models import Module from books.schema.queries import ModuleNode from users.models import User, SchoolClass, SchoolClassMember class SchoolClassNode(DjangoObjectType): pk = graphene.Int() members = graphene.List('users.schema.ClassMemberNode') class Meta: model = SchoolClass filter_fields = ['name'] interfaces = (relay.Node,) def resolve_pk(self, *args, **kwargs): return self.id def resolve_members(self, info, **kwargs): return SchoolClassMember.objects.filter(school_class=self) class UserNode(DjangoObjectType): pk = graphene.Int() permissions = graphene.List(graphene.String) selected_class = graphene.Field(SchoolClassNode) is_teacher = graphene.Boolean() old_classes = DjangoFilterConnectionField(SchoolClassNode) class Meta: model = User filter_fields = ['username', 'email'] only_fields = ['username', 'email', 'first_name', 'last_name', 'school_classes', 'last_module', 'avatar_url', 'selected_class'] interfaces = (relay.Node,) def resolve_pk(self, info, **kwargs): return self.id def resolve_permissions(self, info): return self.get_all_permissions() def resolve_selected_class(self, info): return self.selected_class() def resolve_is_teacher(self, info): return self.is_teacher() def resolve_school_classes(self, info): if self.selected_class() is None: # then we don't have any class to return return [] return SchoolClass.objects.filter( Q(schoolclassmember__active=True, schoolclassmember__user=self) | Q(pk=self.selected_class().pk)).distinct() def resolve_old_classes(self, info): return SchoolClass.objects.filter(schoolclassmember__active=False, schoolclassmember__user=self) class ClassMemberNode(ObjectType): """ We need to build this ourselves, because we want the active property on the node, because providing it on the Connection or Edge for a UserNodeConnection is difficult. """ user = graphene.Field(UserNode) active = graphene.Boolean() first_name = graphene.String() last_name = graphene.String() is_teacher = graphene.Boolean() id = graphene.ID() def resolve_id(self, *args): return to_global_id('UserNode', self.user.pk) def resolve_active(self, *args): return self.active def resolve_first_name(self, *args): return self.user.first_name def resolve_last_name(self, *args): return self.user.last_name def resolve_user(self, info, **kwargs): return self.user def resolve_is_teacher(self, *args): return self.user.is_teacher() class UsersQuery(object): me = graphene.Field(UserNode) all_users = DjangoFilterConnectionField(UserNode) my_activity = DjangoFilterConnectionField(ModuleNode) my_instrument_activity = DjangoFilterConnectionField(InstrumentNode) def resolve_me(self, info, **kwargs): return info.context.user def resolve_all_users(self, info, **kwargs): if not info.context.user.is_superuser: return User.objects.none() else: return User.objects.all() def resolve_my_activity(self, info, **kwargs): return Module.objects.all() def resolve_my_instrument_activity(self, info, **kwargs): return BasicKnowledge.objects.all() class AllUsersQuery(object): me = graphene.Field(UserNode) all_users = DjangoFilterConnectionField(UserNode) def resolve_all_users(self, info, **kwargs): if not info.context.user.is_superuser: return User.objects.none() else: return User.objects.all()