diff --git a/client/src/graphql/gql/mutations/joinClass.gql b/client/src/graphql/gql/mutations/joinClass.gql new file mode 100644 index 00000000..5386a337 --- /dev/null +++ b/client/src/graphql/gql/mutations/joinClass.gql @@ -0,0 +1,5 @@ +mutation JoinClass($input: JoinClassInput!) { + joinClass(input: $input) { + success + } +} diff --git a/client/src/pages/joinClass.vue b/client/src/pages/joinClass.vue index b445fbf1..26456e62 100644 --- a/client/src/pages/joinClass.vue +++ b/client/src/pages/joinClass.vue @@ -1,9 +1,52 @@ + + diff --git a/server/users/admin.py b/server/users/admin.py index 9733310f..db39db05 100644 --- a/server/users/admin.py +++ b/server/users/admin.py @@ -15,7 +15,7 @@ class RoleInline(admin.TabularInline): @admin.register(SchoolClass) class SchoolClassAdmin(admin.ModelAdmin): - list_display = ('id', 'name') + list_display = ('name', 'code', 'is_deleted') @admin.register(Role) diff --git a/server/users/migrations/0010_schoolclass_code.py b/server/users/migrations/0010_schoolclass_code.py new file mode 100644 index 00000000..b1b9557c --- /dev/null +++ b/server/users/migrations/0010_schoolclass_code.py @@ -0,0 +1,18 @@ +# Generated by Django 2.1.15 on 2020-02-11 10:14 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0009_auto_20191009_0905'), + ] + + operations = [ + migrations.AddField( + model_name='schoolclass', + name='code', + field=models.CharField(blank=True, default=None, max_length=10, null=True, unique=True, verbose_name='Code zum Beitreten'), + ), + ] diff --git a/server/users/models.py b/server/users/models.py index 321c9f18..6477a46a 100644 --- a/server/users/models.py +++ b/server/users/models.py @@ -70,9 +70,14 @@ class SchoolClass(models.Model): name = models.CharField(max_length=100, blank=False, null=False, unique=True) is_deleted = models.BooleanField(blank=False, null=False, default=False) users = models.ManyToManyField(get_user_model(), related_name='school_classes', blank=True) + code = models.CharField('Code zum Beitreten', blank=True, null=True, max_length=10, unique=True, default=None) + + class Meta: + verbose_name = 'Schulklasse' + verbose_name_plural = 'Schulklassen' def __str__(self): - return 'SchoolClass {}-{}'.format(self.id, self.name) + return '{}'.format(self.name) @classmethod def generate_default_group_name(cls): @@ -99,6 +104,11 @@ class SchoolClass(models.Model): def get_teacher(self): return self.users.filter(user_roles__role__key='teacher').first() + def save(self, *args, **kwargs): + if self.code == '': # '' can't be unique, so we null it + self.code = None + super().save(*args, **kwargs) + class Role(models.Model): key = models.CharField(_('Key'), max_length=100, blank=False, null=False, unique=True) @@ -165,4 +175,3 @@ class UserRole(models.Model): class UserSetting(models.Model): user = models.OneToOneField(get_user_model(), on_delete=models.CASCADE, related_name='user_setting') selected_class = models.ForeignKey(SchoolClass, blank=True, null=True, on_delete=models.CASCADE) - diff --git a/server/users/mutations.py b/server/users/mutations.py index bbaae8c0..7a5c814b 100644 --- a/server/users/mutations.py +++ b/server/users/mutations.py @@ -9,6 +9,10 @@ from users.models import SchoolClass, UserSetting from users.serializers import PasswordSerialzer, AvatarUrlSerializer +class CodeNotFoundException(Exception): + pass + + class FieldError(graphene.ObjectType): code = graphene.String() @@ -102,8 +106,28 @@ class UpdateSetting(relay.ClientIDMutation): errors = graphene.List(UpdateError) +class JoinClass(relay.ClientIDMutation): + class Input: + code = graphene.String(required=True) + + success = graphene.Boolean() + + @classmethod + def mutate_and_get_payload(cls, root, info, **kwargs): + user = info.context.user + code = kwargs.get('code') + try: + school_class = SchoolClass.objects.get(code__iexact=code) + + school_class.users.add(user) + + return cls(success=True) + except SchoolClass.DoesNotExist: + raise CodeNotFoundException('Code ist nicht gültig') + + class ProfileMutations: update_password = UpdatePassword.Field() update_avatar = UpdateAvatar.Field() update_setting = UpdateSetting.Field() - + join_class = JoinClass.Field()