Refactor completions query to get completions for a list of users
This commit is contained in:
parent
9674abfa94
commit
da348b7756
|
|
@ -1,12 +1,7 @@
|
|||
import { useCSRFFetch } from "@/fetchHelpers";
|
||||
import type { CourseStatisticsType } from "@/gql/graphql";
|
||||
import { graphqlClient } from "@/graphql/client";
|
||||
import {
|
||||
COMPETENCE_NAVI_CERTIFICATE_FOR_USER_QUERY,
|
||||
COMPETENCE_NAVI_CERTIFICATE_QUERY,
|
||||
COURSE_QUERY,
|
||||
COURSE_SESSION_DETAIL_QUERY,
|
||||
} from "@/graphql/queries";
|
||||
import { COURSE_QUERY, COURSE_SESSION_DETAIL_QUERY } from "@/graphql/queries";
|
||||
import {
|
||||
circleFlatChildren,
|
||||
circleFlatLearningContents,
|
||||
|
|
@ -31,6 +26,7 @@ import { useDashboardStore } from "@/stores/dashboard";
|
|||
import { useUserStore } from "@/stores/user";
|
||||
import type {
|
||||
ActionCompetence,
|
||||
AgentParticipantRelation,
|
||||
CircleType,
|
||||
Course,
|
||||
CourseCompletion,
|
||||
|
|
@ -39,7 +35,6 @@ import type {
|
|||
CourseSessionDetail,
|
||||
DashboardPersonsPageMode,
|
||||
LearningContentWithCompletion,
|
||||
AgentParticipantRelation,
|
||||
LearningPathType,
|
||||
LearningUnitPerformanceCriteria,
|
||||
PerformanceCriteria,
|
||||
|
|
@ -51,7 +46,7 @@ import orderBy from "lodash/orderBy";
|
|||
import log from "loglevel";
|
||||
import type { ComputedRef, Ref } from "vue";
|
||||
import { computed, onMounted, ref, watchEffect } from "vue";
|
||||
import { useRouter, type RouteLocationRaw } from "vue-router";
|
||||
import { type RouteLocationRaw, useRouter } from "vue-router";
|
||||
|
||||
export function useCurrentCourseSession() {
|
||||
/**
|
||||
|
|
@ -674,32 +669,6 @@ export function useCourseStatisticsv2(courseSlug: string) {
|
|||
};
|
||||
}
|
||||
|
||||
export function useCertificateQuery(userId: string | undefined, courseSlug: string) {
|
||||
const certificatesQuery = (() => {
|
||||
const courseSession = useCurrentCourseSession();
|
||||
if (userId) {
|
||||
return useQuery({
|
||||
query: COMPETENCE_NAVI_CERTIFICATE_FOR_USER_QUERY,
|
||||
variables: {
|
||||
courseSlug: courseSlug,
|
||||
courseSessionId: courseSession.value.id,
|
||||
userId: userId,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
return useQuery({
|
||||
query: COMPETENCE_NAVI_CERTIFICATE_QUERY,
|
||||
variables: {
|
||||
courseSlug: courseSlug,
|
||||
courseSessionId: courseSession.value.id,
|
||||
},
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
||||
return { certificatesQuery };
|
||||
}
|
||||
|
||||
export function useEvaluationWithFeedback() {
|
||||
const currentCourseSession = useCurrentCourseSession();
|
||||
const hasFeedback = computed(
|
||||
|
|
|
|||
|
|
@ -18,8 +18,7 @@ const documents = {
|
|||
"\n fragment CoursePageFields on CoursePageInterface {\n title\n id\n slug\n content_type\n frontend_url\n }\n": types.CoursePageFieldsFragmentDoc,
|
||||
"\n query attendanceCheckQuery($courseSessionId: ID!) {\n course_session_attendance_course(id: $courseSessionId) {\n id\n attendance_user_list {\n user_id\n status\n }\n }\n }\n": types.AttendanceCheckQueryDocument,
|
||||
"\n query assignmentCompletionQuery(\n $assignmentId: ID!\n $courseSessionId: ID!\n $learningContentId: ID\n $assignmentUserId: UUID\n ) {\n assignment(id: $assignmentId) {\n assignment_type\n needs_expert_evaluation\n max_points\n content_type\n effort_required\n evaluation_description\n evaluation_document_url\n evaluation_tasks\n id\n intro_text\n performance_objectives\n slug\n tasks\n title\n translation_key\n solution_sample {\n id\n url\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n assignment_completion(\n assignment_id: $assignmentId\n course_session_id: $courseSessionId\n assignment_user_id: $assignmentUserId\n learning_content_page_id: $learningContentId\n ) {\n id\n completion_status\n submitted_at\n evaluation_submitted_at\n evaluation_user {\n id\n first_name\n last_name\n }\n assignment_user {\n avatar_url\n first_name\n last_name\n id\n }\n evaluation_points\n evaluation_max_points\n evaluation_points_deducted\n evaluation_points_deducted_reason\n evaluation_points_final\n\n evaluation_passed\n edoniq_extended_time_flag\n completion_data\n task_completion_data\n }\n }\n": types.AssignmentCompletionQueryDocument,
|
||||
"\n query competenceCertificateQuery($courseSlug: String!, $courseSessionId: ID!) {\n competence_certificate_list(course_slug: $courseSlug) {\n ...CoursePageFields\n competence_certificates {\n ...CoursePageFields\n assignments {\n ...CoursePageFields\n assignment_type\n max_points\n competence_certificate_weight\n completion(course_session_id: $courseSessionId) {\n id\n completion_status\n submitted_at\n evaluation_points\n evaluation_points_deducted\n evaluation_points_final\n evaluation_max_points\n evaluation_passed\n }\n learning_content {\n ...CoursePageFields\n circle {\n id\n title\n slug\n }\n }\n }\n }\n }\n }\n": types.CompetenceCertificateQueryDocument,
|
||||
"\n query competenceCertificateForUserQuery(\n $courseSlug: String!\n $courseSessionId: ID!\n $userId: UUID!\n ) {\n competence_certificate_list_for_user(course_slug: $courseSlug, user_id: $userId) {\n ...CoursePageFields\n competence_certificates {\n ...CoursePageFields\n assignments {\n ...CoursePageFields\n assignment_type\n max_points\n competence_certificate_weight\n completion(course_session_id: $courseSessionId) {\n id\n completion_status\n submitted_at\n evaluation_points\n evaluation_points_final\n evaluation_points_deducted\n evaluation_max_points\n evaluation_passed\n }\n learning_content {\n ...CoursePageFields\n circle {\n id\n title\n slug\n }\n }\n }\n }\n }\n }\n": types.CompetenceCertificateForUserQueryDocument,
|
||||
"\n query competenceCertificateForUserQuery(\n $courseSlug: String!\n $courseSessionId: ID!\n $userIds: [UUID!]!\n ) {\n competence_certificate_list(course_slug: $courseSlug, user_ids: $userIds) {\n ...CoursePageFields\n competence_certificates {\n ...CoursePageFields\n assignments {\n ...CoursePageFields\n assignment_type\n max_points\n competence_certificate_weight\n completions(course_session_id: $courseSessionId) {\n id\n completion_status\n submitted_at\n evaluation_points\n evaluation_points_final\n evaluation_points_deducted\n evaluation_max_points\n evaluation_passed\n }\n learning_content {\n ...CoursePageFields\n circle {\n id\n title\n slug\n }\n }\n }\n }\n }\n }\n": types.CompetenceCertificateForUserQueryDocument,
|
||||
"\n query courseSessionDetail($courseSessionId: ID!) {\n course_session(id: $courseSessionId) {\n id\n title\n course {\n id\n title\n slug\n configuration {\n id\n enable_circle_documents\n enable_learning_mentor\n enable_competence_certificates\n }\n }\n users {\n id\n user_id\n first_name\n last_name\n email\n avatar_url\n role\n circles {\n id\n title\n slug\n }\n }\n attendance_courses {\n id\n location\n trainer\n due_date {\n id\n start\n end\n }\n learning_content_id\n learning_content {\n id\n title\n circle {\n id\n title\n slug\n }\n }\n }\n assignments {\n id\n submission_deadline {\n id\n start\n }\n evaluation_deadline {\n id\n start\n }\n learning_content {\n id\n title\n content_assignment {\n id\n title\n assignment_type\n }\n }\n }\n edoniq_tests {\n id\n deadline {\n id\n start\n end\n }\n learning_content {\n id\n title\n content_assignment {\n id\n title\n assignment_type\n }\n }\n }\n }\n }\n": types.CourseSessionDetailDocument,
|
||||
"\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 is_uk\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 is_uk\n }\n }\n }\n": types.DashboardConfigDocument,
|
||||
|
|
@ -67,11 +66,7 @@ export function graphql(source: "\n query assignmentCompletionQuery(\n $assi
|
|||
/**
|
||||
* 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 competenceCertificateQuery($courseSlug: String!, $courseSessionId: ID!) {\n competence_certificate_list(course_slug: $courseSlug) {\n ...CoursePageFields\n competence_certificates {\n ...CoursePageFields\n assignments {\n ...CoursePageFields\n assignment_type\n max_points\n competence_certificate_weight\n completion(course_session_id: $courseSessionId) {\n id\n completion_status\n submitted_at\n evaluation_points\n evaluation_points_deducted\n evaluation_points_final\n evaluation_max_points\n evaluation_passed\n }\n learning_content {\n ...CoursePageFields\n circle {\n id\n title\n slug\n }\n }\n }\n }\n }\n }\n"): (typeof documents)["\n query competenceCertificateQuery($courseSlug: String!, $courseSessionId: ID!) {\n competence_certificate_list(course_slug: $courseSlug) {\n ...CoursePageFields\n competence_certificates {\n ...CoursePageFields\n assignments {\n ...CoursePageFields\n assignment_type\n max_points\n competence_certificate_weight\n completion(course_session_id: $courseSessionId) {\n id\n completion_status\n submitted_at\n evaluation_points\n evaluation_points_deducted\n evaluation_points_final\n evaluation_max_points\n evaluation_passed\n }\n learning_content {\n ...CoursePageFields\n circle {\n id\n title\n slug\n }\n }\n }\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 competenceCertificateForUserQuery(\n $courseSlug: String!\n $courseSessionId: ID!\n $userId: UUID!\n ) {\n competence_certificate_list_for_user(course_slug: $courseSlug, user_id: $userId) {\n ...CoursePageFields\n competence_certificates {\n ...CoursePageFields\n assignments {\n ...CoursePageFields\n assignment_type\n max_points\n competence_certificate_weight\n completion(course_session_id: $courseSessionId) {\n id\n completion_status\n submitted_at\n evaluation_points\n evaluation_points_final\n evaluation_points_deducted\n evaluation_max_points\n evaluation_passed\n }\n learning_content {\n ...CoursePageFields\n circle {\n id\n title\n slug\n }\n }\n }\n }\n }\n }\n"): (typeof documents)["\n query competenceCertificateForUserQuery(\n $courseSlug: String!\n $courseSessionId: ID!\n $userId: UUID!\n ) {\n competence_certificate_list_for_user(course_slug: $courseSlug, user_id: $userId) {\n ...CoursePageFields\n competence_certificates {\n ...CoursePageFields\n assignments {\n ...CoursePageFields\n assignment_type\n max_points\n competence_certificate_weight\n completion(course_session_id: $courseSessionId) {\n id\n completion_status\n submitted_at\n evaluation_points\n evaluation_points_final\n evaluation_points_deducted\n evaluation_max_points\n evaluation_passed\n }\n learning_content {\n ...CoursePageFields\n circle {\n id\n title\n slug\n }\n }\n }\n }\n }\n }\n"];
|
||||
export function graphql(source: "\n query competenceCertificateForUserQuery(\n $courseSlug: String!\n $courseSessionId: ID!\n $userIds: [UUID!]!\n ) {\n competence_certificate_list(course_slug: $courseSlug, user_ids: $userIds) {\n ...CoursePageFields\n competence_certificates {\n ...CoursePageFields\n assignments {\n ...CoursePageFields\n assignment_type\n max_points\n competence_certificate_weight\n completions(course_session_id: $courseSessionId) {\n id\n completion_status\n submitted_at\n evaluation_points\n evaluation_points_final\n evaluation_points_deducted\n evaluation_max_points\n evaluation_passed\n }\n learning_content {\n ...CoursePageFields\n circle {\n id\n title\n slug\n }\n }\n }\n }\n }\n }\n"): (typeof documents)["\n query competenceCertificateForUserQuery(\n $courseSlug: String!\n $courseSessionId: ID!\n $userIds: [UUID!]!\n ) {\n competence_certificate_list(course_slug: $courseSlug, user_ids: $userIds) {\n ...CoursePageFields\n competence_certificates {\n ...CoursePageFields\n assignments {\n ...CoursePageFields\n assignment_type\n max_points\n competence_certificate_weight\n completions(course_session_id: $courseSessionId) {\n id\n completion_status\n submitted_at\n evaluation_points\n evaluation_points_final\n evaluation_points_deducted\n evaluation_max_points\n evaluation_passed\n }\n learning_content {\n ...CoursePageFields\n circle {\n id\n title\n slug\n }\n }\n }\n }\n }\n }\n"];
|
||||
/**
|
||||
* 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
|
|
@ -20,8 +20,7 @@ type Query {
|
|||
learning_content_video: LearningContentVideoObjectType
|
||||
learning_content_document_list: LearningContentDocumentListObjectType
|
||||
competence_certificate(id: ID, slug: String): CompetenceCertificateObjectType
|
||||
competence_certificate_list(id: ID, slug: String, course_id: ID, course_slug: String): CompetenceCertificateListObjectType
|
||||
competence_certificate_list_for_user(id: ID, slug: String, course_id: ID, course_slug: String, user_id: UUID): CompetenceCertificateListObjectType
|
||||
competence_certificate_list(id: ID, slug: String, course_id: ID, course_slug: String, user_ids: [UUID]): CompetenceCertificateListObjectType
|
||||
assignment(id: ID, slug: String): AssignmentObjectType
|
||||
assignment_completion(assignment_id: ID!, course_session_id: ID!, learning_content_page_id: ID, assignment_user_id: UUID): AssignmentCompletionObjectType
|
||||
}
|
||||
|
|
@ -520,7 +519,7 @@ type AssignmentObjectType implements CoursePageInterface {
|
|||
max_points: Int
|
||||
competence_certificate_weight: Float
|
||||
learning_content: LearningContentInterface
|
||||
completion(course_session_id: ID!, learning_content_page_id: ID, assignment_user_id: UUID): AssignmentCompletionObjectType
|
||||
completions(course_session_id: ID!, learning_content_page_id: ID, assignment_user_ids: [UUID]): [AssignmentCompletionObjectType]
|
||||
solution_sample: ContentDocumentObjectType
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -90,47 +90,12 @@ export const ASSIGNMENT_COMPLETION_QUERY = graphql(`
|
|||
`);
|
||||
|
||||
export const COMPETENCE_NAVI_CERTIFICATE_QUERY = graphql(`
|
||||
query competenceCertificateQuery($courseSlug: String!, $courseSessionId: ID!) {
|
||||
competence_certificate_list(course_slug: $courseSlug) {
|
||||
...CoursePageFields
|
||||
competence_certificates {
|
||||
...CoursePageFields
|
||||
assignments {
|
||||
...CoursePageFields
|
||||
assignment_type
|
||||
max_points
|
||||
competence_certificate_weight
|
||||
completion(course_session_id: $courseSessionId) {
|
||||
id
|
||||
completion_status
|
||||
submitted_at
|
||||
evaluation_points
|
||||
evaluation_points_deducted
|
||||
evaluation_points_final
|
||||
evaluation_max_points
|
||||
evaluation_passed
|
||||
}
|
||||
learning_content {
|
||||
...CoursePageFields
|
||||
circle {
|
||||
id
|
||||
title
|
||||
slug
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
export const COMPETENCE_NAVI_CERTIFICATE_FOR_USER_QUERY = graphql(`
|
||||
query competenceCertificateForUserQuery(
|
||||
$courseSlug: String!
|
||||
$courseSessionId: ID!
|
||||
$userId: UUID!
|
||||
$userIds: [UUID!]!
|
||||
) {
|
||||
competence_certificate_list_for_user(course_slug: $courseSlug, user_id: $userId) {
|
||||
competence_certificate_list(course_slug: $courseSlug, user_ids: $userIds) {
|
||||
...CoursePageFields
|
||||
competence_certificates {
|
||||
...CoursePageFields
|
||||
|
|
@ -139,7 +104,7 @@ export const COMPETENCE_NAVI_CERTIFICATE_FOR_USER_QUERY = graphql(`
|
|||
assignment_type
|
||||
max_points
|
||||
competence_certificate_weight
|
||||
completion(course_session_id: $courseSessionId) {
|
||||
completions(course_session_id: $courseSessionId) {
|
||||
id
|
||||
completion_status
|
||||
submitted_at
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ const getIconName = () => {
|
|||
</div>
|
||||
<div class="grow lg:px-8">
|
||||
<div
|
||||
v-if="assignment.completion?.completion_status === 'EVALUATION_SUBMITTED'"
|
||||
v-if="assignment.completions[0]?.completion_status === 'EVALUATION_SUBMITTED'"
|
||||
class="flex items-center"
|
||||
>
|
||||
<div
|
||||
|
|
@ -61,7 +61,7 @@ const getIconName = () => {
|
|||
<div
|
||||
v-else-if="
|
||||
['EVALUATION_IN_PROGRESS', 'SUBMITTED'].includes(
|
||||
assignment.completion?.completion_status || ''
|
||||
assignment.completions[0]?.completion_status || ''
|
||||
)
|
||||
"
|
||||
class="flex items-center"
|
||||
|
|
@ -76,31 +76,31 @@ const getIconName = () => {
|
|||
</div>
|
||||
<div>
|
||||
<div
|
||||
v-if="assignment.completion?.completion_status === 'EVALUATION_SUBMITTED'"
|
||||
v-if="assignment.completions[0]?.completion_status === 'EVALUATION_SUBMITTED'"
|
||||
class="flex flex-col lg:items-center"
|
||||
>
|
||||
<div class="flex flex-col lg:items-center">
|
||||
<div class="heading-2">
|
||||
{{ assignment.completion?.evaluation_points_final }}
|
||||
{{ assignment.completions[0]?.evaluation_points_final }}
|
||||
</div>
|
||||
<div>
|
||||
{{ $t("assignment.von x Punkten", { x: assignment.max_points }) }}
|
||||
({{
|
||||
(
|
||||
((assignment.completion?.evaluation_points_final ?? 0) /
|
||||
(assignment.completion?.evaluation_max_points ?? 1)) *
|
||||
((assignment.completions[0]?.evaluation_points_final ?? 0) /
|
||||
(assignment.completions[0]?.evaluation_max_points ?? 1)) *
|
||||
100
|
||||
).toFixed(0)
|
||||
}}%)
|
||||
</div>
|
||||
<div
|
||||
v-if="(assignment.completion?.evaluation_points_deducted ?? 0) > 0"
|
||||
v-if="(assignment.completions[0]?.evaluation_points_deducted ?? 0) > 0"
|
||||
class="text-gray-900"
|
||||
>
|
||||
{{ $t("a.mit Abzug") }}
|
||||
</div>
|
||||
<div
|
||||
v-if="assignment.completion && !assignment.completion.evaluation_passed"
|
||||
v-if="assignment.completions[0] && !assignment.completions[0].evaluation_passed"
|
||||
class="my-2 rounded-md bg-error-red-200 px-2.5 py-0.5"
|
||||
>
|
||||
{{ $t("a.Nicht Bestanden") }}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ const userGradeRounded2Places = computed(() => {
|
|||
|
||||
const numAssignmentsEvaluated = computed(() => {
|
||||
return props.competenceCertificate.assignments.filter((a) => {
|
||||
return a.completion?.completion_status === "EVALUATION_SUBMITTED";
|
||||
return a.completions[0]?.completion_status === "EVALUATION_SUBMITTED";
|
||||
}).length;
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -2,10 +2,12 @@
|
|||
import log from "loglevel";
|
||||
import { computed } from "vue";
|
||||
import type { CompetenceCertificate } from "@/types";
|
||||
import { useCertificateQuery } from "@/composables";
|
||||
import { useCurrentCourseSession } from "@/composables";
|
||||
import CompetenceCertificateComponent from "@/pages/competence/CompetenceCertificateComponent.vue";
|
||||
import { getCertificates } from "@/services/competence";
|
||||
import { getPreviousRoute } from "@/router/history";
|
||||
import { useQuery } from "@urql/vue";
|
||||
import { COMPETENCE_NAVI_CERTIFICATE_QUERY } from "@/graphql/queries";
|
||||
import { useUserStore } from "@/stores/user";
|
||||
|
||||
const props = defineProps<{
|
||||
courseSlug: string;
|
||||
|
|
@ -15,24 +17,29 @@ const props = defineProps<{
|
|||
|
||||
log.debug("CompetenceCertificateDetailPage setup", props);
|
||||
|
||||
const certificatesQuery = useCertificateQuery(
|
||||
props.userId,
|
||||
props.courseSlug
|
||||
).certificatesQuery;
|
||||
const user = useUserStore();
|
||||
const courseSession = useCurrentCourseSession();
|
||||
|
||||
const certificatesQuery = useQuery({
|
||||
query: COMPETENCE_NAVI_CERTIFICATE_QUERY,
|
||||
variables: {
|
||||
courseSlug: props.courseSlug,
|
||||
courseSessionId: courseSession.value.id,
|
||||
userIds: [user.id ?? user.id],
|
||||
},
|
||||
});
|
||||
|
||||
const competenceCertificates = computed(() => {
|
||||
return (
|
||||
(certificatesQuery.data.value?.competence_certificate_list
|
||||
?.competence_certificates as unknown as CompetenceCertificate[]) ?? []
|
||||
);
|
||||
});
|
||||
|
||||
const certificate = computed(() => {
|
||||
const certificates = getCertificates(
|
||||
certificatesQuery.data.value,
|
||||
props.userId ?? null
|
||||
return competenceCertificates.value.find((cc) =>
|
||||
cc.slug.endsWith(props.certificateSlug)
|
||||
);
|
||||
|
||||
if (!certificates) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
(certificates.competence_certificates as unknown as CompetenceCertificate[]) ?? []
|
||||
).find((cc) => cc.slug.endsWith(props.certificateSlug));
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -2,14 +2,16 @@
|
|||
import log from "loglevel";
|
||||
import { computed, onMounted } from "vue";
|
||||
import type { CompetenceCertificate } from "@/types";
|
||||
import { useCertificateQuery } from "@/composables";
|
||||
import { useCurrentCourseSession } from "@/composables";
|
||||
import CompetenceCertificateComponent from "@/pages/competence/CompetenceCertificateComponent.vue";
|
||||
import {
|
||||
assignmentsUserPoints,
|
||||
calcCompetencesTotalGrade,
|
||||
} from "@/pages/competence/utils";
|
||||
import { useRoute } from "vue-router";
|
||||
import { getCertificates } from "@/services/competence";
|
||||
import { useQuery } from "@urql/vue";
|
||||
import { COMPETENCE_NAVI_CERTIFICATE_QUERY } from "@/graphql/queries";
|
||||
import { useUserStore } from "@/stores/user";
|
||||
|
||||
const props = defineProps<{
|
||||
courseSlug: string;
|
||||
|
|
@ -20,23 +22,22 @@ log.debug("CompetenceCertificateListPage setup", props);
|
|||
|
||||
const route = useRoute();
|
||||
|
||||
const certificatesQuery = useCertificateQuery(
|
||||
props.userId,
|
||||
props.courseSlug
|
||||
).certificatesQuery;
|
||||
const user = useUserStore();
|
||||
const courseSession = useCurrentCourseSession();
|
||||
|
||||
const certificatesQuery = useQuery({
|
||||
query: COMPETENCE_NAVI_CERTIFICATE_QUERY,
|
||||
variables: {
|
||||
courseSlug: props.courseSlug,
|
||||
courseSessionId: courseSession.value.id,
|
||||
userIds: [user.id ?? user.id],
|
||||
},
|
||||
});
|
||||
|
||||
const competenceCertificates = computed(() => {
|
||||
const certificates = getCertificates(
|
||||
certificatesQuery.data.value,
|
||||
props.userId ?? null
|
||||
);
|
||||
|
||||
if (!certificates) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
(certificates?.competence_certificates as unknown as CompetenceCertificate[]) ?? []
|
||||
(certificatesQuery.data.value?.competence_certificate_list
|
||||
?.competence_certificates as unknown as CompetenceCertificate[]) ?? []
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -54,7 +55,7 @@ const userPointsEvaluatedAssignments = computed(() => {
|
|||
|
||||
const numAssignmentsEvaluated = computed(() => {
|
||||
return (assignments.value ?? []).filter((a) => {
|
||||
return a.completion?.completion_status === "EVALUATION_SUBMITTED";
|
||||
return a.completions[0]?.completion_status === "EVALUATION_SUBMITTED";
|
||||
}).length;
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
<script setup lang="ts">
|
||||
import log from "loglevel";
|
||||
import { COMPETENCE_NAVI_CERTIFICATE_QUERY } from "@/graphql/queries";
|
||||
import {
|
||||
COMPETENCE_NAVI_CERTIFICATE_QUERY,
|
||||
} from "@/graphql/queries";
|
||||
import { useQuery } from "@urql/vue";
|
||||
import { computed } from "vue";
|
||||
import type { CompetenceCertificate } from "@/types";
|
||||
|
|
@ -24,11 +26,14 @@ log.debug("CompetenceIndexPage setup", props);
|
|||
|
||||
const courseSession = useCurrentCourseSession();
|
||||
|
||||
const user = useUserStore();
|
||||
|
||||
const certificatesQuery = useQuery({
|
||||
query: COMPETENCE_NAVI_CERTIFICATE_QUERY,
|
||||
variables: {
|
||||
courseSlug: props.courseSlug,
|
||||
courseSessionId: courseSession.value.id,
|
||||
userIds: [user.id ?? user.id],
|
||||
},
|
||||
});
|
||||
|
||||
|
|
@ -105,7 +110,8 @@ const router = useRouter();
|
|||
{{
|
||||
$t("assignment.x von y Kompetenznachweis-Elementen abgeschlossen", {
|
||||
x: certificate.assignments.filter(
|
||||
(a) => a.completion?.completion_status === "EVALUATION_SUBMITTED"
|
||||
(a) =>
|
||||
a.completions[0]?.completion_status === "EVALUATION_SUBMITTED"
|
||||
).length,
|
||||
y: certificate.assignments.length,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ export function assignmentsMaxEvaluationPoints(
|
|||
): number {
|
||||
return _.sum(
|
||||
assignments
|
||||
.filter((a) => a.completion?.completion_status === "EVALUATION_SUBMITTED")
|
||||
.filter((a) => a.completions[0]?.completion_status === "EVALUATION_SUBMITTED")
|
||||
.map((a) => a.max_points)
|
||||
);
|
||||
}
|
||||
|
|
@ -16,8 +16,8 @@ export function assignmentsMaxEvaluationPoints(
|
|||
export function assignmentsUserPoints(assignments: CompetenceCertificateAssignment[]) {
|
||||
return +_.sum(
|
||||
assignments
|
||||
.filter((a) => a.completion?.completion_status === "EVALUATION_SUBMITTED")
|
||||
.map((a) => a.completion?.evaluation_points_final ?? 0)
|
||||
.filter((a) => a.completions[0]?.completion_status === "EVALUATION_SUBMITTED")
|
||||
.map((a) => a.completions[0]?.evaluation_points_final ?? 0)
|
||||
).toFixed(1);
|
||||
}
|
||||
|
||||
|
|
@ -26,12 +26,12 @@ export function calcCompetenceCertificateGrade(
|
|||
roundedToHalfGrade = true
|
||||
) {
|
||||
const evaluatedAssignments = assignments.filter(
|
||||
(a) => a.completion?.completion_status === "EVALUATION_SUBMITTED"
|
||||
(a) => a.completions[0]?.completion_status === "EVALUATION_SUBMITTED"
|
||||
);
|
||||
|
||||
const adjustedResults = evaluatedAssignments.map((a) => {
|
||||
return (
|
||||
((a.completion?.evaluation_points_final ?? 0) / a.max_points) *
|
||||
((a.completions[0]?.evaluation_points_final ?? 0) / a.max_points) *
|
||||
a.competence_certificate_weight
|
||||
);
|
||||
});
|
||||
|
|
@ -76,7 +76,7 @@ export function competenceCertificateProgressStatusCount(
|
|||
assignments: CompetenceCertificateAssignment[]
|
||||
) {
|
||||
const numAssignmentsEvaluated = assignments.filter(
|
||||
(a) => a.completion?.completion_status === "EVALUATION_SUBMITTED"
|
||||
(a) => a.completions[0]?.completion_status === "EVALUATION_SUBMITTED"
|
||||
).length;
|
||||
return {
|
||||
SUCCESS: numAssignmentsEvaluated,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import { useDashboardStore } from "@/stores/dashboard";
|
|||
import LoadingSpinner from "@/components/ui/LoadingSpinner.vue";
|
||||
import _ from "lodash";
|
||||
import { percentToRoundedGrade } from "@/services/assignmentService";
|
||||
import { a } from "vitest/dist/suite-BWgaIsVn";
|
||||
|
||||
const dashboardStore = useDashboardStore();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,3 @@
|
|||
import type {
|
||||
CompetenceCertificateForUserQueryQuery,
|
||||
CompetenceCertificateListObjectType,
|
||||
CompetenceCertificateQueryQuery,
|
||||
} from "@/gql/graphql";
|
||||
import type { PerformanceCriteria } from "@/types";
|
||||
import groupBy from "lodash/groupBy";
|
||||
|
||||
|
|
@ -22,42 +17,3 @@ export function calcPerformanceCriteriaStatusCount(criteria: PerformanceCriteria
|
|||
FAIL: 0,
|
||||
};
|
||||
}
|
||||
|
||||
// Type guards
|
||||
export function isCompetenceCertificateForUserQueryQuery(
|
||||
data: any
|
||||
): data is CompetenceCertificateForUserQueryQuery {
|
||||
return (
|
||||
(data as CompetenceCertificateForUserQueryQuery)
|
||||
.competence_certificate_list_for_user !== undefined
|
||||
);
|
||||
}
|
||||
|
||||
export function isCompetenceCertificateQueryQuery(
|
||||
data: any
|
||||
): data is CompetenceCertificateQueryQuery {
|
||||
return (
|
||||
(data as CompetenceCertificateQueryQuery).competence_certificate_list !== undefined
|
||||
);
|
||||
}
|
||||
|
||||
export function getCertificates(
|
||||
data: any,
|
||||
userId: string | null
|
||||
): CompetenceCertificateListObjectType | null {
|
||||
if (!data) {
|
||||
return null;
|
||||
}
|
||||
let certificates = null;
|
||||
|
||||
if (userId && isCompetenceCertificateForUserQueryQuery(data)) {
|
||||
certificates = data.competence_certificate_list_for_user;
|
||||
} else if (isCompetenceCertificateQueryQuery(data)) {
|
||||
certificates = data.competence_certificate_list;
|
||||
} else {
|
||||
// Handle case where data does not match expected types
|
||||
console.error("Data structure is not recognized!");
|
||||
return null;
|
||||
}
|
||||
return (certificates as unknown as CompetenceCertificateListObjectType) ?? null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -398,7 +398,7 @@ export interface CompetenceCertificateAssignment extends BaseCourseWagtailPage {
|
|||
circle: CircleLight;
|
||||
})
|
||||
| null;
|
||||
completion: {
|
||||
completions: {
|
||||
id: string;
|
||||
completion_status: AssignmentCompletionStatus;
|
||||
evaluation_submitted_at: string | null;
|
||||
|
|
@ -408,7 +408,7 @@ export interface CompetenceCertificateAssignment extends BaseCourseWagtailPage {
|
|||
evaluation_points_reason: string;
|
||||
evaluation_max_points: number | null;
|
||||
evaluation_passed: boolean | null;
|
||||
} | null;
|
||||
}[];
|
||||
}
|
||||
|
||||
export interface CompetenceCertificate extends BaseCourseWagtailPage {
|
||||
|
|
|
|||
|
|
@ -69,11 +69,11 @@ class AssignmentObjectType(DjangoObjectType):
|
|||
max_points = graphene.Int()
|
||||
competence_certificate_weight = graphene.Float()
|
||||
learning_content = graphene.Field(LearningContentInterface)
|
||||
completion = graphene.Field(
|
||||
completions = graphene.List(
|
||||
AssignmentCompletionObjectType,
|
||||
course_session_id=graphene.ID(required=True),
|
||||
learning_content_page_id=graphene.ID(required=False),
|
||||
assignment_user_id=graphene.UUID(required=False),
|
||||
assignment_user_ids=graphene.List(graphene.UUID, required=False),
|
||||
)
|
||||
solution_sample = graphene.Field(ContentDocumentObjectType)
|
||||
|
||||
|
|
@ -103,28 +103,33 @@ class AssignmentObjectType(DjangoObjectType):
|
|||
def resolve_learning_content(self, info):
|
||||
return self.find_attached_learning_content()
|
||||
|
||||
def resolve_completion(
|
||||
def resolve_completions(
|
||||
self,
|
||||
info,
|
||||
course_session_id,
|
||||
learning_content_page_id=None,
|
||||
assignment_user_id=None,
|
||||
assignment_user_ids=None,
|
||||
):
|
||||
if learning_content_page_id is None:
|
||||
lp = self.find_attached_learning_content()
|
||||
if lp:
|
||||
learning_content_page_id = lp.id
|
||||
|
||||
if not assignment_user_id:
|
||||
assignment_user_id = getattr(info.context, "assignment_user_id", None)
|
||||
if not assignment_user_ids:
|
||||
assignment_user_ids = getattr(info.context, "assignment_user_ids", [])
|
||||
|
||||
return resolve_assignment_completion(
|
||||
completions = []
|
||||
for user_id in assignment_user_ids:
|
||||
completion = resolve_assignment_completion(
|
||||
info=info,
|
||||
course_session_id=course_session_id,
|
||||
learning_content_page_id=learning_content_page_id,
|
||||
assignment_user_id=assignment_user_id,
|
||||
assignment_user_id=user_id,
|
||||
assignment_id=self.id,
|
||||
)
|
||||
if completion:
|
||||
completions.append(completion)
|
||||
return completions
|
||||
|
||||
|
||||
def resolve_assignment_completion(
|
||||
|
|
|
|||
|
|
@ -24,47 +24,23 @@ class CompetenceCertificateQuery(object):
|
|||
slug=graphene.String(),
|
||||
course_id=graphene.ID(),
|
||||
course_slug=graphene.String(),
|
||||
)
|
||||
|
||||
competence_certificate_list_for_user = graphene.Field(
|
||||
CompetenceCertificateListObjectType,
|
||||
id=graphene.ID(),
|
||||
slug=graphene.String(),
|
||||
course_id=graphene.ID(),
|
||||
course_slug=graphene.String(),
|
||||
user_id=graphene.UUID(),
|
||||
user_ids=graphene.List(graphene.UUID),
|
||||
)
|
||||
|
||||
def resolve_competence_certificate(root, info, id=None, slug=None):
|
||||
return resolve_course_page(CompetenceCertificate, root, info, id=id, slug=slug)
|
||||
|
||||
def resolve_competence_certificate_list(
|
||||
root, info, id=None, slug=None, course_id=None, course_slug=None
|
||||
root, info, id=None, slug=None, course_id=None, course_slug=None, user_ids=None
|
||||
):
|
||||
return resolve_course_page(
|
||||
CompetenceCertificateList,
|
||||
root,
|
||||
info,
|
||||
id=id,
|
||||
slug=slug,
|
||||
course_id=course_id,
|
||||
course_slug=course_slug,
|
||||
)
|
||||
|
||||
def resolve_competence_certificate_list_for_user(
|
||||
root, info, id=None, slug=None, course_id=None, course_slug=None, user_id=None
|
||||
):
|
||||
try:
|
||||
for user_id in user_ids:
|
||||
course_session_user = CourseSessionUser.objects.filter(
|
||||
user__id=user_id
|
||||
).first()
|
||||
except CourseSessionUser.DoesNotExist:
|
||||
return None
|
||||
|
||||
if not can_view_profile(info.context.user, course_session_user):
|
||||
return None
|
||||
|
||||
setattr(info.context, "assignment_user_id", user_id)
|
||||
setattr(info.context, "assignment_user_ids", user_ids)
|
||||
|
||||
return resolve_course_page(
|
||||
CompetenceCertificateList,
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ class TestCertificateList(GraphQLTestCase):
|
|||
$courseSessionId: ID!,
|
||||
$userId: UUID!
|
||||
) {{
|
||||
competence_certificate_list_for_user(
|
||||
competence_certificate_list(
|
||||
course_slug: $courseSlug,
|
||||
user_id: $userId
|
||||
) {{
|
||||
|
|
@ -136,7 +136,7 @@ fragment CoursePageFields on CoursePageInterface {{
|
|||
# THEN
|
||||
self.assertResponseNoErrors(response)
|
||||
|
||||
certificates = response.json()["data"]["competence_certificate_list_for_user"][
|
||||
certificates = response.json()["data"]["competence_certificate_list"][
|
||||
"competence_certificates"
|
||||
]
|
||||
self.assertEqual(len(certificates), 1)
|
||||
|
|
@ -161,7 +161,7 @@ fragment CoursePageFields on CoursePageInterface {{
|
|||
$courseSessionId: ID!,
|
||||
$userId: UUID!
|
||||
) {{
|
||||
competence_certificate_list_for_user(
|
||||
competence_certificate_list(
|
||||
course_slug: $courseSlug,
|
||||
user_id: $userId
|
||||
) {{
|
||||
|
|
@ -221,7 +221,7 @@ fragment CoursePageFields on CoursePageInterface {{
|
|||
# THEN
|
||||
self.assertResponseNoErrors(response)
|
||||
self.assertIsNone(
|
||||
response.json()["data"]["competence_certificate_list_for_user"]
|
||||
response.json()["data"]["competence_certificate_list"]
|
||||
)
|
||||
|
||||
def test_member_userprofile_certificate_summary(self):
|
||||
|
|
|
|||
Loading…
Reference in New Issue