WIP: Add own components
This commit is contained in:
parent
24aa5d9b8c
commit
6edb5be093
|
|
@ -0,0 +1,36 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, onMounted, ref, Ref } from "vue";
|
||||||
|
import type { ProgressDashboardCompetenceType } from "@/gql/graphql";
|
||||||
|
import CompetenceSummaryBox from "@/components/dashboard/CompetenceSummaryBox.vue";
|
||||||
|
import { fetchProgressData } from "@/services/dashboard";
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
courseId: string;
|
||||||
|
courseSlug: string;
|
||||||
|
sessionToContinueId: string;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const DEFAULT_COMPETENCE = { total_count: 0, success_count: 0, fail_count: 0 };
|
||||||
|
const competence: Ref<ProgressDashboardCompetenceType> = ref(DEFAULT_COMPETENCE);
|
||||||
|
|
||||||
|
const competenceCriteriaUrl = computed(() => {
|
||||||
|
return `/course/${props.courseSlug}/competence/self-evaluation-and-feedback?courseSessionId=${props.sessionToContinueId}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
const some = await fetchProgressData(props.courseId);
|
||||||
|
competence.value = some.competence;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div v-if="competence" class="mb-14 space-y-8">
|
||||||
|
<div class="flex flex-col space-y-7 bg-white p-6">
|
||||||
|
<CompetenceSummaryBox
|
||||||
|
:fail-count="competence.fail_count"
|
||||||
|
:success-count="competence.success_count"
|
||||||
|
:details-link="competenceCriteriaUrl"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, onMounted, ref } from "vue";
|
||||||
|
import type { CourseProgressType } from "@/gql/graphql";
|
||||||
|
import { DashboardConfigType } from "@/gql/graphql";
|
||||||
|
import { fetchCourseData } from "@/services/dashboard";
|
||||||
|
import LearningPathDiagram from "@/components/learningPath/LearningPathDiagram.vue";
|
||||||
|
import CompetenceSummary from "@/components/dashboard/CompetenceSummary.vue";
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
courseConfig: DashboardConfigType;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const isLoading = ref(true);
|
||||||
|
|
||||||
|
const data = ref<CourseProgressType | null>(null);
|
||||||
|
|
||||||
|
const courseSlug = computed(() => props.courseConfig?.slug);
|
||||||
|
const courseName = computed(() => props.courseConfig?.name);
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
data.value = await fetchCourseData(props.courseConfig.id);
|
||||||
|
isLoading.value = false;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div v-if="!isLoading && courseConfig" class="mb-14 space-y-8">
|
||||||
|
<div class="flex flex-col space-y-7 bg-white p-6">
|
||||||
|
<h3>{{ courseName }}</h3>
|
||||||
|
<div v-for="widget in data.widgets" :key="widget.id">
|
||||||
|
{{ widget }}
|
||||||
|
<LearningPathDiagram
|
||||||
|
v-if="
|
||||||
|
widget === 'PROGRESS_WIDGET' && data.session_to_continue_id && courseSlug
|
||||||
|
"
|
||||||
|
:key="courseSlug"
|
||||||
|
:course-slug="courseSlug"
|
||||||
|
:course-session-id="data.session_to_continue_id"
|
||||||
|
diagram-type="horizontal"
|
||||||
|
></LearningPathDiagram>
|
||||||
|
<CompetenceSummary
|
||||||
|
v-else-if="widget === 'COMPETENCE_WIDGET'"
|
||||||
|
:course-slug="courseSlug"
|
||||||
|
:session-to-continue-id="data.session_to_continue_id"
|
||||||
|
:course-id="courseConfig.id"
|
||||||
|
></CompetenceSummary>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
@ -23,6 +23,7 @@ const documents = {
|
||||||
"\n query courseQuery($slug: String!) {\n course(slug: $slug) {\n id\n title\n slug\n category_name\n configuration {\n id\n enable_circle_documents\n enable_learning_mentor\n enable_competence_certificates\n }\n action_competences {\n competence_id\n ...CoursePageFields\n performance_criteria {\n competence_id\n learning_unit {\n id\n slug\n evaluate_url\n }\n ...CoursePageFields\n }\n }\n learning_path {\n ...CoursePageFields\n topics {\n is_visible\n ...CoursePageFields\n circles {\n description\n goals\n ...CoursePageFields\n learning_sequences {\n icon\n ...CoursePageFields\n learning_units {\n evaluate_url\n ...CoursePageFields\n performance_criteria {\n ...CoursePageFields\n }\n learning_contents {\n can_user_self_toggle_course_completion\n content_url\n minutes\n description\n ...CoursePageFields\n ... on LearningContentAssignmentObjectType {\n assignment_type\n content_assignment {\n id\n assignment_type\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n ... on LearningContentEdoniqTestObjectType {\n checkbox_text\n has_extended_time_test\n content_assignment {\n id\n assignment_type\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n ... on LearningContentRichTextObjectType {\n text\n }\n }\n }\n }\n }\n }\n }\n }\n }\n": types.CourseQueryDocument,
|
"\n query courseQuery($slug: String!) {\n course(slug: $slug) {\n id\n title\n slug\n category_name\n configuration {\n id\n enable_circle_documents\n enable_learning_mentor\n enable_competence_certificates\n }\n action_competences {\n competence_id\n ...CoursePageFields\n performance_criteria {\n competence_id\n learning_unit {\n id\n slug\n evaluate_url\n }\n ...CoursePageFields\n }\n }\n learning_path {\n ...CoursePageFields\n topics {\n is_visible\n ...CoursePageFields\n circles {\n description\n goals\n ...CoursePageFields\n learning_sequences {\n icon\n ...CoursePageFields\n learning_units {\n evaluate_url\n ...CoursePageFields\n performance_criteria {\n ...CoursePageFields\n }\n learning_contents {\n can_user_self_toggle_course_completion\n content_url\n minutes\n description\n ...CoursePageFields\n ... on LearningContentAssignmentObjectType {\n assignment_type\n content_assignment {\n id\n assignment_type\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n ... on LearningContentEdoniqTestObjectType {\n checkbox_text\n has_extended_time_test\n content_assignment {\n id\n assignment_type\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n ... on LearningContentRichTextObjectType {\n text\n }\n }\n }\n }\n }\n }\n }\n }\n }\n": types.CourseQueryDocument,
|
||||||
"\n query dashboardConfig {\n dashboard_config {\n id\n slug\n name\n dashboard_type\n course_configuration {\n id\n enable_circle_documents\n enable_learning_mentor\n enable_competence_certificates\n }\n }\n }\n": types.DashboardConfigDocument,
|
"\n query dashboardConfig {\n dashboard_config {\n id\n slug\n name\n dashboard_type\n course_configuration {\n id\n enable_circle_documents\n enable_learning_mentor\n enable_competence_certificates\n }\n }\n }\n": types.DashboardConfigDocument,
|
||||||
"\n query dashboardProgress($courseId: ID!) {\n course_progress(course_id: $courseId) {\n _id\n course_id\n session_to_continue_id\n competence {\n _id\n total_count\n success_count\n fail_count\n }\n assignment {\n _id\n total_count\n points_max_count\n points_achieved_count\n }\n }\n }\n": types.DashboardProgressDocument,
|
"\n query dashboardProgress($courseId: ID!) {\n course_progress(course_id: $courseId) {\n _id\n course_id\n session_to_continue_id\n competence {\n _id\n total_count\n success_count\n fail_count\n }\n assignment {\n _id\n total_count\n points_max_count\n points_achieved_count\n }\n }\n }\n": types.DashboardProgressDocument,
|
||||||
|
"\n query dashboardCourseData($courseId: ID!) {\n course_progress(course_id: $courseId) {\n _id\n course_id\n session_to_continue_id\n widgets\n }\n }\n": types.DashboardCourseDataDocument,
|
||||||
"\n query courseStatistics($courseId: ID!) {\n course_statistics(course_id: $courseId) {\n _id\n course_id\n course_title\n course_slug\n course_session_properties {\n _id\n sessions {\n id\n name\n }\n generations\n circles {\n id\n name\n }\n }\n course_session_selection_ids\n course_session_selection_metrics {\n _id\n session_count\n participant_count\n expert_count\n }\n attendance_day_presences {\n _id\n records {\n _id\n course_session_id\n generation\n circle_id\n due_date\n participants_present\n participants_total\n details_url\n }\n summary {\n _id\n days_completed\n participants_present\n }\n }\n feedback_responses {\n _id\n records {\n _id\n course_session_id\n generation\n circle_id\n experts\n satisfaction_average\n satisfaction_max\n details_url\n }\n summary {\n _id\n satisfaction_average\n satisfaction_max\n total_responses\n }\n }\n assignments {\n _id\n summary {\n _id\n completed_count\n average_passed\n }\n records {\n _id\n course_session_id\n course_session_assignment_id\n circle_id\n generation\n assignment_title\n assignment_type_translation_key\n details_url\n deadline\n metrics {\n _id\n passed_count\n failed_count\n unranked_count\n ranking_completed\n average_passed\n }\n }\n }\n competences {\n _id\n summary {\n _id\n success_total\n fail_total\n }\n records {\n _id\n course_session_id\n generation\n circle_id\n title\n success_count\n fail_count\n details_url\n }\n }\n }\n }\n": types.CourseStatisticsDocument,
|
"\n query courseStatistics($courseId: ID!) {\n course_statistics(course_id: $courseId) {\n _id\n course_id\n course_title\n course_slug\n course_session_properties {\n _id\n sessions {\n id\n name\n }\n generations\n circles {\n id\n name\n }\n }\n course_session_selection_ids\n course_session_selection_metrics {\n _id\n session_count\n participant_count\n expert_count\n }\n attendance_day_presences {\n _id\n records {\n _id\n course_session_id\n generation\n circle_id\n due_date\n participants_present\n participants_total\n details_url\n }\n summary {\n _id\n days_completed\n participants_present\n }\n }\n feedback_responses {\n _id\n records {\n _id\n course_session_id\n generation\n circle_id\n experts\n satisfaction_average\n satisfaction_max\n details_url\n }\n summary {\n _id\n satisfaction_average\n satisfaction_max\n total_responses\n }\n }\n assignments {\n _id\n summary {\n _id\n completed_count\n average_passed\n }\n records {\n _id\n course_session_id\n course_session_assignment_id\n circle_id\n generation\n assignment_title\n assignment_type_translation_key\n details_url\n deadline\n metrics {\n _id\n passed_count\n failed_count\n unranked_count\n ranking_completed\n average_passed\n }\n }\n }\n competences {\n _id\n summary {\n _id\n success_total\n fail_total\n }\n records {\n _id\n course_session_id\n generation\n circle_id\n title\n success_count\n fail_count\n details_url\n }\n }\n }\n }\n": types.CourseStatisticsDocument,
|
||||||
"\n mutation SendFeedbackMutation(\n $courseSessionId: ID!\n $learningContentId: ID!\n $learningContentType: String!\n $data: GenericScalar!\n $submitted: Boolean\n ) {\n send_feedback(\n course_session_id: $courseSessionId\n learning_content_page_id: $learningContentId\n learning_content_type: $learningContentType\n data: $data\n submitted: $submitted\n ) {\n feedback_response {\n id\n data\n submitted\n }\n errors {\n field\n messages\n }\n }\n }\n": types.SendFeedbackMutationDocument,
|
"\n mutation SendFeedbackMutation(\n $courseSessionId: ID!\n $learningContentId: ID!\n $learningContentType: String!\n $data: GenericScalar!\n $submitted: Boolean\n ) {\n send_feedback(\n course_session_id: $courseSessionId\n learning_content_page_id: $learningContentId\n learning_content_type: $learningContentType\n data: $data\n submitted: $submitted\n ) {\n feedback_response {\n id\n data\n submitted\n }\n errors {\n field\n messages\n }\n }\n }\n": types.SendFeedbackMutationDocument,
|
||||||
};
|
};
|
||||||
|
|
@ -81,6 +82,10 @@ export function graphql(source: "\n query dashboardConfig {\n dashboard_conf
|
||||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||||
*/
|
*/
|
||||||
export function graphql(source: "\n query dashboardProgress($courseId: ID!) {\n course_progress(course_id: $courseId) {\n _id\n course_id\n session_to_continue_id\n competence {\n _id\n total_count\n success_count\n fail_count\n }\n assignment {\n _id\n total_count\n points_max_count\n points_achieved_count\n }\n }\n }\n"): (typeof documents)["\n query dashboardProgress($courseId: ID!) {\n course_progress(course_id: $courseId) {\n _id\n course_id\n session_to_continue_id\n competence {\n _id\n total_count\n success_count\n fail_count\n }\n assignment {\n _id\n total_count\n points_max_count\n points_achieved_count\n }\n }\n }\n"];
|
export function graphql(source: "\n query dashboardProgress($courseId: ID!) {\n course_progress(course_id: $courseId) {\n _id\n course_id\n session_to_continue_id\n competence {\n _id\n total_count\n success_count\n fail_count\n }\n assignment {\n _id\n total_count\n points_max_count\n points_achieved_count\n }\n }\n }\n"): (typeof documents)["\n query dashboardProgress($courseId: ID!) {\n course_progress(course_id: $courseId) {\n _id\n course_id\n session_to_continue_id\n competence {\n _id\n total_count\n success_count\n fail_count\n }\n assignment {\n _id\n total_count\n points_max_count\n points_achieved_count\n }\n }\n }\n"];
|
||||||
|
/**
|
||||||
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||||
|
*/
|
||||||
|
export function graphql(source: "\n query dashboardCourseData($courseId: ID!) {\n course_progress(course_id: $courseId) {\n _id\n course_id\n session_to_continue_id\n widgets\n }\n }\n"): (typeof documents)["\n query dashboardCourseData($courseId: ID!) {\n course_progress(course_id: $courseId) {\n _id\n course_id\n session_to_continue_id\n widgets\n }\n }\n"];
|
||||||
/**
|
/**
|
||||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -2,6 +2,7 @@ type Query {
|
||||||
course_statistics(course_id: ID!): CourseStatisticsType
|
course_statistics(course_id: ID!): CourseStatisticsType
|
||||||
course_progress(course_id: ID!): CourseProgressType
|
course_progress(course_id: ID!): CourseProgressType
|
||||||
dashboard_config: [DashboardConfigType!]!
|
dashboard_config: [DashboardConfigType!]!
|
||||||
|
dashboard_data(course_id: ID!): DashboardConfigType
|
||||||
learning_path(id: ID, slug: String, course_id: ID, course_slug: String): LearningPathObjectType
|
learning_path(id: ID, slug: String, course_id: ID, course_slug: String): LearningPathObjectType
|
||||||
course_session_attendance_course(id: ID!, assignment_user_id: ID): CourseSessionAttendanceCourseObjectType
|
course_session_attendance_course(id: ID!, assignment_user_id: ID): CourseSessionAttendanceCourseObjectType
|
||||||
course(id: ID, slug: String): CourseObjectType
|
course(id: ID, slug: String): CourseObjectType
|
||||||
|
|
@ -177,8 +178,9 @@ type CourseProgressType {
|
||||||
_id: ID!
|
_id: ID!
|
||||||
course_id: ID!
|
course_id: ID!
|
||||||
session_to_continue_id: ID
|
session_to_continue_id: ID
|
||||||
competence: ProgressDashboardCompetenceType!
|
competence: ProgressDashboardCompetenceType
|
||||||
assignment: ProgressDashboardAssignmentType!
|
assignment: ProgressDashboardAssignmentType
|
||||||
|
widgets: [WidgetType!]!
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProgressDashboardCompetenceType {
|
type ProgressDashboardCompetenceType {
|
||||||
|
|
@ -195,6 +197,14 @@ type ProgressDashboardAssignmentType {
|
||||||
points_achieved_count: Int!
|
points_achieved_count: Int!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum WidgetType {
|
||||||
|
PROGRESS_WIDGET
|
||||||
|
COMPETENCE_WIDGET
|
||||||
|
MENTEE_WIDGET
|
||||||
|
MENTOR_TASKS_WIDGET
|
||||||
|
COMPETENCE_CERTIFICATE_WIDGET
|
||||||
|
}
|
||||||
|
|
||||||
type DashboardConfigType {
|
type DashboardConfigType {
|
||||||
id: ID!
|
id: ID!
|
||||||
name: String!
|
name: String!
|
||||||
|
|
|
||||||
|
|
@ -84,3 +84,4 @@ export const String = "String";
|
||||||
export const TopicObjectType = "TopicObjectType";
|
export const TopicObjectType = "TopicObjectType";
|
||||||
export const UUID = "UUID";
|
export const UUID = "UUID";
|
||||||
export const UserObjectType = "UserObjectType";
|
export const UserObjectType = "UserObjectType";
|
||||||
|
export const WidgetType = "WidgetType";
|
||||||
|
|
|
||||||
|
|
@ -331,6 +331,17 @@ export const DASHBOARD_COURSE_SESSION_PROGRESS = graphql(`
|
||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
export const DASHBOARD_COURSE_DATA = graphql(`
|
||||||
|
query dashboardCourseData($courseId: ID!) {
|
||||||
|
course_progress(course_id: $courseId) {
|
||||||
|
_id
|
||||||
|
course_id
|
||||||
|
session_to_continue_id
|
||||||
|
widgets
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
export const DASHBOARD_COURSE_STATISTICS = graphql(`
|
export const DASHBOARD_COURSE_STATISTICS = graphql(`
|
||||||
query courseStatistics($courseId: ID!) {
|
query courseStatistics($courseId: ID!) {
|
||||||
course_statistics(course_id: $courseId) {
|
course_statistics(course_id: $courseId) {
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ import LoadingSpinner from "@/components/ui/LoadingSpinner.vue";
|
||||||
import CourseDetailDates from "@/components/dashboard/CourseDetailDates.vue";
|
import CourseDetailDates from "@/components/dashboard/CourseDetailDates.vue";
|
||||||
import NoCourseSession from "@/components/dashboard/NoCourseSession.vue";
|
import NoCourseSession from "@/components/dashboard/NoCourseSession.vue";
|
||||||
import MentorPage from "@/pages/dashboard/MentorPage.vue";
|
import MentorPage from "@/pages/dashboard/MentorPage.vue";
|
||||||
|
import CoursePanel from "@/components/dashboard/CoursePanel.vue";
|
||||||
|
|
||||||
const dashboardStore = useDashboardStore();
|
const dashboardStore = useDashboardStore();
|
||||||
|
|
||||||
|
|
@ -50,6 +51,12 @@ onMounted(dashboardStore.loadDashboardDetails);
|
||||||
></ItDropdownSelect>
|
></ItDropdownSelect>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li v-for="config in dashboardStore.dashboardConfigs" :key="config.id">
|
||||||
|
<p>{{ config }}</p>
|
||||||
|
<CoursePanel :course-config="config" />
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
<component
|
<component
|
||||||
:is="boards[dashboardStore.currentDashboardConfig.dashboard_type].main"
|
:is="boards[dashboardStore.currentDashboardConfig.dashboard_type].main"
|
||||||
></component>
|
></component>
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,7 @@ export async function handleCurrentCourseSession(to: RouteLocationNormalized) {
|
||||||
courseSessionsStore._currentCourseSlug = "";
|
courseSessionsStore._currentCourseSlug = "";
|
||||||
}
|
}
|
||||||
if (!courseSessionsStore.loaded) {
|
if (!courseSessionsStore.loaded) {
|
||||||
|
console.log("handleCurrentCourseSession: loadCourseSessionsData");
|
||||||
await courseSessionsStore.loadCourseSessionsData();
|
await courseSessionsStore.loadCourseSessionsData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -77,6 +78,7 @@ export async function handleCourseSessionAsQueryParam(to: RouteLocationNormalize
|
||||||
if (userStore.loggedIn) {
|
if (userStore.loggedIn) {
|
||||||
const courseSessionsStore = useCourseSessionsStore();
|
const courseSessionsStore = useCourseSessionsStore();
|
||||||
if (!courseSessionsStore.loaded) {
|
if (!courseSessionsStore.loaded) {
|
||||||
|
console.log("handleCourseSessionAsQueryParam: loadCourseSessionsData");
|
||||||
await courseSessionsStore.loadCourseSessionsData();
|
await courseSessionsStore.loadCourseSessionsData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -387,8 +387,25 @@ router.beforeEach(updateLoggedIn);
|
||||||
router.beforeEach(redirectToLoginIfRequired);
|
router.beforeEach(redirectToLoginIfRequired);
|
||||||
|
|
||||||
// register after login hooks
|
// register after login hooks
|
||||||
router.beforeEach(handleCurrentCourseSession);
|
router.beforeEach(
|
||||||
router.beforeEach(handleCourseSessionAsQueryParam);
|
async (to, from) =>
|
||||||
|
await ignoreGuardsForHomeRoute(to, from, handleCurrentCourseSession)
|
||||||
|
);
|
||||||
|
|
||||||
|
router.beforeEach(
|
||||||
|
async (to, from) =>
|
||||||
|
await ignoreGuardsForHomeRoute(to, from, handleCourseSessionAsQueryParam)
|
||||||
|
);
|
||||||
|
|
||||||
|
async function ignoreGuardsForHomeRoute(
|
||||||
|
to: RouteLocationNormalized,
|
||||||
|
from: RouteLocationNormalized,
|
||||||
|
guard: NavigationGuardNext
|
||||||
|
) {
|
||||||
|
if (to.name !== "home") {
|
||||||
|
return await guard(to, from);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
router.beforeEach(addToHistory);
|
router.beforeEach(addToHistory);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { graphqlClient } from "@/graphql/client";
|
import { graphqlClient } from "@/graphql/client";
|
||||||
import {
|
import {
|
||||||
DASHBOARD_CONFIG,
|
DASHBOARD_CONFIG,
|
||||||
|
DASHBOARD_COURSE_DATA,
|
||||||
DASHBOARD_COURSE_SESSION_PROGRESS,
|
DASHBOARD_COURSE_SESSION_PROGRESS,
|
||||||
DASHBOARD_COURSE_STATISTICS,
|
DASHBOARD_COURSE_STATISTICS,
|
||||||
} from "@/graphql/queries";
|
} from "@/graphql/queries";
|
||||||
|
|
@ -61,3 +62,21 @@ export const fetchDashboardConfig = async (): Promise<DashboardConfigType[] | nu
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const fetchCourseData = async (
|
||||||
|
courseId: string
|
||||||
|
): Promise<CourseProgressType | null> => {
|
||||||
|
try {
|
||||||
|
const res = await graphqlClient.query(DASHBOARD_COURSE_DATA, {
|
||||||
|
courseId,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res.error) {
|
||||||
|
console.error("Error fetching data for course ID:", courseId, res.error);
|
||||||
|
}
|
||||||
|
return res.data?.course_progress || null;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error fetching data for course ID: ${courseId}`, error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ from vbv_lernwelt.dashboard.graphql.types.dashboard import (
|
||||||
DashboardType,
|
DashboardType,
|
||||||
ProgressDashboardAssignmentType,
|
ProgressDashboardAssignmentType,
|
||||||
ProgressDashboardCompetenceType,
|
ProgressDashboardCompetenceType,
|
||||||
|
WidgetType,
|
||||||
)
|
)
|
||||||
from vbv_lernwelt.iam.permissions import (
|
from vbv_lernwelt.iam.permissions import (
|
||||||
can_view_course_session,
|
can_view_course_session,
|
||||||
|
|
@ -39,6 +40,10 @@ class DashboardQuery(graphene.ObjectType):
|
||||||
graphene.NonNull(DashboardConfigType), required=True
|
graphene.NonNull(DashboardConfigType), required=True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
dashboard_data = graphene.Field(
|
||||||
|
DashboardConfigType, course_id=graphene.ID(required=True)
|
||||||
|
)
|
||||||
|
|
||||||
def resolve_course_statistics(root, info, course_id: str): # noqa
|
def resolve_course_statistics(root, info, course_id: str): # noqa
|
||||||
user = info.context.user
|
user = info.context.user
|
||||||
course = Course.objects.get(id=course_id)
|
course = Course.objects.get(id=course_id)
|
||||||
|
|
@ -164,8 +169,12 @@ class DashboardQuery(graphene.ObjectType):
|
||||||
points_max_count=int(points_max_count), # noqa
|
points_max_count=int(points_max_count), # noqa
|
||||||
points_achieved_count=int(points_achieved_count), # noqa
|
points_achieved_count=int(points_achieved_count), # noqa
|
||||||
),
|
),
|
||||||
|
widgets=get_widget_for_course(course_id, user), # noqa
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def resolve_dashboard_data(root, info, course_id: str):
|
||||||
|
return get_widget_for_course(course_id, info.context.user)
|
||||||
|
|
||||||
|
|
||||||
def get_user_statistics_dashboards(user: User) -> Tuple[List[Dict[str, str]], Set[int]]:
|
def get_user_statistics_dashboards(user: User) -> Tuple[List[Dict[str, str]], Set[int]]:
|
||||||
course_ids = set()
|
course_ids = set()
|
||||||
|
|
@ -222,7 +231,6 @@ def get_user_course_session_dashboards(
|
||||||
sessions of a course, but with varying permissions?
|
sessions of a course, but with varying permissions?
|
||||||
-> We just show the simple list dashboard for now.
|
-> We just show the simple list dashboard for now.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
dashboards = []
|
dashboards = []
|
||||||
course_ids = set()
|
course_ids = set()
|
||||||
|
|
||||||
|
|
@ -246,6 +254,7 @@ def get_user_course_session_dashboards(
|
||||||
resolved_dashboard_type = DashboardType.SIMPLE_DASHBOARD
|
resolved_dashboard_type = DashboardType.SIMPLE_DASHBOARD
|
||||||
elif course_role == CourseSessionUser.Role.MEMBER:
|
elif course_role == CourseSessionUser.Role.MEMBER:
|
||||||
resolved_dashboard_type = DashboardType.PROGRESS_DASHBOARD
|
resolved_dashboard_type = DashboardType.PROGRESS_DASHBOARD
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# fallback: just go with simple list dashboard
|
# fallback: just go with simple list dashboard
|
||||||
resolved_dashboard_type = DashboardType.SIMPLE_DASHBOARD
|
resolved_dashboard_type = DashboardType.SIMPLE_DASHBOARD
|
||||||
|
|
@ -263,3 +272,42 @@ def get_user_course_session_dashboards(
|
||||||
)
|
)
|
||||||
|
|
||||||
return dashboards, course_ids
|
return dashboards, course_ids
|
||||||
|
|
||||||
|
|
||||||
|
def get_widget_for_course(course_id: str, user: User) -> List[WidgetType]:
|
||||||
|
widgets = []
|
||||||
|
|
||||||
|
course_sessions = CourseSession.objects.filter(course__id=course_id).prefetch_related(
|
||||||
|
"course",
|
||||||
|
"course__configuration",
|
||||||
|
)
|
||||||
|
roles_by_course: Dict[Course, Set[DashboardType]] = {}
|
||||||
|
|
||||||
|
learning_mentors = LearningMentor.objects.filter(mentor=user).values_list(
|
||||||
|
"course_session__course__id", "id"
|
||||||
|
)
|
||||||
|
mentor_course_ids = set([mentor[0] for mentor in learning_mentors])
|
||||||
|
|
||||||
|
# duplicate code
|
||||||
|
for course_session in course_sessions:
|
||||||
|
if can_view_course_session(user=user, course_session=course_session):
|
||||||
|
role = CourseSessionUser.objects.get(
|
||||||
|
course_session=course_session, user=user
|
||||||
|
).role
|
||||||
|
roles_by_course.setdefault(course_session.course, set())
|
||||||
|
roles_by_course[course_session.course].add(role)
|
||||||
|
|
||||||
|
for course, roles in roles_by_course.items():
|
||||||
|
if len(roles) == 1:
|
||||||
|
course_role = roles.pop()
|
||||||
|
|
||||||
|
# test widgets
|
||||||
|
if course_role == CourseSessionUser.Role.MEMBER:
|
||||||
|
widgets.append(WidgetType.PROGRESS_WIDGET)
|
||||||
|
widgets.append(WidgetType.COMPETENCE_WIDGET)
|
||||||
|
if course.configuration.enable_competence_certificates:
|
||||||
|
widgets.append(WidgetType.COMPETENCE_CERTIFICATE_WIDGET)
|
||||||
|
if course.id in mentor_course_ids:
|
||||||
|
widgets.append(WidgetType.MENTOR_TASKS_WIDGET)
|
||||||
|
# add KN if has KN
|
||||||
|
return widgets
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,14 @@ class DashboardType(Enum):
|
||||||
MENTOR_DASHBOARD = "MentorDashboard"
|
MENTOR_DASHBOARD = "MentorDashboard"
|
||||||
|
|
||||||
|
|
||||||
|
class WidgetType(Enum):
|
||||||
|
PROGRESS_WIDGET = "ProgressWidget"
|
||||||
|
COMPETENCE_WIDGET = "CompetenceWidget"
|
||||||
|
MENTEE_WIDGET = "MenteeWidget"
|
||||||
|
MENTOR_TASKS_WIDGET = "MentorTasksWidget"
|
||||||
|
COMPETENCE_CERTIFICATE_WIDGET = "CompetenceCertificateWidget"
|
||||||
|
|
||||||
|
|
||||||
class DashboardConfigType(graphene.ObjectType):
|
class DashboardConfigType(graphene.ObjectType):
|
||||||
id = graphene.ID(required=True)
|
id = graphene.ID(required=True)
|
||||||
name = graphene.String(required=True)
|
name = graphene.String(required=True)
|
||||||
|
|
@ -64,6 +72,11 @@ class DashboardConfigType(graphene.ObjectType):
|
||||||
course_configuration = graphene.Field(CourseConfigurationObjectType, required=True)
|
course_configuration = graphene.Field(CourseConfigurationObjectType, required=True)
|
||||||
|
|
||||||
|
|
||||||
|
class DashboardDataType(graphene.ObjectType):
|
||||||
|
id = graphene.ID(required=True)
|
||||||
|
widgets = graphene.List(graphene.NonNull(WidgetType), required=True)
|
||||||
|
|
||||||
|
|
||||||
class ProgressDashboardCompetenceType(graphene.ObjectType):
|
class ProgressDashboardCompetenceType(graphene.ObjectType):
|
||||||
_id = graphene.ID(required=True)
|
_id = graphene.ID(required=True)
|
||||||
total_count = graphene.Int(required=True)
|
total_count = graphene.Int(required=True)
|
||||||
|
|
@ -82,8 +95,9 @@ class CourseProgressType(graphene.ObjectType):
|
||||||
_id = graphene.ID(required=True)
|
_id = graphene.ID(required=True)
|
||||||
course_id = graphene.ID(required=True)
|
course_id = graphene.ID(required=True)
|
||||||
session_to_continue_id = graphene.ID(required=False)
|
session_to_continue_id = graphene.ID(required=False)
|
||||||
competence = graphene.Field(ProgressDashboardCompetenceType, required=True)
|
competence = graphene.Field(ProgressDashboardCompetenceType, required=False)
|
||||||
assignment = graphene.Field(ProgressDashboardAssignmentType, required=True)
|
assignment = graphene.Field(ProgressDashboardAssignmentType, required=False)
|
||||||
|
widgets = graphene.List(graphene.NonNull(WidgetType), required=True)
|
||||||
|
|
||||||
|
|
||||||
class CourseStatisticsType(graphene.ObjectType):
|
class CourseStatisticsType(graphene.ObjectType):
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue