From 40ff65ad2d5766e1f0c62c064c1aad7e4bd880b0 Mon Sep 17 00:00:00 2001
From: Daniel Egger
Date: Mon, 22 Jul 2024 10:44:10 +0200
Subject: [PATCH] Add `UK_BERUFSBILDNER_STATISTICS_WIDGET`
---
.../dashboard/BerufsbildnerStatistics.vue | 49 +++++
.../src/components/dashboard/CoursePanel.vue | 16 ++
.../dashboard/MentorCompetenceSummary.vue | 17 +-
client/src/gql/graphql.ts | 1 +
client/src/gql/schema.graphql | 1 +
.../statistic/AgentStatisticParentPage.vue | 30 +++
client/src/services/dashboard.ts | 11 +-
scripts/create_berufsbilnder_mobi.py | 1 +
.../dashboard/graphql/types/dashboard.py | 174 +++++++++---------
server/vbv_lernwelt/dashboard/views.py | 3 +-
10 files changed, 205 insertions(+), 98 deletions(-)
create mode 100644 client/src/components/dashboard/BerufsbildnerStatistics.vue
create mode 100644 client/src/pages/dashboard/statistic/AgentStatisticParentPage.vue
diff --git a/client/src/components/dashboard/BerufsbildnerStatistics.vue b/client/src/components/dashboard/BerufsbildnerStatistics.vue
new file mode 100644
index 00000000..5fc5cad4
--- /dev/null
+++ b/client/src/components/dashboard/BerufsbildnerStatistics.vue
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
diff --git a/client/src/components/dashboard/CoursePanel.vue b/client/src/components/dashboard/CoursePanel.vue
index 241ec339..d97a6d02 100644
--- a/client/src/components/dashboard/CoursePanel.vue
+++ b/client/src/components/dashboard/CoursePanel.vue
@@ -9,6 +9,7 @@ import MentorMenteeCount from "@/components/dashboard/MentorMenteeCount.vue";
import MentorCompetenceSummary from "@/components/dashboard/MentorCompetenceSummary.vue";
import { getCockpitUrl, getLearningMentorUrl, getLearningPathUrl } from "@/utils/utils";
import UkStatistics from "@/components/dashboard/UkStatistics.vue";
+import BerufsbildnerStatistics from "@/components/dashboard/BerufsbildnerStatistics.vue";
const mentorWidgets = [
"MentorTasksWidget",
@@ -112,6 +113,7 @@ function hasActionButton(): boolean {
+
+
+
+
+
+
+
+
-import type { Ref } from "vue";
-import { onMounted, ref } from "vue";
+import { computed, onMounted, ref } from "vue";
import {
type DashboardRoleKeyType,
fetchMentorCompetenceSummary,
} from "@/services/dashboard";
-import type { AssignmentsStatisticsType } from "@/gql/graphql";
+import type { BaseStatisticsType } from "@/gql/graphql";
import BaseBox from "@/components/dashboard/BaseBox.vue";
const props = defineProps<{
@@ -13,11 +12,17 @@ const props = defineProps<{
agentRole: DashboardRoleKeyType;
}>();
-const summary: Ref
= ref(null);
+const mentorAssignmentData = ref(null);
+
+const summary = computed(() => {
+ return mentorAssignmentData.value?.assignments ?? null;
+});
onMounted(async () => {
- summary.value = await fetchMentorCompetenceSummary(props.courseId, props.agentRole);
- console.log(summary.value);
+ mentorAssignmentData.value = await fetchMentorCompetenceSummary(
+ props.courseId,
+ props.agentRole
+ );
});
diff --git a/client/src/gql/graphql.ts b/client/src/gql/graphql.ts
index 571f0d96..a21a54a7 100644
--- a/client/src/gql/graphql.ts
+++ b/client/src/gql/graphql.ts
@@ -250,6 +250,7 @@ export type BaseStatisticsType = {
_id: Scalars['ID']['output'];
assignments: AssignmentsStatisticsType;
course_id: Scalars['ID']['output'];
+ course_session_properties: StatisticsCourseSessionPropertiesType;
course_session_selection_ids: Array>;
course_slug: Scalars['String']['output'];
course_title: Scalars['String']['output'];
diff --git a/client/src/gql/schema.graphql b/client/src/gql/schema.graphql
index 8158c73e..701273cc 100644
--- a/client/src/gql/schema.graphql
+++ b/client/src/gql/schema.graphql
@@ -189,6 +189,7 @@ type BaseStatisticsType {
course_session_selection_ids: [ID]!
user_selection_ids: [ID]
assignments: AssignmentsStatisticsType!
+ course_session_properties: StatisticsCourseSessionPropertiesType!
}
type CourseProgressType {
diff --git a/client/src/pages/dashboard/statistic/AgentStatisticParentPage.vue b/client/src/pages/dashboard/statistic/AgentStatisticParentPage.vue
new file mode 100644
index 00000000..29f2dd4c
--- /dev/null
+++ b/client/src/pages/dashboard/statistic/AgentStatisticParentPage.vue
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+ {{ $t("general.back") }}
+
+
+
+
+
diff --git a/client/src/services/dashboard.ts b/client/src/services/dashboard.ts
index b6c427a9..5a93ab0c 100644
--- a/client/src/services/dashboard.ts
+++ b/client/src/services/dashboard.ts
@@ -8,10 +8,10 @@ import {
import { itGetCached, itPost } from "@/fetchHelpers";
import type {
- AssignmentsStatisticsType,
+ AssignmentsStatisticsType, BaseStatisticsType,
CourseProgressType,
CourseStatisticsType,
- DashboardConfigType,
+ DashboardConfigType
} from "@/gql/graphql";
import type {
DashboardPersonsPageMode,
@@ -42,7 +42,8 @@ export type WidgetType =
| "MentorPersonWidget"
| "MentorCompetenceWidget"
| "CompetenceCertificateWidget"
- | "UKStatisticsWidget";
+ | "UKStatisticsWidget"
+ | "UKBerufsbildnerStatisticsWidget";
export type DashboardPersonCourseSessionType = {
id: string;
@@ -152,7 +153,7 @@ export const fetchDashboardConfig = async (): Promise => {
+): Promise => {
let agentRole = "";
if (["MentorUK", "MentorVV"].includes(roleKey)) {
agentRole = "LEARNING_MENTOR";
@@ -174,7 +175,7 @@ export const fetchMentorCompetenceSummary = async (
if (res.error) {
console.error("Error fetching data for course ID:", courseId, res.error);
}
- return res.data?.mentor_course_statistics?.assignments || null;
+ return res.data?.mentor_course_statistics || null;
} catch (error) {
console.error(`Error fetching data for course ID: ${courseId}`, error);
return null;
diff --git a/scripts/create_berufsbilnder_mobi.py b/scripts/create_berufsbilnder_mobi.py
index c784eed5..85eaeccd 100644
--- a/scripts/create_berufsbilnder_mobi.py
+++ b/scripts/create_berufsbilnder_mobi.py
@@ -33,6 +33,7 @@ def main():
for csu in (
CourseSessionUser.objects.filter(user__username__contains="@mobi")
.filter(course_session__course__configuration__is_uk=True)
+ .filter(role=CourseSessionUser.Role.MEMBER.value)
.exclude(course_session_id__in=[4, 5, 6])
):
AgentParticipantRelation.objects.get_or_create(
diff --git a/server/vbv_lernwelt/dashboard/graphql/types/dashboard.py b/server/vbv_lernwelt/dashboard/graphql/types/dashboard.py
index d5701eb8..24544451 100644
--- a/server/vbv_lernwelt/dashboard/graphql/types/dashboard.py
+++ b/server/vbv_lernwelt/dashboard/graphql/types/dashboard.py
@@ -96,6 +96,10 @@ class BaseStatisticsType(graphene.ObjectType):
user_selection_ids = graphene.List(graphene.ID, required=False)
assignments = graphene.Field(AssignmentsStatisticsType, required=True)
+ course_session_properties = graphene.Field(
+ StatisticsCourseSessionPropertiesType, required=True
+ )
+
def resolve_assignments(root, _info) -> AssignmentsStatisticsType:
user_selection_ids = (
[str(user) for user in root.user_selection_ids]
@@ -110,92 +114,6 @@ class BaseStatisticsType(graphene.ObjectType):
urql_id=str(root._id),
)
- def get_circle_ids(self, info):
- return getattr(info.context, "circle_ids", None)
-
-
-class CourseStatisticsType(BaseStatisticsType):
- course_session_properties = graphene.Field(
- StatisticsCourseSessionPropertiesType, required=True
- )
- course_session_selection_metrics = graphene.Field(
- StatisticsCourseSessionsSelectionMetricType, required=True
- )
- attendance_day_presences = graphene.Field(
- AttendanceDayPresencesStatisticsType, required=True
- )
- feedback_responses = graphene.Field(FeedbackStatisticsResponsesType, required=True)
- competences = graphene.Field(CompetencesStatisticsType, required=True)
-
- def resolve_attendance_day_presences(
- root, info
- ) -> AttendanceDayPresencesStatisticsType:
- 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),
- urql_id=str(root._id),
- )
-
- def resolve_feedback_responses(root, info) -> FeedbackStatisticsResponsesType:
- return feedback_responses(
- 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),
- urql_id=str(root._id),
- )
-
- def resolve_competences(root, info) -> CompetencesStatisticsType:
- user_selection_ids = (
- [str(user) for user in root.user_selection_ids]
- if root.user_selection_ids
- else None
- ) # noqa
- records, success_total, fail_total = competences(
- course_slug=str(root.course_slug),
- course_session_selection_ids=[
- 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
- urql_id_postfix=str(root._id), # noqa
- )
- return CompetencesStatisticsType(
- _id=root._id, # noqa
- records=records, # noqa
- summary=CompetencePerformanceStatisticsSummaryType( # noqa
- _id=root._id, # noqa
- success_total=success_total, # noqa
- fail_total=fail_total, # noqa
- ),
- )
-
- def resolve_course_session_selection_metrics(
- root, info
- ) -> StatisticsCourseSessionsSelectionMetricType:
- course_session_count = CourseSession.objects.filter(
- id__in=root.course_session_selection_ids,
- course_id=root.course_id,
- ).count()
-
- expert_count = CourseSessionUser.objects.filter(
- course_session_id__in=root.course_session_selection_ids,
- role=CourseSessionUser.Role.EXPERT,
- ).count()
-
- participant_count = CourseSessionUser.objects.filter(
- course_session_id__in=root.course_session_selection_ids,
- role=CourseSessionUser.Role.MEMBER,
- ).count()
-
- return StatisticsCourseSessionsSelectionMetricType(
- _id=root._id, # noqa
- session_count=course_session_count, # noqa
- participant_count=participant_count, # noqa
- expert_count=expert_count, # noqa
- )
-
def resolve_course_session_properties(root, info):
course_session_data = []
circle_data = []
@@ -238,3 +156,87 @@ class CourseStatisticsType(BaseStatisticsType):
generations=list(generations), # noqa
circles=circle_data, # noqa
)
+
+ def get_circle_ids(self, info):
+ return getattr(info.context, "circle_ids", None)
+
+
+class CourseStatisticsType(BaseStatisticsType):
+ course_session_selection_metrics = graphene.Field(
+ StatisticsCourseSessionsSelectionMetricType, required=True
+ )
+ attendance_day_presences = graphene.Field(
+ AttendanceDayPresencesStatisticsType, required=True
+ )
+ feedback_responses = graphene.Field(FeedbackStatisticsResponsesType, required=True)
+ competences = graphene.Field(CompetencesStatisticsType, required=True)
+
+ def resolve_attendance_day_presences(
+ root, info
+ ) -> AttendanceDayPresencesStatisticsType:
+ 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),
+ urql_id=str(root._id),
+ )
+
+ def resolve_feedback_responses(root, info) -> FeedbackStatisticsResponsesType:
+ return feedback_responses(
+ 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),
+ urql_id=str(root._id),
+ )
+
+ def resolve_competences(root, info) -> CompetencesStatisticsType:
+ user_selection_ids = (
+ [str(user) for user in root.user_selection_ids]
+ if root.user_selection_ids
+ else None
+ ) # noqa
+ records, success_total, fail_total = competences(
+ course_slug=str(root.course_slug),
+ course_session_selection_ids=[
+ 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
+ urql_id_postfix=str(root._id), # noqa
+ )
+ return CompetencesStatisticsType(
+ _id=root._id, # noqa
+ records=records, # noqa
+ summary=CompetencePerformanceStatisticsSummaryType( # noqa
+ _id=root._id, # noqa
+ success_total=success_total, # noqa
+ fail_total=fail_total, # noqa
+ ),
+ )
+
+ def resolve_course_session_selection_metrics(
+ root, info
+ ) -> StatisticsCourseSessionsSelectionMetricType:
+ course_session_count = CourseSession.objects.filter(
+ id__in=root.course_session_selection_ids,
+ course_id=root.course_id,
+ ).count()
+
+ expert_count = CourseSessionUser.objects.filter(
+ course_session_id__in=root.course_session_selection_ids,
+ role=CourseSessionUser.Role.EXPERT,
+ ).count()
+
+ participant_count = CourseSessionUser.objects.filter(
+ course_session_id__in=root.course_session_selection_ids,
+ role=CourseSessionUser.Role.MEMBER,
+ ).count()
+
+ return StatisticsCourseSessionsSelectionMetricType(
+ _id=root._id, # noqa
+ session_count=course_session_count, # noqa
+ participant_count=participant_count, # noqa
+ expert_count=expert_count, # noqa
+ )
diff --git a/server/vbv_lernwelt/dashboard/views.py b/server/vbv_lernwelt/dashboard/views.py
index bf19fe4a..20b5a8ce 100644
--- a/server/vbv_lernwelt/dashboard/views.py
+++ b/server/vbv_lernwelt/dashboard/views.py
@@ -58,6 +58,7 @@ class WidgetType(Enum):
MENTOR_COMPETENCE_WIDGET = "MentorCompetenceWidget"
COMPETENCE_CERTIFICATE_WIDGET = "CompetenceCertificateWidget"
UK_STATISTICS_WIDGET = "UKStatisticsWidget"
+ UK_BERUFSBILDNER_STATISTICS_WIDGET = "UKBerufsbildnerStatisticsWidget"
class RoleKeyType(Enum):
@@ -379,7 +380,7 @@ def get_widgets_for_course(
widgets.append(WidgetType.MENTOR_TASKS_WIDGET.value)
if role_key in [RoleKeyType.BERUFSBILDNER]:
- widgets.append(WidgetType.MENTOR_COMPETENCE_WIDGET.value)
+ widgets.append(WidgetType.UK_BERUFSBILDNER_STATISTICS_WIDGET.value)
return widgets