From ea9822562a43033e43a1c4a357e689f7c0c5df22 Mon Sep 17 00:00:00 2001 From: Christian Cueni Date: Thu, 18 Jul 2019 13:38:22 +0200 Subject: [PATCH 1/7] Use popover in user widget --- client/src/components/HeaderBar.vue | 4 +- client/src/components/MoreOptionsWidget.vue | 4 +- client/src/components/UserWidget.vue | 53 +++++++++++++++++-- .../components/{rooms => }/WidgetPopover.vue | 2 +- .../components/portfolio/ProjectActions.vue | 10 +++- client/src/components/rooms/RoomActions.vue | 10 +++- client/src/styles/_mixins.scss | 4 ++ client/src/styles/_variables.scss | 3 ++ 8 files changed, 76 insertions(+), 14 deletions(-) rename client/src/components/{rooms => }/WidgetPopover.vue (97%) diff --git a/client/src/components/HeaderBar.vue b/client/src/components/HeaderBar.vue index 7c97788b..45af59c5 100644 --- a/client/src/components/HeaderBar.vue +++ b/client/src/components/HeaderBar.vue @@ -5,9 +5,7 @@
- - - +
diff --git a/client/src/components/MoreOptionsWidget.vue b/client/src/components/MoreOptionsWidget.vue index 863129ba..9fcb68d2 100644 --- a/client/src/components/MoreOptionsWidget.vue +++ b/client/src/components/MoreOptionsWidget.vue @@ -12,7 +12,7 @@ + + diff --git a/client/src/components/HeaderBar.vue b/client/src/components/HeaderBar.vue index 45af59c5..35ae07ac 100644 --- a/client/src/components/HeaderBar.vue +++ b/client/src/components/HeaderBar.vue @@ -5,8 +5,8 @@
+ -
@@ -19,6 +19,7 @@ import UserWidget from '@/components/UserWidget.vue'; import LogoutWidget from '@/components/LogoutWidget.vue'; import Logo from '@/components/icons/Logo'; + import ClassSelectionWidget from '@/components/ClassSelectionWidget'; import ME_QUERY from '@/graphql/gql/meQuery.gql'; @@ -28,7 +29,8 @@ UserWidget, LogoutWidget, BookNavigation, - Logo + Logo, + ClassSelectionWidget }, computed: { From 91967ceb218772467fbe9e50e550cfb483c55a7c Mon Sep 17 00:00:00 2001 From: Christian Cueni Date: Wed, 24 Jul 2019 22:26:51 +0200 Subject: [PATCH 3/7] Add mutations and query, fix popover --- .../src/components/ClassSelectionWidget.vue | 2 +- client/src/components/UserWidget.vue | 6 +- server/rooms/mutations.py | 2 +- server/users/migrations/0007_usersetting.py | 23 +++++ server/users/models.py | 21 ++++- server/users/mutations.py | 25 ++++++ server/users/schema.py | 39 ++++---- server/users/tests/test_usersettings.py | 88 +++++++++++++++++++ 8 files changed, 183 insertions(+), 23 deletions(-) create mode 100644 server/users/migrations/0007_usersetting.py create mode 100644 server/users/tests/test_usersettings.py diff --git a/client/src/components/ClassSelectionWidget.vue b/client/src/components/ClassSelectionWidget.vue index bc590db0..33593744 100644 --- a/client/src/components/ClassSelectionWidget.vue +++ b/client/src/components/ClassSelectionWidget.vue @@ -3,7 +3,7 @@
{{currentClassSelection}}
- + - - - @@ -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')) + + From 780602dfd2077bda54b95b4eded1a0bd163dab64 Mon Sep 17 00:00:00 2001 From: Christian Cueni Date: Thu, 25 Jul 2019 11:39:01 +0200 Subject: [PATCH 6/7] Add option for mobile --- .../src/components/ClassSelectionWidget.vue | 8 ++ client/src/components/FilterBar.vue | 76 ------------------- client/src/components/MobileNavigation.vue | 4 +- client/src/components/UserWidget.vue | 17 ++++- client/src/components/WidgetPopover.vue | 11 ++- client/src/layouts/DefaultLayout.vue | 4 - 6 files changed, 34 insertions(+), 86 deletions(-) delete mode 100644 client/src/components/FilterBar.vue diff --git a/client/src/components/ClassSelectionWidget.vue b/client/src/components/ClassSelectionWidget.vue index b72d33e8..214d345a 100644 --- a/client/src/components/ClassSelectionWidget.vue +++ b/client/src/components/ClassSelectionWidget.vue @@ -5,6 +5,7 @@