wip: session group statistics w/ permission
This commit is contained in:
parent
c7920430ca
commit
ca44a913c9
|
|
@ -10,7 +10,7 @@ from vbv_lernwelt.assignment.models import Assignment, AssignmentCompletionStatu
|
||||||
from vbv_lernwelt.assignment.services import update_assignment_completion
|
from vbv_lernwelt.assignment.services import update_assignment_completion
|
||||||
from vbv_lernwelt.core.models import User
|
from vbv_lernwelt.core.models import User
|
||||||
from vbv_lernwelt.course.models import CourseSession, CourseSessionUser
|
from vbv_lernwelt.course.models import CourseSession, CourseSessionUser
|
||||||
from vbv_lernwelt.course.permissions import has_course_access, is_course_session_expert
|
from vbv_lernwelt.iam.permissions import has_course_access, is_course_session_expert
|
||||||
|
|
||||||
logger = structlog.get_logger(__name__)
|
logger = structlog.get_logger(__name__)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ from vbv_lernwelt.assignment.models import Assignment, AssignmentCompletion
|
||||||
from vbv_lernwelt.core.graphql.types import JSONStreamField
|
from vbv_lernwelt.core.graphql.types import JSONStreamField
|
||||||
from vbv_lernwelt.course.graphql.interfaces import CoursePageInterface
|
from vbv_lernwelt.course.graphql.interfaces import CoursePageInterface
|
||||||
from vbv_lernwelt.course.models import CourseSession
|
from vbv_lernwelt.course.models import CourseSession
|
||||||
from vbv_lernwelt.course.permissions import has_course_access, is_course_session_expert
|
from vbv_lernwelt.iam.permissions import has_course_access, is_course_session_expert
|
||||||
from vbv_lernwelt.learnpath.graphql.types import LearningContentInterface
|
from vbv_lernwelt.learnpath.graphql.types import LearningContentInterface
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ from rest_framework.exceptions import PermissionDenied
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
||||||
from vbv_lernwelt.assignment.models import AssignmentCompletion
|
from vbv_lernwelt.assignment.models import AssignmentCompletion
|
||||||
from vbv_lernwelt.course.permissions import is_course_session_expert
|
from vbv_lernwelt.iam.permissions import is_course_session_expert
|
||||||
|
|
||||||
logger = structlog.get_logger(__name__)
|
logger = structlog.get_logger(__name__)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ from graphql import GraphQLError
|
||||||
|
|
||||||
from vbv_lernwelt.course.graphql.types import CourseObjectType, CourseSessionObjectType
|
from vbv_lernwelt.course.graphql.types import CourseObjectType, CourseSessionObjectType
|
||||||
from vbv_lernwelt.course.models import Course, CourseSession
|
from vbv_lernwelt.course.models import Course, CourseSession
|
||||||
from vbv_lernwelt.course.permissions import has_course_access
|
from vbv_lernwelt.iam.permissions import has_course_access
|
||||||
from vbv_lernwelt.learnpath.graphql.types import (
|
from vbv_lernwelt.learnpath.graphql.types import (
|
||||||
LearningContentAssignmentObjectType,
|
LearningContentAssignmentObjectType,
|
||||||
LearningContentAttendanceCourseObjectType,
|
LearningContentAttendanceCourseObjectType,
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ from vbv_lernwelt.course.models import (
|
||||||
CourseSession,
|
CourseSession,
|
||||||
CourseSessionUser,
|
CourseSessionUser,
|
||||||
)
|
)
|
||||||
from vbv_lernwelt.course.permissions import has_course_access
|
|
||||||
from vbv_lernwelt.course_session.graphql.types import (
|
from vbv_lernwelt.course_session.graphql.types import (
|
||||||
CourseSessionAssignmentObjectType,
|
CourseSessionAssignmentObjectType,
|
||||||
CourseSessionAttendanceCourseObjectType,
|
CourseSessionAttendanceCourseObjectType,
|
||||||
|
|
@ -27,6 +26,7 @@ from vbv_lernwelt.course_session.models import (
|
||||||
CourseSessionAttendanceCourse,
|
CourseSessionAttendanceCourse,
|
||||||
CourseSessionEdoniqTest,
|
CourseSessionEdoniqTest,
|
||||||
)
|
)
|
||||||
|
from vbv_lernwelt.iam.permissions import has_course_access
|
||||||
from vbv_lernwelt.learnpath.graphql.types import LearningPathObjectType
|
from vbv_lernwelt.learnpath.graphql.types import LearningPathObjectType
|
||||||
|
|
||||||
logger = structlog.get_logger(__name__)
|
logger = structlog.get_logger(__name__)
|
||||||
|
|
|
||||||
|
|
@ -10,14 +10,6 @@ from vbv_lernwelt.course.models import (
|
||||||
CircleDocument,
|
CircleDocument,
|
||||||
CourseCompletion,
|
CourseCompletion,
|
||||||
CourseSession,
|
CourseSession,
|
||||||
CourseSessionUser,
|
|
||||||
)
|
|
||||||
from vbv_lernwelt.course.permissions import (
|
|
||||||
course_sessions_for_user_qs,
|
|
||||||
has_course_access,
|
|
||||||
has_course_access_by_page_request,
|
|
||||||
is_circle_expert,
|
|
||||||
is_course_session_expert,
|
|
||||||
)
|
)
|
||||||
from vbv_lernwelt.course.serializers import (
|
from vbv_lernwelt.course.serializers import (
|
||||||
CourseCompletionSerializer,
|
CourseCompletionSerializer,
|
||||||
|
|
@ -28,6 +20,13 @@ from vbv_lernwelt.course.serializers import (
|
||||||
from vbv_lernwelt.course.services import mark_course_completion
|
from vbv_lernwelt.course.services import mark_course_completion
|
||||||
from vbv_lernwelt.files.models import UploadFile
|
from vbv_lernwelt.files.models import UploadFile
|
||||||
from vbv_lernwelt.files.services import FileDirectUploadService
|
from vbv_lernwelt.files.services import FileDirectUploadService
|
||||||
|
from vbv_lernwelt.iam.permissions import (
|
||||||
|
has_course_access_by_page_request,
|
||||||
|
has_course_access,
|
||||||
|
is_course_session_expert,
|
||||||
|
course_sessions_for_user_qs,
|
||||||
|
is_circle_expert,
|
||||||
|
)
|
||||||
|
|
||||||
logger = structlog.get_logger(__name__)
|
logger = structlog.get_logger(__name__)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import graphene
|
||||||
import structlog
|
import structlog
|
||||||
from rest_framework.exceptions import PermissionDenied
|
from rest_framework.exceptions import PermissionDenied
|
||||||
|
|
||||||
from vbv_lernwelt.course.permissions import has_course_access
|
|
||||||
from vbv_lernwelt.course_session.graphql.types import (
|
from vbv_lernwelt.course_session.graphql.types import (
|
||||||
CourseSessionAttendanceCourseObjectType,
|
CourseSessionAttendanceCourseObjectType,
|
||||||
)
|
)
|
||||||
|
|
@ -11,6 +10,7 @@ from vbv_lernwelt.course_session.services.attendance import (
|
||||||
AttendanceUserStatus,
|
AttendanceUserStatus,
|
||||||
update_attendance_list,
|
update_attendance_list,
|
||||||
)
|
)
|
||||||
|
from vbv_lernwelt.iam.permissions import has_course_access
|
||||||
|
|
||||||
logger = structlog.get_logger(__name__)
|
logger = structlog.get_logger(__name__)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,11 @@ import graphene
|
||||||
from rest_framework.exceptions import PermissionDenied
|
from rest_framework.exceptions import PermissionDenied
|
||||||
|
|
||||||
from vbv_lernwelt.course.models import CourseSession
|
from vbv_lernwelt.course.models import CourseSession
|
||||||
from vbv_lernwelt.course.permissions import has_course_access, is_course_session_expert
|
|
||||||
from vbv_lernwelt.course_session.graphql.types import (
|
from vbv_lernwelt.course_session.graphql.types import (
|
||||||
CourseSessionAttendanceCourseObjectType,
|
CourseSessionAttendanceCourseObjectType,
|
||||||
)
|
)
|
||||||
from vbv_lernwelt.course_session.models import CourseSessionAttendanceCourse
|
from vbv_lernwelt.course_session.models import CourseSessionAttendanceCourse
|
||||||
|
from vbv_lernwelt.iam.permissions import has_course_access, is_course_session_expert
|
||||||
|
|
||||||
|
|
||||||
class CourseSessionQuery(object):
|
class CourseSessionQuery(object):
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import graphene
|
import graphene
|
||||||
from graphene_django import DjangoObjectType
|
from graphene_django import DjangoObjectType
|
||||||
|
|
||||||
from vbv_lernwelt.course.permissions import is_course_session_expert
|
|
||||||
from vbv_lernwelt.course_session.models import (
|
from vbv_lernwelt.course_session.models import (
|
||||||
CourseSessionAssignment,
|
CourseSessionAssignment,
|
||||||
CourseSessionAttendanceCourse,
|
CourseSessionAttendanceCourse,
|
||||||
|
|
@ -9,6 +8,7 @@ from vbv_lernwelt.course_session.models import (
|
||||||
)
|
)
|
||||||
from vbv_lernwelt.course_session.services.attendance import AttendanceUserStatus
|
from vbv_lernwelt.course_session.services.attendance import AttendanceUserStatus
|
||||||
from vbv_lernwelt.duedate.graphql.types import DueDateObjectType
|
from vbv_lernwelt.duedate.graphql.types import DueDateObjectType
|
||||||
|
from vbv_lernwelt.iam.permissions import is_course_session_expert
|
||||||
from vbv_lernwelt.learnpath.graphql.types import (
|
from vbv_lernwelt.learnpath.graphql.types import (
|
||||||
LearningContentAssignmentObjectType,
|
LearningContentAssignmentObjectType,
|
||||||
LearningContentAttendanceCourseObjectType,
|
LearningContentAttendanceCourseObjectType,
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ from rest_framework.exceptions import PermissionDenied
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
||||||
from vbv_lernwelt.course.models import CircleDocument
|
from vbv_lernwelt.course.models import CircleDocument
|
||||||
from vbv_lernwelt.course.permissions import has_course_session_access
|
|
||||||
from vbv_lernwelt.course.serializers import CircleDocumentSerializer
|
from vbv_lernwelt.course.serializers import CircleDocumentSerializer
|
||||||
|
from vbv_lernwelt.iam.permissions import has_course_session_access
|
||||||
|
|
||||||
|
|
||||||
@api_view(["GET"])
|
@api_view(["GET"])
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,64 @@
|
||||||
import graphene
|
import graphene
|
||||||
|
|
||||||
from vbv_lernwelt.course.models import Course
|
from vbv_lernwelt.course.models import CourseSession, Course
|
||||||
from vbv_lernwelt.dashboard.graphql.types.dashboard import CourseStatisticsType
|
from vbv_lernwelt.course_session_group.models import CourseSessionGroup
|
||||||
|
from vbv_lernwelt.dashboard.graphql.types.dashboard import CourseStatisticsType, DashboardConfigType
|
||||||
|
from vbv_lernwelt.iam.permissions import can_view_course_session_group_statistics, can_view_course_session
|
||||||
|
|
||||||
|
|
||||||
class DashboardQuery(graphene.ObjectType):
|
class DashboardQuery(graphene.ObjectType):
|
||||||
course_statistics = graphene.List(
|
course_statistics = graphene.Field(CourseStatisticsType, course_id=graphene.ID(required=True))
|
||||||
CourseStatisticsType, course_id=graphene.ID(required=True)
|
|
||||||
|
dashboard_config = graphene.List(
|
||||||
|
DashboardConfigType
|
||||||
)
|
)
|
||||||
|
|
||||||
def resolve_course_statistics(root, info, course_id: str):
|
def resolve_course_statistics(root, info, course_id: str): # noqa
|
||||||
query = Course.objects.filter(
|
user = info.context.user
|
||||||
id=course_id
|
course = Course.objects.get(id=course_id)
|
||||||
|
|
||||||
|
course_session_ids = set()
|
||||||
|
|
||||||
|
for group in CourseSessionGroup.objects.filter(course=course):
|
||||||
|
if can_view_course_session_group_statistics(user=user, group=group):
|
||||||
|
course_session_ids.update(group.course_session.all().values_list("id", flat=True))
|
||||||
|
|
||||||
|
if not course_session_ids:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
return CourseStatisticsType(course_id=course.id, course_title=course.title, # 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 = []
|
||||||
|
|
||||||
|
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),
|
||||||
|
"title": course.title,
|
||||||
|
"dashboard_type": "StatisticsDashboard",
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
courses = query.distinct()
|
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
|
||||||
|
dashboards.append(
|
||||||
|
{
|
||||||
|
"id": str(course.id),
|
||||||
|
"title": course.title,
|
||||||
|
"dashboard_type": "SimpleDashboard",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
return [
|
return dashboards
|
||||||
CourseStatisticsType(course_id=course.id, course_title=course.title) # noqa
|
|
||||||
for course in courses
|
|
||||||
]
|
|
||||||
|
|
|
||||||
|
|
@ -124,9 +124,11 @@ def create_record(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def assignments(course_id) -> Assignments:
|
def assignments(
|
||||||
|
course_session_selection_ids: graphene.List(graphene.ID),
|
||||||
|
) -> Assignments:
|
||||||
course_sessions = CourseSession.objects.filter(
|
course_sessions = CourseSession.objects.filter(
|
||||||
course_id=course_id,
|
id_in=course_session_selection_ids,
|
||||||
)
|
)
|
||||||
|
|
||||||
records: List[AssignmentRecord] = []
|
records: List[AssignmentRecord] = []
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,11 @@ class AttendanceDayPresences(graphene.ObjectType):
|
||||||
summary = graphene.Field(AttendanceSummary)
|
summary = graphene.Field(AttendanceSummary)
|
||||||
|
|
||||||
|
|
||||||
def attendance_day_presences(course_id: graphene.String()) -> AttendanceDayPresences:
|
def attendance_day_presences(
|
||||||
|
course_session_selection_ids: graphene.List(graphene.ID),
|
||||||
|
) -> AttendanceDayPresences:
|
||||||
completed = CourseSessionAttendanceCourse.objects.filter(
|
completed = CourseSessionAttendanceCourse.objects.filter(
|
||||||
course_session__course_id=course_id,
|
course_session_id__in=course_session_selection_ids,
|
||||||
due_date__end__lt=timezone.now(),
|
due_date__end__lt=timezone.now(),
|
||||||
).order_by("-due_date__end")
|
).order_by("-due_date__end")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,11 @@ class Competences(graphene.ObjectType):
|
||||||
summary = graphene.Field(CompletionSummary)
|
summary = graphene.Field(CompletionSummary)
|
||||||
|
|
||||||
|
|
||||||
def competences(course_id: graphene.String()) -> Competences:
|
def competences(
|
||||||
|
course_session_selection_ids: graphene.List(graphene.ID),
|
||||||
|
) -> Competences:
|
||||||
completions = CourseCompletion.objects.filter(
|
completions = CourseCompletion.objects.filter(
|
||||||
course_session__course_id=course_id,
|
course_session_id__in=course_session_selection_ids,
|
||||||
page_type="competence.PerformanceCriteria",
|
page_type="competence.PerformanceCriteria",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,9 +31,16 @@ class CourseSessionProperties(graphene.ObjectType):
|
||||||
circles = graphene.List(CircleData)
|
circles = graphene.List(CircleData)
|
||||||
|
|
||||||
|
|
||||||
|
class DashboardConfigType(graphene.ObjectType):
|
||||||
|
id = graphene.ID()
|
||||||
|
title = graphene.String()
|
||||||
|
dashboard_type = graphene.String()
|
||||||
|
|
||||||
|
|
||||||
class CourseStatisticsType(graphene.ObjectType):
|
class CourseStatisticsType(graphene.ObjectType):
|
||||||
course_id = graphene.String()
|
course_id = graphene.ID()
|
||||||
course_title = graphene.String()
|
course_title = graphene.String()
|
||||||
|
course_session_selection_ids = graphene.List(graphene.ID)
|
||||||
course_session_properties = graphene.Field(CourseSessionProperties)
|
course_session_properties = graphene.Field(CourseSessionProperties)
|
||||||
attendance_day_presences = graphene.Field(AttendanceDayPresences)
|
attendance_day_presences = graphene.Field(AttendanceDayPresences)
|
||||||
feedback_responses = graphene.Field(FeedbackResponses)
|
feedback_responses = graphene.Field(FeedbackResponses)
|
||||||
|
|
@ -41,16 +48,16 @@ class CourseStatisticsType(graphene.ObjectType):
|
||||||
competences = graphene.Field(Competences)
|
competences = graphene.Field(Competences)
|
||||||
|
|
||||||
def resolve_attendance_day_presences(root, info) -> AttendanceDayPresences:
|
def resolve_attendance_day_presences(root, info) -> AttendanceDayPresences:
|
||||||
return attendance_day_presences(root.course_id)
|
return attendance_day_presences(root.course_session_selection_ids)
|
||||||
|
|
||||||
def resolve_feedback_responses(root, info) -> FeedbackResponses:
|
def resolve_feedback_responses(root, info) -> FeedbackResponses:
|
||||||
return feedback_responses(root.course_id)
|
return feedback_responses(root.course_session_selection_ids)
|
||||||
|
|
||||||
def resolve_competences(root, info) -> Competences:
|
def resolve_competences(root, info) -> Competences:
|
||||||
return competences(root.course_id)
|
return competences(root.course_session_selection_ids)
|
||||||
|
|
||||||
def resolve_assignments(root, info) -> Assignments:
|
def resolve_assignments(root, info) -> Assignments:
|
||||||
return assignments(root.course_id)
|
return assignments(root.course_session_selection_ids)
|
||||||
|
|
||||||
def resolve_course_session_properties(root, info):
|
def resolve_course_session_properties(root, info):
|
||||||
course_session_data = []
|
course_session_data = []
|
||||||
|
|
|
||||||
|
|
@ -26,10 +26,12 @@ class FeedbackResponses(graphene.ObjectType):
|
||||||
summary = graphene.Field(FeedbackSummary)
|
summary = graphene.Field(FeedbackSummary)
|
||||||
|
|
||||||
|
|
||||||
def feedback_responses(course_id: graphene.String()) -> FeedbackResponses:
|
def feedback_responses(
|
||||||
|
course_session_selection_ids: graphene.List(graphene.ID),
|
||||||
|
) -> FeedbackResponses:
|
||||||
# Get all course sessions for this user in the given course
|
# Get all course sessions for this user in the given course
|
||||||
course_sessions = CourseSession.objects.filter(
|
course_sessions = CourseSession.objects.filter(
|
||||||
course_id=course_id,
|
id_in=course_session_selection_ids,
|
||||||
)
|
)
|
||||||
|
|
||||||
circle_feedbacks = []
|
circle_feedbacks = []
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,70 @@
|
||||||
from graphene_django.utils import GraphQLTestCase
|
from graphene_django.utils import GraphQLTestCase
|
||||||
|
|
||||||
|
from vbv_lernwelt.course.models import CourseSessionUser
|
||||||
from vbv_lernwelt.dashboard.tests.graphql.utils import (
|
from vbv_lernwelt.dashboard.tests.graphql.utils import (
|
||||||
create_course,
|
create_course,
|
||||||
create_course_session,
|
create_course_session,
|
||||||
create_user,
|
create_user,
|
||||||
|
add_course_session_user,
|
||||||
|
create_course_session_group,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class DashboardTestCase(GraphQLTestCase):
|
class DashboardTestCase(GraphQLTestCase):
|
||||||
GRAPHQL_URL = "/server/graphql/"
|
GRAPHQL_URL = "/server/graphql/"
|
||||||
|
|
||||||
|
def test_dashboard_config(self):
|
||||||
|
# GIVEN
|
||||||
|
course_1, _ = create_course("Test Course 1")
|
||||||
|
course_2, _ = create_course("Test Course 2")
|
||||||
|
|
||||||
|
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)
|
||||||
|
supervisor = create_user("supervisor")
|
||||||
|
|
||||||
|
add_course_session_user(
|
||||||
|
course_session=cs_1, user=supervisor, role=CourseSessionUser.Role.MEMBER
|
||||||
|
)
|
||||||
|
|
||||||
|
create_course_session_group(course_session=cs_2, user=supervisor)
|
||||||
|
|
||||||
|
self.client.force_login(supervisor)
|
||||||
|
|
||||||
|
# WHEN
|
||||||
|
query = """query {
|
||||||
|
dashboard_config {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
dashboard_type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
response = self.query(query)
|
||||||
|
|
||||||
|
# THEN
|
||||||
|
self.assertResponseNoErrors(response)
|
||||||
|
|
||||||
|
dashboard_config = response.json()["data"]["dashboard_config"]
|
||||||
|
self.assertEqual(len(dashboard_config), 2)
|
||||||
|
|
||||||
|
course_1_config = find_dashboard_config_by_course_id(
|
||||||
|
dashboard_config, course_1.id
|
||||||
|
)
|
||||||
|
self.assertIsNotNone(course_1_config)
|
||||||
|
self.assertEqual(course_1_config["title"], course_1.title)
|
||||||
|
self.assertEqual(course_1_config["dashboard_type"], "SimpleDashboard")
|
||||||
|
|
||||||
|
course_2_config = find_dashboard_config_by_course_id(
|
||||||
|
dashboard_config, course_2.id
|
||||||
|
)
|
||||||
|
self.assertIsNotNone(course_2_config)
|
||||||
|
self.assertEqual(course_2_config["title"], course_2.title)
|
||||||
|
self.assertEqual(course_2_config["dashboard_type"], "StatisticsDashboard")
|
||||||
|
|
||||||
def test_course_statistics_id(self):
|
def test_course_statistics_id(self):
|
||||||
# GIVEN
|
# GIVEN
|
||||||
|
|
||||||
|
|
@ -41,3 +96,9 @@ class DashboardTestCase(GraphQLTestCase):
|
||||||
|
|
||||||
self.assertEqual(len(course_statistics), 1)
|
self.assertEqual(len(course_statistics), 1)
|
||||||
self.assertEqual(course_statistics[0]["course_id"], str(course_2.id))
|
self.assertEqual(course_statistics[0]["course_id"], str(course_2.id))
|
||||||
|
|
||||||
|
|
||||||
|
def find_dashboard_config_by_course_id(dashboard_configs, course_id):
|
||||||
|
return next(
|
||||||
|
(config for config in dashboard_configs if config["id"] == str(course_id)), None
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ from vbv_lernwelt.course_session.models import (
|
||||||
CourseSessionAttendanceCourse,
|
CourseSessionAttendanceCourse,
|
||||||
CourseSessionEdoniqTest,
|
CourseSessionEdoniqTest,
|
||||||
)
|
)
|
||||||
|
from vbv_lernwelt.course_session_group.models import CourseSessionGroup
|
||||||
from vbv_lernwelt.duedate.models import DueDate
|
from vbv_lernwelt.duedate.models import DueDate
|
||||||
from vbv_lernwelt.learnpath.models import (
|
from vbv_lernwelt.learnpath.models import (
|
||||||
Circle,
|
Circle,
|
||||||
|
|
@ -99,6 +100,19 @@ def add_course_session_user(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def create_course_session_group(
|
||||||
|
course_session: CourseSession, user: User
|
||||||
|
) -> CourseSessionGroup:
|
||||||
|
g = CourseSessionGroup.objects.create(
|
||||||
|
course=course_session.course,
|
||||||
|
)
|
||||||
|
|
||||||
|
g.course_session.add(course_session)
|
||||||
|
g.supervisor.add(user)
|
||||||
|
|
||||||
|
return g
|
||||||
|
|
||||||
|
|
||||||
def create_circle(
|
def create_circle(
|
||||||
title: str, course_page: CoursePage, learning_path: LearningPath | None = None
|
title: str, course_page: CoursePage, learning_path: LearningPath | None = None
|
||||||
) -> Tuple[Circle, LearningPath]:
|
) -> Tuple[Circle, LearningPath]:
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@ from rest_framework.decorators import api_view
|
||||||
from vbv_lernwelt.core.models import User
|
from vbv_lernwelt.core.models import User
|
||||||
from vbv_lernwelt.course.consts import COURSE_UK, COURSE_UK_FR, COURSE_UK_IT
|
from vbv_lernwelt.course.consts import COURSE_UK, COURSE_UK_FR, COURSE_UK_IT
|
||||||
from vbv_lernwelt.course.models import CourseSessionUser
|
from vbv_lernwelt.course.models import CourseSessionUser
|
||||||
from vbv_lernwelt.course.permissions import has_course_access_by_page_request
|
|
||||||
from vbv_lernwelt.edoniq_test.edoniq_sso import create_token
|
from vbv_lernwelt.edoniq_test.edoniq_sso import create_token
|
||||||
|
from vbv_lernwelt.iam.permissions import has_course_access_by_page_request
|
||||||
from vbv_lernwelt.learnpath.models import LearningContentEdoniqTest
|
from vbv_lernwelt.learnpath.models import LearningContentEdoniqTest
|
||||||
|
|
||||||
logger = structlog.get_logger(__name__)
|
logger = structlog.get_logger(__name__)
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,12 @@ from graphene.types.generic import GenericScalar
|
||||||
from graphene_django.types import ErrorType
|
from graphene_django.types import ErrorType
|
||||||
|
|
||||||
from vbv_lernwelt.course.models import CourseSession
|
from vbv_lernwelt.course.models import CourseSession
|
||||||
from vbv_lernwelt.course.permissions import has_course_session_access
|
|
||||||
from vbv_lernwelt.feedback.graphql.types import (
|
from vbv_lernwelt.feedback.graphql.types import (
|
||||||
FeedbackResponseObjectType as FeedbackResponseType,
|
FeedbackResponseObjectType as FeedbackResponseType,
|
||||||
)
|
)
|
||||||
from vbv_lernwelt.feedback.serializers import CourseFeedbackSerializer
|
from vbv_lernwelt.feedback.serializers import CourseFeedbackSerializer
|
||||||
from vbv_lernwelt.feedback.services import update_feedback_response
|
from vbv_lernwelt.feedback.services import update_feedback_response
|
||||||
|
from vbv_lernwelt.iam.permissions import has_course_session_access
|
||||||
from vbv_lernwelt.learnpath.models import LearningContentFeedback
|
from vbv_lernwelt.learnpath.models import LearningContentFeedback
|
||||||
|
|
||||||
logger = structlog.get_logger(__name__)
|
logger = structlog.get_logger(__name__)
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@ from rest_framework.decorators import api_view
|
||||||
from rest_framework.exceptions import PermissionDenied
|
from rest_framework.exceptions import PermissionDenied
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
||||||
from vbv_lernwelt.course.permissions import is_course_session_expert
|
|
||||||
from vbv_lernwelt.feedback.models import FeedbackResponse
|
from vbv_lernwelt.feedback.models import FeedbackResponse
|
||||||
from vbv_lernwelt.feedback.utils import feedback_users
|
from vbv_lernwelt.feedback.utils import feedback_users
|
||||||
|
from vbv_lernwelt.iam.permissions import is_course_session_expert
|
||||||
|
|
||||||
logger = structlog.get_logger(__name__)
|
logger = structlog.get_logger(__name__)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
|
from vbv_lernwelt.core.models import User
|
||||||
from vbv_lernwelt.course.models import CourseSession, CourseSessionUser
|
from vbv_lernwelt.course.models import CourseSession, CourseSessionUser
|
||||||
|
from vbv_lernwelt.course_session_group.models import CourseSessionGroup
|
||||||
from vbv_lernwelt.learnpath.models import LearningSequence
|
from vbv_lernwelt.learnpath.models import LearningSequence
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -10,38 +12,29 @@ def has_course_access(user, course_id):
|
||||||
if user.is_superuser:
|
if user.is_superuser:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if CourseSessionUser.objects.filter(
|
return CourseSessionUser.objects.filter(
|
||||||
course_session__course_id=course_id, user=user
|
course_session__course_id=course_id, user=user
|
||||||
).exists():
|
).exists()
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def has_course_session_access(user, course_session_id: int):
|
def has_course_session_access(user, course_session_id: int):
|
||||||
if user.is_superuser:
|
if user.is_superuser:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if CourseSessionUser.objects.filter(
|
return CourseSessionUser.objects.filter(
|
||||||
course_session_id=course_session_id, user=user
|
course_session_id=course_session_id, user=user
|
||||||
).exists():
|
).exists()
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def is_course_session_expert(user, course_session_id: int):
|
def is_course_session_expert(user, course_session_id: int):
|
||||||
if user.is_superuser:
|
if user.is_superuser:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if CourseSessionUser.objects.filter(
|
return CourseSessionUser.objects.filter(
|
||||||
course_session_id=course_session_id,
|
course_session_id=course_session_id,
|
||||||
user=user,
|
user=user,
|
||||||
role=CourseSessionUser.Role.EXPERT,
|
role=CourseSessionUser.Role.EXPERT,
|
||||||
).exists():
|
).exists()
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def course_sessions_for_user_qs(user):
|
def course_sessions_for_user_qs(user):
|
||||||
|
|
@ -64,12 +57,33 @@ def is_circle_expert(user, course_session_id: int, learning_sequence_id: int) ->
|
||||||
|
|
||||||
circle_id = learning_sequence.get_parent().circle.id
|
circle_id = learning_sequence.get_parent().circle.id
|
||||||
|
|
||||||
if CourseSessionUser.objects.filter(
|
return CourseSessionUser.objects.filter(
|
||||||
course_session_id=course_session_id,
|
course_session_id=course_session_id,
|
||||||
user=user,
|
user=user,
|
||||||
role=CourseSessionUser.Role.EXPERT,
|
role=CourseSessionUser.Role.EXPERT,
|
||||||
expert__id=circle_id,
|
expert__id=circle_id,
|
||||||
|
).exists()
|
||||||
|
|
||||||
|
|
||||||
|
def can_view_course_session_group_statistics(
|
||||||
|
user: User, group: CourseSessionGroup
|
||||||
|
) -> bool:
|
||||||
|
if user.is_superuser:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return user in group.supervisor.all()
|
||||||
|
|
||||||
|
|
||||||
|
def can_view_course_session(user: User, course_session: CourseSession) -> bool:
|
||||||
|
if user.is_superuser:
|
||||||
|
return True
|
||||||
|
|
||||||
|
if CourseSessionGroup.objects.filter(
|
||||||
|
course_session=course_session, supervisor=user
|
||||||
).exists():
|
).exists():
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return CourseSessionUser.objects.filter(
|
||||||
|
course_session=course_session,
|
||||||
|
user=user,
|
||||||
|
).exists()
|
||||||
Loading…
Reference in New Issue