fix: expose id on top-level; use name for dashboard config

This commit is contained in:
Livio Bieri 2023-10-25 10:46:58 +02:00
parent d41bdf84e3
commit 49fdbd9648
8 changed files with 89 additions and 66 deletions

View File

@ -2,16 +2,14 @@ import graphene
from vbv_lernwelt.course.models import CourseSession, Course from vbv_lernwelt.course.models import CourseSession, Course
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 CourseStatisticsType, DashboardConfigType from vbv_lernwelt.dashboard.graphql.types.dashboard import CourseStatisticsType, DashboardConfigType, DashboardType
from vbv_lernwelt.iam.permissions import can_view_course_session_group_statistics, can_view_course_session from vbv_lernwelt.iam.permissions import can_view_course_session_group_statistics, can_view_course_session, \
can_view_course_session_progress
class DashboardQuery(graphene.ObjectType): class DashboardQuery(graphene.ObjectType):
course_statistics = graphene.Field(CourseStatisticsType, course_id=graphene.ID(required=True)) course_statistics = graphene.Field(CourseStatisticsType, course_id=graphene.ID(required=True))
dashboard_config = graphene.List(DashboardConfigType, required=False)
dashboard_config = graphene.List(
DashboardConfigType
)
def resolve_course_statistics(root, info, course_id: str): # noqa def resolve_course_statistics(root, info, course_id: str): # noqa
user = info.context.user user = info.context.user
@ -27,7 +25,7 @@ class DashboardQuery(graphene.ObjectType):
return None return None
return CourseStatisticsType(course_id=course.id, course_title=course.title, # noqa return CourseStatisticsType(id=course.id, course_title=course.title, # noqa
course_session_selection_ids=list(course_session_ids)) # noqa course_session_selection_ids=list(course_session_ids)) # noqa
@ -45,19 +43,27 @@ class DashboardQuery(graphene.ObjectType):
dashboards.append( dashboards.append(
{ {
"id": str(course.id), "id": str(course.id),
"title": course.title, "name": course.title,
"dashboard_type": "StatisticsDashboard", "dashboard_type": DashboardType.STATISTICS_DASHBOARD
} }
) )
for course_session in CourseSession.objects.exclude(course__in=course_index): for course_session in CourseSession.objects.exclude(course__in=course_index):
if can_view_course_session(user=user, course_session=course_session):
course = course_session.course course = course_session.course
if can_view_course_session(user=user, course_session=course_session):
dashboards.append( dashboards.append(
{ {
"id": str(course.id), "id": str(course.id),
"title": course.title, "name": course.title,
"dashboard_type": "SimpleDashboard", "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
} }
) )

View File

@ -4,21 +4,21 @@ from vbv_lernwelt.course.models import CourseCompletion, CourseCompletionStatus
class CompletionSummary(graphene.ObjectType): class CompletionSummary(graphene.ObjectType):
success_total = graphene.Int() success_total = graphene.Int(required=True)
fail_total = graphene.Int() fail_total = graphene.Int(required=True)
class CompetencePerformance(graphene.ObjectType): class CompetencePerformance(graphene.ObjectType):
course_session_id = graphene.ID() course_session_id = graphene.ID(required=True)
generation = graphene.String() generation = graphene.String(required=True)
circle_id = graphene.ID() circle_id = graphene.ID(required=True)
success_count = graphene.Int() success_count = graphene.Int(required=True)
fail_count = graphene.Int() fail_count = graphene.Int(required=True)
class Competences(graphene.ObjectType): class Competences(graphene.ObjectType):
performances = graphene.List(CompetencePerformance) performances = graphene.List(CompetencePerformance, required=True)
summary = graphene.Field(CompletionSummary) summary = graphene.Field(CompletionSummary, required=True)
def competences( def competences(

View File

@ -1,4 +1,5 @@
import graphene import graphene
from graphene import Enum
from vbv_lernwelt.course.models import CourseSession, CourseSessionUser from vbv_lernwelt.course.models import CourseSession, CourseSessionUser
from vbv_lernwelt.dashboard.graphql.types.assignment import Assignments, assignments from vbv_lernwelt.dashboard.graphql.types.assignment import Assignments, assignments
@ -15,14 +16,14 @@ from vbv_lernwelt.learnpath.models import Circle
class CourseSessionData(graphene.ObjectType): class CourseSessionData(graphene.ObjectType):
session_id = graphene.ID() session_id = graphene.ID(required=True)
session_title = graphene.String() session_title = graphene.String(required=True)
class CircleData(graphene.ObjectType): class CircleData(graphene.ObjectType):
circle_id = graphene.ID() circle_id = graphene.ID(required=True)
circle_title = graphene.String() circle_title = graphene.String(required=True)
experts = graphene.List(graphene.String) experts = graphene.List(graphene.String, required=True)
class CourseSessionsSelectionMetrics(graphene.ObjectType): class CourseSessionsSelectionMetrics(graphene.ObjectType):
@ -32,27 +33,35 @@ class CourseSessionsSelectionMetrics(graphene.ObjectType):
class CourseSessionProperties(graphene.ObjectType): class CourseSessionProperties(graphene.ObjectType):
sessions = graphene.List(CourseSessionData) sessions = graphene.List(CourseSessionData, required=True)
generations = graphene.List(graphene.String) generations = graphene.List(graphene.String, required=True)
circles = graphene.List(CircleData) circles = graphene.List(CircleData, required=True)
class DashboardType(Enum):
STATISTICS_DASHBOARD = "StatisticsDashboard"
PROGRESS_DASHBOARD = "ProgressDashboard"
SIMPLE_LIST_DASHBOARD = "SimpleListDashboard"
class DashboardConfigType(graphene.ObjectType): class DashboardConfigType(graphene.ObjectType):
id = graphene.ID() id = graphene.ID(required=True)
title = graphene.String() name = graphene.String(required=True)
dashboard_type = graphene.String() dashboard_type = graphene.Field(DashboardType, required=True)
class CourseStatisticsType(graphene.ObjectType): class CourseStatisticsType(graphene.ObjectType):
course_id = graphene.ID() id = graphene.ID(required=True)
course_title = graphene.String() course_title = graphene.String(required=True)
course_session_properties = graphene.Field(CourseSessionProperties) course_session_properties = graphene.Field(CourseSessionProperties, required=True)
course_session_selection_ids = graphene.List(graphene.ID) course_session_selection_ids = graphene.List(graphene.ID, required=True)
course_session_selection_metrics = graphene.Field(CourseSessionsSelectionMetrics) course_session_selection_metrics = graphene.Field(
attendance_day_presences = graphene.Field(AttendanceDayPresences) CourseSessionsSelectionMetrics, required=True
feedback_responses = graphene.Field(FeedbackResponses) )
assignments = graphene.Field(Assignments) attendance_day_presences = graphene.Field(AttendanceDayPresences, required=True)
competences = graphene.Field(Competences) feedback_responses = graphene.Field(FeedbackResponses, required=True)
assignments = graphene.Field(Assignments, required=True)
competences = graphene.Field(Competences, required=True)
def resolve_attendance_day_presences(root, info) -> AttendanceDayPresences: def resolve_attendance_day_presences(root, info) -> AttendanceDayPresences:
return attendance_day_presences(root.course_session_selection_ids) return attendance_day_presences(root.course_session_selection_ids)
@ -71,18 +80,18 @@ class CourseStatisticsType(graphene.ObjectType):
) -> CourseSessionsSelectionMetrics: ) -> CourseSessionsSelectionMetrics:
course_session_count = CourseSession.objects.filter( course_session_count = CourseSession.objects.filter(
id__in=root.course_session_selection_ids, id__in=root.course_session_selection_ids,
course_id=root.course_id, course_id=root.id,
).count() ).count()
expert_count = CourseSession.objects.filter( expert_count = CourseSession.objects.filter(
id__in=root.course_session_selection_ids, id__in=root.course_session_selection_ids,
course_id=root.course_id, course_id=root.id,
coursesessionuser__role=CourseSessionUser.Role.EXPERT, coursesessionuser__role=CourseSessionUser.Role.EXPERT,
).count() ).count()
participant_count = CourseSession.objects.filter( participant_count = CourseSession.objects.filter(
id__in=root.course_session_selection_ids, id__in=root.course_session_selection_ids,
course_id=root.course_id, course_id=root.id,
coursesessionuser__role=CourseSessionUser.Role.MEMBER, coursesessionuser__role=CourseSessionUser.Role.MEMBER,
).count() ).count()
@ -99,7 +108,7 @@ class CourseStatisticsType(graphene.ObjectType):
course_sessions = CourseSession.objects.filter( course_sessions = CourseSession.objects.filter(
id__in=root.course_session_selection_ids, id__in=root.course_session_selection_ids,
course_id=root.course_id, course_id=root.id,
) )
for course_session in course_sessions: for course_session in course_sessions:

View File

@ -8,22 +8,22 @@ from vbv_lernwelt.feedback.utils import feedback_users
class FeedbackSummary(graphene.ObjectType): class FeedbackSummary(graphene.ObjectType):
satisfaction_average = graphene.Float() satisfaction_average = graphene.Float(required=True)
satisfaction_max = graphene.Int() satisfaction_max = graphene.Int(required=True)
total_responses = graphene.Int() total_responses = graphene.Int(required=True)
class FeedbackRecord(graphene.ObjectType): class FeedbackRecord(graphene.ObjectType):
course_session_id = graphene.ID() course_session_id = graphene.ID(required=True)
generation = graphene.String() generation = graphene.String(required=True)
circle_id = graphene.ID() circle_id = graphene.ID(required=True)
satisfaction_average = graphene.Float() satisfaction_average = graphene.Float(required=True)
satisfaction_max = graphene.Int() satisfaction_max = graphene.Int(required=True)
class FeedbackResponses(graphene.ObjectType): class FeedbackResponses(graphene.ObjectType):
records = graphene.List(FeedbackRecord) records = graphene.List(FeedbackRecord, required=True)
summary = graphene.Field(FeedbackSummary) summary = graphene.Field(FeedbackSummary, required=True)
def feedback_responses( def feedback_responses(

View File

@ -64,7 +64,7 @@ class DashboardCompetenceTestCase(GraphQLTestCase):
query = f"""query($course_id: ID!) {{ query = f"""query($course_id: ID!) {{
course_statistics(course_id: $course_id) {{ course_statistics(course_id: $course_id) {{
course_id id
competences {{ competences {{
performances {{ performances {{
course_session_id course_session_id

View File

@ -39,7 +39,7 @@ class DashboardTestCase(GraphQLTestCase):
query = """query { query = """query {
dashboard_config { dashboard_config {
id id
title name
dashboard_type dashboard_type
} }
} }
@ -51,21 +51,21 @@ class DashboardTestCase(GraphQLTestCase):
self.assertResponseNoErrors(response) self.assertResponseNoErrors(response)
dashboard_config = response.json()["data"]["dashboard_config"] dashboard_config = response.json()["data"]["dashboard_config"]
self.assertEqual(len(dashboard_config), 2) self.assertEqual(len(dashboard_config), 3)
course_1_config = find_dashboard_config_by_course_id( course_1_config = find_dashboard_config_by_course_id(
dashboard_config, course_1.id dashboard_config, course_1.id
) )
self.assertIsNotNone(course_1_config) self.assertIsNotNone(course_1_config)
self.assertEqual(course_1_config["title"], course_1.title) self.assertEqual(course_1_config["name"], course_1.title)
self.assertEqual(course_1_config["dashboard_type"], "SimpleDashboard") self.assertEqual(course_1_config["dashboard_type"], "SIMPLE_LIST_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
) )
self.assertIsNotNone(course_2_config) self.assertIsNotNone(course_2_config)
self.assertEqual(course_2_config["title"], course_2.title) self.assertEqual(course_2_config["name"], course_2.title)
self.assertEqual(course_2_config["dashboard_type"], "StatisticsDashboard") self.assertEqual(course_2_config["dashboard_type"], "STATISTICS_DASHBOARD")
def test_course_statistics_deny_not_allowed_user(self): def test_course_statistics_deny_not_allowed_user(self):
# GIVEN # GIVEN
@ -77,7 +77,7 @@ class DashboardTestCase(GraphQLTestCase):
query = f"""query($course_id: ID!) {{ query = f"""query($course_id: ID!) {{
course_statistics(course_id: $course_id) {{ course_statistics(course_id: $course_id) {{
course_id id
}} }}
}} }}
""" """
@ -111,7 +111,7 @@ class DashboardTestCase(GraphQLTestCase):
query = f"""query($course_id: ID!) {{ query = f"""query($course_id: ID!) {{
course_statistics(course_id: $course_id) {{ course_statistics(course_id: $course_id) {{
course_id id
course_title course_title
}} }}
}} }}
@ -126,7 +126,7 @@ class DashboardTestCase(GraphQLTestCase):
course_statistics = response.json()["data"]["course_statistics"] course_statistics = response.json()["data"]["course_statistics"]
self.assertEqual(course_statistics["course_id"], str(course_2.id)) self.assertEqual(course_statistics["id"], str(course_2.id))
self.assertEqual(course_statistics["course_title"], course_2.title) self.assertEqual(course_statistics["course_title"], course_2.title)

View File

@ -71,7 +71,7 @@ class DashboardFeedbackTestCase(GraphQLTestCase):
query = f"""query($course_id: ID!) {{ query = f"""query($course_id: ID!) {{
course_statistics(course_id: $course_id) {{ course_statistics(course_id: $course_id) {{
course_id id
feedback_responses {{ feedback_responses {{
records {{ records {{
course_session_id course_session_id

View File

@ -74,6 +74,14 @@ def can_view_course_session_group_statistics(
return user in group.supervisor.all() return user in group.supervisor.all()
def can_view_course_session_progress(user: User, course_session: CourseSession) -> bool:
return CourseSessionUser.objects.filter(
course_session=course_session,
user=user,
role=CourseSessionUser.Role.MEMBER,
).exists()
def can_view_course_session(user: User, course_session: CourseSession) -> bool: def can_view_course_session(user: User, course_session: CourseSession) -> bool:
if user.is_superuser: if user.is_superuser:
return True return True