diff --git a/server/vbv_lernwelt/dashboard/graphql/queries.py b/server/vbv_lernwelt/dashboard/graphql/queries.py index 797c0b4c..6e220f98 100644 --- a/server/vbv_lernwelt/dashboard/graphql/queries.py +++ b/server/vbv_lernwelt/dashboard/graphql/queries.py @@ -1,5 +1,9 @@ +from typing import Set, Dict, List, Tuple + import graphene +from vbv_lernwelt.core.admin import User +from vbv_lernwelt.course.models import CourseSessionUser from vbv_lernwelt.course.models import Course, CourseSession from vbv_lernwelt.course_session_group.models import CourseSessionGroup from vbv_lernwelt.dashboard.graphql.types.dashboard import ( @@ -10,7 +14,6 @@ from vbv_lernwelt.dashboard.graphql.types.dashboard import ( from vbv_lernwelt.iam.permissions import ( can_view_course_session, can_view_course_session_group_statistics, - can_view_course_session_progress, ) @@ -38,48 +41,86 @@ class DashboardQuery(graphene.ObjectType): return None return CourseStatisticsType( - id=course.id, + id=course.id, # noqa course_title=course.title, # noqa - course_session_selection_ids=list(course_session_ids), - ) # noqa + course_session_selection_ids=list(course_session_ids), # noqa + ) def resolve_dashboard_config(root, info): # noqa user = info.context.user - course_index = set() - dashboards = [] + ( + statistic_dashboards, + statistics_dashboard_course_ids, + ) = get_user_statistics_dashboards(user=user) - for group in CourseSessionGroup.objects.all(): - if can_view_course_session_group_statistics(user=user, group=group): - course = group.course - course_index.add(course) - dashboards.append( - { - "id": str(course.id), - "name": course.title, - "dashboard_type": DashboardType.STATISTICS_DASHBOARD, - } - ) + course_session_dashboards = get_user_course_session_dashboards( + user=user, exclude_course_ids=statistics_dashboard_course_ids + ) - for course_session in CourseSession.objects.exclude(course__in=course_index): - course = course_session.course - if can_view_course_session(user=user, course_session=course_session): - dashboards.append( - { - "id": str(course.id), - "name": course.title, - "dashboard_type": DashboardType.SIMPLE_LIST_DASHBOARD, - } - ) - if can_view_course_session_progress( - user=user, course_session=course_session - ): - dashboards.append( - { - "id": str(course.id), - "name": course.title, - "dashboard_type": DashboardType.PROGRESS_DASHBOARD, - } - ) + return statistic_dashboards + course_session_dashboards - return dashboards + +def get_user_statistics_dashboards(user: User) -> Tuple[List[Dict[str, str]], Set[int]]: + course_index = set() + dashboards = [] + + for group in CourseSessionGroup.objects.all(): + if can_view_course_session_group_statistics(user=user, group=group): + course = group.course + course_index.add(course) + dashboards.append( + { + "id": str(course.id), + "name": course.title, + "dashboard_type": DashboardType.STATISTICS_DASHBOARD, + } + ) + + return dashboards, course_index + + +def get_user_course_session_dashboards( + user: User, exclude_course_ids: Set[int] +) -> List[Dict[str, str]]: + """ + Edge case: what do we show to users with access to multiple + sessions of a course, but with varying permissions? + -> We just show the simple list dashboard for now. + """ + + dashboards = [] + + course_sessions = CourseSession.objects.exclude(course__in=exclude_course_ids) + roles_by_course: Dict[Course, Set[DashboardType]] = {} + + for course_session in course_sessions: + if can_view_course_session(user=user, course_session=course_session): + role = CourseSessionUser.objects.get( + course_session=course_session, user=user + ).role + roles_by_course.setdefault(course_session.course, set()) + roles_by_course[course_session.course].add(role) + + for course, roles in roles_by_course.items(): + resolved_dashboard_type = None + + if len(roles) == 1: + course_role = roles.pop() + if course_role == CourseSessionUser.Role.EXPERT: + resolved_dashboard_type = DashboardType.SIMPLE_LIST_DASHBOARD + elif course_role == CourseSessionUser.Role.MEMBER: + resolved_dashboard_type = DashboardType.PROGRESS_DASHBOARD + else: + # fallback: just go with simple list dashboard + resolved_dashboard_type = DashboardType.SIMPLE_LIST_DASHBOARD + + dashboards.append( + { + "id": str(course.id), + "name": course.title, + "dashboard_type": resolved_dashboard_type, + } + ) + + return dashboards diff --git a/server/vbv_lernwelt/dashboard/tests/graphql/test_dashboard.py b/server/vbv_lernwelt/dashboard/tests/graphql/test_dashboard.py index e7b4de92..d6085835 100644 --- a/server/vbv_lernwelt/dashboard/tests/graphql/test_dashboard.py +++ b/server/vbv_lernwelt/dashboard/tests/graphql/test_dashboard.py @@ -18,20 +18,35 @@ class DashboardTestCase(GraphQLTestCase): # GIVEN course_1, _ = create_course("Test Course 1") course_2, _ = create_course("Test Course 2") + course_3, _ = create_course("Test Course 3") cs_1 = create_course_session(course=course_1, title="Test Course 1 Session") cs_2 = create_course_session(course=course_2, title="Test Course 2 Session") - # Member of course 1 (via cs_1) - # Supervisor of course 2 (via cs_2) + cs_3_a = create_course_session(course=course_3, title="CS 3 A (as member)") + cs_3_b = create_course_session(course=course_3, title="CS 3 B (as expert)") + supervisor = create_user("supervisor") + # CS 1 add_course_session_user( course_session=cs_1, user=supervisor, role=CourseSessionUser.Role.MEMBER ) - group = create_course_session_group(course_session=cs_2) - add_course_session_group_supervisor(group=group, user=supervisor) + # CS 2 + add_course_session_group_supervisor( + group=create_course_session_group(course_session=cs_2), user=supervisor + ) + + # CS 3 A + add_course_session_user( + course_session=cs_3_a, user=supervisor, role=CourseSessionUser.Role.MEMBER + ) + + # CS 3 B + add_course_session_user( + course_session=cs_3_b, user=supervisor, role=CourseSessionUser.Role.EXPERT + ) self.client.force_login(supervisor) @@ -58,7 +73,7 @@ class DashboardTestCase(GraphQLTestCase): ) self.assertIsNotNone(course_1_config) self.assertEqual(course_1_config["name"], course_1.title) - self.assertEqual(course_1_config["dashboard_type"], "SIMPLE_LIST_DASHBOARD") + self.assertEqual(course_1_config["dashboard_type"], "PROGRESS_DASHBOARD") course_2_config = find_dashboard_config_by_course_id( dashboard_config, course_2.id @@ -67,6 +82,13 @@ class DashboardTestCase(GraphQLTestCase): self.assertEqual(course_2_config["name"], course_2.title) self.assertEqual(course_2_config["dashboard_type"], "STATISTICS_DASHBOARD") + course_3_config = find_dashboard_config_by_course_id( + dashboard_config, course_3.id + ) + self.assertIsNotNone(course_3_config) + self.assertEqual(course_3_config["name"], course_3.title) + self.assertEqual(course_3_config["dashboard_type"], "SIMPLE_LIST_DASHBOARD") + def test_course_statistics_deny_not_allowed_user(self): # GIVEN disallowed_user = create_user("1337_hacker_schorsch")