VBV-585 feat: "Wissens- und Verständnisfragen im Cockpit"
This commit is contained in:
parent
be2488ff73
commit
0ee783219b
|
|
@ -2,13 +2,13 @@
|
|||
<li
|
||||
class="flex flex-col justify-between gap-2 border-t border-gray-500 py-4 leading-[45px] lg:flex-row lg:gap-4"
|
||||
>
|
||||
<div class="flex flex-row items-center lg:w-1/3">
|
||||
<div class="flex flex-row items-center lg:w-1/4">
|
||||
<slot name="firstRow"></slot>
|
||||
</div>
|
||||
<div class="flex flex-1 lg:items-center">
|
||||
<slot name="center"></slot>
|
||||
</div>
|
||||
<div class="flex items-center lg:w-1/4">
|
||||
<div class="flex items-center">
|
||||
<slot name="link"></slot>
|
||||
</div>
|
||||
</li>
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ const documents = {
|
|||
"\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 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 }\n assignment_user {\n id\n }\n evaluation_points\n evaluation_max_points\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 completion(course_session_id: $courseSessionId) {\n id\n completion_status\n submitted_at\n evaluation_points\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 courseSessionDetail($courseSessionId: ID!) {\n course_session(id: $courseSessionId) {\n id\n title\n course {\n id\n title\n slug\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 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 }\n competence_certificate {\n ...CoursePageFields\n }\n }\n ... on LearningContentEdoniqTestObjectType {\n checkbox_text\n has_extended_time_test\n content_assignment {\n id\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 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 }\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 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,
|
||||
|
|
@ -72,7 +72,7 @@ export function graphql(source: "\n query courseSessionDetail($courseSessionId:
|
|||
/**
|
||||
* 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 courseQuery($slug: String!) {\n course(slug: $slug) {\n id\n title\n slug\n category_name\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 }\n competence_certificate {\n ...CoursePageFields\n }\n }\n ... on LearningContentEdoniqTestObjectType {\n checkbox_text\n has_extended_time_test\n content_assignment {\n id\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n ... on LearningContentRichTextObjectType {\n text\n }\n }\n }\n }\n }\n }\n }\n }\n }\n"): (typeof documents)["\n query courseQuery($slug: String!) {\n course(slug: $slug) {\n id\n title\n slug\n category_name\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 }\n competence_certificate {\n ...CoursePageFields\n }\n }\n ... on LearningContentEdoniqTestObjectType {\n checkbox_text\n has_extended_time_test\n content_assignment {\n id\n }\n competence_certificate {\n ...CoursePageFields\n }\n }\n ... on LearningContentRichTextObjectType {\n text\n }\n }\n }\n }\n }\n }\n }\n }\n }\n"];
|
||||
export function graphql(source: "\n query courseQuery($slug: String!) {\n course(slug: $slug) {\n id\n title\n slug\n category_name\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"): (typeof documents)["\n query courseQuery($slug: String!) {\n course(slug: $slug) {\n id\n title\n slug\n category_name\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"];
|
||||
/**
|
||||
* 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
|
|
@ -241,6 +241,7 @@ export const COURSE_QUERY = graphql(`
|
|||
assignment_type
|
||||
content_assignment {
|
||||
id
|
||||
assignment_type
|
||||
}
|
||||
competence_certificate {
|
||||
...CoursePageFields
|
||||
|
|
@ -251,6 +252,7 @@ export const COURSE_QUERY = graphql(`
|
|||
has_extended_time_test
|
||||
content_assignment {
|
||||
id
|
||||
assignment_type
|
||||
}
|
||||
competence_certificate {
|
||||
...CoursePageFields
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import type {
|
|||
CourseSession,
|
||||
CourseSessionUser,
|
||||
LearningContentAssignment,
|
||||
LearningContentEdoniqTest,
|
||||
} from "@/types";
|
||||
import log from "loglevel";
|
||||
import { computed, onMounted, reactive } from "vue";
|
||||
|
|
@ -14,10 +15,13 @@ import AssignmentSubmissionProgress from "@/pages/cockpit/cockpitPage/Assignment
|
|||
import { useCourseSessionDetailQuery } from "@/composables";
|
||||
import { formatDueDate } from "../../../components/dueDates/dueDatesUtils";
|
||||
import { stringifyParse } from "@/utils/utils";
|
||||
import { useTranslation } from "i18next-vue";
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
const props = defineProps<{
|
||||
courseSession: CourseSession;
|
||||
learningContentAssignment: LearningContentAssignment;
|
||||
learningContent: LearningContentAssignment | LearningContentEdoniqTest;
|
||||
}>();
|
||||
|
||||
log.debug("AssignmentDetails created", stringifyParse(props));
|
||||
|
|
@ -31,28 +35,54 @@ const state = reactive({
|
|||
});
|
||||
|
||||
const assignmentDetail = computed(() => {
|
||||
return courseSessionDetailResult.findAssignment(props.learningContentAssignment.id);
|
||||
return courseSessionDetailResult.findAssignment(props.learningContent.id);
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
const { gradedUsers, assignmentSubmittedUsers } =
|
||||
await loadAssignmentCompletionStatusData(
|
||||
props.learningContentAssignment.content_assignment.id,
|
||||
props.learningContent.content_assignment.id,
|
||||
props.courseSession.id,
|
||||
props.learningContentAssignment.id
|
||||
props.learningContent.id
|
||||
);
|
||||
state.gradedUsers = gradedUsers;
|
||||
state.assignmentSubmittedUsers = assignmentSubmittedUsers;
|
||||
});
|
||||
|
||||
function findGradedUser(userId: string) {
|
||||
return state.gradedUsers.find((gu) => gu.user.user_id === userId);
|
||||
}
|
||||
|
||||
function findUserPointsHtml(userId: string) {
|
||||
let result = "";
|
||||
const gradedUser = findGradedUser(userId);
|
||||
if (gradedUser) {
|
||||
result = `${gradedUser.points} ${t("assignment.von x Punkten", {
|
||||
x: gradedUser.maxPoints,
|
||||
})}`;
|
||||
|
||||
result +=
|
||||
" (" +
|
||||
(((gradedUser.points ?? 0) / (gradedUser.maxPoints ?? 1)) * 100).toFixed(0) +
|
||||
"%)";
|
||||
|
||||
if (!gradedUser.passed) {
|
||||
result += ` <span class="my-2 rounded-md bg-error-red-200 px-2.5 py-0.5">${t(
|
||||
"a.Nicht bestanden"
|
||||
)}</span>`;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<h2 class="heading-2 font-bold">
|
||||
{{ learningContentAssignment.title }}
|
||||
{{ learningContent.title }}
|
||||
</h2>
|
||||
<div class="pt-1 underline">
|
||||
{{ $t("a.Circle") }} «{{ learningContentAssignment.circle?.title }}»
|
||||
{{ $t("a.Circle") }} «{{ learningContent.circle?.title }}»
|
||||
</div>
|
||||
<div v-if="assignmentDetail">
|
||||
<span v-if="assignmentDetail.submission_deadline?.start">
|
||||
|
|
@ -73,7 +103,7 @@ onMounted(async () => {
|
|||
<!-- how to determine assignment-type? how to get AssignmentLearningContent? -->
|
||||
<AssignmentSubmissionProgress
|
||||
:course-session="courseSession"
|
||||
:learning-content-assignment="learningContentAssignment"
|
||||
:learning-content="learningContent"
|
||||
:show-title="false"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -88,7 +118,7 @@ onMounted(async () => {
|
|||
:data-cy="csu.last_name"
|
||||
>
|
||||
<template #center>
|
||||
<section class="flex w-full justify-between">
|
||||
<section class="flex w-full flex-col justify-between lg:flex-row lg:gap-8">
|
||||
<div
|
||||
v-if="
|
||||
state.gradedUsers.map((gradedUser) => gradedUser.user).includes(csu)
|
||||
|
|
@ -114,27 +144,28 @@ onMounted(async () => {
|
|||
<div class="ml-2">{{ $t("a.Ergebnisse abgegeben") }}</div>
|
||||
</div>
|
||||
|
||||
<!-- eslint-disable vue/no-v-html -->
|
||||
<div
|
||||
v-if="
|
||||
state.gradedUsers.map((gradedUser) => gradedUser.user).includes(csu)
|
||||
"
|
||||
>
|
||||
{{
|
||||
state.gradedUsers.find((u) => u.user.user_id === csu.user_id)?.points
|
||||
}}
|
||||
{{ $t("a.Punkte") }}
|
||||
</div>
|
||||
v-if="findGradedUser(csu.user_id)"
|
||||
v-html="findUserPointsHtml(csu.user_id)"
|
||||
></div>
|
||||
</section>
|
||||
</template>
|
||||
<template #link>
|
||||
<router-link
|
||||
v-if="state.assignmentSubmittedUsers.includes(csu)"
|
||||
:to="`/course/${props.courseSession.course.slug}/cockpit/assignment/${learningContentAssignment.content_assignment.id}/${csu.user_id}`"
|
||||
class="link lg:w-full lg:text-right"
|
||||
data-cy="show-results"
|
||||
>
|
||||
{{ $t("a.Ergebnisse anschauen") }}
|
||||
</router-link>
|
||||
<div class="lg:ml-4">
|
||||
<router-link
|
||||
v-if="
|
||||
state.assignmentSubmittedUsers.includes(csu) &&
|
||||
props.learningContent.content_type !==
|
||||
'learnpath.LearningContentEdoniqTest'
|
||||
"
|
||||
:to="`/course/${props.courseSession.course.slug}/cockpit/assignment/${learningContent.content_assignment.id}/${csu.user_id}`"
|
||||
class="link lg:w-full lg:text-right"
|
||||
data-cy="show-results"
|
||||
>
|
||||
{{ $t("a.Ergebnisse anschauen") }}
|
||||
</router-link>
|
||||
</div>
|
||||
</template>
|
||||
</ItPersonRow>
|
||||
</ul>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<script setup lang="ts">
|
||||
import { useCurrentCourseSession, useCourseData } from "@/composables";
|
||||
import { useCourseData, useCurrentCourseSession } from "@/composables";
|
||||
import AssignmentDetails from "@/pages/cockpit/assignmentsPage/AssignmentDetails.vue";
|
||||
import * as log from "loglevel";
|
||||
import { computed, onMounted } from "vue";
|
||||
import type { LearningContentAssignment } from "@/types";
|
||||
import type { LearningContentAssignment, LearningContentEdoniqTest } from "@/types";
|
||||
|
||||
const props = defineProps<{
|
||||
courseSlug: string;
|
||||
|
|
@ -42,7 +42,7 @@ const learningContentAssignment = computed(() => {
|
|||
<AssignmentDetails
|
||||
v-if="learningContentAssignment"
|
||||
:course-session="courseSession"
|
||||
:learning-content-assignment="learningContentAssignment as LearningContentAssignment"
|
||||
:learning-content="learningContentAssignment as (LearningContentAssignment | LearningContentEdoniqTest)"
|
||||
/>
|
||||
</div>
|
||||
</main>
|
||||
|
|
|
|||
|
|
@ -6,14 +6,15 @@ import type {
|
|||
AssignmentCompletionStatus,
|
||||
CourseSession,
|
||||
LearningContentAssignment,
|
||||
LearningContentEdoniqTest,
|
||||
} from "@/types";
|
||||
import log from "loglevel";
|
||||
import { onMounted, reactive } from "vue";
|
||||
import { computed, onMounted, reactive } from "vue";
|
||||
import { stringifyParse } from "@/utils/utils";
|
||||
|
||||
const props = defineProps<{
|
||||
courseSession: CourseSession;
|
||||
learningContentAssignment: LearningContentAssignment;
|
||||
learningContent: LearningContentAssignment | LearningContentEdoniqTest;
|
||||
showTitle: boolean;
|
||||
}>();
|
||||
|
||||
|
|
@ -32,9 +33,9 @@ const state = reactive({
|
|||
onMounted(async () => {
|
||||
const { assignmentSubmittedUsers, gradedUsers, total } =
|
||||
await loadAssignmentCompletionStatusData(
|
||||
props.learningContentAssignment.content_assignment.id,
|
||||
props.learningContent.content_assignment.id,
|
||||
props.courseSession.id,
|
||||
props.learningContentAssignment.id
|
||||
props.learningContent.id
|
||||
);
|
||||
|
||||
state.submissionProgressStatusCount = {
|
||||
|
|
@ -56,16 +57,31 @@ const doneCount = (status: StatusCount) => {
|
|||
const totalCount = (status: StatusCount) => {
|
||||
return doneCount(status) + status.UNKNOWN || 0;
|
||||
};
|
||||
|
||||
const showEvaluationStatus = computed(() => {
|
||||
return (
|
||||
props.learningContent.content_assignment.assignment_type === "CASEWORK" ||
|
||||
props.learningContent.content_assignment.assignment_type === "EDONIQ_TEST"
|
||||
);
|
||||
});
|
||||
|
||||
const showSubmissionStatus = computed(() => {
|
||||
return (
|
||||
props.learningContent.content_assignment.assignment_type === "PREP_ASSIGNMENT" ||
|
||||
props.learningContent.content_assignment.assignment_type === "REFLECTION" ||
|
||||
props.learningContent.content_assignment.assignment_type === "CONDITION_ACCEPTANCE"
|
||||
);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="showTitle">
|
||||
{{ props.learningContentAssignment.title }}
|
||||
{{ props.learningContent.title }}
|
||||
</div>
|
||||
<ItProgress :status-count="state.submissionProgressStatusCount" />
|
||||
<div class="text-gray-900">
|
||||
<div v-if="props.learningContentAssignment.assignment_type === 'CASEWORK'">
|
||||
<div v-if="showEvaluationStatus">
|
||||
{{
|
||||
$t("x von y Ergebnisse abgegeben", {
|
||||
x: doneCount(state.submissionProgressStatusCount),
|
||||
|
|
@ -80,13 +96,7 @@ const totalCount = (status: StatusCount) => {
|
|||
})
|
||||
}}
|
||||
</div>
|
||||
<div
|
||||
v-else-if="
|
||||
props.learningContentAssignment.assignment_type === 'PREP_ASSIGNMENT' ||
|
||||
props.learningContentAssignment.assignment_type === 'CONDITION_ACCEPTANCE' ||
|
||||
props.learningContentAssignment.assignment_type === 'REFLECTION'
|
||||
"
|
||||
>
|
||||
<div v-else-if="showSubmissionStatus">
|
||||
{{
|
||||
$t("x von y abgeschlossen", {
|
||||
x: doneCount(state.submissionProgressStatusCount),
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ const courseSessionDetailResult = useCourseSessionDetailQuery();
|
|||
>
|
||||
<template #center>
|
||||
<div
|
||||
class="mt-2 flex w-full flex-col items-center justify-between lg:mt-0 lg:flex-row"
|
||||
class="mt-2 flex w-full flex-col items-center justify-start lg:mt-0 lg:flex-row"
|
||||
>
|
||||
<LearningPathDiagram
|
||||
:course-session-id="courseSession.id"
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import type {
|
|||
CourseSession,
|
||||
LearningContent,
|
||||
LearningContentAssignment,
|
||||
LearningContentEdoniqTest,
|
||||
} from "@/types";
|
||||
import log from "loglevel";
|
||||
import { computed } from "vue";
|
||||
|
|
@ -12,8 +13,8 @@ import { useTranslation } from "i18next-vue";
|
|||
import FeedbackSubmissionProgress from "@/pages/cockpit/cockpitPage/FeedbackSubmissionProgress.vue";
|
||||
import { learningContentTypeData } from "@/utils/typeMaps";
|
||||
import {
|
||||
useCourseSessionDetailQuery,
|
||||
useCourseDataWithCompletion,
|
||||
useCourseSessionDetailQuery,
|
||||
} from "@/composables";
|
||||
import { circleFlatLearningContents } from "@/services/circle";
|
||||
|
||||
|
|
@ -51,7 +52,8 @@ const submittables = computed(() => {
|
|||
const learningContents = circleFlatLearningContents(circle).filter(
|
||||
(lc) =>
|
||||
lc.content_type === "learnpath.LearningContentAssignment" ||
|
||||
lc.content_type === "learnpath.LearningContentFeedback"
|
||||
lc.content_type === "learnpath.LearningContentFeedback" ||
|
||||
lc.content_type === "learnpath.LearningContentEdoniqTest"
|
||||
);
|
||||
|
||||
return learningContents.map((lc) => {
|
||||
|
|
@ -77,6 +79,10 @@ const isAssignment = (lc: LearningContent) => {
|
|||
return lc.content_type === "learnpath.LearningContentAssignment";
|
||||
};
|
||||
|
||||
const isEdoniqTest = (lc: LearningContent) => {
|
||||
return lc.content_type === "learnpath.LearningContentEdoniqTest";
|
||||
};
|
||||
|
||||
const getLearningContentType = (lc: LearningContent) => {
|
||||
if (isAssignment(lc)) {
|
||||
const lcTypeData = learningContentTypeData(lc);
|
||||
|
|
@ -84,8 +90,12 @@ const getLearningContentType = (lc: LearningContent) => {
|
|||
return lcTypeData.title;
|
||||
}
|
||||
return `${lcTypeData.title}: ${lc.title}`;
|
||||
} else if (isEdoniqTest(lc)) {
|
||||
return lc.title;
|
||||
} else if (isFeedback(lc)) {
|
||||
return t("Feedback: Feedback zum Lehrgang");
|
||||
}
|
||||
return t("Feedback: Feedback zum Lehrgang");
|
||||
return "!!unknown!!";
|
||||
};
|
||||
|
||||
const getShowDetailsText = (lc: LearningContent) => {
|
||||
|
|
@ -99,15 +109,21 @@ const getShowDetailsText = (lc: LearningContent) => {
|
|||
) {
|
||||
return t("Status anschauen");
|
||||
}
|
||||
} else if (isEdoniqTest(lc)) {
|
||||
return t("a.Ergebnisse anschauen");
|
||||
} else if (isFeedback(lc)) {
|
||||
return t("Feedback anschauen");
|
||||
}
|
||||
return t("Feedback anschauen");
|
||||
return "!!unknown!!";
|
||||
};
|
||||
|
||||
const getDetailsLink = (lc: LearningContent, circleId: string) => {
|
||||
if (isFeedback(lc)) {
|
||||
return `cockpit/feedback/${circleId}`;
|
||||
} else if (isAssignment(lc) || isEdoniqTest(lc)) {
|
||||
return `cockpit/assignment/${lc.id}`;
|
||||
}
|
||||
return `cockpit/assignment/${lc.id}`;
|
||||
return "";
|
||||
};
|
||||
|
||||
const getIconName = (lc: LearningContent) => {
|
||||
|
|
@ -153,9 +169,9 @@ const getIconName = (lc: LearningContent) => {
|
|||
</div>
|
||||
</div>
|
||||
<AssignmentSubmissionProgress
|
||||
v-if="isAssignment(submittable.content)"
|
||||
v-if="isAssignment(submittable.content) || isEdoniqTest(submittable.content)"
|
||||
:course-session="props.courseSession"
|
||||
:learning-content-assignment="submittable.content as LearningContentAssignment"
|
||||
:learning-content="submittable.content as (LearningContentAssignment | LearningContentEdoniqTest)"
|
||||
:show-title="false"
|
||||
class="grow pr-8"
|
||||
/>
|
||||
|
|
@ -166,7 +182,7 @@ const getIconName = (lc: LearningContent) => {
|
|||
class="grow pr-8"
|
||||
></FeedbackSubmissionProgress>
|
||||
<div class="flex items-center lg:w-1/4 lg:justify-end">
|
||||
<button class="btn-primary">
|
||||
<button v-if="submittable.detailsLink" class="btn-primary">
|
||||
<router-link
|
||||
:to="submittable.detailsLink"
|
||||
:data-cy="
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ const assignmentStats = (metrics: AssignmentCompletionMetricsType) => {
|
|||
};
|
||||
|
||||
const total = (metrics: AssignmentCompletionMetricsType) => {
|
||||
return metrics.passed_count + metrics.failed_count;
|
||||
return metrics.passed_count + metrics.failed_count + metrics.unranked_count;
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ import pick from "lodash/pick";
|
|||
export interface GradedUser {
|
||||
user: CourseSessionUser;
|
||||
points: number;
|
||||
maxPoints: number;
|
||||
passed: boolean;
|
||||
}
|
||||
|
||||
export async function loadAssignmentCompletionStatusData(
|
||||
|
|
@ -46,6 +48,8 @@ export async function loadAssignmentCompletionStatusData(
|
|||
gradedUsers.push({
|
||||
user: csu,
|
||||
points: userAssignmentStatus.evaluation_points ?? 0,
|
||||
maxPoints: userAssignmentStatus.evaluation_max_points ?? 0,
|
||||
passed: userAssignmentStatus.evaluation_passed ?? false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -531,6 +531,8 @@ export interface UserAssignmentCompletionStatus {
|
|||
assignment_user_id: string;
|
||||
completion_status: AssignmentCompletionStatus;
|
||||
evaluation_points: number | null;
|
||||
evaluation_max_points: number | null;
|
||||
evaluation_passed: boolean;
|
||||
learning_content_page_id: string;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ def request_assignment_completion_status(request, assignment_id, course_session_
|
|||
"assignment_user_id",
|
||||
"completion_status",
|
||||
"evaluation_points",
|
||||
"evaluation_max_points",
|
||||
"evaluation_passed",
|
||||
"learning_content_page_id",
|
||||
)
|
||||
|
|
|
|||
|
|
@ -17,12 +17,12 @@ from vbv_lernwelt.assignment.tests.assignment_factories import (
|
|||
from vbv_lernwelt.competence.factories import (
|
||||
ActionCompetenceFactory,
|
||||
ActionCompetenceListPageFactory,
|
||||
CompetenceCertificateFactory,
|
||||
CompetenceCertificateListFactory,
|
||||
CompetenceNaviPageFactory,
|
||||
PerformanceCriteriaFactory,
|
||||
CompetenceCertificateListFactory,
|
||||
CompetenceCertificateFactory,
|
||||
)
|
||||
from vbv_lernwelt.competence.models import PerformanceCriteria, CompetenceCertificate
|
||||
from vbv_lernwelt.competence.models import CompetenceCertificate, PerformanceCriteria
|
||||
from vbv_lernwelt.core.models import User
|
||||
from vbv_lernwelt.course.factories import CoursePageFactory
|
||||
from vbv_lernwelt.course.models import (
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ class CourseSessionEdoniqTest(models.Model):
|
|||
self.deadline.url = self.learning_content.get_frontend_url(
|
||||
course_session_id=self.course_session.id
|
||||
)
|
||||
self.deadline.url_expert = f"/course/{self.course_session.course.slug}/cockpit?courseSessionId={self.course_session.id}"
|
||||
self.deadline.url_expert = f"/course/{self.course_session.course.slug}/cockpit/assignment/{self.learning_content_id}?courseSessionId={self.course_session.id}"
|
||||
self.deadline.title = self.learning_content.title
|
||||
self.deadline.page = self.learning_content.page_ptr
|
||||
self.deadline.assignment_type_translation_key = (
|
||||
|
|
|
|||
|
|
@ -100,11 +100,11 @@ def get_assignment_completion_metrics(
|
|||
average_passed = math.ceil(passed_count / participants_count * 100)
|
||||
|
||||
return AssignmentCompletionMetricsType(
|
||||
_id=assignment.id, # noqa
|
||||
_id=f"{course_session.id}-{assignment.id}", # noqa
|
||||
passed_count=passed_count, # noqa
|
||||
failed_count=failed_count, # noqa
|
||||
unranked_count=unranked_count, # noqa
|
||||
ranking_completed=unranked_count == 0, # noqa
|
||||
ranking_completed=(passed_count > 0 or failed_count > 0), # noqa
|
||||
average_passed=average_passed, # noqa
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -11,13 +11,13 @@ from vbv_lernwelt.course.creators.test_utils import (
|
|||
create_assignment_completion,
|
||||
create_assignment_learning_content,
|
||||
create_circle,
|
||||
create_competence_certificate,
|
||||
create_course,
|
||||
create_course_session,
|
||||
create_course_session_assignment,
|
||||
create_course_session_edoniq_test,
|
||||
create_course_session_group,
|
||||
create_user,
|
||||
create_competence_certificate,
|
||||
)
|
||||
from vbv_lernwelt.course.models import CourseSession, CourseSessionUser
|
||||
from vbv_lernwelt.course_session.models import (
|
||||
|
|
@ -284,11 +284,11 @@ class AssignmentTestCase(GraphQLTestCase):
|
|||
|
||||
# 1 -> incomplete (not counted for average)
|
||||
# 2 -> complete 66% passed ...
|
||||
# 3 -> complete 100% passed --> 83.5%
|
||||
# 3 -> complete 100% passed --> 67%
|
||||
# 4 -> not included in certificate
|
||||
summary = dashboard["assignments"]["summary"]
|
||||
self.assertEqual(summary["completed_count"], 2)
|
||||
self.assertEqual(summary["average_passed"], 83.5)
|
||||
self.assertEqual(summary["completed_count"], 3)
|
||||
self.assertEqual(summary["average_passed"], 67.0)
|
||||
|
||||
records = dashboard["assignments"]["records"]
|
||||
self.assertEqual(len(records), 3)
|
||||
|
|
@ -298,7 +298,7 @@ class AssignmentTestCase(GraphQLTestCase):
|
|||
self.assertEqual(assignment_1_metrics["passed_count"], 1)
|
||||
self.assertEqual(assignment_1_metrics["failed_count"], 1)
|
||||
self.assertEqual(assignment_1_metrics["unranked_count"], 1)
|
||||
self.assertEqual(assignment_1_metrics["ranking_completed"], False)
|
||||
self.assertEqual(assignment_1_metrics["ranking_completed"], True)
|
||||
self.assertEqual(assignment_1_metrics["average_passed"], 34)
|
||||
|
||||
# 2 -> assignment_2_results
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
# Generated by Django 3.2.20 on 2023-11-08 06:47
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def set_url_expert_course_session_edoniq_test(apps, schema_editor):
|
||||
# need to load concrete model, so that wagtail page has `specific` instance method...
|
||||
from vbv_lernwelt.course_session.models import CourseSessionEdoniqTest
|
||||
|
||||
for edoniq_test in CourseSessionEdoniqTest.objects.all():
|
||||
# trigger save to update due_date foreign key fields
|
||||
edoniq_test.save()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("duedate", "0007_auto_20231010_1505"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(
|
||||
set_url_expert_course_session_edoniq_test, migrations.RunPython.noop
|
||||
),
|
||||
]
|
||||
Loading…
Reference in New Issue