feat: adds mentor dashboard type
This commit is contained in:
parent
754fa52fd3
commit
2989085a42
|
|
@ -464,6 +464,7 @@ export type DashboardConfigType = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type DashboardType =
|
export type DashboardType =
|
||||||
|
| 'MENTOR_DASHBOARD'
|
||||||
| 'PROGRESS_DASHBOARD'
|
| 'PROGRESS_DASHBOARD'
|
||||||
| 'SIMPLE_DASHBOARD'
|
| 'SIMPLE_DASHBOARD'
|
||||||
| 'STATISTICS_DASHBOARD';
|
| 'STATISTICS_DASHBOARD';
|
||||||
|
|
|
||||||
|
|
@ -207,6 +207,7 @@ enum DashboardType {
|
||||||
STATISTICS_DASHBOARD
|
STATISTICS_DASHBOARD
|
||||||
PROGRESS_DASHBOARD
|
PROGRESS_DASHBOARD
|
||||||
SIMPLE_DASHBOARD
|
SIMPLE_DASHBOARD
|
||||||
|
MENTOR_DASHBOARD
|
||||||
}
|
}
|
||||||
|
|
||||||
type CourseConfigurationObjectType {
|
type CourseConfigurationObjectType {
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import SimpleCoursePage from "@/pages/dashboard/SimpleCoursePage.vue";
|
||||||
import LoadingSpinner from "@/components/ui/LoadingSpinner.vue";
|
import LoadingSpinner from "@/components/ui/LoadingSpinner.vue";
|
||||||
import CourseDetailDates from "@/components/dashboard/CourseDetailDates.vue";
|
import CourseDetailDates from "@/components/dashboard/CourseDetailDates.vue";
|
||||||
import NoCourseSession from "@/components/dashboard/NoCourseSession.vue";
|
import NoCourseSession from "@/components/dashboard/NoCourseSession.vue";
|
||||||
|
import MentorPage from "@/pages/dashboard/MentorPage.vue";
|
||||||
|
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
|
|
||||||
|
|
@ -23,6 +24,7 @@ const boards: Record<DashboardType, DashboardPage> = {
|
||||||
PROGRESS_DASHBOARD: { main: ProgressPage, aside: SimpleDates },
|
PROGRESS_DASHBOARD: { main: ProgressPage, aside: SimpleDates },
|
||||||
SIMPLE_DASHBOARD: { main: SimpleCoursePage, aside: SimpleDates },
|
SIMPLE_DASHBOARD: { main: SimpleCoursePage, aside: SimpleDates },
|
||||||
STATISTICS_DASHBOARD: { main: StatisticPage, aside: CourseDetailDates },
|
STATISTICS_DASHBOARD: { main: StatisticPage, aside: CourseDetailDates },
|
||||||
|
MENTOR_DASHBOARD: { main: MentorPage, aside: SimpleDates },
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(dashboardStore.loadDashboardDetails);
|
onMounted(dashboardStore.loadDashboardDetails);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { getCockpitUrl } from "@/utils/utils";
|
||||||
|
import { useDashboardStore } from "@/stores/dashboard";
|
||||||
|
|
||||||
|
const dashboardStore = useDashboardStore();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div v-if="dashboardStore.currentDashboardConfig">
|
||||||
|
<div class="mb-14">
|
||||||
|
<div class="h-full bg-white p-6">
|
||||||
|
<h3 class="mb-4">{{ dashboardStore.currentDashboardConfig.name }}</h3>
|
||||||
|
<div>
|
||||||
|
<router-link
|
||||||
|
class="btn-blue"
|
||||||
|
:to="getCockpitUrl(dashboardStore.currentDashboardConfig.slug)"
|
||||||
|
:data-cy="`continue-course-${dashboardStore.currentDashboardConfig.id}`"
|
||||||
|
>
|
||||||
|
{{ $t("a.Zur Lernbegleitung") }}
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
@ -58,7 +58,7 @@ export const useCourseSessionsStore = defineStore("courseSessions", () => {
|
||||||
|
|
||||||
function selectedCourseSessionForCourse(courseSlug: string) {
|
function selectedCourseSessionForCourse(courseSlug: string) {
|
||||||
// Wir wollen pro Kurs wissen, welche Durchführung der User zuletzt ausgewählt hat.
|
// Wir wollen pro Kurs wissen, welche Durchführung der User zuletzt ausgewählt hat.
|
||||||
// Die letzte Durchführung wird im localStorage via `selectedCoruseSessionMap`
|
// Die letzte Durchführung wird im localStorage via `selectedCourseSessionMap`
|
||||||
// gespeichert und hier geladen.
|
// gespeichert und hier geladen.
|
||||||
// Wenn noch keine Durchführung ausgewählt wurde, wird die erste Durchführung
|
// Wenn noch keine Durchführung ausgewählt wurde, wird die erste Durchführung
|
||||||
// in `courseSessionForCourse` zurückgegeben.
|
// in `courseSessionForCourse` zurückgegeben.
|
||||||
|
|
|
||||||
|
|
@ -83,11 +83,16 @@ class DashboardQuery(graphene.ObjectType):
|
||||||
statistics_dashboard_course_ids,
|
statistics_dashboard_course_ids,
|
||||||
) = get_user_statistics_dashboards(user=user)
|
) = get_user_statistics_dashboards(user=user)
|
||||||
|
|
||||||
course_session_dashboards = get_user_course_session_dashboards(
|
(
|
||||||
|
course_session_dashboards,
|
||||||
|
course_session_dashboard_course_ids,
|
||||||
|
) = get_user_course_session_dashboards(
|
||||||
user=user, exclude_course_ids=statistics_dashboard_course_ids
|
user=user, exclude_course_ids=statistics_dashboard_course_ids
|
||||||
)
|
)
|
||||||
|
|
||||||
learning_mentor_dashboards = get_learning_mentor_dashboards(user=user)
|
learning_mentor_dashboards, _ = get_learning_mentor_dashboards(
|
||||||
|
user=user, exclude_course_ids=course_session_dashboard_course_ids
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
statistic_dashboards
|
statistic_dashboards
|
||||||
|
|
@ -163,13 +168,13 @@ class DashboardQuery(graphene.ObjectType):
|
||||||
|
|
||||||
|
|
||||||
def get_user_statistics_dashboards(user: User) -> Tuple[List[Dict[str, str]], Set[int]]:
|
def get_user_statistics_dashboards(user: User) -> Tuple[List[Dict[str, str]], Set[int]]:
|
||||||
course_index = set()
|
course_ids = set()
|
||||||
dashboards = []
|
dashboards = []
|
||||||
|
|
||||||
for group in CourseSessionGroup.objects.all():
|
for group in CourseSessionGroup.objects.all():
|
||||||
if can_view_course_session_group_statistics(user=user, group=group):
|
if can_view_course_session_group_statistics(user=user, group=group):
|
||||||
course = group.course
|
course = group.course
|
||||||
course_index.add(course)
|
course_ids.add(course)
|
||||||
dashboards.append(
|
dashboards.append(
|
||||||
{
|
{
|
||||||
"id": str(course.id),
|
"id": str(course.id),
|
||||||
|
|
@ -180,31 +185,38 @@ def get_user_statistics_dashboards(user: User) -> Tuple[List[Dict[str, str]], Se
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
return dashboards, course_index
|
return dashboards, course_ids
|
||||||
|
|
||||||
|
|
||||||
def get_learning_mentor_dashboards(user: User) -> List[Dict[str, str]]:
|
def get_learning_mentor_dashboards(
|
||||||
learning_mentor = LearningMentor.objects.filter(mentor=user)
|
user: User, exclude_course_ids: Set[int]
|
||||||
|
) -> Tuple[List[Dict[str, str]], Set[int]]:
|
||||||
|
learning_mentor = LearningMentor.objects.filter(mentor=user).exclude(
|
||||||
|
course_id__in=exclude_course_ids
|
||||||
|
)
|
||||||
|
|
||||||
dashboards = []
|
dashboards = []
|
||||||
|
course_ids = set()
|
||||||
|
|
||||||
for mentor in learning_mentor:
|
for mentor in learning_mentor:
|
||||||
course = mentor.course
|
course = mentor.course
|
||||||
|
course_ids.add(course.id)
|
||||||
dashboards.append(
|
dashboards.append(
|
||||||
{
|
{
|
||||||
"id": str(course.id),
|
"id": str(course.id),
|
||||||
"name": course.title,
|
"name": course.title,
|
||||||
"slug": course.slug,
|
"slug": course.slug,
|
||||||
"dashboard_type": DashboardType.SIMPLE_DASHBOARD,
|
"dashboard_type": DashboardType.MENTOR_DASHBOARD,
|
||||||
"course_configuration": course.configuration,
|
"course_configuration": course.configuration,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
return dashboards
|
return dashboards, course_ids
|
||||||
|
|
||||||
|
|
||||||
def get_user_course_session_dashboards(
|
def get_user_course_session_dashboards(
|
||||||
user: User, exclude_course_ids: Set[int]
|
user: User, exclude_course_ids: Set[int]
|
||||||
) -> List[Dict[str, str]]:
|
) -> Tuple[List[Dict[str, str]], Set[int]]:
|
||||||
"""
|
"""
|
||||||
Edge case: what do we show to users with access to multiple
|
Edge case: what do we show to users with access to multiple
|
||||||
sessions of a course, but with varying permissions?
|
sessions of a course, but with varying permissions?
|
||||||
|
|
@ -212,6 +224,7 @@ def get_user_course_session_dashboards(
|
||||||
"""
|
"""
|
||||||
|
|
||||||
dashboards = []
|
dashboards = []
|
||||||
|
course_ids = set()
|
||||||
|
|
||||||
course_sessions = CourseSession.objects.exclude(course__in=exclude_course_ids)
|
course_sessions = CourseSession.objects.exclude(course__in=exclude_course_ids)
|
||||||
roles_by_course: Dict[Course, Set[DashboardType]] = {}
|
roles_by_course: Dict[Course, Set[DashboardType]] = {}
|
||||||
|
|
@ -237,6 +250,8 @@ def get_user_course_session_dashboards(
|
||||||
# fallback: just go with simple list dashboard
|
# fallback: just go with simple list dashboard
|
||||||
resolved_dashboard_type = DashboardType.SIMPLE_DASHBOARD
|
resolved_dashboard_type = DashboardType.SIMPLE_DASHBOARD
|
||||||
|
|
||||||
|
course_ids.add(course.id)
|
||||||
|
|
||||||
dashboards.append(
|
dashboards.append(
|
||||||
{
|
{
|
||||||
"id": str(course.id),
|
"id": str(course.id),
|
||||||
|
|
@ -247,4 +262,4 @@ def get_user_course_session_dashboards(
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
return dashboards
|
return dashboards, course_ids
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ class DashboardType(Enum):
|
||||||
STATISTICS_DASHBOARD = "StatisticsDashboard"
|
STATISTICS_DASHBOARD = "StatisticsDashboard"
|
||||||
PROGRESS_DASHBOARD = "ProgressDashboard"
|
PROGRESS_DASHBOARD = "ProgressDashboard"
|
||||||
SIMPLE_DASHBOARD = "SimpleDashboard"
|
SIMPLE_DASHBOARD = "SimpleDashboard"
|
||||||
|
MENTOR_DASHBOARD = "MentorDashboard"
|
||||||
|
|
||||||
|
|
||||||
class DashboardConfigType(graphene.ObjectType):
|
class DashboardConfigType(graphene.ObjectType):
|
||||||
|
|
|
||||||
|
|
@ -291,7 +291,55 @@ class DashboardTestCase(GraphQLTestCase):
|
||||||
self.assertEqual(len(response.json()["data"]["dashboard_config"]), 1)
|
self.assertEqual(len(response.json()["data"]["dashboard_config"]), 1)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
response.json()["data"]["dashboard_config"][0]["dashboard_type"],
|
response.json()["data"]["dashboard_config"][0]["dashboard_type"],
|
||||||
"SIMPLE_DASHBOARD",
|
"MENTOR_DASHBOARD",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_mentor_and_member_mixed(self):
|
||||||
|
# GIVEN
|
||||||
|
course, _ = create_course("Test Course")
|
||||||
|
cs = create_course_session(course=course, title="Test Course Session 1")
|
||||||
|
|
||||||
|
# in same course session
|
||||||
|
mentor_and_member = create_user("mentor_and_member")
|
||||||
|
|
||||||
|
mentee = add_course_session_user(
|
||||||
|
course_session=cs,
|
||||||
|
user=create_user("mentee"),
|
||||||
|
role=CourseSessionUser.Role.MEMBER,
|
||||||
|
)
|
||||||
|
|
||||||
|
add_course_session_user(
|
||||||
|
course_session=cs,
|
||||||
|
user=mentor_and_member,
|
||||||
|
role=CourseSessionUser.Role.MEMBER,
|
||||||
|
)
|
||||||
|
|
||||||
|
add_learning_mentor(course=course, mentor=mentor_and_member, mentee=mentee)
|
||||||
|
|
||||||
|
# WHEN
|
||||||
|
self.client.force_login(mentor_and_member)
|
||||||
|
|
||||||
|
query = """query {
|
||||||
|
dashboard_config {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
slug
|
||||||
|
dashboard_type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
response = self.query(query)
|
||||||
|
|
||||||
|
# THEN
|
||||||
|
self.assertResponseNoErrors(response)
|
||||||
|
|
||||||
|
# given mentor + member -> should see the PROGRESS_DASHBOARD,
|
||||||
|
# not the MENTOR_DASHBOARD which is only for "pure" mentors.
|
||||||
|
self.assertEqual(len(response.json()["data"]["dashboard_config"]), 1)
|
||||||
|
self.assertEqual(
|
||||||
|
response.json()["data"]["dashboard_config"][0]["dashboard_type"],
|
||||||
|
"PROGRESS_DASHBOARD",
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_course_statistics_deny_not_allowed_user(self):
|
def test_course_statistics_deny_not_allowed_user(self):
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue