import("@/pages/dashboard/DashboardPersonsPage.vue"),
},
+ {
+ path: "/dashboard/persons-competence",
+ component: () => import("@/pages/dashboard/DashboardPersonsPage.vue"),
+ props: { mode: "competenceMetrics" },
+ },
{
path: "/dashboard/due-dates",
component: () => import("@/pages/dashboard/DashboardDueDatesPage.vue"),
diff --git a/client/src/services/dashboard.ts b/client/src/services/dashboard.ts
index 678af9ab..60beb348 100644
--- a/client/src/services/dashboard.ts
+++ b/client/src/services/dashboard.ts
@@ -13,7 +13,7 @@ import type {
CourseStatisticsType,
DashboardConfigType,
} from "@/gql/graphql";
-import type { DueDate } from "@/types";
+import type { DashboardPersonsPageMode, DueDate } from "@/types";
export type DashboardPersonRoleType =
| "SUPERVISOR"
@@ -52,6 +52,10 @@ export type DashboardPersonCourseSessionType = {
my_role_display: string;
is_uk: boolean;
is_vv: boolean;
+ competence_metrics?: {
+ passed_count: number;
+ failed_count: number;
+ };
};
export type DashboardPersonType = {
@@ -62,6 +66,10 @@ export type DashboardPersonType = {
course_sessions: DashboardPersonCourseSessionType[];
avatar_url: string;
avatar_url_small: string;
+ competence_metrics?: {
+ passed_count: number;
+ failed_count: number;
+ };
};
export type DashboardCourseConfigType = {
@@ -153,8 +161,12 @@ export const fetchMentorCompetenceSummary = async (
}
};
-export async function fetchDashboardPersons() {
- return await itGetCached("/api/dashboard/persons/");
+export async function fetchDashboardPersons(mode: DashboardPersonsPageMode) {
+ let url = "/api/dashboard/persons/";
+ if (mode === "competenceMetrics") {
+ url += "?with_competence_metrics=true";
+ }
+ return await itGetCached(url);
}
export async function fetchDashboardDueDates() {
diff --git a/client/src/types.ts b/client/src/types.ts
index 7ef3a364..cf7a2268 100644
--- a/client/src/types.ts
+++ b/client/src/types.ts
@@ -610,3 +610,5 @@ export type User = {
course_session_experts: any[];
language: string;
};
+
+export type DashboardPersonsPageMode = "default" | "competenceMetrics";
diff --git a/server/vbv_lernwelt/competence/services.py b/server/vbv_lernwelt/competence/services.py
new file mode 100644
index 00000000..0ef4d306
--- /dev/null
+++ b/server/vbv_lernwelt/competence/services.py
@@ -0,0 +1,42 @@
+from vbv_lernwelt.assignment.models import AssignmentType
+from vbv_lernwelt.course_session.models import (
+ CourseSessionAssignment,
+ CourseSessionEdoniqTest,
+)
+
+
+def query_competence_course_session_assignments(course_session_ids, circle_ids=None):
+ if circle_ids is None:
+ circle_ids = []
+
+ result = []
+
+ for csa in CourseSessionAssignment.objects.filter(
+ course_session_id__in=course_session_ids,
+ learning_content__content_assignment__assignment_type__in=[
+ AssignmentType.CASEWORK.value,
+ ],
+ learning_content__content_assignment__competence_certificate__isnull=False,
+ ):
+ if circle_ids and csa.learning_content.get_circle().id not in circle_ids:
+ continue
+ result.append(csa)
+
+ return result
+
+
+def query_competence_course_session_edoniq_tests(course_session_ids, circle_ids=None):
+ if circle_ids is None:
+ circle_ids = []
+
+ result = []
+
+ for cset in CourseSessionEdoniqTest.objects.filter(
+ course_session_id__in=course_session_ids,
+ learning_content__content_assignment__competence_certificate__isnull=False,
+ ):
+ if circle_ids and cset.learning_content.get_circle().id not in circle_ids:
+ continue
+ result.append(cset)
+
+ return result
diff --git a/server/vbv_lernwelt/dashboard/graphql/types/assignment.py b/server/vbv_lernwelt/dashboard/graphql/types/assignment.py
index 499ccf61..98939fd0 100644
--- a/server/vbv_lernwelt/dashboard/graphql/types/assignment.py
+++ b/server/vbv_lernwelt/dashboard/graphql/types/assignment.py
@@ -9,6 +9,10 @@ from vbv_lernwelt.assignment.models import (
AssignmentCompletionStatus,
AssignmentType,
)
+from vbv_lernwelt.competence.services import (
+ query_competence_course_session_assignments,
+ query_competence_course_session_edoniq_tests,
+)
from vbv_lernwelt.course.models import CourseSession, CourseSessionUser
from vbv_lernwelt.course_session.models import (
CourseSessionAssignment,
@@ -169,26 +173,15 @@ def assignments(
records: List[AssignmentStatisticsRecordType] = []
for course_session in course_sessions:
- for csa in CourseSessionAssignment.objects.filter(
- course_session=course_session,
- learning_content__content_assignment__assignment_type__in=[
- AssignmentType.CASEWORK.value,
- ],
- learning_content__content_assignment__competence_certificate__isnull=False,
+ for csa in query_competence_course_session_assignments(
+ [course_session.id], circle_ids
):
- if circle_ids and csa.learning_content.get_circle().id not in circle_ids:
- continue
- record = create_record(
- course_session_assignment=csa, user_selection_ids=user_selection_ids
- )
+ record = create_record(csa, user_selection_ids)
records.append(record)
- for cset in CourseSessionEdoniqTest.objects.filter(
- course_session=course_session,
- learning_content__content_assignment__competence_certificate__isnull=False,
+ for cset in query_competence_course_session_edoniq_tests(
+ [course_session.id], circle_ids
):
- if circle_ids and cset.learning_content.get_circle().id not in circle_ids:
- continue
record = create_record(
course_session_assignment=cset, user_selection_ids=user_selection_ids
)
diff --git a/server/vbv_lernwelt/dashboard/views.py b/server/vbv_lernwelt/dashboard/views.py
index d1f0ffcf..bb05a202 100644
--- a/server/vbv_lernwelt/dashboard/views.py
+++ b/server/vbv_lernwelt/dashboard/views.py
@@ -11,6 +11,10 @@ from vbv_lernwelt.assignment.models import (
AssignmentCompletion,
AssignmentCompletionStatus,
)
+from vbv_lernwelt.competence.services import (
+ query_competence_course_session_assignments,
+ query_competence_course_session_edoniq_tests,
+)
from vbv_lernwelt.core.models import User
from vbv_lernwelt.course.models import (
CourseConfiguration,
@@ -142,8 +146,7 @@ def _create_course_session_dict(course_session_object, my_role, user_role):
}
-@api_view(["GET"])
-def get_dashboard_persons(request):
+def _create_person_list_with_roles(user):
def create_user_dict(user_object):
return {
"user_id": user_object.id,
@@ -154,72 +157,121 @@ def get_dashboard_persons(request):
"avatar_url": user_object.avatar_url,
}
- try:
- course_sessions = get_course_sessions_with_roles_for_user(request.user)
+ course_sessions = get_course_sessions_with_roles_for_user(user)
- result_persons = {}
- for cs in course_sessions:
- if has_cs_role(cs.roles) and cs.course.configuration.is_uk:
- course_session_users = CourseSessionUser.objects.filter(
- course_session=cs.id
+ result_persons = {}
+ for cs in course_sessions:
+ if has_cs_role(cs.roles) and cs.course.configuration.is_uk:
+ course_session_users = CourseSessionUser.objects.filter(
+ course_session=cs.id
+ )
+ my_role = user_role(cs.roles)
+ for csu in course_session_users:
+ person_data = create_user_dict(csu.user)
+ person_data["course_sessions"] = [
+ _create_course_session_dict(cs, my_role, csu.role)
+ ]
+ result_persons[csu.user.id] = person_data
+
+ # add persons where request.user is mentor
+ for cs in course_sessions:
+ if "LEARNING_MENTOR" in cs.roles:
+ lm = LearningMentor.objects.filter(
+ mentor=user, course_session=cs.id
+ ).first()
+
+ for participant in lm.participants.all():
+ course_session_entry = _create_course_session_dict(
+ cs,
+ "LEARNING_MENTOR",
+ "LEARNING_MENTEE",
)
- my_role = user_role(cs.roles)
- for csu in course_session_users:
- person_data = create_user_dict(csu.user)
- person_data["course_sessions"] = [
- _create_course_session_dict(cs, my_role, csu.role)
- ]
- result_persons[csu.user.id] = person_data
- # add persons where request.user is mentor
- for cs in course_sessions:
- if "LEARNING_MENTOR" in cs.roles:
- lm = LearningMentor.objects.filter(
- mentor=request.user, course_session=cs.id
- ).first()
-
- for participant in lm.participants.all():
- course_session_entry = _create_course_session_dict(
- cs,
- "LEARNING_MENTOR",
- "LEARNING_MENTEE",
+ if participant.user.id not in result_persons:
+ person_data = create_user_dict(participant.user)
+ person_data["course_sessions"] = [course_session_entry]
+ result_persons[participant.user.id] = person_data
+ else:
+ # user is already in result_persons
+ result_persons[participant.user.id]["course_sessions"].append(
+ course_session_entry
)
- if participant.user.id not in result_persons:
- person_data = create_user_dict(participant.user)
- person_data["course_sessions"] = [course_session_entry]
- result_persons[participant.user.id] = person_data
- else:
- # user is already in result_persons
- result_persons[participant.user.id]["course_sessions"].append(
- course_session_entry
- )
+ # add persons where request.user is mentee
+ mentor_relation_qs = LearningMentor.objects.filter(
+ participants__user=user
+ ).prefetch_related("mentor", "course_session")
+ for mentor_relation in mentor_relation_qs:
+ cs = mentor_relation.course_session
+ course_session_entry = _create_course_session_dict(
+ cs,
+ "LEARNING_MENTEE",
+ "LEARNING_MENTOR",
+ )
- # add persons where request.user is mentee
- mentor_relation_qs = LearningMentor.objects.filter(
- participants__user=request.user
- ).prefetch_related("mentor", "course_session")
- for mentor_relation in mentor_relation_qs:
- cs = mentor_relation.course_session
- course_session_entry = _create_course_session_dict(
- cs,
- "LEARNING_MENTEE",
- "LEARNING_MENTOR",
+ if mentor_relation.mentor.id not in result_persons:
+ person_data = create_user_dict(mentor_relation.mentor)
+ person_data["course_sessions"] = [course_session_entry]
+ result_persons[mentor_relation.mentor.id] = person_data
+ else:
+ # user is already in result_persons
+ result_persons[mentor_relation.mentor.id]["course_sessions"].append(
+ course_session_entry
)
- if mentor_relation.mentor.id not in result_persons:
- person_data = create_user_dict(mentor_relation.mentor)
- person_data["course_sessions"] = [course_session_entry]
- result_persons[mentor_relation.mentor.id] = person_data
- else:
- # user is already in result_persons
- result_persons[mentor_relation.mentor.id]["course_sessions"].append(
- course_session_entry
- )
+ return result_persons.values()
+
+
+def _persons_list_add_competence_metrics(persons):
+ course_session_ids = {cs["id"] for p in persons for cs in p["course_sessions"]}
+ competence_assignments = query_competence_course_session_assignments(
+ course_session_ids
+ ) + query_competence_course_session_edoniq_tests(course_session_ids)
+ assignment_ids = {
+ a.learning_content.content_assignment.id for a in competence_assignments
+ }
+
+ for p in persons:
+ passed_count = 0
+ failed_count = 0
+ for cs in p["course_sessions"]:
+ evaluation_results = AssignmentCompletion.objects.filter(
+ completion_status=AssignmentCompletionStatus.EVALUATION_SUBMITTED.value,
+ assignment_user_id=p.get("user_id"),
+ course_session=cs.get("id"),
+ assignment_id__in=assignment_ids,
+ )
+ cs_passed_count = len(
+ [ac for ac in evaluation_results if ac.evaluation_passed]
+ )
+ cs_failed_count = len(evaluation_results) - cs_passed_count
+ cs["competence_metrics"] = {
+ "passed_count": cs_passed_count,
+ "failed_count": cs_failed_count,
+ }
+ passed_count += len(
+ [ac for ac in evaluation_results if ac.evaluation_passed]
+ )
+ failed_count += len(evaluation_results) - passed_count
+ p["competence_metrics"] = {
+ "passed_count": passed_count,
+ "failed_count": failed_count,
+ }
+
+ return persons
+
+
+@api_view(["GET"])
+def get_dashboard_persons(request):
+ try:
+ persons = list(_create_person_list_with_roles(request.user))
+
+ if request.GET.get("with_competence_metrics", "") == "true":
+ persons = _persons_list_add_competence_metrics(persons)
return Response(
status=200,
- data=list(result_persons.values()),
+ data=list(persons),
)
except PermissionDenied as e:
raise e