WIP: Filter statistics by circle

This commit is contained in:
Christian Cueni 2024-04-15 13:48:56 +02:00
parent 121f7c227a
commit 68d44f950f
9 changed files with 63 additions and 7 deletions

View File

@ -1,14 +1,17 @@
<script setup lang="ts">
import { useDashboardStore } from "@/stores/dashboard";
import { computed } from "vue";
import { computed, onMounted } from "vue";
import AttendanceSummaryBox from "@/components/dashboard/AttendanceSummaryBox.vue";
import type { CourseStatisticsType } from "@/gql/graphql";
import AssignmentSummaryBox from "@/components/dashboard/AssignmentSummaryBox.vue";
import FeedbackSummaryBox from "@/components/dashboard/FeedbackSummaryBox.vue";
import CompetenceSummaryBox from "@/components/dashboard/CompetenceSummaryBox.vue";
const dashboardStore = useDashboardStore();
const props = defineProps<{
courseId: string;
}>();
const dashboardStore = useDashboardStore();
const statistics = computed(() => {
return dashboardStore.currentDashBoardData as CourseStatisticsType;
});
@ -28,6 +31,10 @@ const competenceSummary = computed(() => {
const feebackSummary = computed(() => {
return statistics.value.feedback_responses.summary;
});
onMounted(async () => {
await dashboardStore.loadStatisticsData(props.courseId);
});
</script>
<template>
@ -47,7 +54,7 @@ const feebackSummary = computed(() => {
/>
</div>
<div
class="flex flex-col flex-wrap gap-x-5 border-b border-gray-300 pb-8 align-top last:border-0 md:flex-row"
class="flex flex-col flex-wrap gap-x-5 border-b border-gray-300 align-top last:border-0 md:flex-row"
>
<FeedbackSummaryBox
:feedback-count="feebackSummary.total_responses"

View File

@ -72,6 +72,12 @@ export const useDashboardStore = defineStore("dashboard", () => {
}
};
const loadStatisticsData = async (id: string) => {
const data = await fetchStatisticData(id);
dashBoardDataCache[id] = data;
currentDashBoardData.value = data;
};
return {
dashboardConfigs,
currentDashboardConfig,
@ -80,5 +86,6 @@ export const useDashboardStore = defineStore("dashboard", () => {
loadDashboardDetails,
currentDashBoardData,
loading,
loadStatisticsData,
};
});

View File

@ -26,6 +26,7 @@ from vbv_lernwelt.iam.permissions import (
can_view_course_session_progress,
)
from vbv_lernwelt.learning_mentor.models import LearningMentor
from vbv_lernwelt.learnpath.models import Circle
class DashboardQuery(graphene.ObjectType):
@ -56,9 +57,25 @@ class DashboardQuery(graphene.ObjectType):
course_session_ids.update(
group.course_session.all().values_list("id", flat=True)
)
course_session_ids = set()
# let's assume that users are not supervisors in one region/group and trainer in another
if not course_session_ids:
return None
circle_ids = set()
circle_ids.update(
Circle.objects.filter(
expert__user=user, expert__role=CourseSessionUser.Role.EXPERT
).values_list("id", flat=True)
)
course_session_ids = CourseSession.objects.filter(
course=course,
coursesessionuser__user=user,
coursesessionuser__role=CourseSessionUser.Role.EXPERT,
).values_list("id", flat=True)
setattr(info.context, "circle_ids", list(circle_ids))
# get trainer courses & circles
# return None
return CourseStatisticsType(
_id=course.id, # noqa

View File

@ -161,6 +161,7 @@ def assignments(
course_id: graphene.ID(required=True),
course_session_selection_ids: graphene.List(graphene.ID),
user_selection_ids: List[str] | None = None,
circle_ids: List[graphene.ID] | None = None,
) -> AssignmentsStatisticsType:
course_sessions = CourseSession.objects.filter(
id__in=course_session_selection_ids,
@ -175,6 +176,8 @@ def assignments(
],
learning_content__content_assignment__competence_certificate__isnull=False,
):
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
)
@ -184,6 +187,8 @@ def assignments(
course_session=course_session,
learning_content__content_assignment__competence_certificate__isnull=False,
):
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
)

View File

@ -37,6 +37,7 @@ class AttendanceDayPresencesStatisticsType(graphene.ObjectType):
def attendance_day_presences(
course_id: graphene.ID,
course_session_selection_ids: graphene.List(graphene.ID),
circle_ids: List[graphene.ID] = None,
) -> AttendanceDayPresencesStatisticsType:
completed = CourseSessionAttendanceCourse.objects.filter(
course_session_id__in=course_session_selection_ids,
@ -48,6 +49,9 @@ def attendance_day_presences(
for attendance_day in completed:
circle = attendance_day.learning_content.get_parent_circle()
if circle_ids and circle.id not in circle_ids:
continue
course_session = attendance_day.course_session
url = f"/course/{course_session.course.slug}/cockpit/attendance?id={attendance_day.learning_content.id}&courseSessionId={course_session.id}"
@ -85,7 +89,7 @@ def attendance_day_presences(
summary = AttendanceSummaryStatisticsType(
_id=course_id, # noqa
days_completed=completed.count(), # noqa
days_completed=len(records), # noqa
participants_present=calculate_avg_participation(records), # noqa
)

View File

@ -35,6 +35,7 @@ def competences(
course_session_selection_ids: List[str],
course_slug: str,
user_selection_ids: List[str] | None = None,
circle_ids: List[str] | None = None,
) -> Tuple[List[CompetenceRecordStatisticsType], int, int]:
completions = CourseCompletion.objects.filter(
course_session_id__in=course_session_selection_ids,
@ -54,7 +55,8 @@ def competences(
circles = {
lu.id: c
for lu in learning_units.values()
if lu is not None and (c := lu.get_circle()) is not None
if (lu is not None and (c := lu.get_circle()) is not None)
and (circle_ids is None or c.id in circle_ids)
}
for completion in completions:
@ -65,6 +67,9 @@ def competences(
circle = circles.get(learning_unit.id)
if not circle:
continue
combined_id = f"{circle.id}-{completion.course_session.id}"
competence_records.setdefault(combined_id, {}).setdefault(

View File

@ -106,8 +106,12 @@ class BaseStatisticsType(graphene.ObjectType):
course_id=root.course_id,
course_session_selection_ids=root.course_session_selection_ids,
user_selection_ids=user_selection_ids,
circle_ids=root.get_circle_ids(_info),
)
def get_circle_ids(self, info):
return getattr(info.context, "circle_ids", None)
class CourseStatisticsType(BaseStatisticsType):
course_session_properties = graphene.Field(
@ -128,6 +132,7 @@ class CourseStatisticsType(BaseStatisticsType):
return attendance_day_presences(
course_id=root.course_id,
course_session_selection_ids=root.course_session_selection_ids,
circle_ids=root.get_circle_ids(info),
)
def resolve_feedback_responses(root, info) -> FeedbackStatisticsResponsesType:
@ -135,6 +140,7 @@ class CourseStatisticsType(BaseStatisticsType):
course_session_selection_ids=root.course_session_selection_ids,
course_id=root.course_id,
course_slug=root.course_slug,
circle_ids=root.get_circle_ids(info),
)
def resolve_competences(root, info) -> CompetencesStatisticsType:
@ -149,6 +155,7 @@ class CourseStatisticsType(BaseStatisticsType):
str(cs) for cs in root.course_session_selection_ids # noqa
],
user_selection_ids=user_selection_ids, # noqa
circle_ids=root.get_circle_ids(info), # noqa
)
return CompetencesStatisticsType(
_id=root._id, # noqa

View File

@ -37,6 +37,7 @@ def feedback_responses(
course_session_selection_ids: graphene.List(graphene.ID),
course_id: graphene.ID,
course_slug: graphene.String,
circle_ids: List[graphene.ID] = None,
) -> FeedbackStatisticsResponsesType:
# Get all course sessions for this user in the given course
course_sessions = CourseSession.objects.filter(
@ -53,6 +54,9 @@ def feedback_responses(
feedback_user__in=feedback_users(course_session.id),
)
if circle_ids and len(circle_ids):
fbs = fbs.filter(circle__id__in=circle_ids)
total_responses += len(fbs)
circle_feedbacks.extend(

View File

@ -242,7 +242,7 @@ def get_widgets_for_course(
if is_uk:
widgets.append(WidgetType.COMPETENCE_CERTIFICATE_WIDGET.value)
if role_key == RoleKeyType.SUPERVISOR:
if role_key in [RoleKeyType.SUPERVISOR, RoleKeyType.TRAINER] and is_uk:
widgets.append(WidgetType.UK_STATISTICS_WIDGET.value)
if is_mentor: