Add `UK_BERUFSBILDNER_STATISTICS_WIDGET`
This commit is contained in:
parent
0581f3d820
commit
40ff65ad2d
|
|
@ -0,0 +1,49 @@
|
|||
<script setup lang="ts">
|
||||
import { computed, onMounted, type Ref, ref } from "vue";
|
||||
import {
|
||||
type DashboardRoleKeyType,
|
||||
fetchMentorCompetenceSummary,
|
||||
} from "@/services/dashboard";
|
||||
import type { AssignmentsStatisticsType, BaseStatisticsType } from "@/gql/graphql";
|
||||
import LoadingSpinner from "@/components/ui/LoadingSpinner.vue";
|
||||
import AssignmentSummaryBox from "@/components/dashboard/AssignmentSummaryBox.vue";
|
||||
|
||||
const props = defineProps<{
|
||||
courseSlug: string;
|
||||
courseId: string;
|
||||
agentRole: DashboardRoleKeyType;
|
||||
}>();
|
||||
|
||||
const mentorData = ref<BaseStatisticsType | null>(null);
|
||||
const loading = ref(true);
|
||||
|
||||
const assignmentStats = computed(() => {
|
||||
return mentorData.value?.assignments ?? null;
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
mentorData.value = await fetchMentorCompetenceSummary(
|
||||
props.courseId,
|
||||
props.agentRole
|
||||
);
|
||||
loading.value = false;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="loading" class="m-8 flex justify-center">
|
||||
<LoadingSpinner />
|
||||
</div>
|
||||
<div v-if="assignmentStats" class="space-y-8">
|
||||
<div
|
||||
class="flex flex-col flex-wrap justify-between gap-x-5 border-b border-gray-300 pb-8 last:border-0 md:flex-row"
|
||||
>
|
||||
<AssignmentSummaryBox
|
||||
class="flex-grow"
|
||||
:assignments-completed="assignmentStats.summary.completed_count"
|
||||
:avg-passed="assignmentStats.summary.average_passed"
|
||||
:course-slug="props.courseSlug"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -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 {
|
|||
</router-link>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="
|
||||
hasWidget('ProgressWidget') &&
|
||||
|
|
@ -127,6 +129,7 @@ function hasActionButton(): boolean {
|
|||
diagram-type="horizontal"
|
||||
></LearningPathDiagram>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="numberOfProgressWidgets"
|
||||
class="flex flex-col flex-wrap gap-x-[60px] border-b border-gray-300 pb-8 last:border-0 md:flex-row"
|
||||
|
|
@ -144,12 +147,25 @@ function hasActionButton(): boolean {
|
|||
:course-id="courseConfig.course_id"
|
||||
></CompetenceSummary>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="hasWidget('UKStatisticsWidget')"
|
||||
class="flex flex-col flex-wrap gap-x-[60px] border-b border-gray-300 pb-8 last:border-0 md:flex-row"
|
||||
>
|
||||
<UkStatistics :course-slug="courseSlug" :course-id="courseConfig.course_id" />
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="hasWidget('UKBerufsbildnerStatisticsWidget')"
|
||||
class="flex flex-col flex-wrap gap-x-[60px] border-b border-gray-300 pb-8 last:border-0 md:flex-row"
|
||||
>
|
||||
<BerufsbildnerStatistics
|
||||
:course-slug="courseSlug"
|
||||
:course-id="courseConfig.course_id"
|
||||
:agent-role="courseConfig.role_key"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="numberOfMentorWidgets > 0"
|
||||
class="flex flex-col flex-wrap items-stretch md:flex-row"
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
<script setup lang="ts">
|
||||
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<AssignmentsStatisticsType | null> = ref(null);
|
||||
const mentorAssignmentData = ref<BaseStatisticsType | null>(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
|
||||
);
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -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<Maybe<Scalars['ID']['output']>>;
|
||||
course_slug: Scalars['String']['output'];
|
||||
course_title: Scalars['String']['output'];
|
||||
|
|
|
|||
|
|
@ -189,6 +189,7 @@ type BaseStatisticsType {
|
|||
course_session_selection_ids: [ID]!
|
||||
user_selection_ids: [ID]
|
||||
assignments: AssignmentsStatisticsType!
|
||||
course_session_properties: StatisticsCourseSessionPropertiesType!
|
||||
}
|
||||
|
||||
type CourseProgressType {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
<script setup lang="ts">
|
||||
import LoadingSpinner from "@/components/ui/LoadingSpinner.vue";
|
||||
import { useCourseStatisticsv2 } from "@/composables";
|
||||
|
||||
const props = defineProps<{
|
||||
courseSlug: string;
|
||||
}>();
|
||||
|
||||
const { courseStatistics, loading, courseSessionName, circleMeta } =
|
||||
useCourseStatisticsv2(props.courseSlug);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="bg-gray-200">
|
||||
<div v-if="loading" class="m-8 flex justify-center">
|
||||
<LoadingSpinner />
|
||||
</div>
|
||||
<div v-else class="container-large flex flex-col space-y-8">
|
||||
<router-link class="btn-text inline-flex items-center pl-0" to="/">
|
||||
<it-icon-arrow-left />
|
||||
<span>{{ $t("general.back") }}</span>
|
||||
</router-link>
|
||||
<router-view
|
||||
:course-statistics="courseStatistics"
|
||||
:course-session-name="courseSessionName"
|
||||
:circle-meta="circleMeta"
|
||||
></router-view>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -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<DashboardConfigType[] | nu
|
|||
export const fetchMentorCompetenceSummary = async (
|
||||
courseId: string,
|
||||
roleKey: DashboardRoleKeyType
|
||||
): Promise<AssignmentsStatisticsType | null> => {
|
||||
): Promise<BaseStatisticsType | null> => {
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue