Merged in feature/VBV-585-cockpit-edoniq-tests (pull request #229)
Feature/VBV-585 cockpit edoniq tests Approved-by: Christian Cueni
This commit is contained in:
commit
f99e58ee88
|
|
@ -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,14 +38,14 @@ 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>
|
||||
|
||||
<template>
|
||||
<main v-if="statistics">
|
||||
<div class="mb-10 flex items-center justify-between">
|
||||
<h3>{{ $t("a.Arbeiten") }}</h3>
|
||||
<h3>{{ $t("a.Kompetenznachweis-Elemente") }}</h3>
|
||||
<ItDropdownSelect
|
||||
:model-value="dashboardStore.currentDashboardConfig"
|
||||
class="mt-4 w-full lg:mt-0 lg:w-96"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ describe("assignmentTrainer.cy.js", () => {
|
|||
).click();
|
||||
|
||||
cy.get('[data-cy="Student1"]').should("contain", "Bewertung freigegeben");
|
||||
cy.get('[data-cy="Student1"]').should("contain", "17 Punkte");
|
||||
cy.get('[data-cy="Student1"]').should("contain", "17 von 24 Punkte");
|
||||
|
||||
// clicking on results page will go to last step
|
||||
cy.get('[data-cy="Student1"]').find('[data-cy="show-results"]').click();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
import {login} from "../helpers";
|
||||
import { login } from "../helpers";
|
||||
|
||||
// ignore automatic import mess-up...
|
||||
|
||||
const getDashboardStatistics = (what) => {
|
||||
return cy.get(`[data-cy="dashboard.stats.${what}"]`);
|
||||
|
|
@ -7,12 +9,14 @@ const getDashboardStatistics = (what) => {
|
|||
const clickOnDetailsLink = (within) => {
|
||||
cy.get(`[data-cy="dashboard.stats.${within}"]`).within(() => {
|
||||
cy.get('[data-cy="basebox.detailsLink"]').click();
|
||||
})
|
||||
});
|
||||
};
|
||||
|
||||
describe("dashboardSupervisor.cy.js", () => {
|
||||
beforeEach(() => {
|
||||
cy.manageCommand("cypress_reset --create-assignment-evaluation --create-feedback-responses --create-course-completion-performance-criteria --create-attendance-days");
|
||||
cy.manageCommand(
|
||||
"cypress_reset --create-assignment-evaluation --create-feedback-responses --create-course-completion-performance-criteria --create-attendance-days"
|
||||
);
|
||||
login("test-supervisor1@example.com", "test");
|
||||
cy.visit("/");
|
||||
});
|
||||
|
|
@ -21,8 +25,8 @@ describe("dashboardSupervisor.cy.js", () => {
|
|||
it("contains correct numbers", () => {
|
||||
// we have no completed assignments, but some are in progress
|
||||
// -> makes sure that the numbers are correct
|
||||
getDashboardStatistics("assignments.completed").should("have.text", "0");
|
||||
getDashboardStatistics("assignments.passed").should("have.text", "0%");
|
||||
getDashboardStatistics("assignments.completed").should("have.text", "1");
|
||||
getDashboardStatistics("assignments.passed").should("have.text", "34%");
|
||||
});
|
||||
|
||||
it("contains correct details link", () => {
|
||||
|
|
@ -31,15 +35,21 @@ describe("dashboardSupervisor.cy.js", () => {
|
|||
// might be improved: roughly check
|
||||
// that the correct data is displayed
|
||||
cy.contains("Noch nicht bestätigt");
|
||||
cy.contains("Fahrzeug - Mein erstes Auto");
|
||||
cy.contains("Überprüfen einer Motorfahrzeugs-Versicherungspolice");
|
||||
cy.contains("Test Bern 2022 a");
|
||||
});
|
||||
});
|
||||
|
||||
describe("attendance day summary box", () => {
|
||||
it("contains correct numbers", () => {
|
||||
getDashboardStatistics("attendance.dayCompleted").should("have.text", "1");
|
||||
getDashboardStatistics("attendance.participantsPresent").should("have.text", "34%");
|
||||
getDashboardStatistics("attendance.dayCompleted").should(
|
||||
"have.text",
|
||||
"1"
|
||||
);
|
||||
getDashboardStatistics("attendance.participantsPresent").should(
|
||||
"have.text",
|
||||
"34%"
|
||||
);
|
||||
});
|
||||
it("contains correct details link", () => {
|
||||
clickOnDetailsLink("attendance");
|
||||
|
|
@ -53,7 +63,6 @@ describe("dashboardSupervisor.cy.js", () => {
|
|||
});
|
||||
});
|
||||
|
||||
|
||||
describe("overall summary box", () => {
|
||||
it("contains correct numbers (members, experts etc.)", () => {
|
||||
getDashboardStatistics("participant.count").should("have.text", "4");
|
||||
|
|
@ -66,7 +75,6 @@ describe("dashboardSupervisor.cy.js", () => {
|
|||
it("contains correct numbers", () => {
|
||||
getDashboardStatistics("feedback.average").should("have.text", "3.3");
|
||||
getDashboardStatistics("feedback.count").should("have.text", "3");
|
||||
|
||||
});
|
||||
it("contains correct details link", () => {
|
||||
clickOnDetailsLink("feedback");
|
||||
|
|
@ -76,8 +84,8 @@ describe("dashboardSupervisor.cy.js", () => {
|
|||
// that the correct data is displayed
|
||||
cy.contains("3.3 von 4");
|
||||
cy.contains("Test Trainer1");
|
||||
cy.contains("Durchführung «Test Bern 2022 a»")
|
||||
cy.contains("Circle «Fahrzeug»")
|
||||
cy.contains("Durchführung «Test Bern 2022 a»");
|
||||
cy.contains("Circle «Fahrzeug»");
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -94,8 +102,7 @@ describe("dashboardSupervisor.cy.js", () => {
|
|||
// that the correct data is displayed
|
||||
cy.contains("Selbsteinschätzung: Vorbereitung");
|
||||
cy.contains("Durchführung «Test Bern 2022 a»");
|
||||
cy.contains("Circle «Fahrzeug»")
|
||||
cy.contains("Circle «Fahrzeug»");
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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,10 +17,12 @@ from vbv_lernwelt.assignment.tests.assignment_factories import (
|
|||
from vbv_lernwelt.competence.factories import (
|
||||
ActionCompetenceFactory,
|
||||
ActionCompetenceListPageFactory,
|
||||
CompetenceCertificateFactory,
|
||||
CompetenceCertificateListFactory,
|
||||
CompetenceNaviPageFactory,
|
||||
PerformanceCriteriaFactory,
|
||||
)
|
||||
from vbv_lernwelt.competence.models import PerformanceCriteria
|
||||
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 (
|
||||
|
|
@ -160,6 +162,12 @@ def create_attendance_course(
|
|||
)
|
||||
|
||||
|
||||
def create_competence_certificate(course: Course) -> CompetenceCertificate:
|
||||
navi = CompetenceNaviPageFactory(parent=course.coursepage)
|
||||
certificate_list = CompetenceCertificateListFactory(parent=navi)
|
||||
return CompetenceCertificateFactory(parent=certificate_list)
|
||||
|
||||
|
||||
def create_assignment(
|
||||
course: Course,
|
||||
assignment_type: AssignmentType,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
|
||||
|
|
@ -121,12 +121,14 @@ def create_record(
|
|||
|
||||
return AssignmentStatisticsRecordType(
|
||||
# make sure it's unique, across all types of assignments!
|
||||
_id=f"{course_session_assignment._meta.model_name}#{course_session_assignment.id}", # noqa
|
||||
_id=f"{course_session_assignment._meta.model_name}#{course_session_assignment.id}",
|
||||
# noqa
|
||||
course_session_id=str(course_session_assignment.course_session.id), # noqa
|
||||
circle_id=learning_content.get_circle().id, # noqa
|
||||
course_session_assignment_id=str(course_session_assignment.id), # noqa
|
||||
generation=course_session_assignment.course_session.generation, # noqa
|
||||
assignment_type_translation_key=due_date.assignment_type_translation_key, # noqa
|
||||
assignment_type_translation_key=due_date.assignment_type_translation_key,
|
||||
# noqa
|
||||
assignment_title=learning_content.content_assignment.title, # noqa
|
||||
metrics=get_assignment_completion_metrics( # noqa
|
||||
course_session=course_session_assignment.course_session, # noqa
|
||||
|
|
@ -149,16 +151,17 @@ def assignments(
|
|||
for course_session in course_sessions:
|
||||
for csa in CourseSessionAssignment.objects.filter(
|
||||
course_session=course_session,
|
||||
learning_content__assignment_type__in=[
|
||||
learning_content__content_assignment__assignment_type__in=[
|
||||
AssignmentType.CASEWORK.value,
|
||||
AssignmentType.PREP_ASSIGNMENT.value,
|
||||
],
|
||||
learning_content__content_assignment__competence_certificate__isnull=False,
|
||||
):
|
||||
record = create_record(course_session_assignment=csa)
|
||||
records.append(record)
|
||||
|
||||
for cset in CourseSessionEdoniqTest.objects.filter(
|
||||
course_session=course_session
|
||||
course_session=course_session,
|
||||
learning_content__content_assignment__competence_certificate__isnull=False,
|
||||
):
|
||||
record = create_record(course_session_assignment=cset)
|
||||
records.append(record)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ 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,
|
||||
|
|
@ -101,11 +102,6 @@ class AssignmentTestCase(GraphQLTestCase):
|
|||
assignment_type=AssignmentType.CASEWORK
|
||||
)
|
||||
|
||||
def test_dashboard_contains_prep_assignments(self):
|
||||
self._test_assignment_type_dashboard_details(
|
||||
assignment_type=AssignmentType.PREP_ASSIGNMENT
|
||||
)
|
||||
|
||||
def test_dashboard_contains_edoniq_tests(self):
|
||||
self._test_assignment_type_dashboard_details(
|
||||
assignment_type=AssignmentType.EDONIQ_TEST
|
||||
|
|
@ -120,7 +116,6 @@ class AssignmentTestCase(GraphQLTestCase):
|
|||
|
||||
irrelevant_types_for_dashboard = set(AssignmentType) - {
|
||||
AssignmentType.CASEWORK,
|
||||
AssignmentType.PREP_ASSIGNMENT,
|
||||
AssignmentType.EDONIQ_TEST,
|
||||
}
|
||||
|
||||
|
|
@ -134,6 +129,7 @@ class AssignmentTestCase(GraphQLTestCase):
|
|||
deadline_at=datetime(2000, 4, 1),
|
||||
course_session=self.course_session,
|
||||
circle=self.circle,
|
||||
add_competence_certificate=True,
|
||||
)
|
||||
|
||||
create_assignment_completion(
|
||||
|
|
@ -203,6 +199,7 @@ class AssignmentTestCase(GraphQLTestCase):
|
|||
assignment_type=AssignmentType.CASEWORK,
|
||||
course_session=self.course_session,
|
||||
circle=self.circle,
|
||||
add_competence_certificate=True,
|
||||
)
|
||||
|
||||
assignment_2, _ = mix_assignment_cocktail(
|
||||
|
|
@ -210,13 +207,15 @@ class AssignmentTestCase(GraphQLTestCase):
|
|||
assignment_type=AssignmentType.EDONIQ_TEST,
|
||||
course_session=self.course_session,
|
||||
circle=self.circle,
|
||||
add_competence_certificate=True,
|
||||
)
|
||||
|
||||
assignment_3, _ = mix_assignment_cocktail(
|
||||
deadline_at=datetime(2010, 4, 1),
|
||||
assignment_type=AssignmentType.PREP_ASSIGNMENT,
|
||||
assignment_type=AssignmentType.CASEWORK,
|
||||
course_session=self.course_session,
|
||||
circle=self.circle,
|
||||
add_competence_certificate=True,
|
||||
)
|
||||
|
||||
# no completions for this assignment yet
|
||||
|
|
@ -225,6 +224,7 @@ class AssignmentTestCase(GraphQLTestCase):
|
|||
assignment_type=AssignmentType.EDONIQ_TEST,
|
||||
course_session=self.course_session,
|
||||
circle=self.circle,
|
||||
add_competence_certificate=False,
|
||||
)
|
||||
|
||||
# assignment 1
|
||||
|
|
@ -284,21 +284,21 @@ class AssignmentTestCase(GraphQLTestCase):
|
|||
|
||||
# 1 -> incomplete (not counted for average)
|
||||
# 2 -> complete 66% passed ...
|
||||
# 3 -> complete 100% passed --> 83.5%
|
||||
# 4 -> incomplete (not counted for average)
|
||||
# 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), 4)
|
||||
self.assertEqual(len(records), 3)
|
||||
|
||||
# 1 -> assigment_1_results (oldest)
|
||||
assignment_1_metrics = records[0]["metrics"]
|
||||
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
|
||||
|
|
@ -317,19 +317,12 @@ class AssignmentTestCase(GraphQLTestCase):
|
|||
self.assertEqual(assignment_3_metrics["ranking_completed"], True)
|
||||
self.assertEqual(assignment_3_metrics["average_passed"], 100)
|
||||
|
||||
# 4 -> no completions (newest)
|
||||
assignment_4_metrics = records[3]["metrics"]
|
||||
self.assertEqual(assignment_4_metrics["passed_count"], 0)
|
||||
self.assertEqual(assignment_4_metrics["failed_count"], 0)
|
||||
self.assertEqual(assignment_4_metrics["unranked_count"], 3)
|
||||
self.assertEqual(assignment_4_metrics["ranking_completed"], False)
|
||||
self.assertEqual(assignment_4_metrics["average_passed"], 0)
|
||||
|
||||
|
||||
def mix_assignment_cocktail(
|
||||
assignment_type: AssignmentType,
|
||||
course_session: CourseSession,
|
||||
circle: Circle,
|
||||
add_competence_certificate: bool = False,
|
||||
deadline_at: datetime | None = None,
|
||||
) -> Tuple[Assignment, CourseSessionAssignment | CourseSessionEdoniqTest]:
|
||||
"""
|
||||
|
|
@ -338,9 +331,15 @@ def mix_assignment_cocktail(
|
|||
"""
|
||||
|
||||
assignment = create_assignment(
|
||||
course=course_session.course, assignment_type=assignment_type
|
||||
course=course_session.course,
|
||||
assignment_type=assignment_type,
|
||||
)
|
||||
|
||||
if add_competence_certificate:
|
||||
certificate = create_competence_certificate(course=course_session.course)
|
||||
assignment.competence_certificate = certificate
|
||||
assignment.save()
|
||||
|
||||
if assignment_type == AssignmentType.EDONIQ_TEST:
|
||||
cset = create_course_session_edoniq_test(
|
||||
deadline_at=deadline_at,
|
||||
|
|
|
|||
|
|
@ -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