fix: dedup course dashboard stuff

This commit is contained in:
Livio Bieri 2023-10-25 12:46:58 +02:00
parent 6f973d7e93
commit 04d40e1f57
2 changed files with 106 additions and 43 deletions

View File

@ -1,5 +1,9 @@
from typing import Set, Dict, List, Tuple
import graphene 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.models import Course, CourseSession
from vbv_lernwelt.course_session_group.models import CourseSessionGroup from vbv_lernwelt.course_session_group.models import CourseSessionGroup
from vbv_lernwelt.dashboard.graphql.types.dashboard import ( 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 ( from vbv_lernwelt.iam.permissions import (
can_view_course_session, can_view_course_session,
can_view_course_session_group_statistics, can_view_course_session_group_statistics,
can_view_course_session_progress,
) )
@ -38,48 +41,86 @@ class DashboardQuery(graphene.ObjectType):
return None return None
return CourseStatisticsType( return CourseStatisticsType(
id=course.id, id=course.id, # noqa
course_title=course.title, # noqa course_title=course.title, # noqa
course_session_selection_ids=list(course_session_ids), course_session_selection_ids=list(course_session_ids), # noqa
) # noqa )
def resolve_dashboard_config(root, info): # noqa def resolve_dashboard_config(root, info): # noqa
user = info.context.user 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(): course_session_dashboards = get_user_course_session_dashboards(
if can_view_course_session_group_statistics(user=user, group=group): user=user, exclude_course_ids=statistics_dashboard_course_ids
course = group.course )
course_index.add(course)
dashboards.append(
{
"id": str(course.id),
"name": course.title,
"dashboard_type": DashboardType.STATISTICS_DASHBOARD,
}
)
for course_session in CourseSession.objects.exclude(course__in=course_index): return statistic_dashboards + course_session_dashboards
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 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

View File

@ -18,20 +18,35 @@ class DashboardTestCase(GraphQLTestCase):
# GIVEN # GIVEN
course_1, _ = create_course("Test Course 1") course_1, _ = create_course("Test Course 1")
course_2, _ = create_course("Test Course 2") 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_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") cs_2 = create_course_session(course=course_2, title="Test Course 2 Session")
# Member of course 1 (via cs_1) cs_3_a = create_course_session(course=course_3, title="CS 3 A (as member)")
# Supervisor of course 2 (via cs_2) cs_3_b = create_course_session(course=course_3, title="CS 3 B (as expert)")
supervisor = create_user("supervisor") supervisor = create_user("supervisor")
# CS 1
add_course_session_user( add_course_session_user(
course_session=cs_1, user=supervisor, role=CourseSessionUser.Role.MEMBER course_session=cs_1, user=supervisor, role=CourseSessionUser.Role.MEMBER
) )
group = create_course_session_group(course_session=cs_2) # CS 2
add_course_session_group_supervisor(group=group, user=supervisor) 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) self.client.force_login(supervisor)
@ -58,7 +73,7 @@ class DashboardTestCase(GraphQLTestCase):
) )
self.assertIsNotNone(course_1_config) self.assertIsNotNone(course_1_config)
self.assertEqual(course_1_config["name"], course_1.title) 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( course_2_config = find_dashboard_config_by_course_id(
dashboard_config, course_2.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["name"], course_2.title)
self.assertEqual(course_2_config["dashboard_type"], "STATISTICS_DASHBOARD") 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): def test_course_statistics_deny_not_allowed_user(self):
# GIVEN # GIVEN
disallowed_user = create_user("1337_hacker_schorsch") disallowed_user = create_user("1337_hacker_schorsch")