Merged in feature/VBV-474-auftragstyp-condition-acceptance (pull request #173)

Add CONDITION_ACCEPTANCE assignment type

* Add CONDITION_ACCEPTANCE assignment type

* Add translations

* Create default CONDITION_ACCEPTANCE assignment

* Move CONDITION_ACCEPTANCE assignment in learning sequence

* Add additional translations

* Add condition acceptance to ÜK basis circle

# Conflicts:
#	server/vbv_lernwelt/course/management/commands/create_default_courses.py

* Move condition acceptance to kickoff circle
This commit is contained in:
Elia Bieri 2023-08-02 08:13:35 +00:00
parent 8cee1346c5
commit 3a2d12c0b9
12 changed files with 162 additions and 8 deletions

View File

@ -92,7 +92,10 @@ const getShowDetailsText = (lc: LearningContent) => {
const assignmentType = (lc as LearningContentAssignment).assignment_type;
if (assignmentType === "CASEWORK" || assignmentType === "REFLECTION") {
return t("Ergebnisse anschauen");
} else if (assignmentType === "PREP_ASSIGNMENT") {
} else if (
assignmentType === "PREP_ASSIGNMENT" ||
assignmentType === "CONDITION_ACCEPTANCE"
) {
return t("Status anschauen");
}
}
@ -109,7 +112,11 @@ const getDetailsLink = (lc: LearningContent) => {
const getIconName = (lc: LearningContent) => {
if (isAssignment(lc)) {
const assignmentType = (lc as LearningContentAssignment).assignment_type;
if (assignmentType === "PREP_ASSIGNMENT" || assignmentType === "CASEWORK") {
if (
assignmentType === "PREP_ASSIGNMENT" ||
assignmentType === "CASEWORK" ||
assignmentType === "CONDITION_ACCEPTANCE"
) {
return "it-icon-assignment-large";
} else if (assignmentType === "REFLECTION") {
return "it-icon-test-large";

View File

@ -190,9 +190,11 @@ const assignmentUser = computed(() => {
const endBadgeText = computed(() => {
if (assignmentType.value === "PREP_ASSIGNMENT") {
return "Aufgaben";
return t("Aufgaben");
} else if (assignmentType.value === "CASEWORK") {
return "Abgabe";
return t("Abgabe");
} else if (assignmentType.value === "CONDITION_ACCEPTANCE") {
return t("Akzeptieren");
}
// just return the number of tasks as default

View File

@ -344,7 +344,11 @@ export interface AssignmentEvaluationTask {
};
}
export type AssignmentType = "CASEWORK" | "PREP_ASSIGNMENT" | "REFLECTION";
export type AssignmentType =
| "CASEWORK"
| "PREP_ASSIGNMENT"
| "REFLECTION"
| "CONDITION_ACCEPTANCE";
export interface Assignment extends BaseCourseWagtailPage {
readonly content_type: "assignment.Assignment";

View File

@ -1,5 +1,6 @@
import type { LearningContent } from "@/types";
import { assertUnreachable } from "@/utils/utils";
import { useTranslation } from "i18next-vue";
export interface LearningContentIdentifier {
title: string;
@ -9,15 +10,18 @@ export interface LearningContentIdentifier {
export function learningContentTypeData(
lc: LearningContent
): LearningContentIdentifier {
const { t } = useTranslation();
switch (lc.content_type) {
case "learnpath.LearningContentAssignment": {
let title = "unknown";
if (lc.assignment_type === "CASEWORK") {
title = "Geleitete Fallarbeit";
title = t("Geleitete Fallarbeit");
} else if (lc.assignment_type === "PREP_ASSIGNMENT") {
title = "Vorbereitungsaufgabe";
title = t("Vorbereitungsaufgabe");
} else if (lc.assignment_type === "REFLECTION") {
title = "Reflexion";
title = t("Reflexion");
} else if (lc.assignment_type === "CONDITION_ACCEPTANCE") {
title = t("Vorbedingung");
}
return {
title: title,

View File

@ -2673,6 +2673,66 @@ def create_uk_basis_prep_assignment(course_id=COURSE_UK):
return assignment
def create_uk_condition_acceptance(course_id=COURSE_UK_FR):
assignment_list_page = (
CoursePage.objects.get(course_id=course_id)
.get_children()
.exact_type(AssignmentListPage)
.first()
)
assignment = AssignmentFactory(
parent=assignment_list_page,
assignment_type=AssignmentType.CONDITION_ACCEPTANCE.name,
title="Redlichkeitserklärung",
intro_text=replace_whitespace(
"""
<h3>Was akzeptierst du?</h3>
<p>
Die folgende Redlichkeitserklärung ist ein wichtiges Dokument, das bestätigt, dass die Arbeit, die du einreichst, ganz und gar deine eigene ist und dass du alle Regeln der akademischen Integrität eingehalten hast. Akademische Integrität beinhaltet Ehrlichkeit, Verantwortung und Respekt für das geistige Eigentum anderer. Dies bedeutet, dass du keine unerlaubte Hilfe in Anspruch nimmst und dass du alle Quellen und Materialien, die du zur Unterstützung deiner Arbeit genutzt hast, korrekt zitierst und anerkennst.
Durch das Unterzeichnen dieser Erklärung bestätigst du, dass du die Bedeutung der akademischen Integrität verstanden hast und die Verantwortung für die Einhaltung dieser Prinzipien übernimmst. Bitte bedenke, dass das Brechen dieser Regeln ernsthafte Konsequenzen nach sich ziehen kann, darunter eine Verringerung deiner Note, das Durchfallen des Kurses oder andere disziplinarische Maßnahmen.
</p>
"""
),
performance_objectives=[],
)
assignment.tasks = []
assignment.tasks.append(
(
"task",
TaskBlockFactory(
title="Erklärung",
# it is hard to create a StreamValue programmatically, we have to
# create a `StreamValue` manually. Ask Daniel and/or Ramon
content=StreamValue(
TaskContentStreamBlock(),
stream_data=[
(
"explanation",
ExplanationBlockFactory(
text=RichText(
"Ich erkläre hiermit, dass ich diese Prüfung oder Aufgabe selbstständig und ohne unzulässige Hilfe Dritter ausgeführt habe. Alle verwendeten Quellen und Hilfsmittel sind korrekt und vollständig angegeben. Ich verstehe, dass ein Verstoß gegen diese Erklärung ernsthafte Konsequenzen nach sich ziehen kann, einschließlich, aber nicht beschränkt auf, Notenreduzierung, Kursversagen und disziplinarische Maßnahmen."
)
),
),
(
"user_confirmation",
ExplanationBlockFactory(
text=RichText("Ja, ich akzeptiere diese Bedingungen.")
),
),
],
),
),
)
)
assignment.save()
return assignment
def create_uk_reflection(course_id=COURSE_UK):
assignment_list_page = (
CoursePage.objects.get(course_id=course_id)

View File

@ -0,0 +1,27 @@
# Generated by Django 3.2.13 on 2023-08-01 08:34
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("assignment", "0004_alter_assignmentcompletion_additional_json_data"),
]
operations = [
migrations.AlterField(
model_name="assignment",
name="assignment_type",
field=models.CharField(
choices=[
("CASEWORK", "CASEWORK"),
("PREP_ASSIGNMENT", "PREP_ASSIGNMENT"),
("REFLECTION", "REFLECTION"),
("CONDITION_ACCEPTANCE", "CONDITION_ACCEPTANCE"),
],
default="CASEWORK",
max_length=50,
),
),
]

View File

@ -112,6 +112,7 @@ class AssignmentType(Enum):
CASEWORK = "CASEWORK" # Geleitete Fallarbeit
PREP_ASSIGNMENT = "PREP_ASSIGNMENT" # Vorbereitungsauftrag
REFLECTION = "REFLECTION" # Reflexion
CONDITION_ACCEPTANCE = "CONDITION_ACCEPTANCE" # Bedingungsannahme
class Assignment(CourseBasePage):

View File

@ -6,6 +6,7 @@ from slugify import slugify
from wagtail.rich_text import RichText
from vbv_lernwelt.assignment.creators.create_assignments import (
create_uk_condition_acceptance,
create_uk_fahrzeug_casework,
create_uk_fahrzeug_prep_assignment,
create_uk_reflection,
@ -79,6 +80,7 @@ def create_test_course(include_uk=True, include_vv=True, with_sessions=False):
)
create_uk_fahrzeug_casework(course_id=COURSE_TEST_ID)
create_uk_fahrzeug_prep_assignment(course_id=COURSE_TEST_ID)
create_uk_condition_acceptance(course_id=COURSE_TEST_ID)
create_uk_reflection(course_id=COURSE_TEST_ID)
create_test_learning_path(include_uk=include_uk, include_vv=include_vv)
@ -292,6 +294,13 @@ damit du erfolgreich mit deinem Lernpfad (durch-)starten kannst.
),
content_url=f"/course/{lp.get_course().slug}/media/handlungsfelder/{slugify(title)}",
)
LearningContentAssignmentFactory(
title="Redlichkeitserklärung",
parent=circle,
content_assignment=Assignment.objects.get(
slug__startswith="test-lehrgang-assignment-redlichkeits"
),
),
LearningContentAssignmentFactory(
title="Fahrzeug - Mein erstes Auto",
assignment_type="PREP_ASSIGNMENT",

View File

@ -324,6 +324,13 @@ In diesem Circle erfährst du wie die überbetrieblichen Kurse aufgebaut sind. Z
)
LearningSequenceFactory(title="Transfer", parent=circle, icon="it-icon-ls-end")
LearningUnitFactory(title="Reflexion", title_hidden=True, parent=circle)
LearningContentAssignmentFactory(
title="Redlichkeitserklärung",
parent=circle,
content_assignment=Assignment.objects.get(
slug__startswith="überbetriebliche-kurse-assignment-redlichkeits"
),
)
LearningContentAssignmentFactory(
title="Reflexion",
assignment_type="REFLECTION",

View File

@ -8,6 +8,7 @@ from django.utils import timezone
from vbv_lernwelt.assignment.creators.create_assignments import (
create_uk_basis_prep_assignment,
create_uk_condition_acceptance,
create_uk_fahrzeug_casework,
create_uk_fahrzeug_prep_assignment,
create_uk_fr_fahrzeug_casework,
@ -236,6 +237,7 @@ def create_course_uk_de(course_id=COURSE_UK, lang="de"):
parent=course.coursepage,
)
create_uk_kickoff_prep_assignment(course_id=course_id)
create_uk_condition_acceptance(course_id=course_id)
create_uk_basis_prep_assignment(course_id=course_id)
create_uk_fahrzeug_casework(course_id=course_id)
create_uk_fahrzeug_prep_assignment(course_id=course_id)

View File

@ -0,0 +1,27 @@
# Generated by Django 3.2.13 on 2023-08-01 08:34
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("learnpath", "0001_initial"),
]
operations = [
migrations.AlterField(
model_name="learningcontentassignment",
name="assignment_type",
field=models.CharField(
choices=[
("CASEWORK", "CASEWORK"),
("PREP_ASSIGNMENT", "PREP_ASSIGNMENT"),
("REFLECTION", "REFLECTION"),
("CONDITION_ACCEPTANCE", "CONDITION_ACCEPTANCE"),
],
default="CASEWORK",
max_length=50,
),
),
]

View File

@ -376,6 +376,10 @@ class LearningContentAssignment(LearningContent):
FieldPanel("description"),
]
def save(self, clean=True, user=None, log_action=False, **kwargs):
self.assignment_type = self.content_assignment.assignment_type
super().save(**kwargs)
class LearningContentDocumentList(LearningContent):
can_user_self_toggle_course_completion = models.BooleanField(default=True)