From 125d3b2b1403d9876f093878aed41a111a0d9266 Mon Sep 17 00:00:00 2001 From: Elia Bieri Date: Thu, 25 Jul 2024 11:04:32 +0200 Subject: [PATCH] Calculate competence certificate grades over all course sessions --- client/src/composables.ts | 11 ++-- .../CompetenceCertificateDetailPage.vue | 6 ++- .../CompetenceCertificateListPage.vue | 51 +++++++++++++------ 3 files changed, 46 insertions(+), 22 deletions(-) diff --git a/client/src/composables.ts b/client/src/composables.ts index 15ecb645..6c231576 100644 --- a/client/src/composables.ts +++ b/client/src/composables.ts @@ -693,15 +693,18 @@ export function useCourseStatisticsv2(courseSlug: string) { }; } -export function useCertificateQuery(userId: string | undefined, courseSlug: string) { +export function useCertificateQuery( + userId: string | undefined, + courseSlug: string, + courseSession: CourseSession +) { const certificatesQuery = (() => { - const courseSession = useCurrentCourseSession(); if (userId) { return useQuery({ query: COMPETENCE_NAVI_CERTIFICATE_FOR_USER_QUERY, variables: { courseSlug: courseSlug, - courseSessionId: courseSession.value.id, + courseSessionId: courseSession.id, userId: userId, }, }); @@ -710,7 +713,7 @@ export function useCertificateQuery(userId: string | undefined, courseSlug: stri query: COMPETENCE_NAVI_CERTIFICATE_QUERY, variables: { courseSlug: courseSlug, - courseSessionId: courseSession.value.id, + courseSessionId: courseSession.id, }, }); } diff --git a/client/src/pages/competence/CompetenceCertificateDetailPage.vue b/client/src/pages/competence/CompetenceCertificateDetailPage.vue index 80bdf276..aa5dd79c 100644 --- a/client/src/pages/competence/CompetenceCertificateDetailPage.vue +++ b/client/src/pages/competence/CompetenceCertificateDetailPage.vue @@ -2,7 +2,7 @@ import log from "loglevel"; import { computed } from "vue"; import type { CompetenceCertificate } from "@/types"; -import { useCertificateQuery } from "@/composables"; +import { useCertificateQuery, useCurrentCourseSession } from "@/composables"; import CompetenceCertificateComponent from "@/pages/competence/CompetenceCertificateComponent.vue"; import { getCertificates } from "@/services/competence"; import { getPreviousRoute } from "@/router/history"; @@ -15,9 +15,11 @@ const props = defineProps<{ log.debug("CompetenceCertificateDetailPage setup", props); +const courseSession = useCurrentCourseSession(); const certificatesQuery = useCertificateQuery( props.userId, - props.courseSlug + props.courseSlug, + courseSession.value ).certificatesQuery; const certificate = computed(() => { diff --git a/client/src/pages/competence/CompetenceCertificateListPage.vue b/client/src/pages/competence/CompetenceCertificateListPage.vue index 7beb5b70..5bd80975 100644 --- a/client/src/pages/competence/CompetenceCertificateListPage.vue +++ b/client/src/pages/competence/CompetenceCertificateListPage.vue @@ -2,7 +2,7 @@ import log from "loglevel"; import { computed, onMounted } from "vue"; import type { CompetenceCertificate } from "@/types"; -import { useCertificateQuery } from "@/composables"; +import { useCertificateQuery, useCurrentCourseSession } from "@/composables"; import CompetenceCertificateComponent from "@/pages/competence/CompetenceCertificateComponent.vue"; import { assignmentsUserPoints, @@ -10,6 +10,8 @@ import { } from "@/pages/competence/utils"; import { useRoute } from "vue-router"; import { getCertificates } from "@/services/competence"; +import { useCourseSessionsStore } from "@/stores/courseSessions"; +import dayjs from "dayjs"; const props = defineProps<{ courseSlug: string; @@ -20,24 +22,41 @@ log.debug("CompetenceCertificateListPage setup", props); const route = useRoute(); -const certificatesQuery = useCertificateQuery( - props.userId, - props.courseSlug -).certificatesQuery; +const store = useCourseSessionsStore(); +const certificateQueries = store.allCourseSessions.map((courseSession) => { + return useCertificateQuery(props.userId, props.courseSlug, courseSession) + .certificatesQuery; +}); const competenceCertificates = computed(() => { - const certificates = getCertificates( - certificatesQuery.data.value, - props.userId ?? null - ); - - if (!certificates) { - return null; + const competenceCertificates: Record = {}; + for (const query of certificateQueries) { + const certificates = + (getCertificates(query.data.value, props.userId ?? null) + ?.competence_certificates as unknown as CompetenceCertificate[]) ?? []; + for (const certificate of certificates) { + if (!competenceCertificates[certificate.id]) { + // Competence certificate does not exist yet + competenceCertificates[certificate.id] = certificate; + } else { + // Merge with assignment completions of existing competence certificate. If there are multiple completions for the same assignment, keep the latest one. + competenceCertificates[certificate.id].assignments.push( + ...certificate.assignments.filter((assignment) => { + const existingAssignment = competenceCertificates[ + certificate.id + ].assignments.find((a) => a.id === assignment.id); + return ( + !existingAssignment || + dayjs(assignment.completion?.evaluation_submitted_at).isAfter( + dayjs(existingAssignment.completion?.evaluation_submitted_at) + ) + ); + }) + ); + } + } } - - return ( - (certificates?.competence_certificates as unknown as CompetenceCertificate[]) ?? [] - ); + return Object.values(competenceCertificates); }); const assignments = computed(() => {