WIP: Filter statistics by circle
This commit is contained in:
parent
121f7c227a
commit
68d44f950f
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
Loading…
Reference in New Issue