feat: introduce course config

This commit is contained in:
Livio Bieri 2024-02-27 14:47:26 +01:00
parent 9dc412502e
commit c4bb5b0351
20 changed files with 369 additions and 150 deletions

View File

@ -19,8 +19,8 @@ const documents = {
"\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_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 enable_circle_documents\n circle_contact_type\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 enable_circle_documents\n circle_contact_type\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 feedback_user\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 courseSessionDetail($courseSessionId: ID!) {\n course_session(id: $courseSessionId) {\n id\n title\n course {\n id\n title\n slug\n configuration {\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 enable_circle_documents\n enable_learning_mentor\n enable_competence_certificates\n }\n action_competences {\n competence_id\n ...CoursePageFields\n performance_criteria {\n competence_id\n learning_unit {\n id\n slug\n evaluate_url\n }\n ...CoursePageFields\n }\n }\n learning_path {\n ...CoursePageFields\n topics {\n is_visible\n ...CoursePageFields\n circles {\n description\n goals\n ...CoursePageFields\n learning_sequences {\n icon\n ...CoursePageFields\n learning_units {\n feedback_user\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,
@ -68,11 +68,11 @@ export function graphql(source: "\n query competenceCertificateQuery($courseSlu
/**
* 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 courseSessionDetail($courseSessionId: ID!) {\n course_session(id: $courseSessionId) {\n id\n title\n course {\n id\n title\n slug\n enable_circle_documents\n circle_contact_type\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"): (typeof documents)["\n query courseSessionDetail($courseSessionId: ID!) {\n course_session(id: $courseSessionId) {\n id\n title\n course {\n id\n title\n slug\n enable_circle_documents\n circle_contact_type\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"];
export function graphql(source: "\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 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"): (typeof documents)["\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 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"];
/**
* 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 enable_circle_documents\n circle_contact_type\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 feedback_user\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 enable_circle_documents\n circle_contact_type\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 feedback_user\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"];
export function graphql(source: "\n query courseQuery($slug: String!) {\n course(slug: $slug) {\n id\n title\n slug\n category_name\n configuration {\n enable_circle_documents\n enable_learning_mentor\n enable_competence_certificates\n }\n action_competences {\n competence_id\n ...CoursePageFields\n performance_criteria {\n competence_id\n learning_unit {\n id\n slug\n evaluate_url\n }\n ...CoursePageFields\n }\n }\n learning_path {\n ...CoursePageFields\n topics {\n is_visible\n ...CoursePageFields\n circles {\n description\n goals\n ...CoursePageFields\n learning_sequences {\n icon\n ...CoursePageFields\n learning_units {\n feedback_user\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 configuration {\n enable_circle_documents\n enable_learning_mentor\n enable_competence_certificates\n }\n action_competences {\n competence_id\n ...CoursePageFields\n performance_criteria {\n competence_id\n learning_unit {\n id\n slug\n evaluate_url\n }\n ...CoursePageFields\n }\n }\n learning_path {\n ...CoursePageFields\n topics {\n is_visible\n ...CoursePageFields\n circles {\n description\n goals\n ...CoursePageFields\n learning_sequences {\n icon\n ...CoursePageFields\n learning_units {\n feedback_user\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

View File

@ -236,19 +236,15 @@ type CourseObjectType {
title: String!
category_name: String!
slug: String!
enable_circle_documents: Boolean!
circle_contact_type: CourseCourseCircleContactTypeChoices!
configuration: CourseConfigurationObjectType!
learning_path: LearningPathObjectType!
action_competences: [ActionCompetenceObjectType!]!
}
"""An enumeration."""
enum CourseCourseCircleContactTypeChoices {
"""EXPERT"""
EXPERT
"""LEARNING_MENTOR"""
LEARNING_MENTOR
type CourseConfigurationObjectType {
enable_circle_documents: Boolean!
enable_learning_mentor: Boolean!
enable_competence_certificates: Boolean!
}
type ActionCompetenceObjectType implements CoursePageInterface {
@ -580,9 +576,9 @@ type UserObjectType {
first_name: String!
last_name: String!
id: UUID!
avatar_url: String!
email: String!
language: CoreUserLanguageChoices!
avatar_url: String
}
"""An enumeration."""

View File

@ -25,7 +25,7 @@ export const CompetenceRecordStatisticsType = "CompetenceRecordStatisticsType";
export const CompetencesStatisticsType = "CompetencesStatisticsType";
export const ContentDocumentObjectType = "ContentDocumentObjectType";
export const CoreUserLanguageChoices = "CoreUserLanguageChoices";
export const CourseCourseCircleContactTypeChoices = "CourseCourseCircleContactTypeChoices";
export const CourseConfigurationObjectType = "CourseConfigurationObjectType";
export const CourseObjectType = "CourseObjectType";
export const CoursePageInterface = "CoursePageInterface";
export const CourseProgressType = "CourseProgressType";

View File

@ -126,8 +126,11 @@ export const COURSE_SESSION_DETAIL_QUERY = graphql(`
id
title
slug
enable_circle_documents
circle_contact_type
configuration {
enable_circle_documents
enable_learning_mentor
enable_competence_certificates
}
}
users {
id
@ -211,8 +214,11 @@ export const COURSE_QUERY = graphql(`
title
slug
category_name
enable_circle_documents
circle_contact_type
configuration {
enable_circle_documents
enable_learning_mentor
enable_competence_certificates
}
action_competences {
competence_id
...CoursePageFields

View File

@ -59,7 +59,6 @@ const courseSessionDetailResult = useCourseSessionDetailQuery();
</div>
</div>
<div
v-if="courseSession.course.enable_circle_documents"
class="my-4 flex flex-col justify-between bg-white p-6 lg:my-0"
data-cy="circle-documents"
>

View File

@ -57,33 +57,14 @@ const learningContentReadonly = computed(() => {
return props.readonly || !actions.includes("complete-learning-content");
});
const duration = computed(() => {
// if (circleStore.circle) {
// const minutes = sumBy(circleStore.circle.learningSequences, "minutes");
// return humanizeDuration(minutes);
// }
return "";
});
const showDuration = computed(() => {
// return (
// circleStore.circle && sumBy(circleStore.circle.learningSequences, "minutes") > 0
// );
return false;
});
const showDocumentSection = computed(() => {
return lpQueryResult.course.value?.enable_circle_documents && !props.readonly;
return (
lpQueryResult.course.value?.configuration.enable_circle_documents && !props.readonly
);
});
const courseConfig = computed(() => {
if (lpQueryResult.course.value?.circle_contact_type === "EXPERT") {
return {
contactDescription: "circlePage.contactExpertDescription",
contactButton: "circlePage.contactExpertButton",
showContact: true,
};
} else if (lpQueryResult.course.value?.circle_contact_type === "LEARNING_MENTOR") {
if (lpQueryResult.course.value?.configuration.enable_learning_mentor) {
return {
contactDescription: "circlePage.contactLearningMentorDescription",
contactButton: "circlePage.contactLearningMentorButton",
@ -91,8 +72,8 @@ const courseConfig = computed(() => {
};
} else {
return {
contactDescription: "",
contactButton: "",
contactDescription: "circlePage.contactExpertDescription",
contactButton: "circlePage.contactExpertButton",
showContact: true,
};
}
@ -117,12 +98,12 @@ interface Mentor {
const experts = computed<Expert[] | null>(() => {
if (courseConfig.value.showContact) {
if (lpQueryResult.course.value?.circle_contact_type === "EXPERT") {
return circleExperts.value;
} else if (lpQueryResult.course.value?.circle_contact_type === "LEARNING_MENTOR") {
if (lpQueryResult.course.value?.configuration.enable_learning_mentor) {
if (mentors.value?.length > 0) {
return mentors.value.map((m: Mentor) => m.mentor);
}
} else {
return circleExperts.value;
}
}
return null;
@ -216,11 +197,6 @@ watch(
{{ circle?.title }}
</h1>
<div v-if="showDuration" class="mt-2">
{{ $t("circlePage.duration") }}:
{{ duration }}
</div>
<div class="mt-8 w-full">
<CircleDiagram v-if="circle" :circle="circle"></CircleDiagram>
</div>

View File

@ -5,7 +5,6 @@ import type {
AssignmentCompletionStatus as AssignmentCompletionStatusGenerated,
AssignmentObjectType,
CircleObjectType,
CourseCourseCircleContactTypeChoices,
CourseSessionObjectType,
CourseSessionUserObjectsType,
LearningContentAssignmentObjectType,
@ -190,13 +189,18 @@ export interface CourseCompletion {
additional_json_data: unknown;
}
export interface CourseConfiguration {
enable_circle_documents: boolean;
enable_learning_mentor: boolean;
enable_competence_certificates: boolean;
}
export interface Course {
id: string;
title: string;
category_name: string;
slug: string;
enable_circle_documents: boolean;
circle_contact_type: CourseCourseCircleContactTypeChoices;
configuration: CourseConfiguration;
}
export interface CourseCategory {

View File

@ -369,5 +369,5 @@ def command(
)
course = Course.objects.get(id=COURSE_TEST_ID)
course.enable_circle_documents = enable_circle_documents
course.configuration.enable_circle_documents = enable_circle_documents
course.save()

View File

@ -1,9 +1,24 @@
from django.contrib import admin
from vbv_lernwelt.course.models import Course, CourseSession, CourseSessionUser
from vbv_lernwelt.course.models import (
Course,
CourseConfiguration,
CourseSession,
CourseSessionUser,
)
from vbv_lernwelt.learnpath.models import Circle
@admin.register(CourseConfiguration)
class CourseConfigurationAdmin(admin.ModelAdmin):
list_display = [
"course",
"enable_circle_documents",
"enable_learning_mentor",
"enable_competence_certificates",
]
@admin.register(Course)
class CourseAdmin(admin.ModelAdmin):
list_display = [

View File

@ -9,3 +9,19 @@ COURSE_UK_TRAINING_IT = -9
COURSE_VERSICHERUNGSVERMITTLERIN_FR_ID = -10
COURSE_VERSICHERUNGSVERMITTLERIN_IT_ID = -11
COURSE_VERSICHERUNGSVERMITTLERIN_PRUEFUNG_ID = -12
VV_COURSE_IDS = [
COURSE_VERSICHERUNGSVERMITTLERIN_ID,
COURSE_VERSICHERUNGSVERMITTLERIN_FR_ID,
COURSE_VERSICHERUNGSVERMITTLERIN_IT_ID,
COURSE_VERSICHERUNGSVERMITTLERIN_PRUEFUNG_ID,
]
UK_COURSE_IDS = [
COURSE_UK,
COURSE_UK_FR,
COURSE_UK_IT,
COURSE_UK_TRAINING,
COURSE_UK_TRAINING_FR,
COURSE_UK_TRAINING_IT,
]

View File

@ -24,6 +24,7 @@ from vbv_lernwelt.competence.factories import (
)
from vbv_lernwelt.competence.models import CompetenceCertificate, PerformanceCriteria
from vbv_lernwelt.core.models import User
from vbv_lernwelt.course.consts import COURSE_TEST_ID, UK_COURSE_IDS, VV_COURSE_IDS
from vbv_lernwelt.course.factories import CoursePageFactory
from vbv_lernwelt.course.models import (
Course,
@ -337,3 +338,68 @@ def create_circle_expert(
course_session_expert_user.expert.add(circle)
return course_session_expert_user
def apply_course_configuration(course: Course):
"""
Apply course configuration based on course id:
By default everything is enabled, disable unnecessary features
"""
if course.id == COURSE_TEST_ID:
pass # all features are enabled
elif course.id in VV_COURSE_IDS:
course.configuration.enable_competence_certificates = False
elif course.id in UK_COURSE_IDS:
course.configuration.enable_learning_mentor = False
else:
raise ValueError(f"Unknown course id {course.id}")
course.configuration.save()
def create_course_with_categories(
course_id,
title,
apps=None,
):
if apps is not None:
Course = apps.get_model("course", "Course")
CourseCategory = apps.get_model("course", "CourseCategory")
else:
# pylint: disable=import-outside-toplevel
from vbv_lernwelt.course.models import Course, CourseCategory
course, _ = Course.objects.get_or_create(
id=course_id,
title=title,
category_name="Handlungsfeld",
)
apply_course_configuration(course)
CourseCategory.objects.get_or_create(course=course, title="Allgemein", general=True)
for cat in [
"Fahrzeug",
"Reisen",
"Einkommenssicherung",
"Gesundheit",
"Haushalt",
"Sparen",
"Pensionierung",
"KMU",
"Wohneigentum",
"Rechtsstreitigkeiten",
"Erben / Vererben",
"Selbstständigkeit",
]:
CourseCategory.objects.get_or_create(course=course, title=cat)
course_page = CoursePageFactory(
title=title,
parent=get_wagtail_default_site().root_page,
course=course,
)
course.slug = course_page.slug
course.save()
return course

View File

@ -1,54 +0,0 @@
from vbv_lernwelt.course.consts import COURSE_VERSICHERUNGSVERMITTLERIN_ID
from vbv_lernwelt.course.factories import CoursePageFactory
from vbv_lernwelt.course.models import CircleContactType
from vbv_lernwelt.course.utils import get_wagtail_default_site
def create_versicherungsvermittlerin_with_categories(
apps=None,
schema_editor=None,
course_id=COURSE_VERSICHERUNGSVERMITTLERIN_ID,
title="Versicherungsvermittler/-in",
):
if apps is not None:
Course = apps.get_model("course", "Course")
CourseCategory = apps.get_model("course", "CourseCategory")
else:
# pylint: disable=import-outside-toplevel
from vbv_lernwelt.course.models import Course, CourseCategory
course, _ = Course.objects.get_or_create(
id=course_id,
title=title,
category_name="Handlungsfeld",
enable_circle_documents=False,
circle_contact_type=CircleContactType.LEARNING_MENTOR.value,
)
CourseCategory.objects.get_or_create(course=course, title="Allgemein", general=True)
for cat in [
"Fahrzeug",
"Reisen",
"Einkommenssicherung",
"Gesundheit",
"Haushalt",
"Sparen",
"Pensionierung",
"KMU",
"Wohneigentum",
"Rechtsstreitigkeiten",
"Erben / Vererben",
"Selbstständigkeit",
]:
CourseCategory.objects.get_or_create(course=course, title=cat)
course_page = CoursePageFactory(
title=title,
parent=get_wagtail_default_site().root_page,
course=course,
)
course.slug = course_page.slug
course.save()
return course

View File

@ -12,6 +12,7 @@ from vbv_lernwelt.course.models import (
CircleDocument,
Course,
CourseBasePage,
CourseConfiguration,
CoursePage,
CourseSession,
CourseSessionUser,
@ -86,11 +87,22 @@ def resolve_course_page(
raise e
class CourseConfigurationObjectType(DjangoObjectType):
class Meta:
model = CourseConfiguration
fields = (
"enable_circle_documents",
"enable_learning_mentor",
"enable_competence_certificates",
)
class CourseObjectType(DjangoObjectType):
learning_path = graphene.Field(LearningPathObjectType, required=True)
action_competences = graphene.List(
graphene.NonNull(ActionCompetenceObjectType), required=True
)
configuration = graphene.Field(CourseConfigurationObjectType, required=True)
class Meta:
model = Course
@ -99,8 +111,7 @@ class CourseObjectType(DjangoObjectType):
"title",
"category_name",
"slug",
"enable_circle_documents",
"circle_contact_type",
"configuration",
)
@staticmethod

View File

@ -65,6 +65,7 @@ from vbv_lernwelt.course.creators.test_course import (
create_edoniq_test_assignment,
create_test_course,
)
from vbv_lernwelt.course.creators.test_utils import create_course_with_categories
from vbv_lernwelt.course.creators.uk_course import (
create_competence_navi,
create_uk_fr_learning_path,
@ -74,9 +75,6 @@ from vbv_lernwelt.course.creators.uk_course import (
from vbv_lernwelt.course.creators.uk_training_course import (
create_uk_training_learning_path,
)
from vbv_lernwelt.course.creators.versicherungsvermittlerin import (
create_versicherungsvermittlerin_with_categories,
)
from vbv_lernwelt.course.models import (
Course,
CoursePage,
@ -200,7 +198,7 @@ def create_versicherungsvermittlerin_course(
"it": "Intermediario/a assicurativo/a",
}
# Versicherungsvermittler/in mit neuen Circles
course = create_versicherungsvermittlerin_with_categories(
course = create_course_with_categories(
course_id=course_id,
title=names[language],
)
@ -290,7 +288,7 @@ def create_versicherungsvermittlerin_pruefung_course(
"it": "Intermediario/a assicurativo/a AFA Esame",
}
# Versicherungsvermittler/in mit neuen Circles
course = create_versicherungsvermittlerin_with_categories(
course = create_course_with_categories(
course_id=course_id,
title=names[language],
)
@ -315,9 +313,7 @@ def create_course_uk_de(course_id=COURSE_UK, lang="de"):
"fr": "Cours interentreprises",
"it": "Corsi interaziendali",
}
course = create_versicherungsvermittlerin_with_categories(
course_id=course_id, title=names[lang]
)
course = create_course_with_categories(course_id=course_id, title=names[lang])
# assignments create assignments parent page
_assignment_list_page = AssignmentListPageFactory(
@ -476,7 +472,7 @@ def create_course_uk_de_course_sessions():
def create_course_uk_fr():
# Überbetriebliche Kurse FR
course = create_versicherungsvermittlerin_with_categories(
course = create_course_with_categories(
course_id=COURSE_UK_FR, title="Cours interentreprises"
)
@ -526,7 +522,7 @@ def create_course_uk_fr():
def create_course_uk_it():
# Überbetriebliche Kurse FR
course = create_versicherungsvermittlerin_with_categories(
course = create_course_with_categories(
course_id=COURSE_UK_IT, title="Corso interaziendale"
)
@ -627,7 +623,7 @@ def create_course_uk_de_completion_data(course_session):
def create_course_training_de():
# Test Lehrgang für üK Trainer
course = create_versicherungsvermittlerin_with_categories(
course = create_course_with_categories(
course_id=COURSE_UK_TRAINING, title="myVBV Training"
)
@ -717,7 +713,7 @@ def create_course_session_assignments(course_session, assignment_slug, i=1):
def create_course_training_fr():
# Test Lehrgang für üK Trainer FR
course = create_versicherungsvermittlerin_with_categories(
course = create_course_with_categories(
course_id=COURSE_UK_TRAINING_FR, title="myVBV Training (FR)"
)
@ -804,7 +800,7 @@ def create_course_training_fr():
def create_course_training_it():
# Test Lehrgang für üK Trainer FR
course = create_versicherungsvermittlerin_with_categories(
course = create_course_with_categories(
course_id=COURSE_UK_TRAINING_IT, title="myVBV Training (IT)"
)

View File

@ -0,0 +1,111 @@
import django.db.models.deletion
from django.db import migrations, models
TEST_COURSE_ID = -1
UK_COURSE_IDS = [
-3, # uk-de
-6, # uk-training-de
-5, # uk-fr
-7, # uk-training-fr
-8, # uk-it
-9, # uk-training-it
]
VV_COURSE_IDS = [
-4, # vv-de
-10, # vv-fr
-11, # vv-it
-12, # vv-prüfung
]
def forward_migration(apps, schema_editor):
Course = apps.get_model("course", "Course")
CourseConfiguration = apps.get_model("course", "CourseConfiguration")
for course in Course.objects.all():
config, created = CourseConfiguration.objects.get_or_create(
course=course,
)
if created:
# moved -> use existing value from course
config.enable_circle_documents = course.enable_circle_documents
# by default everything is enabled
# -> disable unnecessary features
if course.id in UK_COURSE_IDS:
config.enable_learning_mentor = False
elif course.id in VV_COURSE_IDS:
config.enable_competence_certificates = False
config.save()
def backward_migration(apps, schema_editor):
CourseConfiguration = apps.get_model("course", "CourseConfiguration")
for config in CourseConfiguration.objects.all():
course = config.course
course.enable_circle_documents = config.enable_circle_documents
course.save()
class Migration(migrations.Migration):
dependencies = [
("course", "0006_auto_20231221_1411"),
]
operations = [
migrations.CreateModel(
name="CourseConfiguration",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"enable_circle_documents",
models.BooleanField(
default=True, verbose_name="Dokumente im Circle ein/aus"
),
),
(
"enable_learning_mentor",
models.BooleanField(
default=True, verbose_name="Lernmentor-Funktion ein/aus"
),
),
(
"enable_competence_certificates",
models.BooleanField(
default=True, verbose_name="Kompetenzweise ein/aus"
),
),
(
"course",
models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE,
related_name="configuration",
to="course.course",
),
),
],
),
migrations.RunPython(forward_migration, backward_migration),
migrations.RemoveField(
model_name="course",
name="circle_contact_type",
),
migrations.RemoveField(
model_name="course",
name="enable_circle_documents",
),
]

View File

@ -28,14 +28,6 @@ class Course(models.Model):
slug = models.SlugField(
_("Slug"), max_length=255, unique=True, blank=True, allow_unicode=True
)
enable_circle_documents = models.BooleanField(
_("Trainer Dokumente in Circles"), default=True
)
circle_contact_type = models.CharField(
max_length=50,
choices=[(cct.value, cct.value) for cct in CircleContactType],
default=CircleContactType.EXPERT.value,
)
def get_course_url(self):
return f"/course/{self.slug}"
@ -329,3 +321,24 @@ class CircleDocument(models.Model):
self.file.upload_finished_at = None
self.file.save()
return super().delete(*args, **kwargs)
class CourseConfiguration(models.Model):
course = models.OneToOneField(
Course, on_delete=models.CASCADE, related_name="configuration"
)
enable_circle_documents = models.BooleanField(
_("Dokumente im Circle ein/aus"), default=True
)
enable_learning_mentor = models.BooleanField(
_("Lernmentor-Funktion ein/aus"), default=True
)
enable_competence_certificates = models.BooleanField(
_("Kompetenzweise ein/aus"), default=True
)
def __str__(self):
return f"Course Configuration for '{self.course.title}'"

View File

@ -7,6 +7,7 @@ from vbv_lernwelt.course.models import (
Course,
CourseCategory,
CourseCompletion,
CourseConfiguration,
CourseSession,
)
from vbv_lernwelt.duedate.models import DueDate
@ -14,12 +15,27 @@ from vbv_lernwelt.duedate.serializers import DueDateSerializer
from vbv_lernwelt.iam.permissions import course_session_permissions
class CourseConfigurationSerializer(serializers.ModelSerializer):
class Meta:
model = CourseConfiguration
fields = [
"id",
"course",
"enable_circle_documents",
"enable_learning_mentor",
"enable_competence_certificates",
]
class CourseSerializer(serializers.ModelSerializer):
id = StringIDField()
configuration = CourseConfigurationSerializer(
read_only=True,
)
class Meta:
model = Course
fields = ["id", "title", "category_name", "slug", "enable_circle_documents"]
fields = ["id", "title", "category_name", "slug", "configuration"]
class CourseCategorySerializer(serializers.ModelSerializer):

View File

@ -0,0 +1,10 @@
from django.db.models.signals import post_save
from django.dispatch import receiver
from vbv_lernwelt.course.models import Course, CourseConfiguration
@receiver(post_save, sender=Course)
def create_course_configuration(sender, instance, created, **kwargs):
if created:
CourseConfiguration.objects.create(course=instance)

View File

@ -0,0 +1,39 @@
# Generated by Django 3.2.20 on 2024-02-26 15:42
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("notify", "0005_alter_notification_notification_trigger"),
]
operations = [
migrations.AlterField(
model_name="notification",
name="notification_trigger",
field=models.CharField(
choices=[
("ATTENDANCE_COURSE_REMINDER", "Attendance Course Reminder"),
("ASSIGNMENT_REMINDER", "Assignment Reminder"),
(
"CASEWORK_EXPERT_EVALUATION_REMINDER",
"Casework Expert Evaluation Reminder",
),
("CASEWORK_SUBMITTED", "Casework Submitted"),
("CASEWORK_EVALUATED", "Casework Evaluated"),
("NEW_FEEDBACK", "New Feedback"),
(
"SELF_EVALUATION_FEEDBACK_REQUESTED",
"Self Evaluation Feedback Requested",
),
(
"SELF_EVALUATION_FEEDBACK_PROVIDED",
"Self Evaluation Feedback Provided",
),
],
default="",
max_length=255,
),
),
]