Update types and schema
This commit is contained in:
parent
d1664592ce
commit
266356b510
|
|
@ -1,5 +1,13 @@
|
||||||
mutation Coupon($input: CouponInput!) {
|
mutation Coupon($input: CouponInput!) {
|
||||||
coupon(input: $input) {
|
coupon(input: $input) {
|
||||||
success
|
result {
|
||||||
|
__typename
|
||||||
|
... on Success {
|
||||||
|
message
|
||||||
|
}
|
||||||
|
... on InvalidCoupon {
|
||||||
|
reason
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,9 @@ class CouponTests(TestCase):
|
||||||
school_class = SchoolClass.objects.get(users__in=[self.user])
|
school_class = SchoolClass.objects.get(users__in=[self.user])
|
||||||
self.assertIsNotNone(school_class)
|
self.assertIsNotNone(school_class)
|
||||||
|
|
||||||
self.assertTrue(result.get("data").get("coupon").get("success"))
|
self.assertEqual(
|
||||||
|
result.get("data").get("coupon").get("result").get("__typename"), "Success"
|
||||||
|
)
|
||||||
self.assertTrue(self.user.is_authenticated)
|
self.assertTrue(self.user.is_authenticated)
|
||||||
|
|
||||||
@patch.object(
|
@patch.object(
|
||||||
|
|
|
||||||
|
|
@ -354,7 +354,7 @@ input CouponInput {
|
||||||
}
|
}
|
||||||
|
|
||||||
type CouponPayload {
|
type CouponPayload {
|
||||||
success: Boolean
|
result: RedeemCouponResult
|
||||||
clientMutationId: String
|
clientMutationId: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -508,7 +508,7 @@ type DuplicateContentBlockPayload {
|
||||||
clientMutationId: String
|
clientMutationId: String
|
||||||
}
|
}
|
||||||
|
|
||||||
type DuplicateName {
|
type DuplicateName implements FailureNode {
|
||||||
reason: String
|
reason: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -578,6 +578,10 @@ type InstrumentTypeNode implements Node {
|
||||||
type: String!
|
type: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type InvalidCoupon implements FailureNode {
|
||||||
|
reason: String
|
||||||
|
}
|
||||||
|
|
||||||
scalar JSONString
|
scalar JSONString
|
||||||
|
|
||||||
input JoinClassInput {
|
input JoinClassInput {
|
||||||
|
|
@ -938,6 +942,8 @@ type Query {
|
||||||
_debug: DjangoDebug
|
_debug: DjangoDebug
|
||||||
}
|
}
|
||||||
|
|
||||||
|
union RedeemCouponResult = Success | InvalidCoupon
|
||||||
|
|
||||||
type RoomEntryNode implements Node {
|
type RoomEntryNode implements Node {
|
||||||
id: ID!
|
id: ID!
|
||||||
title: String!
|
title: String!
|
||||||
|
|
|
||||||
|
|
@ -5,17 +5,27 @@ from django.db import IntegrityError
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from graphene import relay
|
from graphene import relay
|
||||||
from graphql_relay import from_global_id
|
from graphql_relay import from_global_id
|
||||||
|
from api.types import FailureNode
|
||||||
|
|
||||||
from api.utils import get_object
|
from api.utils import get_object
|
||||||
from core.logger import get_logger
|
from core.logger import get_logger
|
||||||
from users.inputs import PasswordUpdateInput
|
from users.inputs import PasswordUpdateInput
|
||||||
from users.models import SchoolClass, SchoolClassMember, Team
|
from users.models import SchoolClass, SchoolClassMember, Team
|
||||||
from users.schema import CreateSchoolClassResult, CreateTeamResult, FieldError, SchoolClassNode, TeamNode, UpdateError
|
from users.schema import (
|
||||||
|
CreateSchoolClassResult,
|
||||||
|
CreateTeamResult,
|
||||||
|
FieldError,
|
||||||
|
SchoolClassNode,
|
||||||
|
TeamNode,
|
||||||
|
UpdateError,
|
||||||
|
DuplicateName,
|
||||||
|
)
|
||||||
from users.serializers import AvatarUrlSerializer, PasswordSerialzer
|
from users.serializers import AvatarUrlSerializer, PasswordSerialzer
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
DUPLICATE_REASON = {"reason": "Dieser Name wird bereits verwendet."}
|
|
||||||
|
DuplicateFailure = DuplicateName(reason="Dieser Name wird bereits verwendet.")
|
||||||
|
|
||||||
|
|
||||||
class CodeNotFoundException(Exception):
|
class CodeNotFoundException(Exception):
|
||||||
|
|
@ -29,8 +39,8 @@ class TeacherOnlyMutation(relay.ClientIDMutation):
|
||||||
@classmethod
|
@classmethod
|
||||||
def mutate(cls, root, info, input):
|
def mutate(cls, root, info, input):
|
||||||
user = info.context.user
|
user = info.context.user
|
||||||
if 'users.can_manage_school_class_content' not in user.get_role_permissions():
|
if "users.can_manage_school_class_content" not in user.get_role_permissions():
|
||||||
raise PermissionError('Permission denied')
|
raise PermissionError("Permission denied")
|
||||||
return super().mutate(root, info, input)
|
return super().mutate(root, info, input)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -44,12 +54,12 @@ class UpdatePassword(relay.ClientIDMutation):
|
||||||
@classmethod
|
@classmethod
|
||||||
def mutate_and_get_payload(cls, root, info, **kwargs):
|
def mutate_and_get_payload(cls, root, info, **kwargs):
|
||||||
user = info.context.user
|
user = info.context.user
|
||||||
password_data = kwargs.get('password_input')
|
password_data = kwargs.get("password_input")
|
||||||
|
|
||||||
serializer = PasswordSerialzer(data=password_data, context=user)
|
serializer = PasswordSerialzer(data=password_data, context=user)
|
||||||
|
|
||||||
if serializer.is_valid():
|
if serializer.is_valid():
|
||||||
user.set_password(password_data['new_password'])
|
user.set_password(password_data["new_password"])
|
||||||
user.save()
|
user.save()
|
||||||
update_session_auth_hash(info.context, user)
|
update_session_auth_hash(info.context, user)
|
||||||
return cls(success=True)
|
return cls(success=True)
|
||||||
|
|
@ -75,9 +85,9 @@ class UpdateAvatar(relay.ClientIDMutation):
|
||||||
@classmethod
|
@classmethod
|
||||||
def mutate_and_get_payload(cls, root, info, **kwargs):
|
def mutate_and_get_payload(cls, root, info, **kwargs):
|
||||||
user = info.context.user
|
user = info.context.user
|
||||||
avatar_data = kwargs.get('avatar_url')
|
avatar_data = kwargs.get("avatar_url")
|
||||||
|
|
||||||
serializer = AvatarUrlSerializer(data={'avatar_url': avatar_data})
|
serializer = AvatarUrlSerializer(data={"avatar_url": avatar_data})
|
||||||
if serializer.is_valid():
|
if serializer.is_valid():
|
||||||
user.avatar_url = avatar_data
|
user.avatar_url = avatar_data
|
||||||
user.save()
|
user.save()
|
||||||
|
|
@ -85,7 +95,6 @@ class UpdateAvatar(relay.ClientIDMutation):
|
||||||
|
|
||||||
errors = []
|
errors = []
|
||||||
for key, value in serializer.errors.items():
|
for key, value in serializer.errors.items():
|
||||||
|
|
||||||
error = UpdateError(field=key, errors=[])
|
error = UpdateError(field=key, errors=[])
|
||||||
|
|
||||||
for field_error in serializer.errors[key]:
|
for field_error in serializer.errors[key]:
|
||||||
|
|
@ -102,12 +111,12 @@ class UpdateSetting(relay.ClientIDMutation):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def mutate_and_get_payload(cls, root, info, **kwargs):
|
def mutate_and_get_payload(cls, root, info, **kwargs):
|
||||||
class_id = kwargs.get('id')
|
class_id = kwargs.get("id")
|
||||||
school_class = get_object(SchoolClass, class_id)
|
school_class = get_object(SchoolClass, class_id)
|
||||||
user = info.context.user
|
user = info.context.user
|
||||||
|
|
||||||
if school_class and school_class not in user.school_classes.all():
|
if school_class and school_class not in user.school_classes.all():
|
||||||
raise PermissionDenied('Permission denied: Incorrect school class')
|
raise PermissionDenied("Permission denied: Incorrect school class")
|
||||||
|
|
||||||
user.set_selected_class(school_class)
|
user.set_selected_class(school_class)
|
||||||
return cls(success=True)
|
return cls(success=True)
|
||||||
|
|
@ -126,22 +135,23 @@ class JoinClass(relay.ClientIDMutation):
|
||||||
@classmethod
|
@classmethod
|
||||||
def mutate_and_get_payload(cls, root, info, **kwargs):
|
def mutate_and_get_payload(cls, root, info, **kwargs):
|
||||||
user = info.context.user
|
user = info.context.user
|
||||||
code = kwargs.get('code')
|
code = kwargs.get("code")
|
||||||
try:
|
try:
|
||||||
school_class = SchoolClass.objects.get(Q(code__iexact=code))
|
school_class = SchoolClass.objects.get(Q(code__iexact=code))
|
||||||
|
|
||||||
if user not in list(school_class.users.all()):
|
if user not in list(school_class.users.all()):
|
||||||
SchoolClassMember.objects.create(
|
SchoolClassMember.objects.create(user=user, school_class=school_class)
|
||||||
user=user,
|
|
||||||
school_class=school_class
|
|
||||||
)
|
|
||||||
user.set_selected_class(school_class)
|
user.set_selected_class(school_class)
|
||||||
else:
|
else:
|
||||||
raise CodeNotFoundException('[CAJ] Schüler ist bereits in Klasse') # CAJ = Class Already Joined
|
raise CodeNotFoundException(
|
||||||
|
"[CAJ] Schüler ist bereits in Klasse"
|
||||||
|
) # CAJ = Class Already Joined
|
||||||
|
|
||||||
return cls(success=True, school_class=school_class)
|
return cls(success=True, school_class=school_class)
|
||||||
except SchoolClass.DoesNotExist:
|
except SchoolClass.DoesNotExist:
|
||||||
raise CodeNotFoundException('[CNV] Code ist nicht gültig') # CNV = Code Not Valid
|
raise CodeNotFoundException(
|
||||||
|
"[CNV] Code ist nicht gültig"
|
||||||
|
) # CNV = Code Not Valid
|
||||||
|
|
||||||
|
|
||||||
class AddRemoveMember(relay.ClientIDMutation):
|
class AddRemoveMember(relay.ClientIDMutation):
|
||||||
|
|
@ -154,18 +164,20 @@ class AddRemoveMember(relay.ClientIDMutation):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def mutate_and_get_payload(cls, root, info, **kwargs):
|
def mutate_and_get_payload(cls, root, info, **kwargs):
|
||||||
member_id = kwargs.get('member')
|
member_id = kwargs.get("member")
|
||||||
school_class_id = kwargs.get('school_class')
|
school_class_id = kwargs.get("school_class")
|
||||||
active = kwargs.get('active')
|
active = kwargs.get("active")
|
||||||
user = info.context.user
|
user = info.context.user
|
||||||
|
|
||||||
member_pk = from_global_id(member_id)[1]
|
member_pk = from_global_id(member_id)[1]
|
||||||
school_class = get_object(SchoolClass, school_class_id)
|
school_class = get_object(SchoolClass, school_class_id)
|
||||||
|
|
||||||
if not user.is_teacher() or not school_class.users.filter(pk=user.pk).exists():
|
if not user.is_teacher() or not school_class.users.filter(pk=user.pk).exists():
|
||||||
raise PermissionError('Permission denied')
|
raise PermissionError("Permission denied")
|
||||||
|
|
||||||
school_class_member = SchoolClassMember.objects.get(user__pk=member_pk, school_class=school_class)
|
school_class_member = SchoolClassMember.objects.get(
|
||||||
|
user__pk=member_pk, school_class=school_class
|
||||||
|
)
|
||||||
school_class_member.active = active
|
school_class_member.active = active
|
||||||
school_class_member.save()
|
school_class_member.save()
|
||||||
|
|
||||||
|
|
@ -182,8 +194,8 @@ class UpdateSchoolClass(TeacherOnlyMutation):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def mutate_and_get_payload(cls, root, info, **kwargs):
|
def mutate_and_get_payload(cls, root, info, **kwargs):
|
||||||
id = kwargs.get('id')
|
id = kwargs.get("id")
|
||||||
name = kwargs.get('name')
|
name = kwargs.get("name")
|
||||||
user = info.context.user
|
user = info.context.user
|
||||||
|
|
||||||
# todo: only allow to edit your own school class
|
# todo: only allow to edit your own school class
|
||||||
|
|
@ -202,7 +214,7 @@ class CreateSchoolClass(TeacherOnlyMutation):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def mutate_and_get_payload(cls, root, info, **kwargs):
|
def mutate_and_get_payload(cls, root, info, **kwargs):
|
||||||
name = kwargs.get('name')
|
name = kwargs.get("name")
|
||||||
user = info.context.user
|
user = info.context.user
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -222,7 +234,7 @@ class CreateTeam(TeacherOnlyMutation):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def mutate_and_get_payload(cls, root, info, **kwargs):
|
def mutate_and_get_payload(cls, root, info, **kwargs):
|
||||||
name = kwargs.get('name')
|
name = kwargs.get("name")
|
||||||
user = info.context.user
|
user = info.context.user
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
@ -232,7 +244,7 @@ class CreateTeam(TeacherOnlyMutation):
|
||||||
user.save()
|
user.save()
|
||||||
return cls(result=team)
|
return cls(result=team)
|
||||||
except IntegrityError:
|
except IntegrityError:
|
||||||
return cls(result=DUPLICATE_REASON)
|
return cls(result=DuplicateFailure)
|
||||||
|
|
||||||
|
|
||||||
class UpdateTeam(TeacherOnlyMutation):
|
class UpdateTeam(TeacherOnlyMutation):
|
||||||
|
|
@ -245,14 +257,14 @@ class UpdateTeam(TeacherOnlyMutation):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def mutate_and_get_payload(cls, root, info, **kwargs):
|
def mutate_and_get_payload(cls, root, info, **kwargs):
|
||||||
id = kwargs.get('id')
|
id = kwargs.get("id")
|
||||||
name = kwargs.get('name')
|
name = kwargs.get("name")
|
||||||
user = info.context.user
|
user = info.context.user
|
||||||
|
|
||||||
team = get_object(Team, id)
|
team = get_object(Team, id)
|
||||||
if user not in team.members.all():
|
if user not in team.members.all():
|
||||||
logger.info('User not part of this team')
|
logger.info("User not part of this team")
|
||||||
raise PermissionError('Permission denied')
|
raise PermissionError("Permission denied")
|
||||||
team.name = name
|
team.name = name
|
||||||
team.save()
|
team.save()
|
||||||
|
|
||||||
|
|
@ -269,7 +281,7 @@ class JoinTeam(TeacherOnlyMutation):
|
||||||
@classmethod
|
@classmethod
|
||||||
def mutate_and_get_payload(cls, root, info, **kwargs):
|
def mutate_and_get_payload(cls, root, info, **kwargs):
|
||||||
user = info.context.user
|
user = info.context.user
|
||||||
code = kwargs.get('code')
|
code = kwargs.get("code")
|
||||||
try:
|
try:
|
||||||
team = Team.objects.get(Q(code__iexact=code))
|
team = Team.objects.get(Q(code__iexact=code))
|
||||||
user.team = team
|
user.team = team
|
||||||
|
|
@ -277,7 +289,9 @@ class JoinTeam(TeacherOnlyMutation):
|
||||||
|
|
||||||
return cls(success=True, team=team)
|
return cls(success=True, team=team)
|
||||||
except Team.DoesNotExist:
|
except Team.DoesNotExist:
|
||||||
raise CodeNotFoundException('[CNV] Code ist nicht gültig') # CNV = Code Not Valid
|
raise CodeNotFoundException(
|
||||||
|
"[CNV] Code ist nicht gültig"
|
||||||
|
) # CNV = Code Not Valid
|
||||||
|
|
||||||
|
|
||||||
class LeaveTeam(graphene.Mutation):
|
class LeaveTeam(graphene.Mutation):
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ from graphene import ObjectType, relay
|
||||||
from graphene_django import DjangoObjectType
|
from graphene_django import DjangoObjectType
|
||||||
from graphene_django.filter import DjangoFilterConnectionField
|
from graphene_django.filter import DjangoFilterConnectionField
|
||||||
from graphql_relay import to_global_id
|
from graphql_relay import to_global_id
|
||||||
|
from api.types import FailureNode
|
||||||
|
|
||||||
from books.models import Module
|
from books.models import Module
|
||||||
from books.schema.queries import ModuleNode
|
from books.schema.queries import ModuleNode
|
||||||
|
|
@ -17,25 +18,21 @@ from users.models import SchoolClass, SchoolClassMember, Team, User
|
||||||
class RecentModuleFilter(FilterSet):
|
class RecentModuleFilter(FilterSet):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Module
|
model = Module
|
||||||
fields = ('recent_modules',)
|
fields = ("recent_modules",)
|
||||||
|
|
||||||
order_by = OrderingFilter(
|
order_by = OrderingFilter(fields=(("recent_modules__visited", "visited"),))
|
||||||
fields=(
|
|
||||||
('recent_modules__visited', 'visited'),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class SchoolClassNode(DjangoObjectType):
|
class SchoolClassNode(DjangoObjectType):
|
||||||
pk = graphene.Int()
|
pk = graphene.Int()
|
||||||
members = graphene.List('users.schema.ClassMemberNode')
|
members = graphene.List("users.schema.ClassMemberNode")
|
||||||
code = graphene.String()
|
code = graphene.String()
|
||||||
read_only = graphene.Boolean()
|
read_only = graphene.Boolean()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SchoolClass
|
model = SchoolClass
|
||||||
only_fields = ['name', 'code', 'members', 'pk', 'read_only']
|
only_fields = ["name", "code", "members", "pk", "read_only"]
|
||||||
filter_fields = ['name']
|
filter_fields = ["name"]
|
||||||
interfaces = (relay.Node,)
|
interfaces = (relay.Node,)
|
||||||
|
|
||||||
def resolve_pk(self, *args, **kwargs):
|
def resolve_pk(self, *args, **kwargs):
|
||||||
|
|
@ -61,11 +58,11 @@ class SchoolClassNode(DjangoObjectType):
|
||||||
class TeamNode(DjangoObjectType):
|
class TeamNode(DjangoObjectType):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Team
|
model = Team
|
||||||
filter_fields = ['name']
|
filter_fields = ["name"]
|
||||||
interfaces = (relay.Node,)
|
interfaces = (relay.Node,)
|
||||||
|
|
||||||
pk = graphene.Int()
|
pk = graphene.Int()
|
||||||
members = graphene.List('users.schema.PublicUserNode')
|
members = graphene.List("users.schema.PublicUserNode")
|
||||||
|
|
||||||
def resolve_pk(self, *args, **kwargs):
|
def resolve_pk(self, *args, **kwargs):
|
||||||
return self.id
|
return self.id
|
||||||
|
|
@ -80,7 +77,7 @@ class PublicUserNode(DjangoObjectType):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
only_fields = ['full_name', 'first_name', 'last_name', 'avatar_url']
|
only_fields = ["full_name", "first_name", "last_name", "avatar_url"]
|
||||||
interfaces = (relay.Node,)
|
interfaces = (relay.Node,)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
@ -91,10 +88,22 @@ class PublicUserNode(DjangoObjectType):
|
||||||
class PrivateUserNode(DjangoObjectType):
|
class PrivateUserNode(DjangoObjectType):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
filter_fields = ['username', 'email']
|
filter_fields = ["username", "email"]
|
||||||
only_fields = ['username', 'email', 'first_name', 'last_name', 'school_classes', 'last_module',
|
only_fields = [
|
||||||
'last_topic', 'avatar_url',
|
"username",
|
||||||
'selected_class', 'expiry_date', 'onboarding_visited', 'team', 'read_only']
|
"email",
|
||||||
|
"first_name",
|
||||||
|
"last_name",
|
||||||
|
"school_classes",
|
||||||
|
"last_module",
|
||||||
|
"last_topic",
|
||||||
|
"avatar_url",
|
||||||
|
"selected_class",
|
||||||
|
"expiry_date",
|
||||||
|
"onboarding_visited",
|
||||||
|
"team",
|
||||||
|
"read_only",
|
||||||
|
]
|
||||||
interfaces = (relay.Node,)
|
interfaces = (relay.Node,)
|
||||||
|
|
||||||
pk = graphene.Int()
|
pk = graphene.Int()
|
||||||
|
|
@ -104,7 +113,9 @@ class PrivateUserNode(DjangoObjectType):
|
||||||
is_teacher = graphene.Boolean()
|
is_teacher = graphene.Boolean()
|
||||||
old_classes = graphene.List(SchoolClassNode)
|
old_classes = graphene.List(SchoolClassNode)
|
||||||
school_classes = graphene.List(SchoolClassNode)
|
school_classes = graphene.List(SchoolClassNode)
|
||||||
recent_modules = DjangoFilterConnectionField(ModuleNode, filterset_class=RecentModuleFilter)
|
recent_modules = DjangoFilterConnectionField(
|
||||||
|
ModuleNode, filterset_class=RecentModuleFilter
|
||||||
|
)
|
||||||
team = graphene.Field(TeamNode)
|
team = graphene.Field(TeamNode)
|
||||||
read_only = graphene.Boolean()
|
read_only = graphene.Boolean()
|
||||||
|
|
||||||
|
|
@ -121,7 +132,7 @@ class PrivateUserNode(DjangoObjectType):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def resolve_expiry_date(root: User, info):
|
def resolve_expiry_date(root: User, info):
|
||||||
if not root.hep_id: # concerns users that already have an (old) account
|
if not root.hep_id: # concerns users that already have an (old) account
|
||||||
return format(datetime(2020, 7, 31), 'U') # just set some expiry date
|
return format(datetime(2020, 7, 31), "U") # just set some expiry date
|
||||||
else:
|
else:
|
||||||
return root.license_expiry_date
|
return root.license_expiry_date
|
||||||
|
|
||||||
|
|
@ -133,10 +144,14 @@ class PrivateUserNode(DjangoObjectType):
|
||||||
if root.selected_class is None: # then we don't have any class to return
|
if root.selected_class is None: # then we don't have any class to return
|
||||||
return SchoolClass.objects.none()
|
return SchoolClass.objects.none()
|
||||||
return SchoolClass.objects.filter(
|
return SchoolClass.objects.filter(
|
||||||
Q(schoolclassmember__active=True, schoolclassmember__user=root) | Q(pk=root.selected_class.pk)).distinct()
|
Q(schoolclassmember__active=True, schoolclassmember__user=root)
|
||||||
|
| Q(pk=root.selected_class.pk)
|
||||||
|
).distinct()
|
||||||
|
|
||||||
def resolve_old_classes(self: User, info):
|
def resolve_old_classes(self: User, info):
|
||||||
return SchoolClass.objects.filter(schoolclassmember__active=False, schoolclassmember__user=self)
|
return SchoolClass.objects.filter(
|
||||||
|
schoolclassmember__active=False, schoolclassmember__user=self
|
||||||
|
)
|
||||||
|
|
||||||
def resolve_recent_modules(self, info, **kwargs):
|
def resolve_recent_modules(self, info, **kwargs):
|
||||||
# see https://docs.graphene-python.org/projects/django/en/latest/filtering/
|
# see https://docs.graphene-python.org/projects/django/en/latest/filtering/
|
||||||
|
|
@ -151,7 +166,8 @@ class ClassMemberNode(ObjectType):
|
||||||
We need to build this ourselves, because we want the active property on the node, because providing it on the
|
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.
|
Connection or Edge for a UserNodeConnection is difficult.
|
||||||
"""
|
"""
|
||||||
user = graphene.Field('users.schema.PublicUserNode')
|
|
||||||
|
user = graphene.Field("users.schema.PublicUserNode")
|
||||||
active = graphene.Boolean()
|
active = graphene.Boolean()
|
||||||
first_name = graphene.String()
|
first_name = graphene.String()
|
||||||
last_name = graphene.String()
|
last_name = graphene.String()
|
||||||
|
|
@ -160,7 +176,7 @@ class ClassMemberNode(ObjectType):
|
||||||
is_me = graphene.Boolean()
|
is_me = graphene.Boolean()
|
||||||
|
|
||||||
def resolve_id(self, *args):
|
def resolve_id(self, *args):
|
||||||
return to_global_id('PublicUserNode', self.user.pk)
|
return to_global_id("PublicUserNode", self.user.pk)
|
||||||
|
|
||||||
def resolve_active(self, *args):
|
def resolve_active(self, *args):
|
||||||
return self.active
|
return self.active
|
||||||
|
|
@ -183,7 +199,8 @@ class ClassMemberNode(ObjectType):
|
||||||
|
|
||||||
|
|
||||||
class DuplicateName(graphene.ObjectType):
|
class DuplicateName(graphene.ObjectType):
|
||||||
reason = graphene.String()
|
class Meta:
|
||||||
|
interfaces = (FailureNode,)
|
||||||
|
|
||||||
|
|
||||||
class CreateTeamResult(graphene.Union):
|
class CreateTeamResult(graphene.Union):
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue