diff --git a/client/src/components/ClassSelectionWidget.vue b/client/src/components/ClassSelectionWidget.vue
index 33593744..b72d33e8 100644
--- a/client/src/components/ClassSelectionWidget.vue
+++ b/client/src/components/ClassSelectionWidget.vue
@@ -1,15 +1,16 @@
-
{{currentClassSelection}}
+
+
Klasse: {{currentClassSelection.name}}
-
+
+ @click="updateFilter(schoolClass)">
{{schoolClass.name}}
@@ -17,9 +18,9 @@
diff --git a/client/src/components/MobileNavigation.vue b/client/src/components/MobileNavigation.vue
index 8e229990..8ddb17ac 100644
--- a/client/src/components/MobileNavigation.vue
+++ b/client/src/components/MobileNavigation.vue
@@ -6,10 +6,8 @@
-
-
-
-
+
+
@@ -19,6 +17,7 @@
import UserWidget from '@/components/UserWidget';
import LogoutWidget from '@/components/LogoutWidget';
import TopNavigation from '@/components/TopNavigation';
+ import ClassSelectionWidget from '@/components/ClassSelectionWidget';
import {meQuery} from '@/graphql/queries';
@@ -27,7 +26,8 @@
TopNavigation,
Cross,
UserWidget,
- LogoutWidget
+ LogoutWidget,
+ ClassSelectionWidget
},
methods: {
diff --git a/client/src/components/UserWidget.vue b/client/src/components/UserWidget.vue
index 2eceefa2..ac17bdb5 100644
--- a/client/src/components/UserWidget.vue
+++ b/client/src/components/UserWidget.vue
@@ -3,22 +3,21 @@
-
- {{firstName}} {{lastName}}
-
- Aktivität
+ class="user-widget__popover ">
+ {{firstName}} {{lastName}}
+
+ Aktivität
-
+
Profil
-
+
Klassenliste
- Logout
+
+ Logout
@@ -64,6 +63,7 @@
diff --git a/client/src/graphql/gql/fragments/userParts.gql b/client/src/graphql/gql/fragments/userParts.gql
index 1ea3939c..befaf6f0 100644
--- a/client/src/graphql/gql/fragments/userParts.gql
+++ b/client/src/graphql/gql/fragments/userParts.gql
@@ -11,6 +11,9 @@ fragment UserParts on UserNode {
id
slug
}
+ selectedClass {
+ id
+ }
schoolClasses {
edges {
node {
diff --git a/client/src/graphql/gql/mutations/updateUserSetting.gql b/client/src/graphql/gql/mutations/updateUserSetting.gql
new file mode 100644
index 00000000..0e8190ee
--- /dev/null
+++ b/client/src/graphql/gql/mutations/updateUserSetting.gql
@@ -0,0 +1,8 @@
+mutation UpdateSettings($input: UpdateSettingInput!) {
+ updateSetting(input: $input) {
+ success
+ errors {
+ field
+ }
+ }
+}
diff --git a/client/src/pages/rooms.vue b/client/src/pages/rooms.vue
index 23fecf01..61479564 100644
--- a/client/src/pages/rooms.vue
+++ b/client/src/pages/rooms.vue
@@ -23,7 +23,7 @@
return this.rooms.filter(room => this.visibleFor(room, this.currentFilter));
},
currentFilter() {
- return this.$store.state.filterForSchoolClass;
+ return this.me.selectedClass.id;
},
canAddRoom() {
return this.me.permissions.includes('users.can_manage_school_class_content')
@@ -53,6 +53,9 @@
return {
rooms: [],
me: {
+ selectedClass: {
+ id: ''
+ },
permissions: []
}
}
diff --git a/client/src/store/index.js b/client/src/store/index.js
index 3bbe932a..6b6b41cb 100644
--- a/client/src/store/index.js
+++ b/client/src/store/index.js
@@ -12,7 +12,6 @@ export default new Vuex.Store({
showMobileNavigation: false,
contentBlockPosition: {},
scrollPosition: 0,
- filterForSchoolClass: '',
currentContentBlock: '',
currentRoomEntry: '',
parentRoom: null,
@@ -108,9 +107,6 @@ export default new Vuex.Store({
document.body.classList.add('no-scroll'); // won't get at the body any other way
commit('setModal', payload);
},
- setfilterForSchoolClass({commit}, payload) {
- commit('setfilterForSchoolClass', payload);
- },
addProjectEntry({commit, dispatch}, payload) {
commit('setParentProject', payload);
dispatch('showModal', 'new-project-entry-wizard');
@@ -174,9 +170,6 @@ export default new Vuex.Store({
setCurrentContentBlock(state, payload) {
state.currentContentBlock = payload;
},
- setfilterForSchoolClass(state, payload) {
- state.filterForSchoolClass = payload;
- },
setParentRoom(state, payload) {
state.parentRoom = payload;
},
diff --git a/server/users/admin.py b/server/users/admin.py
index c1f96794..9733310f 100644
--- a/server/users/admin.py
+++ b/server/users/admin.py
@@ -2,7 +2,7 @@ from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from users.forms import CustomUserCreationForm, CustomUserChangeForm
-from .models import User, SchoolClass, Role, UserRole
+from .models import User, SchoolClass, Role, UserRole, UserSetting
class SchoolClassInline(admin.TabularInline):
@@ -53,3 +53,9 @@ class CustomUserAdmin(UserAdmin):
admin.site.register(User, CustomUserAdmin)
+
+
+@admin.register(UserSetting)
+class UserSettingAdmin(admin.ModelAdmin):
+ list_display = ('user', 'selected_class')
+ raw_id_fields = ('user', 'selected_class')
diff --git a/server/users/mutations.py b/server/users/mutations.py
index 29200972..bbaae8c0 100644
--- a/server/users/mutations.py
+++ b/server/users/mutations.py
@@ -5,7 +5,7 @@ from graphene import relay
from api.utils import get_object
from users.inputs import PasswordUpdateInput
-from users.models import SchoolClass
+from users.models import SchoolClass, UserSetting
from users.serializers import PasswordSerialzer, AvatarUrlSerializer
@@ -89,11 +89,13 @@ class UpdateSetting(relay.ClientIDMutation):
class_id = kwargs.get('id')
school_class = get_object(SchoolClass, class_id)
user = info.context.user
- if 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')
- user.user_setting.selected_class = school_class
- user.user_setting.save()
+ user_settings, created = UserSetting.objects.get_or_create(user=user)
+ user_settings.selected_class = school_class
+ user_settings.save()
return cls(success=True)
success = graphene.Boolean()
diff --git a/server/users/tests/test_usersettings.py b/server/users/tests/test_usersettings.py
index 963273be..147bd223 100644
--- a/server/users/tests/test_usersettings.py
+++ b/server/users/tests/test_usersettings.py
@@ -94,3 +94,25 @@ class UserSettingTests(TestCase):
self.assertIsNone(query_result.get('errors'))
self.assertEqual(query_result.get('data').get('me').get('selectedClass').get('name'),
selected_class.name)
+
+ def test_user_can_select_class_even_no_settings_exist(self):
+
+ selected_class = self.user.school_classes.all()[1]
+ mutation_result = self.make_mutation(selected_class.pk)
+ self.assertIsNone(mutation_result.get('errors'))
+ query_result = self.make_query()
+ self.assertIsNone(query_result.get('errors'))
+ self.assertEqual(query_result.get('data').get('me').get('selectedClass').get('name'),
+ selected_class.name)
+
+
+ def test_user_cannot_select_class_shes_not_part_of(self):
+
+ default_class = self.user.school_classes.first()
+ setting = UserSetting.objects.create(user=self.user, selected_class=default_class)
+ setting.save()
+
+ mutation_result = self.make_mutation(self.class3.pk)
+ self.assertIsNotNone(mutation_result.get('errors'))
+
+